09. 종합 실습 — 비전·로봇·그리퍼 자동화 셀
트랙의 마지막 편. 따로 배운 통신 조각들 — 03편 TCP/IP, 06편 로봇=Server 명령 사이클, 07편 로봇=Client 그리퍼 제어, 08편 모니터링 — 을 하나의 자동화 셀로 묶습니다. 상위 비전이 부품 위치를 알려주면(TCP/IP) 로봇이 그 좌표로 이동(Modbus)해 그리퍼로 집고, 지정 위치에 놓고 원점 복귀하는 픽앤플레이스 셀을 PC 한 대로 완성하고 사이클 타임을 측정합니다.
이 강의에서 배우는 것
- 1비전=TCP Server·로봇=Modbus Slave·그리퍼=Modbus Slave를 한 컨트롤러에서 동시에 다룬다
- 2비전 실수 좌표를 split_word 로 인코딩해 로봇 직교 LIN 사이클로 보낸다(음수 포함)
- 3로봇·그리퍼 사이클을 상태 폴링으로 직렬화해 안전하게 연결한다(latch 회피)
- 4비전→픽(2단 Z)→집기→플레이스→놓기→원점복귀 전체 사이클을 오케스트레이션하고 사이클 타임을 측정한다
소개
셀 제어기(cell_controller)가 지휘자입니다. 비전에는 TCP Client로 접속하고, 로봇·그리퍼에는 Modbus Master로 명령합니다. 역할은 "누가 먼저 말을 거는가"로 가립니다 — 비전은 로봇 관점에선 Server지만 이 셀에서는 컨트롤러가 접속하는 Client입니다.
핵심 개념
1) 한 사이클의 동작 순서
① 비전에 {TRIG} 송신 → {X,Y,R} 수신 (TCP/IP, 03편)
② 로봇 LIN 이동: (X,Y,접근Z) → (X,Y,픽Z) (Modbus, 06편)
③ 그리퍼 닫기 = 부품 집기 (Modbus, 07편)
④ 로봇 LIN 이동: 픽 상승 → 플레이스 위치 (Modbus, 06편)
⑤ 그리퍼 열기 = 부품 놓기 (Modbus, 07편)
⑥ 로봇 GO HOME = 원점 복귀 (Modbus, 06편)세 시뮬레이터는 비전 6000 / 로봇 1502 / 그리퍼 1503 으로 포트를 분리합니다(같은 포트면 Address already in use). 터미널은 총 4개(시뮬레이터 3 + 컨트롤러 1).
2) 통합의 함정 — 상태 잔상(latch)
세 장치를 직렬로 이으면 직전 동작의 완료 신호가 레지스터에 남아(latch) 다음 동작 시작 전에 폴링이 통과해 버립니다. 두 가지 방어를 씁니다: ① 로봇은 IR524==2(Running) 시작을 먼저 기다린 뒤 IR524==1(Idle)+IR200==1(Success) 완료를 기다리는 2단계 폴링, ② 그리퍼는 IR769==2 그리고 HR1606==0 을 함께 확인. HR200=0 리셋 직후 곧바로 다음 트리거를 쓰면 로봇이 리셋을 못 봐 잠기므로 리셋 뒤 폴링 한두 주기를 비워 둡니다.
핵심 예제
함수가 get_vision / robot_move / gripper_act / go_home 으로 분리돼 각 단계를 독립적으로 디버깅할 수 있습니다.
def robot_move(m, x, y, z, a=0, b=0, c=0, cmd=1, mtype=1):
axis = []
for v in (x, y, z, a, b, c):
low, high = split_word(round(v * 1000)) # ×1000 정수화 후 32bit 분할(음수도 그대로)
axis += [low, high]
m.write_holding(201, [cmd, mtype] + axis + [50, 100, 1, 0])
m.write_holding(200, 1)
while m.read_input(524,1)[0] != 2: time.sleep(POLL) # ① Running 시작 대기
while not (m.read_input(524,1)[0]==1 and m.read_input(200,1)[0]==1):
time.sleep(POLL) # ② 완료
m.write_holding(200, 0); time.sleep(POLL * 2) # 리셋 + 인지 대기로봇·그리퍼 연결은 with RobotMaster(...) as robot, RobotMaster(...) as gripper: 로 한 번 열어 여러 사이클에 재사용합니다. --trig TRIG2 로 음수 좌표를, --cycles 2 로 두 부품을 연속 처리하고 평균/최소/최대 사이클 타임을 출력합니다.
자주 하는 실수
Q. 두 번째 이동부터 로봇이 즉시 "완료"로 표시돼요(실제로는 안 움직임).
A. IR524==1(Idle) 하나만 보면 직전 명령의 Idle 가 latch 로 남아 통과합니다. 먼저 IR524==2(Running) 시작을 기다린 뒤 IR524==1 & IR200==1 완료를 보세요(2단계 폴링).
Q. 두 번째 이동부터 로봇이 아예 안 움직이고 타임아웃 나요.
A. HR200=0 리셋 직후 곧바로 HR200=1 을 쓰면 로봇이 0 을 못 봐 ack 가 안 풀려 명령이 잠깁니다(매뉴얼 5.3.3.5 ⑤). 리셋 후 폴링 한두 주기를 비워 두세요.
Q. 시뮬레이터가 Address already in use 로 안 떠요.
A. 세 시뮬레이터가 같은 포트를 쓰거나 이전 프로세스가 점유 중입니다. 6000/1502/1503으로 포트를 분리하고 기존 터미널을 Ctrl+C 후 재실행하세요.
정리
- 자동화 셀 = 비전(TCP/IP)+로봇(Modbus 명령 사이클)+그리퍼(Modbus 사이클)+원점 복귀를 한 컨트롤러로 오케스트레이션
- 컨트롤러는 비전에 TCP Client, 로봇·그리퍼에 Modbus Master — "누가 먼저 말을 거는가"로 구분
- 비전 실수 좌표 → split_word(round(v*1000)) → 직교 LIN, 음수도 & 0xFFFF 자동 인코딩으로 왕복
- 단계 연결의 핵심은 상태 폴링 직렬화: 로봇 IR524 2→1 & IR200=1, 그리퍼 IR769=2 & HR1606=0 (latch 회피)
과제
- 세 시뮬레이터를 띄우고 한 사이클을 완주해 사이클 타임을 확인
- --trig TRIG2 음수 좌표 사이클을 완주하고 IR400~411 을 디코딩해 X=-45.10 확인
- --cycles 2 로 TRIG/TRIG2 를 연속 처리하며 연결을 재사용하고 평균 사이클 타임을 출력