# 05. 알람 진단 & 트러블슈팅

출처: `xbox_motor_control.cpp` 주석/구현, `resource/ZLAC8015D V4 Series RS485 Communication*.pdf`,
`resource/ZLAC8015D V4 Series Manual*.pdf`

## 5.1 드라이버 알람(에러코드) 대응표

콘솔에 `[!!! 드라이버 알람 발생 !!!]`이 출력되면 `0x20A5`(좌)/`0x20A6`(우) 값을 근거로
`decodeDriverError()`가 원인을 표시한다. HUD의 `[!!알람!!]` 태그도 `fault_active` 동안 계속
표시된다.

| 비트 | 한글 표기 | 가능한 원인 | 권장 대응 |
| :-- | :--- | :--- | :--- |
| `0x0001` 과전압 | 과전압 | 배터리 전압이 75V 근접/초과, 급감속 시 회생 전류 유입 | 배터리 전압 확인, 회생 저항(`RES` 단자) 장착 검토, `2011h` 급정지 설정을 감속시간 포함(6) 방식으로 |
| `0x0002` 저전압 | 저전압 | 배터리 방전, 배선 전압강하, 순간 대전류로 전압 새그 | 배터리 충전 상태·배선 굵기 확인, `--max_current_a`로 최대전류를 낮춰 순간 전압강하 완화 |
| `0x0004` 과전류 | 과전류 | 상간 단락, 급격한 부하 변화, 배선 손상 | 배선/커넥터 점검, 모터 상간 저항 측정. 지속 시 드라이버 교체 검토 |
| `0x0008` 과부하 | 과부하 | 지형 저항/걸림 상태가 `2035h`(과부하 보호시간, 기본 300×10ms=3s) 이상 지속 | §5.3 전류 한계 튜닝 참고. 걸림(Stall) HUD 표시와 함께 발생하면 지형/장애물 확인 |
| `0x0020` 엔코더오차 | 엔코더오차 | 위치 폐루프 추종 오차가 `2036h`(기본 4090 counts) 초과 | 급격한 외력(충돌, 헛도는 지면)으로 순간 발생 가능. 반복 시 엔코더 배선 확인 |
| `0x0080` 기준전압오류 | 기준전압오류 | 드라이버 내부 기준전압 회로 이상 | 드라이버 하드웨어 이상 — 제조사 문의 |
| `0x0100` EEPROM오류 | EEPROM오류 | 파라미터 저장영역 읽기 실패 | `2009h=1`로 공장 초기화 후 필요한 파라미터(전류한계, 가감속 등) 재설정 |
| `0x0200` 홀센서오류 | 홀센서오류 | 홀 케이블 미접속/단선, 핀 순서 오류 | J2/J6 커넥터 및 홀 배선 점검 |
| `0x0400` 모터과열 | 모터과열 | 모터 온도가 임계치 초과(과부하 지속 주행 등) | 잠시 정지해 냉각, 반복 시 `--max_current_a` 하향 또는 부하 조건 재검토 |
| `0x0800` 엔코더오류 | 엔코더오류 | 엔코더 케이블 헐거움/핀 순서 오류(매뉴얼 명시) | J2/J6 커넥터 재체결, 케이블 단선 여부 확인 |
| `0x2000` 속도설정오류 | 속도설정오류 | 지령속도가 정격 속도(`2008h`, 기본 1000rpm) 초과 | 코드의 `setRPMs()` 클램프(±3000)가 드라이버 정격보다 커서 이론상 발생 가능 — `2008h` 값과 실제 사용 RPM 범위 확인 |

> `0x0010`(전류이상), `0x0040`(속도이상)은 매뉴얼상 예약(Reserved) 비트로 정상 동작에서는
> 발생하지 않는다.

**공통 대응 원칙**: 알람 발생 시 드라이버가 명령을 무시하는 잠금 상태가 될 수 있어 소프트웨어
재시작만으로는 풀리지 않는 경우가 많다. RS485로 `0x200E ← 0x0006`(알람 클리어) 후
`0x200E ← 0x0008`(Enable) 순으로 재초기화가 필요하며, `initDriver()`가 프로그램 재시작 시
이 시퀀스를 자동 수행한다. 그래도 반복되면 전원 재투입(Power Cycle)을 시도한다.

## 5.2 휠 이상(들뜸/걸림) 진단 — 알람이 아닌 소프트웨어 레벨 진단

드라이버 알람과 별개로, 애플리케이션 레벨에서 4륜 각각의 상태를 실시간 분류한다
(원리는 [04-software-control.md](04-software-control.md) §4.8 참고). HUD `WHL` 표시:

| 표시 | 의미 | 조치 |
| :-: | :--- | :--- |
| `O` | 정상(Ok) | - |
| `A` | 들뜸(Airborne) — 동료 바퀴 대비 전류가 비정상적으로 낮음 (무부하 헛돎) | 자동으로 해당 바퀴 지령을 0으로 낮춤. 지속되면 지형(웅덩이, 턱) 확인 |
| `S` | 걸림(Stall) — 지령 대비 실제속도가 크게 못 따라가며 고전류 지속 | 장애물 끼임, 지형 저항 확인. 반복 시 `0x0008` 과부하 알람으로 이어질 수 있음 |

