엔지니어링 · 2024
협동로봇 바리스타 셀 운영 프로그램
주문 접수부터 로봇 추출 제어까지 담당하는 매장용 터치 데스크톱 앱
키오스크 주문과 직원의 수동 주문을 하나의 대기열로 모아 협동로봇에 Modbus TCP로 전달하고, 추출 진행 상황과 소모품, 알람을 한 화면에서 확인하도록 만든 운영 프로그램입니다.
- 고객
- 비공개 고객
- 분야
- 엔지니어링

개요
커피를 추출하는 협동로봇 셀의 운영 PC에서 돌아가는 Windows 데스크톱 프로그램입니다. 매장 직원이 터치 모니터로 조작하며, 주문을 받고 로봇에 추출을 지시하고 설비 상태를 확인하는 일을 한 화면에서 처리합니다.
로봇은 Modbus TCP 레지스터로만 명령을 주고받습니다. 이 프로그램은 그 사이에 들어가, 사람이 쓰는 "카페인 더블샷 4잔" 같은 주문을 로봇이 읽는 레지스터 값과 핸드쉐이크 절차로 바꿉니다. 반대로 로봇과 설비가 올리는 상태 비트는 직원이 바로 알아볼 수 있는 인디케이터와 한글 안내 문구로 바꿔 보여 줍니다.
조작 대상이 터치 모니터 하나뿐이므로 화면은 1920x1200 전체화면 전용으로 만들었고, 숫자 입력이 필요한 자리에는 화면 키패드를 띄웁니다.
과제
주문이 두 경로로 들어옵니다. 외부 키오스크가 네트워크로 보내는 주문과 직원이 화면에서 직접 넣는 주문을 하나의 대기열로 합쳐야 했습니다.
로봇과의 통신은 한 번의 요청과 응답으로 끝나지 않습니다. 명령 레지스터에 값을 쓰고, 로봇이 같은 값을 피드백 레지스터로 돌려주면 명령을 지우고, 작업 완료 신호가 올라오면 다시 핸드쉐이크 레지스터를 주고받아 양쪽이 모두 0으로 돌아가야 다음 잔으로 넘어갑니다. 이 절차 중 어느 단계에서 끊기더라도 대기열이 멈추지 않아야 했습니다.
추출 도중 프로그램이 종료되거나 네트워크가 끊기면 로봇은 직전 명령을 쥔 채로 남습니다. 다시 켰을 때 그 상태를 먼저 정리하지 않으면 새 주문이 전달되지 않습니다.
해결 방법
주문 경로를 하나로 모으고, 그 대기열을 로봇 상태에 맞춰 순서대로 흘려보내는 구조로 만들었습니다.
- 키오스크는 TCP 소켓으로 세 자리 주문 코드를 보냅니다. 첫 자리는 카페인 여부, 둘째 자리는 샷 수, 셋째 자리는 잔 수입니다
- 직원은 메인 화면에서 같은 조건을 라디오 버튼과 수량 버튼으로 골라 주문을 넣습니다. 수량을 정하지 않고 연속 추출을 거는 것도 가능합니다
- 키오스크 연동은 토글 하나로 끌 수 있어, 점검 중에는 외부 주문을 막고 수동으로만 운영할 수 있습니다
- 직전 대기 주문과 종류가 같으면 새 주문을 그 주문에 합쳐 최대 99잔까지 누적합니다
- 대기열에서는 대기 중인 주문만 취소할 수 있고, 대기 중인 주문 전체를 한 번에 비우는 버튼을 따로 두었습니다

매일 반복되는 개점과 마감 절차도 화면에 넣었습니다. 시작 준비는 커피머신 점검부터 그리퍼 확인까지 8페이지의 안내로 나누어 보여 주고, 마감은 로봇을 마감 자세로 보내는 버튼 하나로 처리합니다. 같은 화면 오른쪽에는 포터필터 거치, 넉박스, 투입·배출 컨베이어 센서, 서보, 비상정지 상태를 실시간 인디케이터로 함께 띄워, 안내를 따라가면서 설비 상태를 바로 확인할 수 있게 했습니다.

