# Radick (라자지) Radick은 Ai-Thinker RD-03D V1 24 GHz 레이더와 Elecrow 7인치 CrowPanel 하나로 동작하는 독립형 다중 목표 레이더입니다. 원본 [Arduino-ESP32-Radarproject](https://github.com/Stevee87/Arduino-ESP32-Radarproject)의 레이더 표현과 거리 기반 경고음을 유지하면서, XIAO·Arduino GIGA·Wi-Fi·UDP를 모두 제거했습니다. 펌웨어는 Arduino 계층 없이 ESP-IDF 5.3과 LVGL 8로 작성되어 레이더 UART부터 화면까지 한 ESP32-S3 안에서 처리합니다. > [!IMPORTANT] > 이 프로젝트는 **Basic CrowPanel 7.0 V3.0 (`DIS08070H`, ESP32-S3 N4R8)** 및 **RD-03D V1 (`S5KM312CL`, 15 × 44 mm)** 전용입니다. CrowPanel V1/V2와 RD-03D V2는 핀 및 프로토콜이 달라 지원하지 않습니다. ## 필요한 하드웨어 - Elecrow Basic CrowPanel 7.0-inch HMI ESP32 Display V3.0 - Ai-Thinker RD-03D V1 레이더 모듈 - 보호회로가 있는 1셀 Li-ion/LiPo 배터리(공칭 3.7 V, 최대 4.2 V) - 출력 리플 100 mV 이하의 5 V 승압 모듈(연속 200 mA 이상, 500 mA급 권장) - 5 V 레이더 전원 스위치와 승압 모듈 제조사가 권장하는 입·출력 캐패시터 - 경고음을 사용할 경우 J5 `SPK`에 맞는 스피커 배터리는 CrowPanel의 J1에 직접 연결할 수 있지만, RD-03D의 동작 전압은 4.5–5.5 V입니다. 따라서 레이더 VCC에는 배터리나 3V3 핀을 직접 연결하지 말고 반드시 별도 5 V 승압 출력을 사용해야 합니다. MCU/디스플레이는 CrowPanel 한 장뿐이지만, 이 승압 전원부는 생략할 수 없는 최소 부품입니다. ## 배선 | RD-03D V1 | CrowPanel V3 / 전원 | 설명 | |---|---|---| | `VCC` | 5 V 승압 모듈 `OUT+` | **J10의 3V3 또는 배터리에 직접 연결 금지** | | `GND` | 공통 GND(J7 pin 4 등) | CrowPanel·승압 모듈·레이더의 GND를 공통 연결 | | `TX` | J7 `GPIO_D` pin 1, GPIO38 | ESP32-S3 UART1 RX | | `RX` | J10 `UART` pin 2, GPIO43 | ESP32-S3 UART1 TX | 배터리 전원은 아래처럼 분기합니다. ```text 보호형 1S 배터리 ──> CrowPanel J1 BAT+/GND └─────────> 5 V 저리플 승압 ──> RD-03D VCC/GND RD-03D TX ─────────> J7 pin 1 / GPIO38 RD-03D RX <───────── J10 pin 2 / GPIO43 ``` J10 pin 1(GPIO44)은 온보드 CH340C의 TX 출력과 같은 네트이므로 레이더 TX를 연결하면 출력끼리 충돌할 수 있습니다. 이 때문에 레이더 수신과 송신을 서로 다른 커넥터로 나눈 것입니다. GPIO43은 CH340C RX와 레이더 RX라는 두 입력으로만 연결되어 안전하게 플래싱 경로를 유지합니다. 다만 부트 ROM의 송신도 레이더 RX에 들어가므로 **플래싱 중에는 레이더 5 V 전원을 끄는 것을 권장**합니다. RD-03D V1의 1.25 mm 4핀 커넥터는 데이터시트 기준 pin 1 `5V`, pin 2 `GND`, pin 3 `TX`, pin 4 `RX`입니다. 모듈 방향에 따라 좌우가 뒤집혀 보일 수 있으므로 실크와 pin 1 표시를 반드시 확인하십시오. J1 커넥터의 pin 1은 `BAT+`, pin 2는 `GND`입니다. 커넥터 규격만 믿지 말고 실제 배터리 극성을 멀티미터로 확인하십시오. CrowPanel에는 MCU가 읽을 수 있는 배터리 전압/잔량 회로가 없어 UI에 근거 없는 배터리 퍼센트를 표시하지 않습니다. 자세한 전체 핀맵과 전원 주의사항은 [하드웨어 문서](docs/HARDWARE.md)를 참고하십시오. ## 동작 방식 - UART1, 256000 baud, 8N1로 RD-03D의 30바이트 프레임을 직접 수신 - 스트림 노이즈·분할 프레임·손상 프레임 이후 자동 재동기화 - 최대 세 목표를 전역 최근접 매칭과 이동 예측으로 추적해 슬롯 순서가 바뀌어도 ID 유지 - 위치/속도 EMA로 화면 떨림 완화 - 원본의 1 m 강제 병합과 2초 정지 고스트 로직을 제거해 가까운 두 사람을 별도 목표로 유지하고 잔상을 빠르게 제거 - 0–8 m를 근거리 중심 비선형 스케일로 그려 작은 화면 이동도 알아보기 쉽게 표시 - 가장 가까운 목표의 거리에 따라 온보드 NS4168 스피커의 핑 주기와 음높이를 변경 - 터치로 음소거와 밝기를 조절하고, 60초 동안 터치와 목표가 없으면 자동 감광 - 마지막 정상 프레임으로부터 1.5초가 지나면 명확한 `RADAR OFFLINE` 상태 표시 레이더 명령 전송은 앱 부팅 후 공식 멀티 타깃 명령 `0x90`만 사용합니다. 기본 단일 타깃 스트림이 이미 출력되는 경우도 놓치지 않도록 5초 간격으로 총 세 번만 멱등 전송하며 UART와 UI 태스크를 막지 않습니다. 센서 전원이 꺼졌다가 정상 프레임이 다시 들어오면 같은 제한된 설정 절차를 한 번 재수행합니다. ## 빌드와 설치 직접 빌드하지 않고 바로 플래싱하려면 저장소의 [사전 빌드 펌웨어](firmware/)를 사용하십시오. 앱·부트로더·파티션 테이블과 Linux/macOS 및 Windows용 플래시 스크립트가 함께 들어 있습니다. 권장 환경은 ESP-IDF **v5.3.4**입니다. 다른 ESP-IDF 버전은 RGB LCD와 I2S API 차이 때문에 빌드 결과가 달라질 수 있습니다. ### 1. 플래싱 준비 1. RD-03D에 공급하는 외부 5 V 승압 전원을 끄거나 레이더 VCC를 분리합니다. UART 선은 그대로 두어도 됩니다. 2. 데이터 통신이 가능한 USB-C 케이블로 CrowPanel의 CH340C 프로그래밍 포트를 PC에 연결합니다. 첫 플래싱은 배터리를 분리하고 USB 전원만 사용하는 것을 권장합니다. 3. 새로 생긴 시리얼 포트를 확인합니다. Linux에서는 보통 `/dev/ttyUSB0`입니다. ```bash ls -l /dev/serial/by-id/ 2>/dev/null ls /dev/ttyUSB* 2>/dev/null ``` Windows에서는 장치 관리자의 `포트(COM 및 LPT)`에서 `COM5` 같은 이름을 확인합니다. macOS에서는 `/dev/cu.usbserial-*` 또는 `/dev/cu.wchusbserial*` 형태입니다. 아래 명령의 `/dev/ttyUSB0`을 확인한 포트로 바꾸십시오. ### 2. ESP-IDF로 빌드하고 바로 올리기 ESP-IDF v5.3.4 환경을 활성화한 뒤 저장소 루트에서 실행합니다. `set-target`은 최초 한 번만 필요합니다. ```bash . "$IDF_PATH/export.sh" idf.py set-target esp32s3 idf.py -p /dev/ttyUSB0 build flash ``` Windows의 ESP-IDF PowerShell에서는 환경이 이미 활성화되므로 저장소로 이동한 뒤 `idf.py set-target esp32s3`와 `idf.py -p COM5 build flash`를 실행하면 됩니다. 첫 빌드에서 Component Manager가 LVGL 8.3.11을 받습니다. 성공하면 다음 세 파일이 생성되고 ESP-IDF가 올바른 오프셋에 모두 기록합니다. | 파일 | Flash 오프셋 | |---|---:| | `build/bootloader/bootloader.bin` | `0x0` | | `build/partition_table/partition-table.bin` | `0x8000` | | `build/radick.bin` | `0x10000` | 애플리케이션 UART 콘솔은 레이더 핀과의 간섭을 피하려고 꺼 두었습니다. 따라서 `idf.py monitor`에 런타임 로그가 표시되지 않는 것은 정상이며, 플래싱 성공 메시지와 실제 화면으로 동작을 확인합니다. ### 3. 생성된 바이너리를 esptool로 다시 올리기 이미 한 번 빌드했다면 다시 컴파일하지 않고 아래 명령으로 세 바이너리를 직접 기록할 수 있습니다. `radick.bin` 하나만 기록하면 부트로더나 파티션 테이블이 없는 보드에서는 부팅되지 않을 수 있으므로 세 파일을 모두 지정합니다. ```bash python3 -m esptool \ --chip esp32s3 \ --port /dev/ttyUSB0 \ --baud 460800 \ --before default_reset \ --after hard_reset \ write_flash \ --flash_mode dio \ --flash_freq 80m \ --flash_size 4MB \ 0x0 build/bootloader/bootloader.bin \ 0x8000 build/partition_table/partition-table.bin \ 0x10000 build/radick.bin ``` `esptool`이 없다면 ESP-IDF 환경을 활성화하거나 별도 Python 환경에 `python3 -m pip install esptool==4.9.0`으로 설치할 수 있습니다. ### 4. Docker로 빌드하기 로컬 ESP-IDF 설치 없이 Docker로 빌드할 수도 있습니다. ```bash docker run --rm \ -v "$PWD:/project" -w /project \ espressif/idf:v5.3.4 \ idf.py -B build-docker build ``` Linux에서는 시리얼 장치를 컨테이너에 전달해 빌드와 플래시를 한 번에 할 수도 있습니다. ```bash docker run --rm \ --device=/dev/ttyUSB0 \ -v "$PWD:/project" -w /project \ espressif/idf:v5.3.4 \ idf.py -B build-docker -p /dev/ttyUSB0 build flash ``` Windows/macOS Docker Desktop은 USB 직렬 장치 전달이 복잡하므로 네이티브 ESP-IDF 또는 `esptool` 사용을 권장합니다. ### 5. 연결 문제 해결 - `Connecting...`에서 멈추면 `BOOT`을 누른 상태로 `RESET`을 짧게 누르고, `BOOT`을 놓은 뒤 플래시 명령을 다시 실행합니다. - Linux에서 `Permission denied`가 나오면 `sudo usermod -aG dialout "$USER"`를 실행하고 로그아웃한 뒤 다시 로그인합니다. - 포트가 보이지 않으면 충전 전용이 아닌 데이터 USB 케이블인지 확인하고 다른 USB 포트에 연결합니다. - 직렬 모니터나 다른 프로그램이 포트를 잡고 있으면 종료한 후 다시 시도합니다. - 설정까지 완전히 초기화해야 할 때만 `idf.py -p /dev/ttyUSB0 erase-flash`를 실행한 후 다시 플래싱합니다. 이 작업은 저장된 밝기와 음소거 설정도 삭제합니다. - 플래싱이 끝나면 RD-03D의 외부 5 V 전원을 켜고 CrowPanel을 한 번 리셋합니다. ## 호스트 테스트 레이더 프로토콜과 추적기는 ESP32 의존성 없이 테스트할 수 있습니다. ```bash cmake -S tests -B build-host cmake --build build-host --parallel ctest --test-dir build-host --output-on-failure ``` 테스트는 sign-magnitude 디코딩, 모든 청크 분할 위치, 노이즈/손상/바이트 유실 후 복구, 연속 프레임, 슬롯 재정렬, 근접 목표 비병합, 누락/재획득, 서로 교차하는 두 목표의 ID 유지를 포함합니다. ## 구조 ```text main/ ├── board.* RGB LCD, GT911/PCA9557, LVGL, 백라이트 ├── radar_protocol.* RD-03D 스트림 파서 ├── target_tracker.* 안정 ID, 예측, EMA, 만료 처리 ├── radar_service.* UART 태스크와 thread-safe 화면 스냅샷 ├── audio_service.* I2S 거리 경고음 ├── ui.* 800×480 단순 레이더 UI ├── app_settings.* NVS 밝기/음소거 저장 └── app_main.c 서비스 연결, 자동 감광, LVGL 루프 ``` ## 실기 확인 항목 전체 소프트웨어 빌드와 호스트 테스트 외에, 조립 후 다음 항목은 실제 하드웨어에서 확인해야 합니다. - 승압 출력이 레이더 연결 상태에서도 5 V 근처로 안정적인지 - GT911 터치 방향과 RGB 패널 색/플리커 - 안테나 방향 기준 좌우 좌표가 화면과 일치하는지 - 스피커 임피던스에 맞춘 실제 음량과 전원 노이즈 - 배터리 구동 시간과 충전 중 발열 레이더 사양은 Ai-Thinker의 [RD-03D V1 문서](https://docs.ai-thinker.com/en/Rd-03D_V1/), 디스플레이 핀은 Elecrow의 [CrowPanel 7-inch 저장소](https://github.com/Elecrow-RD/CrowPanel-7.0-HMI-ESP32-Display-800x480)와 V3 회로도를 기준으로 했습니다. ## License [WTFPL v2](LICENSE)