docs: 스태커 실제 동작(하부 적층 방식) 기준으로 주석/상수명 정정
현장 확인 결과 스태커는 상부 압축이 아니라 하부 적층(bottom-stacking) 장치: - 책 인입(DI0) -> 리프터(coil0)가 책을 위로 밀어올림 -> 선반(coil1) 열림/닫힘 -> 새 책이 스택 맨 아래에 끼워진 채 선반 위에 걸쳐짐 -> 픽업량 도달(DI1) 시 로봇 픽업 - 리프터 상승 중(DI3=0)에는 컨베이어 일시정지 연동 변경 사항 (로직/타이밍 변경 없음, 명칭/주석만): - 스태커 상수명 정정: LIFT_START_WAIT / SHELF_OPEN_DELAY / SHELF_OPEN_TIME / SHELF_CLOSE_SETTLE - 헤더 I/O 맵, [스태커 동작 원리] 섹션, 스레드/픽업 조건 주석 전면 정정 - DO0 그리퍼 명칭을 누름판(포크 받침 + 상부 누름 고정) 구조로 명확화 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
111
api_routes.py
111
api_routes.py
@@ -1,36 +1,48 @@
|
|||||||
"""팔레타이징 로봇 제어 API (책 재단기 라인).
|
"""팔레타이징 로봇 제어 API (책 재단기 라인).
|
||||||
|
|
||||||
[시스템 개요]
|
[시스템 개요]
|
||||||
재단기에서 나온 책 묶음이 컨베이어를 타고 '스태커(정렬대)'에 쌓이면,
|
재단기에서 나온 책이 낱권씩 컨베이어를 타고 '스태커(하부 적층 장치)'로 들어와
|
||||||
JAKA 로봇이 포크형 그리퍼로 묶음을 떠서 팔레트 위에 층층이 적재한다.
|
스택으로 쌓이고, 픽업량만큼 모이면 JAKA 로봇이 포크형 그리퍼로 스택을 통째로
|
||||||
|
떠서 팔레트 위에 층층이 적재한다.
|
||||||
이 파일은 Flask Blueprint 로서 웹 UI(webview) 요청을 받아 아래 전부를 수행한다.
|
이 파일은 Flask Blueprint 로서 웹 UI(webview) 요청을 받아 아래 전부를 수행한다.
|
||||||
- 팔레트 종류별 적재 메인 루프 (wooden_wheel / iron_wheel / wooden_Flat / one_line_*)
|
- 팔레트 종류별 적재 메인 루프 (wooden_wheel / iron_wheel / wooden_Flat / one_line_*)
|
||||||
- 로봇 상태 폴링 + 경광등/컨베이어 인터록 (get_status_thread)
|
- 로봇 상태 폴링 + 경광등/컨베이어 인터록 (get_status_thread)
|
||||||
- 스태커 실린더 시퀀스 제어 (stacker_thread, Modbus RTU)
|
- 스태커 실린더 시퀀스 제어 (stacker_thread, Modbus RTU)
|
||||||
|
|
||||||
[로봇 제어박스 I/O 맵 - IO_CABINET]
|
[로봇 제어박스 I/O 맵 - IO_CABINET]
|
||||||
DO0 : 그리퍼 수직 실린더(파지) 1=파지 / 0=해제
|
DO0 : 그리퍼 누름판(수직) 실린더 1=하강(파지) / 0=상승(해제)
|
||||||
|
(포크가 책 밑을 받친 상태에서 누름판이 위에서 내려와 눌러 고정)
|
||||||
DO1 : 그리퍼 수평 실린더(적재 푸셔) 1=전진 / 0=후퇴
|
DO1 : 그리퍼 수평 실린더(적재 푸셔) 1=전진 / 0=후퇴
|
||||||
DO2 : 경광등 주황 (마지막 층 근접 예고)
|
DO2 : 경광등 주황 (마지막 층 근접 예고)
|
||||||
DO3 : 경광등 초록 (정상 운전)
|
DO3 : 경광등 초록 (정상 운전)
|
||||||
DO4 : 경광등 빨강 (정지/완료/비상)
|
DO4 : 경광등 빨강 (정지/완료/비상)
|
||||||
DO5 : 동력장치(컨베이어) 운전 1=운전 / 0=정지
|
DO5 : 동력장치(컨베이어) 운전 1=운전 / 0=정지
|
||||||
DI0 : 스태커 수직 반사판 센서 (낱권 감지 → 스태커 1회 압축 동작 트리거)
|
DI0 : 스태커 책 인입 반사판 센서 (책이 들어오면 가려짐 → 리프트 사이클 트리거)
|
||||||
DI1 : 스태커 책 준비 센서 (묶음 완성 → 로봇 픽업 조건)
|
DI1 : 스태커 스택 준비 반사판 센서 (선반 위 스택이 픽업량만큼 쌓이면 가려짐 → 로봇 픽업)
|
||||||
DI2 : 스태커 수직 실린더 '위' 센서
|
DI2 : 스태커 리프터(수직 실린더) '위' 센서
|
||||||
DI3 : 스태커 수직 실린더 '아래' 센서 (완전히 내려가야 로봇 진입 가능)
|
DI3 : 스태커 리프터(수직 실린더) '아래' 센서
|
||||||
|
(완전 하강 상태여야 로봇 포크 진입 가능 + 컨베이어 재가동)
|
||||||
※ DI 번호는 get_robot_status() 반환값의 din 배열 인덱스 기준.
|
※ DI 번호는 get_robot_status() 반환값의 din 배열 인덱스 기준.
|
||||||
|
|
||||||
[Modbus RTU (COM3, slave 1) - 스태커 실린더]
|
[Modbus RTU (COM3, slave 1) - 스태커 실린더]
|
||||||
coil 0 : 스태커 수직 실린더 (책 누름)
|
coil 0 : 스태커 리프터(수직 실린더) 1=상승(책 밀어올림) / 0=하강
|
||||||
coil 1 : 스태커 수평 실린더 (책 밀어 정렬)
|
coil 1 : 스태커 선반(수평 실린더) 1=닫힘(스택 받침) / 0=열림(책 통과)
|
||||||
|
|
||||||
|
[스태커 동작 원리 - 하부 적층(bottom-stacking)]
|
||||||
|
1) 컨베이어로 들어온 책이 인입 센서(DI0)를 가림 → 리프터가 책을 위로 밀어올림.
|
||||||
|
리프터가 하강 위치를 벗어나 있는 동안(DI3=0) 컨베이어는 일시정지된다.
|
||||||
|
2) 리프트 중 선반(coil 1)이 잠시 열려, 책(과 그 위의 기존 스택)이 선반 높이를 통과
|
||||||
|
3) 선반이 다시 닫히고 리프터가 내려오면 새 책이 스택 맨 아래에 끼워진 채
|
||||||
|
스택 전체가 선반 위에 걸쳐진다
|
||||||
|
4) 스택이 픽업량(DI1)만큼 쌓이면 로봇이 포크로 스택 밑을 받치고
|
||||||
|
누름판(DO0)으로 잡아 통째로 팔레트에 적재한다
|
||||||
|
|
||||||
[스레드 구조]
|
[스레드 구조]
|
||||||
- Flask 요청 스레드 : /robot_start, /one_line_run 요청 안에서 적재 메인 루프가
|
- Flask 요청 스레드 : /robot_start, /one_line_run 요청 안에서 적재 메인 루프가
|
||||||
그대로 돌기 때문에 해당 HTTP 요청은 작업 종료까지 블록된다.
|
그대로 돌기 때문에 해당 HTTP 요청은 작업 종료까지 블록된다.
|
||||||
- get_status_thread : 0.1s 주기로 로봇 상태/센서 폴링, 경광등·컨베이어 제어,
|
- get_status_thread : 0.1s 주기로 로봇 상태/센서 폴링, 경광등·컨베이어 제어,
|
||||||
비상정지(EMO) 해제 후 홈 복귀 처리.
|
비상정지(EMO) 해제 후 홈 복귀 처리.
|
||||||
- stacker_thread : 스태커 실린더로 책을 정렬/압축하는 반복 시퀀스.
|
- stacker_thread : 스태커 리프터/선반 실린더로 책을 하부 적층하는 반복 시퀀스.
|
||||||
|
|
||||||
[진행 상태 저장]
|
[진행 상태 저장]
|
||||||
- static/json/cache.json : 일반 적재 진행 상태 (몇 층/몇 권/현재 적재 높이)
|
- static/json/cache.json : 일반 적재 진행 상태 (몇 층/몇 권/현재 적재 높이)
|
||||||
@@ -136,17 +148,17 @@ IN_POS_POLL_INTERVAL = 0.01 # [신규] is_in_pos() 폴링 주기 (기존: 간
|
|||||||
IDLE_LOOP_INTERVAL = 0.02 # [신규] 메인 루프 유휴 폴링 주기 (기존: 간격 없는 busy-wait)
|
IDLE_LOOP_INTERVAL = 0.02 # [신규] 메인 루프 유휴 폴링 주기 (기존: 간격 없는 busy-wait)
|
||||||
JKS_POLL_INTERVAL = 0.05 # [신규] 높이탐색 JKS 프로그램 종료 폴링 주기
|
JKS_POLL_INTERVAL = 0.05 # [신규] 높이탐색 JKS 프로그램 종료 폴링 주기
|
||||||
# ── 스태커 실린더 시퀀스 대기 (물리 스트로크 시간, 기존값 유지) ──
|
# ── 스태커 실린더 시퀀스 대기 (물리 스트로크 시간, 기존값 유지) ──
|
||||||
STACKER_BACKOFF = 0.5 # [기존 2.0] 책 준비 완료 상태에서 스태커 대기(재확인) 주기
|
STACKER_BACKOFF = 0.5 # [기존 2.0] 스택 픽업 대기(DI1 가려짐) 상태에서 재확인 주기
|
||||||
STACKER_PRE_PRESS_WAIT = 0.5 # 낱권 감지 후 수직 누름 시작 전 대기
|
STACKER_LIFT_START_WAIT = 0.5 # 책 인입 감지 후 리프트 시작 전 대기 (책이 완전히 들어올 시간)
|
||||||
STACKER_PRESS_SETTLE = 0.05 # 수직 누름 후 수평 후퇴 시작 전 대기
|
STACKER_SHELF_OPEN_DELAY = 0.05 # 리프트 시작 후 선반 열기까지 지연
|
||||||
STACKER_SIDE_RETRACT = 1.2 # 수평 실린더 후퇴 유지(다음 책 유입 공간 확보) 시간
|
STACKER_SHELF_OPEN_TIME = 1.2 # 선반 열림 유지 시간 (리프터가 스택을 선반 위로 올리는 동안)
|
||||||
STACKER_SIDE_PUSH = 0.2 # 수평 재전진 후 수직 해제 전 대기
|
STACKER_SHELF_CLOSE_SETTLE = 0.2 # 선반 닫힘 후 리프터 하강 전 대기 (스택 안착)
|
||||||
# ═══════════════════════════════════════════════════════════════════════
|
# ═══════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
# ── 스태커 센서 상태 (get_status_thread 가 0.1s 주기로 갱신) ──────────────
|
# ── 스태커 센서 상태 (get_status_thread 가 0.1s 주기로 갱신) ──────────────
|
||||||
stacker_vertical_cyl_sensor = 0 # DI2: 수직 실린더 '위' 센서
|
stacker_vertical_cyl_sensor = 0 # DI2: 리프터(수직 실린더) '위' 센서
|
||||||
stacker_vertical_cyl_down_sensor = 0 # DI3: 수직 실린더 '아래' 센서
|
stacker_vertical_cyl_down_sensor = 0 # DI3: 리프터(수직 실린더) '아래' 센서
|
||||||
stacker_book_ready_sensor = 0 # DI1: 책 묶음 준비 센서
|
stacker_book_ready_sensor = 0 # DI1: 스택 준비(픽업량 도달) 센서
|
||||||
|
|
||||||
# ── 팔레트별 최대 하강 z (사용자좌표계 기준 거리) ─────────────────────────
|
# ── 팔레트별 최대 하강 z (사용자좌표계 기준 거리) ─────────────────────────
|
||||||
wooden_wheel_pallet_max_z_pos = 864
|
wooden_wheel_pallet_max_z_pos = 864
|
||||||
@@ -767,8 +779,8 @@ def wooden_wheel_pallet():
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
# ── 픽업 시작 조건 ──
|
# ── 픽업 시작 조건 ──
|
||||||
# (책 묶음 준비 AND 스태커 수직 실린더 완전 하강 AND 로봇 정상)
|
# (스택 픽업량 도달(DI1) AND 리프터 완전 하강(DI3) AND 로봇 정상)
|
||||||
# 또는 (UI '즉시 픽업' AND 수직 실린더 상승 아님 AND 로봇 정상)
|
# 또는 (UI '즉시 픽업' AND 리프터 상승 상태 아님 AND 로봇 정상)
|
||||||
if (((stacker_book_ready_sensor == 1) and (stacker_vertical_cyl_sensor == 0) and (stacker_vertical_cyl_down_sensor == 1)) and (emergency_stop == 0 or protected_stop_stat == 0) and (power_on_stat == 1 and enabled_stat == 1)) or (((immediately_take_book == 'robot_immediately_take_book') and (stacker_vertical_cyl_sensor == 0)) and (emergency_stop == 0 or protected_stop_stat == 0) and (power_on_stat == 1 and enabled_stat == 1)):
|
if (((stacker_book_ready_sensor == 1) and (stacker_vertical_cyl_sensor == 0) and (stacker_vertical_cyl_down_sensor == 1)) and (emergency_stop == 0 or protected_stop_stat == 0) and (power_on_stat == 1 and enabled_stat == 1)) or (((immediately_take_book == 'robot_immediately_take_book') and (stacker_vertical_cyl_sensor == 0)) and (emergency_stop == 0 or protected_stop_stat == 0) and (power_on_stat == 1 and enabled_stat == 1)):
|
||||||
immediately_take_book = None
|
immediately_take_book = None
|
||||||
|
|
||||||
@@ -1253,8 +1265,8 @@ def iron_wheel_pallet():
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
# ── 픽업 시작 조건 ──
|
# ── 픽업 시작 조건 ──
|
||||||
# (책 묶음 준비 AND 스태커 수직 실린더 완전 하강 AND 로봇 정상)
|
# (스택 픽업량 도달(DI1) AND 리프터 완전 하강(DI3) AND 로봇 정상)
|
||||||
# 또는 (UI '즉시 픽업' AND 수직 실린더 상승 아님 AND 로봇 정상)
|
# 또는 (UI '즉시 픽업' AND 리프터 상승 상태 아님 AND 로봇 정상)
|
||||||
if (((stacker_book_ready_sensor == 1) and (stacker_vertical_cyl_sensor == 0) and (stacker_vertical_cyl_down_sensor == 1)) and (emergency_stop == 0 or protected_stop_stat == 0) and (power_on_stat == 1 and enabled_stat == 1)) or (((immediately_take_book == 'robot_immediately_take_book') and (stacker_vertical_cyl_sensor == 0)) and (emergency_stop == 0 or protected_stop_stat == 0) and (power_on_stat == 1 and enabled_stat == 1)):
|
if (((stacker_book_ready_sensor == 1) and (stacker_vertical_cyl_sensor == 0) and (stacker_vertical_cyl_down_sensor == 1)) and (emergency_stop == 0 or protected_stop_stat == 0) and (power_on_stat == 1 and enabled_stat == 1)) or (((immediately_take_book == 'robot_immediately_take_book') and (stacker_vertical_cyl_sensor == 0)) and (emergency_stop == 0 or protected_stop_stat == 0) and (power_on_stat == 1 and enabled_stat == 1)):
|
||||||
immediately_take_book = None
|
immediately_take_book = None
|
||||||
|
|
||||||
@@ -1744,8 +1756,8 @@ def wooden_Flat_pallet():
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
# ── 픽업 시작 조건 ──
|
# ── 픽업 시작 조건 ──
|
||||||
# (책 묶음 준비 AND 스태커 수직 실린더 완전 하강 AND 로봇 정상)
|
# (스택 픽업량 도달(DI1) AND 리프터 완전 하강(DI3) AND 로봇 정상)
|
||||||
# 또는 (UI '즉시 픽업' AND 수직 실린더 상승 아님 AND 로봇 정상)
|
# 또는 (UI '즉시 픽업' AND 리프터 상승 상태 아님 AND 로봇 정상)
|
||||||
if (((stacker_book_ready_sensor == 1) and (stacker_vertical_cyl_sensor == 0) and (stacker_vertical_cyl_down_sensor == 1)) and (emergency_stop == 0 or protected_stop_stat == 0) and (power_on_stat == 1 and enabled_stat == 1)) or (((immediately_take_book == 'robot_immediately_take_book') and (stacker_vertical_cyl_sensor == 0)) and (emergency_stop == 0 or protected_stop_stat == 0) and (power_on_stat == 1 and enabled_stat == 1)):
|
if (((stacker_book_ready_sensor == 1) and (stacker_vertical_cyl_sensor == 0) and (stacker_vertical_cyl_down_sensor == 1)) and (emergency_stop == 0 or protected_stop_stat == 0) and (power_on_stat == 1 and enabled_stat == 1)) or (((immediately_take_book == 'robot_immediately_take_book') and (stacker_vertical_cyl_sensor == 0)) and (emergency_stop == 0 or protected_stop_stat == 0) and (power_on_stat == 1 and enabled_stat == 1)):
|
||||||
immediately_take_book = None
|
immediately_take_book = None
|
||||||
|
|
||||||
@@ -2378,8 +2390,8 @@ def one_line_wooden_wheel_pallet():
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
# ── 픽업 시작 조건 ──
|
# ── 픽업 시작 조건 ──
|
||||||
# (책 묶음 준비 AND 스태커 수직 실린더 완전 하강 AND 로봇 정상)
|
# (스택 픽업량 도달(DI1) AND 리프터 완전 하강(DI3) AND 로봇 정상)
|
||||||
# 또는 (UI '즉시 픽업' AND 수직 실린더 상승 아님 AND 로봇 정상)
|
# 또는 (UI '즉시 픽업' AND 리프터 상승 상태 아님 AND 로봇 정상)
|
||||||
if (((stacker_book_ready_sensor == 1) and (stacker_vertical_cyl_sensor == 0) and (stacker_vertical_cyl_down_sensor == 1)) and (emergency_stop == 0 or protected_stop_stat == 0) and (power_on_stat == 1 and enabled_stat == 1)) or (((immediately_take_book == 'robot_immediately_take_book') and (stacker_vertical_cyl_sensor == 0)) and (emergency_stop == 0 or protected_stop_stat == 0) and (power_on_stat == 1 and enabled_stat == 1)):
|
if (((stacker_book_ready_sensor == 1) and (stacker_vertical_cyl_sensor == 0) and (stacker_vertical_cyl_down_sensor == 1)) and (emergency_stop == 0 or protected_stop_stat == 0) and (power_on_stat == 1 and enabled_stat == 1)) or (((immediately_take_book == 'robot_immediately_take_book') and (stacker_vertical_cyl_sensor == 0)) and (emergency_stop == 0 or protected_stop_stat == 0) and (power_on_stat == 1 and enabled_stat == 1)):
|
||||||
immediately_take_book = None
|
immediately_take_book = None
|
||||||
|
|
||||||
@@ -2859,8 +2871,8 @@ def one_line_iron_wheel_pallet():
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
# ── 픽업 시작 조건 ──
|
# ── 픽업 시작 조건 ──
|
||||||
# (책 묶음 준비 AND 스태커 수직 실린더 완전 하강 AND 로봇 정상)
|
# (스택 픽업량 도달(DI1) AND 리프터 완전 하강(DI3) AND 로봇 정상)
|
||||||
# 또는 (UI '즉시 픽업' AND 수직 실린더 상승 아님 AND 로봇 정상)
|
# 또는 (UI '즉시 픽업' AND 리프터 상승 상태 아님 AND 로봇 정상)
|
||||||
if (((stacker_book_ready_sensor == 1) and (stacker_vertical_cyl_sensor == 0) and (stacker_vertical_cyl_down_sensor == 1)) and (emergency_stop == 0 or protected_stop_stat == 0) and (power_on_stat == 1 and enabled_stat == 1)) or (((immediately_take_book == 'robot_immediately_take_book') and (stacker_vertical_cyl_sensor == 0)) and (emergency_stop == 0 or protected_stop_stat == 0) and (power_on_stat == 1 and enabled_stat == 1)):
|
if (((stacker_book_ready_sensor == 1) and (stacker_vertical_cyl_sensor == 0) and (stacker_vertical_cyl_down_sensor == 1)) and (emergency_stop == 0 or protected_stop_stat == 0) and (power_on_stat == 1 and enabled_stat == 1)) or (((immediately_take_book == 'robot_immediately_take_book') and (stacker_vertical_cyl_sensor == 0)) and (emergency_stop == 0 or protected_stop_stat == 0) and (power_on_stat == 1 and enabled_stat == 1)):
|
||||||
immediately_take_book = None
|
immediately_take_book = None
|
||||||
|
|
||||||
@@ -3251,10 +3263,10 @@ def robot_get_status_realtime():
|
|||||||
emergency_stop = status[1][23] # 비상정지 눌림 여부
|
emergency_stop = status[1][23] # 비상정지 눌림 여부
|
||||||
protected_stop_stat = status[1][5] # 보호정지(충돌 감지) 여부
|
protected_stop_stat = status[1][5] # 보호정지(충돌 감지) 여부
|
||||||
|
|
||||||
current_DI_9_status = status[1][11][0] # 스태커 수직 반사판 센서
|
current_DI_9_status = status[1][11][0] # DI0: 스태커 책 인입 반사판 센서
|
||||||
stacker_book_ready_sensor = status[1][11][1] # 스태커 수평 반사판 센서
|
stacker_book_ready_sensor = status[1][11][1] # DI1: 스태커 스택 준비(픽업량 도달) 센서
|
||||||
stacker_vertical_cyl_sensor = status[1][11][2] # 스태커 수직 실린더 위에 센서
|
stacker_vertical_cyl_sensor = status[1][11][2] # DI2: 스태커 리프터 '위' 센서
|
||||||
stacker_vertical_cyl_down_sensor = status[1][11][3] # 스태커 수직 실린더 아래 센서
|
stacker_vertical_cyl_down_sensor = status[1][11][3] # DI3: 스태커 리프터 '아래' 센서
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -3345,11 +3357,12 @@ def robot_get_status_realtime():
|
|||||||
|
|
||||||
|
|
||||||
def stacker_thread_start_function():
|
def stacker_thread_start_function():
|
||||||
"""스태커(책 정렬대) 실린더 제어 스레드를 시작한다.
|
"""스태커(하부 적층 장치) 실린더 제어 스레드를 시작한다.
|
||||||
|
|
||||||
스태커: 재단기에서 낱권으로 들어오는 책을 수평 실린더로 밀어 정렬하고,
|
동작 원리: 책이 들어오면(DI0) 리프터(coil 0)가 책을 위로 밀어올리고,
|
||||||
낱권 감지(DI0) 시 수직 실린더로 한 번 눌러 압축하는 장치.
|
그 사이 선반(coil 1)이 열렸다 닫히면서 책이 선반 위 스택 맨 아래에 끼워진다.
|
||||||
책 묶음이 완성(DI1=1)되면 로봇이 가져갈 때까지 대기한다.
|
스택이 픽업량(DI1=1)에 도달하면 로봇이 가져갈 때까지 대기한다.
|
||||||
|
(자세한 원리는 파일 상단 [스태커 동작 원리] 참고)
|
||||||
"""
|
"""
|
||||||
global stacker_thread_running, stacker_thread_operator
|
global stacker_thread_running, stacker_thread_operator
|
||||||
|
|
||||||
@@ -3367,27 +3380,27 @@ def stacker_thread_start_function():
|
|||||||
|
|
||||||
while stacker_thread_running:
|
while stacker_thread_running:
|
||||||
try:
|
try:
|
||||||
instrument.write_bit(1, True) # 수평 실린더 전진 유지 (책 정렬 기본 상태)
|
instrument.write_bit(1, True) # 선반 닫힘 유지 (스택 받침 기본 상태)
|
||||||
|
|
||||||
if stacker_book_ready_sensor == 1:
|
if stacker_book_ready_sensor == 1:
|
||||||
# 묶음 완성 → 로봇이 가져갈 때까지 스태커는 쉰다.
|
# 스택 픽업량 도달 → 로봇이 가져갈 때까지 스태커는 쉰다.
|
||||||
# (기존 2.0s → 0.5s: 픽업 직후 스태커 재개가 최대 1.5s 빨라짐)
|
# (기존 2.0s → 0.5s: 픽업 직후 스태커 재개가 최대 1.5s 빨라짐)
|
||||||
time.sleep(STACKER_BACKOFF)
|
time.sleep(STACKER_BACKOFF)
|
||||||
elif current_DI_9_status == 1 and stacker_book_ready_sensor == 0 and (emergency_stop == 0 or protected_stop_stat == 0):
|
elif current_DI_9_status == 1 and stacker_book_ready_sensor == 0 and (emergency_stop == 0 or protected_stop_stat == 0):
|
||||||
# 낱권 감지 → 1회 압축 시퀀스:
|
# 책 인입 감지 → 하부 적층 1사이클:
|
||||||
# 수직 누름 → 수평 후퇴(다음 책 유입 공간 확보) → 수평 재전진 → 수직 해제
|
# 리프터 상승(책+스택을 선반 위로) → 선반 열기 → 선반 닫기 → 리프터 하강
|
||||||
print(f"스태커 스레드 current_DI_9_status: {current_DI_9_status}")
|
print(f"스태커 스레드 current_DI_9_status: {current_DI_9_status}")
|
||||||
time.sleep(STACKER_PRE_PRESS_WAIT)
|
time.sleep(STACKER_LIFT_START_WAIT)
|
||||||
instrument.write_bit(0, True) # 수직 실린더 누름
|
instrument.write_bit(0, True) # 리프터 상승 (책을 위로 밀어올림)
|
||||||
time.sleep(STACKER_PRESS_SETTLE)
|
time.sleep(STACKER_SHELF_OPEN_DELAY)
|
||||||
instrument.write_bit(1, False) # 수평 실린더 후퇴 (다음 책 유입 공간 확보)
|
instrument.write_bit(1, False) # 선반 열기 (책이 선반 높이를 통과하도록)
|
||||||
time.sleep(STACKER_SIDE_RETRACT)
|
time.sleep(STACKER_SHELF_OPEN_TIME)
|
||||||
instrument.write_bit(1, True) # 수평 실린더 재전진 (정렬)
|
instrument.write_bit(1, True) # 선반 닫기 (스택을 다시 받침)
|
||||||
time.sleep(STACKER_SIDE_PUSH)
|
time.sleep(STACKER_SHELF_CLOSE_SETTLE)
|
||||||
instrument.write_bit(0, False) # 수직 실린더 해제
|
instrument.write_bit(0, False) # 리프터 하강 (스택은 선반 위에 걸쳐 남음)
|
||||||
|
|
||||||
if emergency_stop == 1 or protected_stop_stat == 1:
|
if emergency_stop == 1 or protected_stop_stat == 1:
|
||||||
instrument.write_bit(1, False) # 비상 시 수평 실린더 해제
|
instrument.write_bit(1, False) # 비상 시 선반 열림 (실린더 압력 해제)
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
pass # Modbus 일시 오류는 무시하고 다음 주기에 재시도
|
pass # Modbus 일시 오류는 무시하고 다음 주기에 재시도
|
||||||
|
|||||||
Reference in New Issue
Block a user