시스템 구조
구성 요소
- 운영 PC의 wxPython 데스크톱 앱. 헤더, 본문 패널 다섯 개, 푸터 탭으로 구성되며 패널은 모두 배경 이미지 위에 직접 그리는 방식입니다
- 협동로봇과의 Modbus TCP 클라이언트. 코일과 홀딩 레지스터를 0.3초 주기로 읽어 상태를 갱신하고, 명령은 쓰기 작업으로 전달합니다
- 키오스크용 TCP 소켓 서버. 접속한 키오스크마다 수신 스레드를 띄우고, 형식이 맞지 않는 주문은 버리고 로그에 남깁니다
- SQLite 데이터베이스. 설정, 주문, 알람 로그 세 개의 테이블을 둡니다
데이터 흐름
- 키오스크 소켓 또는 메인 화면에서 주문이 들어오면 6자리 주문번호를 붙여 대기열과 DB에 넣습니다
- 로봇이 연결되어 있고 작업 중이 아니면, 대기열에서 가장 오래된 주문을 꺼내 명령 레지스터에 메뉴 코드를 씁니다
- 로봇이 같은 값을 피드백으로 돌려주면 명령을 지우고, 샷 카운트 피드백을 읽어 주문의 진행 수량을 갱신합니다
- 작업 완료 신호가 올라오면 핸드쉐이크 레지스터를 주고받아 양쪽을 0으로 되돌리고, 주문을 완료로 바꾼 뒤 다음 주문으로 넘어갑니다
- 추출이 한 잔 시작될 때마다 그라인더, 넉박스, 커피머신 사용 횟수를 올리고, 설정한 상한에 닿으면 모달 알림을 띄웁니다

구현
비동기 통신과 UI 분리
로봇 통신은 asyncio 이벤트 루프에서 처리하고, 이 루프를 별도 스레드에서 돌립니다. UI는 wxPython 메인 루프가 그대로 쥐고 있어, 통신이 지연되어도 화면이 멈추지 않습니다. 통신 스레드와 키오스크 수신 스레드에서 발생한 화면 갱신은 모두 wx.CallAfter로 메인 스레드에 넘깁니다.
중단 지점에서의 복구
프로그램을 시작하면 로봇에 붙자마자 정지 피드백과 작업 완료 피드백 레지스터를 먼저 읽습니다. 직전 실행이 핸드쉐이크 도중에 끊긴 흔적이 있으면 그 절차를 마저 끝낸 뒤에야 새 주문을 받습니다. 연결이 끊어지면 끊김을 알람에 남기고 같은 주소로 재연결을 계속 시도하며, 다시 붙으면 로봇에 저장된 설정값을 읽어 와 화면에 반영합니다.
오류 코드의 번역
로봇이 올리는 오류 코드와 상태 코드를 "빈컵 없음. 투입구에 빈 컵을 넣어주세요.", "포터필터 없음. 포터필터 거치대를 확인 해주세요.", "충돌멈춤" 같은 한글 문구로 매핑했습니다. 오류가 뜨면 조치 방법을 담은 모달을 띄우고, 조치가 끝나 코드가 해제될 때까지 모달을 닫지 않습니다. 같은 내용은 알람 화면에도 쌓여, 지나간 오류를 발생 시각과 함께 되짚을 수 있습니다. 로그는 100일간 보관하고 화면에는 최근 50건을 보여 줍니다.

현장 조정용 관리자 화면
설치와 점검 때 필요한 조작은 숨은 관리자 화면에 모았습니다. 컨베이어 투입·배출, 커피머신 1·2그룹 분배, 그리퍼를 토글로 직접 구동해 배선과 동작을 확인할 수 있고, 그라인더 분쇄 딜레이와 로봇 IP, 헤더 로고 이미지를 현장에서 바꿀 수 있습니다. 로봇이 연결되면 로봇에 저장된 현재 설정값을 읽어 와 토글과 입력란을 채웁니다.

단일 파일 배포
화면 배경 이미지, 한글 폰트, 알림 효과음을 모두 base64 문자열로 소스에 담았습니다. 설치 폴더에 리소스 파일을 따로 두지 않아도 실행되며, 폰트는 실행 시점에 임시 파일로 풀어 등록한 뒤 바로 지웁니다.
결과
매장 직원은 로봇의 레지스터나 통신 상태를 몰라도 화면의 한글 문구만 보고 주문을 넣고, 설비 상태를 확인하고, 오류에 대응할 수 있게 되었습니다.
키오스크 주문과 직원의 수동 주문이 같은 대기열에 들어가면서, 두 경로가 섞여도 추출 순서와 진행 상황을 한 곳에서 추적할 수 있습니다. 어떤 주문이 몇 잔 중 몇 잔째를 뽑고 있는지, 어떤 주문이 중단되었는지가 화면에 그대로 남습니다.
그라인더 원두, 넉박스, 커피머신 사용 횟수를 추출 단위로 세고 상한에 닿으면 먼저 알리므로, 소모품 교체 시점을 직원이 따로 기억하지 않아도 됩니다. 발생한 오류는 코드와 시각이 함께 알람에 쌓여, 설비 문제를 나중에 되짚을 근거가 남습니다.
사용 기술
- Python
- wxPython
- asyncio
- Modbus TCP
- pymodbus
- SQLite
화면




진행하려는 프로젝트가 있으신가요?
해결하려는 문제와 지금 상황을 알려 주시면, 어떤 방식이 맞을지 함께 검토합니다.
프로젝트 문의하기