이 진단은 어디까지나 소프트웨어 추정치이며, 드라이버 알람(§5.1)과는 독립적으로 동작한다.
`--log`로 CSV를 남기면 `stat_*`/`amp_*` 컬럼으로 사후 분석이 가능하다.

## 5.3 최대전류(`0x2034`/`0x2064`) 튜닝 배경

코드 기본값은 `--max_current_a 20.0`(공장 기본 최대전류 30A보다 낮춤). 코드 주석에 남겨진
실측 배경:

> 실측 결과 정격 15A / 최대 30A(공장 기본값) 그대로 사용 시, 걸림/과부하 상황에서 드라이버가
> 30A까지 전류를 밀어붙이며 3초(과부하 보호시간 `2035h` 기본값)씩 버티다가 과부하 알람이
> 발생하는 문제가 있었다. 정격(15A) 위로 5A 정도의 여유는 남기되, 상한을 20A로 낮춰 과도한
> 전류로 장시간 버티는 상황 자체를 줄인 것.

* `--max_current_a`에 음수를 주면 드라이버에 저장된 기존/공장 설정을 그대로 둔다(미변경).
* 정격전류(`0x2033`/`0x2063`)는 코드가 변경하지 않는다 — 최대전류만 낮춘다.
* 실외 험지 주행에서 순간 고부하가 잦다면 이 값을 상황에 맞게 재조정할 것. 너무 낮추면
  정상 등판/가속 상황에서도 전류 제한에 걸려 토크 부족이 발생할 수 있다.
* 시작 시 콘솔에 출력되는 "전방/후방 드라이버 전류설정" 로그로 **실제 드라이버에 저장된 값**을
  항상 확인할 수 있다(문서 기본값이 아니라 하드웨어에 실제로 쓰여있는 값).

## 5.4 RS485 통신 트러블슈팅

| 증상 | 가능한 원인 | 확인/조치 |
| :--- | :--- | :--- |
| 시작 시 "포트 열기 실패" | 잘못된 `/dev/ttyUSB*` 경로, 권한 부족 | `ls /dev/ttyUSB*`로 실제 장치명 확인, `dialout` 그룹 권한 확인 |
| "전류설정 조회 실패" 경고 | 배선 불량, 종단저항 미설정, 슬레이브 주소 불일치 | J5 커넥터 A/B/SGND 배선, 데이지체인 마지막 드라이버의 SW2 종단저항, `--id1`/`--id2`가 실제 드라이버 주소와 일치하는지 확인 |
| 명령은 가는데 응답이 자주 누락(HUD `comm_ms` 급등, 피드백 값이 갱신 안 됨) | 100Hz 루프 대비 응답 지연/노이즈, USB latency_timer 미적용 | `set_low_latency.sh` 적용 여부 확인(`cat /sys/bus/usb-serial/devices/<dev>/latency_timer`가 1이어야 함), 차폐 트위스트페어 케이블 및 접지 확인 |
| 알람은 없는데 바퀴가 반대로 회전 | 좌/우 모터 배선 반대 장착 오인, `2029h` 기본 회전방향 설정 문제 | [03-system-architecture.md](03-system-architecture.md) §3.2의 우측 부호 반전 로직 확인. 하드웨어적으로 U/V/W가 뒤바뀐 경우 `2029h`(Default running direction)로도 보정 가능 |
| CRC 불일치로 통신 실패 반환 (`readRegs`/`writeReg`가 `false`) | 전기 노이즈, 접지 불량, 데이지체인 배선 길이 과다 | 코드는 CRC16을 재계산해 손상된 응답을 자동으로 폐기하므로 오탐 지령은 방지되지만, 값 자체가 갱신되지 않아 HUD가 멈춘 것처럼 보일 수 있다. 배선 점검 필요 |

> 코드는 통신 실패 시 **재시도(retry)를 하지 않는다** — 실패한 틱은 그냥 다음 100Hz 틱으로
> 넘어간다. 이는 저지연(latency)을 우선한 설계 선택이며, 지속적인 통신 불량은 알람이 아니라
> "피드백이 갱신되지 않음"으로만 나타날 수 있으므로 HUD의 `comm_ms` 값과 위치/전류 피드백이
> 실제로 변하는지 함께 관찰해야 한다.

## 5.5 운용 전 체크리스트

1. 배선: 좌/우 U/V/W, 엔코더/홀(J2·J6), RS485 A/B/SGND(J5), 브레이크(J3) 재확인.
2. RS485 종단저항: 데이지체인 마지막 드라이버에서만 SW2 ON.
3. `run_4wd.sh` 실행 후 콘솔에서 "전방/후방 드라이버 전류설정" 값이 기대값(정격15A 근방,
   최대 20~30A)인지 확인.
4. 알람 없이 브레이크가 해제/잠금되는지(휠 수동 회전 저항으로 체감) 확인.
5. 저속으로 A버튼(트립리셋) → 직진 → 정지 → 후진 테스트로 좌/우 회전 방향이 의도대로인지
   확인.
6. 라이다 연결 시 HUD에 `LIDAR:OFF`가 아닌 실측 거리(`F:x.xxm|L:...|R:...`)가 표시되는지 확인.
7. 실외 주행 전 `--log`로 CSV 기록을 켜서 최초 주행 구간을 남겨두면 사후 튜닝(§5.3, §4.11의
   `--stall_*`/`--airborne_*` 인자)에 유용하다.
