
C ROBOT
caconee22/c_robot
처음 사용하는 사람은 펌웨어 구조·사용법 전체 설명을 먼저 읽는다. 파일별 책임, 실제 FSM/안전 흐름, 센서 설정·교정, UART 규격, 모터 API, 주기와 실물 시험 순서를 설명한다. 별도 벤치의 콘솔/CSV는 BENCHTESTS.md, 검토 근거는 VERIFICATION.md에 있다. 아래는 저장소 전체와 영상 프로그램 안내다.

처음 사용하는 사람은 펌웨어 구조·사용법 전체 설명을 먼저 읽는다. 파일별 책임, 실제 FSM/안전 흐름, 센서 설정·교정, UART 규격, 모터 API, 주기와 실물 시험 순서를 설명한다. 별도 벤치의 콘솔/CSV는 BENCHTESTS.md, 검토 근거는 VERIFICATION.md에 있다. 아래는 저장소 전체와 영상 프로그램 안내다.
C ROBOT is an open-source printed circuit board by caconee22, from the caconee22/c_robot repository on GitHub. It is a 2-layer board of 65 × 90 mm with 53 parts on 71 nets, routed with 325 tracks and 34 vias.
It is built around the AMS1117-3.3. Its parts include 21 connectors, 17 resistors, 5 ICs and 3 capacitors. It belongs with the robots and motor control boards and the ESP32 boards of this library.
ESP32-S3 주행 제어, 라즈베리파이 영상 처리, 회로 설계를 관리하는 저장소다. 현재 주행 펌웨어는 V1 하드웨어를 대상으로 한다.
처음 사용하는 사람은 펌웨어 구조·사용법 전체 설명을 먼저 읽는다. 파일별 책임, 실제 FSM/안전 흐름, 센서 설정·교정, UART 규격, 모터 API, 주기와 실물 시험 순서를 설명한다. 별도 벤치의 콘솔/CSV는 BENCH_TESTS.md, 검토 근거는 VERIFICATION.md에 있다. 아래는 저장소 전체와 영상 프로그램 안내다.
2026-10-05 기준, ESP32 펌웨어는 부팅부터 센서·통신·안전·FSM·모터 출력까지 연결했다. 하드웨어 없는 자동 시험과 ESP32용 빌드를 통과했으며, 실제 기체 시험과 튜닝은 남아 있다. 컴파일/PC 시험 통과를 실제 차량의 완전한 동작 보증으로 해석하면 안 된다.
| 항목 | 진행 상태 |
|---|---|
| PlatformIO / Arduino / ESP32-S3 프로젝트 | 구성 완료 |
| V1 핀 정의 및 초기 안전 출력 | 구현 완료, V2 핀 배치는 미적용 |
| 부팅·리셋 원인·시작 대기 | 구현 완료 |
| SW1 인터럽트 비상정지 | 영구 래치, 브레이크 요청, 재부팅 전까지 구동 금지 |
| SW2 인터럽트 시작 버튼 | 정상 눌림·해제 각각 40ms 확인 후 한 번 시작 |
| BTS7960 좌우 모터 공용 API | 출력 제한, 정지/브레이크, 방향 설정, 상태 조회 구현 |
| 모터 명령 만료 감시 | 공용 API 기본 100ms, FSM 80ms, 별도 5ms 감시 |
| AS7341 / TCS34725 네 모서리 센서 | 빌드 시 한 종류 선택, TCA9548A 경유 읽기 구현 |
| 바닥색 판별 | 빨강·노랑·파랑·검정, 새 측정의 동일 색 3회 확인 |
| 컬러 캘리브레이션 | UART 안내식 48단계, 자세별 3초 측정, NVS 저장 구현 |
| 라즈 UART1 | 115200bps, 14바이트, CRC 없음, sequence/신선도 검사 구현 |
| 이벤트 로그 / WS2812 LED | 변경 감지·중복 억제·우선순위 표시 구현 |
| 공격 FSM | 탐색·목표 확인·정렬·접근·돌진·급정거·삽입·밀기·회피 연결 |
| PC 자동 검증 | 두 센서 구성 각각 12개 시험 그룹 통과 |
| ESP32 빌드 | 생산/센서 전용/벤치 × 두 센서 구성, 여섯 환경 통과 |
| 별도 실물 시험 펌웨어 | 모터/UART 수동/데이터/회전 정렬/추적/바닥 회피 구현, 두 센서 구성 빌드·PC 검사 통과 |
| 실물 성능·브레이크·색 임계값·전략 튜닝 | 미완료, 하드웨어 확보 후 진행 |
V1에는 IR, 거리센서, IMU, 전류센서, 엔코더, 배터리 ADC를 사용하지 않는다. V2 회로 확장 논의와 V1 펌웨어를 혼동하지 않는다.
AS7341을 약 5ms 단일 수광(F2/F3/F5/F6/F7/Clear) 연속 측정으로 변경했다.
새 측정 3회 확인은 유지한다. 수광·게인·센서별 LED·검정 임계값·비율/밝기 판별 허용 범위를
ESP_MAIN/include/sensors/sensor_config.hpp에 모았다. 실물 성능은 아직 검증되지 않았다.
기체는 추가 가림막 없이 자체 LED를 사용하며 10mm 단차에서 센서-바닥 간격이 3/10/20mm로 변한다.
근접 포화, 먼 거리에서 검정 오인, 색 경계 혼합을 반드시 고려한다.
교정 높이 안내와 튜닝 방법은 센서 조정 안내를 읽는다.
ESP_MAIN/: 주행 펌웨어와 하드웨어 없는 자동 시험.ESP_MAIN/README.md: 펌웨어의 의도·파일별 역할·안전/FSM·센서·통신·사용법 전체 설명.ESP_MAIN/BENCH_TESTS.md: 별도 시험 펌웨어의 모터/수동 UART/데이터/회전 정렬/추적/구역 회피 모드.ESP_MAIN/VERIFICATION.md: 요구사항 대응, 실행 흐름, 수정 내역, 시험 범위와 한계.ESP_MAIN/AGENTS.md: 사용자 요구사항과 다른 AI/개발자를 위한 작업 기준.scripts/: 영상 처리·시험 영상 준비 등의 파이썬 코드.COLOR_DETECTOR.md: 기존 영상 검출기 실행·튜닝 안내.PCB/: 회로 설계 자료. 펌웨어 핀의 기준은 ESP_MAIN/include/pins.hpp다.PCBV2/: V2 회로/PCB, 프로젝트 라이브러리, 3D 모델, 제작 자료와 설계 백업.
V2 자료를 보관하지만 ESP32 펌웨어는 여전히 V1 핀 배치다.영상 처리 파이썬 코드의 존재와 현재 ESP32 패킷 규격의 종단간 호환성 검증은 별개다. 실제 라즈 송신기와 UART 연결 시험은 남아 있다.
ESP_MAIN/
include/
pins.hpp V1 GPIO
config.hpp UART/공통 주기
motor/motor_config.hpp
sensors/sensor_config.hpp
control/control_config.hpp
src/
main.cpp 전체 실행 연결
app/ 부팅
hardware/ 초기 핀 상태/리셋 원인
interrupts/ 안전/시작 버튼
sensors/ 측정/색 판별/캘리브레이션
communication/ 라즈 UART 패킷
system/ 안전관리/로그/LED
control/ FSM/좌우 구동 변환
motor/ 공용 제어/BTS7960 출력
sensor_serial_test.cpp
tests/ 생산 소스를 사용하는 PC 자동 검증기본 실행은 메인 루프이며, 모터 명령 만료만 작은 FreeRTOS 태스크로 별도 감시한다. 일반 제어 루프에서 수광 시간 전체를 기다리지 않고 센서 읽기를 짧은 단계로 진행한다. LED와 이벤트 로그는 제어 뒤에 처리한다.
부팅 → 시작 대기 → SW2 눌림·해제 → 탐색
→ 목표 프레임 2회 확인 → 정렬/접근
→ 돌진 220ms → 브레이크 90ms → 스포크 삽입 350ms → 밀기
→ 목표 상실 시 제한된 시간만 밀기 → 후진 260ms → 탐색
위험색 확인 → 공격보다 먼저 위험구역 회피
SW1 입력 → 일반 실행 종료 → ESTOP만 3초마다 출력 → 재부팅 필요기동 시간과 출력은 실측 전의 초기값이다. 실제 접촉이나 스포크 삽입 성공을 측정하는 제어는 아니다.
PlatformIO가 설치된 터미널에서 실행한다.
현재 보드 설정은 esp32-s3-devkitc-1의 8MB 플래시이며 PSRAM은 사용하지 않는다.
실제 YD-ESP32-S3 사양과 업로드 포트는 실물에서 확인해야 한다.
cd D:\C_ROBOT\ESP_MAIN
pio run -e yd_esp32_s3| 환경 | 용도 | UART0 모니터 |
|---|---|---|
yd_esp32_s3 | 설정 파일에서 선택한 센서의 생산 펌웨어 | 57600 |
yd_esp32_s3_tcs34725 | TCS34725를 지정한 생산 펌웨어 | 57600 |
sensor_serial_test | 설정 파일에서 선택한 센서 전용 점검 | 115200 |
sensor_serial_test_tcs34725 | TCS34725 센서 전용 점검 | 115200 |
robot_bench | 설정 파일의 센서로 저출력 단계별 실물 시험 | 57600 |
robot_bench_tcs34725 | TCS34725 실물 시험 | 57600 |
업로드와 생산 펌웨어 모니터:
pio run -e yd_esp32_s3 -t upload
pio device monitor -b 57600센서 전용 점검은 모터 핀을 초기화하거나 변경하지 않고 약 100ms마다 버튼/컬러 원시값을 출력한다. 이 환경을 사용할 때는 모터 전원을 분리한다. 생산 펌웨어의 안전 제어가 실행되는 환경이 아니다.
| 수정할 내용 | 파일 |
|---|---|
| V1 GPIO 배치 | ESP_MAIN/include/pins.hpp |
| UART/로그/버튼 주기 | ESP_MAIN/include/config.hpp |
| PWM, 출력 상한, 모터 방향, 브레이크 조합 | ESP_MAIN/include/motor/motor_config.hpp |
| 센서 종류, TCA 채널, 수광 시간, 게인, 임시 색 임계값 | ESP_MAIN/include/sensors/sensor_config.hpp |
| 탐색·공격·회피 출력/시간, 목표 박스 기준 | ESP_MAIN/include/control/control_config.hpp |
기본 환경의 센서 종류는 sensor_config.hpp의 다음 한 줄로 선택한다.
#define COLOR_SENSOR_MODEL COLOR_SENSOR_AS7341
// TCS34725 차량: 위 값을 COLOR_SENSOR_TCS34725로 변경TCS34725 전용 환경은 빌드 옵션으로 종류를 지정한다. 종류·수광·게인·채널 설정을 바꾸면 이전 교정 데이터가 호환되지 않아 임시 임계값으로 동작한다. 센서 위치는 전방 기준 1=왼쪽 위, 2=오른쪽 위, 3=왼쪽 아래, 4=오른쪽 아래다.
시작 대기 중 UART0에 CAL START를 입력한다.
센서 네 개 × 바닥색 네 개 × 평행/들림/눌림 세 자세를 각각 안내받아 측정한다.
READY 후 3초 카운트다운과 3초 측정, ACCEPT로 다음 단계, 완료 후 CAL SAVE로 저장한다.
RETRY, BACK, ABORT, STATUS, CAL ERASE, CAL MARGIN <색비율%> <밝기%>도 지원한다.
교정 중에는 모터가 정지하며, SW2로 중단하면 새로운 눌림·해제 없이 출발하지 않는다.
2026-10-05 코드 검토 후 결과:
| 검증 | 결과 |
|---|---|
| AS7341 PC 생산 시험 | 12그룹, assert 4,994회 통과 |
| TCS34725 PC 생산 시험 | 12그룹, assert 4,555회 통과 |
| PC 벤치 시험 | 두 센서 구성 각각 67회 통과 |
| ESP32 여섯 환경 빌드 | 모두 성공 |
| Python 핵심 시험 | 가상 이미지 기반 5개 테스트 통과 |
| 두 Pi 추적기 | 로컬 영상 각각 20프레임, 화면 없이 실행·종료 확인 |
assert 횟수에는 반복 측정 확인이 포함되며 서로 다른 시나리오 개수는 아니다.
실제 생산 소스와 setup()/loop()를 가짜 GPIO/UART/I2C/NVS에 연결해 검증한다.
네이티브 g++가 필요하며 PATH 또는 PlatformIO의 toolchain-gccmingw32를 사용한다.
cd D:\C_ROBOT\ESP_MAIN
.\tests\run_host_tests.ps1
.\tests\run_host_tests.ps1 -Demo
.\tests\run_host_tests.ps1 -Bench-Demo는 공격 상태와 좌우 출력을 가상 입력으로 보여주는 텍스트 데모다.
시험 상세와 수정한 오류는 검증 기록에 정리했다.
바닥의 네 색 판별은 ESP32의 광학 센서 코드다. 아래 Python 코드의 녹색 타워 검출과 교정 데이터를 공유하지 않는다. 라즈는 영상만 처리하고, 주행 판단/안전은 ESP32에서 수행하는 구조다.
카메라 또는 영상 파일
→ 저해상도 BGR/ExG 후보 → 후보 ROI 확대 → 원본 해상도 BGR/ExG/HSV/Lab 검증
→ 마스크 정리 → 연결 성분 / 후보 선택(최대2개) → 전역 좌표
→ 텍스트 / JSON / 화면 / 성능 보고서
→ [미구현: 14바이트 UART 패킷 송신] → ESP32 RaspberryLink → FSM → 모터pi_green_tracker.py는 UART 송신을 하지 않는다(--json은 표준출력). ESP32 송신은 scripts/pi_vision_sender.py가 한다:
같은 검출기로 처리한 최신 결과를 /dev/ttyAMA0(GPIO14 TX/15 RX)에 50Hz로 보내고, 새 프레임을 처리했을 때만 sequence를 올린다.
2026-11-04 Pi 5 + Camera Module 3 Wide 실측: 타워가 보일 때 검출 약22fps, 송신 50Hz, 누락0 (ESP32 연결 전, 수신 미검증).
2026-11-05 갱신: 기본 감지기는 scripts/tower_detector_hsv.py(여러 색 범위 합치기), 720p 60fps, 셔터 1ms 고정(scripts/camera_settings.py).
라즈 실측 감지 약 50~60fps·4ms·영상 지연 약 16ms, ESP32 수신 확인(LINK 60/60). 설정은 scripts/tower_settings_app.py.
그 JSON에는 현재 박스 폭/높이 등 ESP 패킷 필드가 전부 들어 있지도 않다.
실물 ALIGN/FOLLOW/AVOID에는 규격 송신기가 필요하며, JSON을 그대로 UART1에 보내면 안 된다.
50fps 카메라 설정도 실제 처리/송신 50Hz를 증명하지 않는다.
| 파일 | 역할과 사용 의도 |
|---|---|
scripts/color_detection_core.py | 원본 전체 프레임 검출 기준. BGR/ExG/HSV/Lab, 융합, 모폴로지, 연결 성분, 후보 자료형 |
scripts/color_detection_lightweight.py | 작은 후보 영상에서 ROI를 찾고 원본 ROI만 정밀 검증. 전역 bbox/centroid/contour 변환으로 계산량 감소 |
scripts/pi_green_tracker.py | 공유 검출기를 파일/USB카메라/Picamera2에 연결. JSON/미리보기/파일 반복/측정/내보내기 UI |
raspberry_pi_green_tracker_single.py | 복사하기 쉬운 단일 파일 Pi 검출기. 상단 고정 녹색 임계값과 미소 타워의 엄격한 필터 |
scripts/color_detector_ui.py | 실행 입구. 기본 단계별 wizard, --advanced-ui 전체 설정 UI, --benchmark 화면 없는 측정 |
scripts/color_detector_wizard.py | 순서대로 BGR→ExG→HSV→Lab→융합→후처리 튜닝, ROI 자동 조정, 설정/스냅샷/내보내기 |
scripts/benchmark_lightweight_compare.py | 동일 영상의 전체 프레임/ROI 검출 시간·마스크·후보 비교. 실행 순서를 번갈아 편향 완화 |
scripts/color_detector_export.py | 기준 검출기의 원본/결과/각 마스크를 분석 영상으로 저장 |
scripts/export_lightweight_full_video.py | ROI 검출기의 전체 분석 영상 저장. 실제 제어 루프에서 인코딩하지 않고 별도 실행 |
scripts/prepare_test_video.py | 시험 영상을1920×1080/50fps로 리사이즈·시간 기반 프레임 반복, 메타데이터 검증 |
scripts/green_cylinder_video_live.py | 초기 녹색 검출기 재생/슬라이더/마스크/샘플 저장. 현재 공유 검출기와 별도 실험 구현 |
scripts/green_cylinder_image_batch.py | img 이미지의 초기 녹색 후보를 일괄 검출해 주석 이미지/CSV 생성 |
scripts/preprocess_green_images.py | 초기 영상 검출기 기본 설정으로 이미지·마스크·검출 데이터를 준비 |
scripts/opencv_green_cylinder_demo.py | 합성 도형으로 OpenCV 검출/마스크 저장의 간단한 설치 점검 |
scripts/face_tracking_demo.py | Haar 얼굴 검출 설치 점검. 경기 타워 검출이나 FSM에 사용하지 않음 |
cv_live_view.py | 별도 합성 영상 data/synthetic.avi의 루프 표시 예제. 그 입력 파일이 있어야 하며 주요 Pi 실행 입구가 아님 |
scripts/generate_htd5m_20t_pulley.py | CadQuery/DXF 기반 기구 STEP/STL 생성. 주행/CV와 무관, 별도 CadQuery 환경 필요 |
scripts/vision_packet.py | 패킷 V1 인코더. ESP32 파서와 같은 규칙으로 잘못된 패킷은 만들지 않음 |
scripts/pi_vision_sender.py | 카메라 검출 → 패킷 V1을 UART로 50Hz 송신. --dry-run은 UART 없이 출력만 |
tests/test_vision_packet.py | README 예시 바이트, 무목표 0x30, 거부 규칙, 축척·플래그 검증 |
tests/test_vision.py | 가상 대상/비대상색·좌표·ROI 병합·경계·마스크 형식 검증. 실제 카메라 성능 시험은 아님 |
setup_raspberry_pi.sh | Raspberry Pi OS의 OpenCV/NumPy/Picamera2 시스템 패키지 설치 |
run_pi_tracker.sh | 저장소 위치로 이동 후 Pi 카메라 입력50fps로 공유 추적기 실행 |
공유 검출기는 config/color_detector_last.json을 기본값 위에 덮어쓴다.
단일 파일 추적기는 이 JSON을 읽지 않는다. 따라서 UI 설정을 저장했다고 두 추적기 임계값이
동시에 바뀌지는 않는다. 단일 파일은 상단 상수를 조정해야 한다.
예를 들어 순수(0,255,0) 녹색도 단일 파일의 좁은 HSV/Lab 범위 밖이면 거부될 수 있다.
저해상도 후보를 놓친 대상은 ROI 정밀 검증에 들어오지 않는다. 두 방식의 검출 결과가 항상 같지는 않다.
프로젝트 루트에서 가상환경 Python을 사용한다. 기존 .venv가 없다면 생성 후 의존성을 준비한다.
핵심 CV 실행에는 OpenCV/NumPy가 필요하고 저장소 전체 requirements.txt는 다른 실험용 패키지도 포함한다.
cd D:\C_ROBOT
python -m venv .venv
.\.venv\Scripts\python.exe -m pip install opencv-python==4.12.0.88 numpy
# 기존 환경을 쓰면 위 생성/설치는 생략
.\.venv\Scripts\python.exe scripts/pi_green_tracker.py --source dataset/videos/irc_highlight_1080p50.mp4 --preview --realtimeQ 종료, M 마스크 표시, E 전체 파일 내보내기. --realtime은 파일 원래 FPS에 맞춰 기다리므로
순수 처리 성능 시험에서는 빼야 한다. --loop는 파일을 반복한다.
GUI는 실제 데스크톱 세션이 필요하다. 파일/카메라 해상도와 처리 시간은 별도 확인한다.
화면 유무 비교와 좌표 출력:
.\.venv\Scripts\python.exe scripts/pi_green_tracker.py --quiet --benchmark --max-frames 300
.\.venv\Scripts\python.exe scripts/pi_green_tracker.py --quiet --benchmark --max-frames 300 --preview
.\.venv\Scripts\python.exe scripts/pi_green_tracker.py --json --max-frames 20
.\.venv\Scripts\python.exe raspberry_pi_green_tracker_single.py --source dataset/videos/irc_highlight_1080p50.mp4 --preview
.\.venv\Scripts\python.exe scripts/color_detector_ui.py벤치 보고서는 output/color_detector/benchmarks에 저장된다. 기본10프레임 예열은 통계에서 제외한다.
검출 시간과 입력/표시/대기 포함 loop 시간을 구분한다. 일반 실행의 FPS 이력은60프레임으로 제한하고,
명시적 --benchmark는 전체 통계를 위한 목록을 보관하므로 장시간 운전 옵션이 아니라 유한 시험용으로 쓴다.
전체 프레임/ROI 비교가 필요하면 benchmark_lightweight_compare.py를 실행한다.
각 보조 도구의 옵션은 --help, 튜닝·GUI·내보내기의 상세 키는 COLOR_DETECTOR.md.
Raspberry Pi OS의 Picamera2는 시스템 패키지와 카메라 드라이버가 필요하다. 일반 PC에 pip로 설치한 OpenCV만으로 카메라 입력이 되지는 않는다.
bash setup_raspberry_pi.sh
python3 -m venv --system-site-packages .venv
.venv/bin/python scripts/pi_green_tracker.py --source camera --fps 50 --preview
# 또는 시스템 Python 실행 래퍼:
bash run_pi_tracker.sh --preview이미 설정한 환경이라면 설치를 반복할 필요 없다. 현재 Windows 검토는 라즈에 원격 접속하거나 패키지를 변경하지 않았다. 실행 중인 카메라/GUI/50Hz UART의 실측과 종단간 검증은 남아 있다.
.\.venv\Scripts\python.exe -m unittest discover -s tests -v
.\.venv\Scripts\python.exe -m compileall -q scripts tests cv_live_view.py raspberry_pi_green_tracker_single.py이 검증은 주요 공유/단일 검출기의 오프라인 논리를 검사한다. 모든 GUI/내보내기/CAD 경로, 실제 영상의 정답 정확도, 카메라 성능과 UART 송신까지 보증하는 시험은 아니다. 영상·출력·가상환경·빌드 결과물은 Git에 올리지 않으므로 새 clone에는 기본 시험 영상이 없을 수 있다. 영상이 없으면 별도로 준비하거나 --source로 실제 파일을 지정한다.
이 절은 제작 전 기구 설계와 경기 전략의 기준을 기록한다. 사진으로 분석한 다른 팀 로봇의 치수는 공개 도면이 아닌 원근 보정 기반 추정값이며, 아래 기동 시간·거리·출력은 실물 시험 전에는 확정값으로 사용하지 않는다. 현재 생산 펌웨어가 아래 모든 기동을 구현했다는 뜻도 아니다.
| 구분 | 추정 휠베이스 | 관찰한 설계 의도 |
|---|---|---|
| 비교 로봇 1 | 약 110mm | 짧은 휠베이스와 전방 모터 배치로 일반 탱크턴과 전방 하중을 확보 |
| 비교 로봇 2 | 약 170mm | 모터를 전방으로 기울여 무게중심을 앞에 두고, 큰 회전에는 뒤를 들어 앞바퀴만으로 회전 |
| 비교 로봇 3 | 약 140mm | 넓은 바퀴와 네 모터 직결로 회전 효율보다 구동력을 우선 |
| 이전 자작 기체 | 180mm | 31mm 폭의 연한 바퀴와 긴 휠베이스가 결합되어 제자리회전 시 심한 횡끌림·변형·털림 발생 |
사진 추정값은 설계 비교에만 사용한다. 이전 기체의 180mm와 실제 털림은 확인된 경험값이므로 새 기체의 휠베이스 결정에서 사진 추정보다 우선한다.
pi * 휠베이스이므로,
180mm에서는 약 565mm, 129mm에서는 약 405mm다.휠베이스 / 좌우 중심거리는 약 129 / 265 = 0.487이다.두 구동 구간 모두 HTD5M 20T 풀리, 피치 5mm, 벨트 폭 15mm를 사용한다. 20T 풀리의 피치원은
100 / pi = 31.83099mm이며, 풀리 외경이나 톱니 뿌리원을 벨트 길이 계산에 대신 사용하지 않는다.
| 구간 | 중심거리 | 구매 벨트 | 아이들러가 없을 때 피치 길이 | 용도 |
|---|---|---|---|---|
| 전륜-후륜 | 129mm | 360mm | 358mm | 좌우 각 측의 두 바퀴 연결 |
| 모터-전륜 | 79mm | 260mm | 258mm | 높은 위치의 모터에서 전륜으로 전달 |
벨트 길이는 같은 20T 풀리 두 개일 때 L = 2C + 100mm로 계산한다. 구매한 260/360mm 벨트는 각각
아이들러로 약 2mm의 추가 피치 경로와 초기 장력을 만든다. 모터는 장력 조절을 위해 슬라이드하지 않는다.
모터-전륜 260mm 구간의 현재 기준은 다음과 같다.
8 x 22 x 7mm 베어링과 M8 볼트를 사용한다.mechanical/belt/에는 피치선 검사용 DXF, 1mm 단순 벨트 외형, 슬롯 DXF,
치수 그림과 현재 STEP 검토본을 보관한다. STEP 검토본은 제작 승인본이 아니다. 현재 파일에는
Ø31.183mm 원이 들어 있어 Ø31.831mm 피치원과 숫자 순서가 다르고, 아이들러 주변 벨트 경계도
R10R11로 베어링 안쪽에 놓여 있다. 최종 물리 외형은 베어링 표면 R11 바깥쪽인 R11R12에 두고,
벨트 길이는 별도의 피치선으로 검증해야 한다.
회전 저항을 단순 쿨롱 마찰로 보면 저항 모멘트는 대략 다음과 같다.
M_scrub ~= mu_y * W * L / 2다만 실제 기체는 앞축 하중이 크므로 회전 중심이 앞축 쪽으로 이동하고 가벼운 뒤축이 더 많이 미끄러질 수 있다. 따라서 위 식은 균등 하중 기체의 비교식이며 실제 저항을 그대로 보장하지 않는다. 넓고 부드러운 실리콘 타이어에서는 단순 마찰 외에 횡변형, 히스테리시스, 점착-미끄러짐 반복이 털림을 만든다.
현재 무게 추정에서 전방에 배치되는 주요 부품은 모터 두 개 약 1,090g, 모터 브래킷 두 개 약 400g, 배터리 약 180g, 전방 슬라이드 약 200g으로 합계 약 1,870g이다. 이는 4,500g 기체의 약 41.6%다. 실제 위치가 확정되지 않았으므로 정확한 무게중심은 Fusion의 부품별 무게중심 좌표로 다시 계산해야 한다.
앞축을 x=0, 뒤쪽을 양수로 두면 다음 식을 사용한다.
x_CG = sum(m_i * x_i) / sum(m_i)
앞축 하중 비율 = 1 - x_CG / 휠베이스
뒤축 하중 비율 = x_CG / 휠베이스129mm 휠베이스에서 무게중심이 앞축 뒤 약 42mm라면 앞축 약 67.4%, 뒤축 약 32.6%가 된다.
설계 목표는 앞축 약 6570%, 뒤축 약 3035%다. 4.5kg 기준 앞축 약 2.933.15kg,
뒤축 약 1.351.58kg 범위다. 앞축이 70%를 크게 넘으면 전방 스키드는 잘 눌리지만 후륜 접지와 착지
안정성이 부족할 수 있다. 배터리는 최종 계측 후 앞뒤 위치를 조절할 수 있게 고정한다.
무게중심 높이는 약 60mm를 초기 목표로 한다. 모터 두 개와 배터리는 전륜 위쪽에 집중하고, 약 110g의 컬러타워도 전륜 위 높은 위치에 놓아 리어리프트 제동 기동에 활용한다. 반면 PCB, 라즈베리파이와 모터드라이버는 중앙·하부에 배치해 과도한 전복성을 억제한다. 모터 축과 전륜 축의 79mm 간격은 벨트 규격뿐 아니라 전체 무게중심 높이에 직접 영향을 주므로 완성 CAD의 질량 특성으로 다시 확인한다.
경기 중량 제한은 4,500g이며 측정 허용범위를 포함한 절대 상한은 4,545g으로 관리한다. 허용범위는 설계 여유가 아니므로 CAD 목표는 4,500g보다 충분히 낮게 둔다. 5T 6061 사이드판은 유지하고 트러스와 불필요한 면적을 줄인다. 출력물은 낮은 하중의 마운트와 스페이서에 사용하며, 전방 슬라이드 약 200g, 모터 두 개 약 1,090g, 배터리 약 180g, 컬러타워 약 110g처럼 실제 계측값이 있는 항목을 우선한다. 608 베어링, 샤프트 칼라 8개, 배터리 벨크로, M8 너트·와셔, 스위치와 비상정지 스위치, 커넥터와 수축튜브는 누락되기 쉬운 항목으로 별도 계상한다.
축 하중은 완성 기체에서 앞바퀴 두 개를 저울에 올리고 뒷바퀴는 같은 높이의 받침에 둔 상태로 측정한다. 반대 축도 같은 방식으로 확인하고 두 측정값의 합이 전체 중량과 맞는지 검사한다.
전방은 낮은 침투부와 급경사 상승부를 결합한 2단 형상을 우선한다.
30도 구간은 급제동 시 바닥을 스치며 상대 아래로 들어가는 역할을 하고, 이미 상대 전방 하중을 줄인 뒤 65~70도 구간이 빠르게 들어 올리는 역할을 한다. 70도 단독 경사는 초기 침투에서 벽처럼 작용할 수 있다. 스포크 끝은 경기장 표면을 손상시킬 정도로 날카롭게 만들지 않으며 실제 규정과 표면에서 확인한다.
바닥 센서는 총 네 개를 유지한다. 전방 좌우 두 개는 독립적으로 경계를 먼저 확인하고, 후방 두 개는 기체 구조상 중앙에 가깝게 놓이므로 제어에서 하나의 후방 위험 그룹처럼 OR 처리할 수 있다. 후방 센서는 밀리고 있는 사실을 새로 알려도 기동이 달라지지 않는 상황이 많지만, 잘못된 후진 회피가 길어지는 경우와 상대 공격으로 후방부터 경계에 들어가는 경우의 안전 입력으로 남긴다.
충돌 시 부러질 수 있는 돌출 센서 마운트나 바퀴 뒤쪽으로 내려오는 구조는 사용하지 않는다. 기체가 들렸을 때 바퀴 다음으로 센서가 바닥에 닿지 않게 하판 안쪽에 보호하고, 3/10/20mm 센서-바닥 간격과 10mm 단차, 하부 그늘과 센서 내장 백색 LED 조건을 모두 교정에 포함한다. 센서 위치 변경은 펌웨어의 네 채널 순서와 함께 갱신한다.
1. 비상정지와 모터 명령 만료 안전
2. 위험색·경계 회피
3. 접촉 중 밀기 유지 또는 안전 이탈
4. 리어리프트 공격
5. 리어리프트 턴
6. 일반 정렬·추적·탱크턴
7. 스타트 정렬과 탐색경계 센서가 위험을 확인하면 모든 공격·리어리프트 기동보다 먼저 회피한다. 현재 V1은 IMU, 엔코더, 거리센서, 전류센서를 사용하지 않으므로 자세를 직접 확인했다고 가정하지 않는다. V1에서 리어리프트를 시험한다면 카메라 목표 정보와 제한된 시간 기반 단계로 시작하고, 출력 상한을 낮춘 실물 시험으로 시간을 결정한다. 센서를 추가하는 V2 전략과 V1 구현을 혼동하지 않는다.
우리 시작점, 경기장 중앙, 상대 시작점이 일직선이라는 경기장 배치를 이용한다.
우리 시작점 -> 경기장 중앙 -> 상대 시작점목적은 시작 직후 불필요한 전방위 탐색을 줄이고 상대가 있을 가능성이 가장 높은 선을 먼저 점유하는 것이다. 실제 시작 배치 오차와 상대의 즉시 회피를 고려해 장시간 직진을 고정 명령으로 사용하지 않는다.
기존 FSM의 기본 공격 흐름은 다음과 같다.
탐색 -> 목표 확인 -> 정렬 -> 접근 -> 돌진 -> 급정거 -> 스포크 삽입 -> 밀기현재 코드의 돌진 220ms, 브레이크 90ms, 삽입 350ms는 실물 검증 전 초기값이다. 카메라의 상자 중심으로 방향 오차를 판단하고, 거리센서가 없는 V1에서는 상자 크기를 실제 거리의 대용값으로 교정해야 한다.
상대가 설정 거리 안에 있고 방향이 충분히 일치할 때, 전진 가속 뒤 강한 제동으로 뒤축 하중을 줄이고 전방 스포크가 바닥을 스치며 상대 아래로 들어가게 하는 공격이다.
정렬 -> 전진 가속 -> 짧은 강제 제동 -> 스포크 하강·침투 -> 양쪽 전진 출력 -> 밀기앞축을 기준으로 뒤축이 들리기 시작하는 단순 조건은 다음과 같다.
a > g * x_CG / h_CGx_CG는 앞축에서 무게중심까지의 뒤쪽 거리, h_CG는 무게중심 높이다. 예를 들어 x_CG=42mm,
h_CG=60mm라면 약 0.70g보다 큰 감속이 필요하다. 타이어 변형, 스키드 접촉, 모터 제동 특성 때문에
계산값만으로 동작을 보장하지 않는다.
상대와의 방향 오차가 커서 일반 탱크턴의 횡끌림이 커질 때 사용하는 특수 회전이다.
짧은 전진 가속 -> 강제 제동 -> 뒤축 하중 감소 또는 이륙
-> 앞바퀴 좌우 반대 출력 -> 목표 방향 직전에 감속 -> 뒤축 착지 -> 추적 복귀뒤축이 실제로 들리면 접지 휠베이스가 거의 0이 되어 129mm 휠베이스의 횡끌림을 우회할 수 있다. 초기 사용 조건은 큰 방향 오차 약 70~100도 이상을 후보로 두되, 고정값으로 확정하지 않는다. 전방에 가속 공간이 없거나 경계가 가까우면 사용하지 않는다.
착지 시 공중에서 회전하던 뒤 바퀴가 바닥과 큰 속도 차이로 닿으면 벨트, 풀리, 샤프트, 베어링에 충격이 생긴다. 목표 각도 전에 회전 출력을 줄이고 착지 직전 좌우 속도 차이를 완화해야 한다. 앞바퀴 두 개와 전방 구조는 순간적으로 기체 전체 하중을 받을 수 있게 설계한다.
공격과 회전을 별개의 제동 튜닝으로 만들지 않고 공통 준비 단계를 공유한다.
REAR_LIFT_PREPARE
-> 제한된 전진 가속
-> 제한 시간 강제 제동
-> 목적에 따라 분기
공격: 양쪽 전진
회전: 좌우 반대 출력V1에는 자세 센서가 없으므로 뒤축 들림 감지 완료 같은 조건을 현재 하드웨어의 실제 입력처럼 구현하면
안 된다. 실물 시험 전에는 이 전략을 생산 기본값으로 활성화하지 않고, 저출력 벤치 모드와 안전 지그에서
제동 시간, 이동 거리, 드라이버 온도, 벨트 충격을 먼저 확인한다.
영상처리 부하는 가까운 전용 공유기의 로컬 네트워크에 연결된 외부 서버 PC로 옮기는 구성을 시험한다. 외부 서버는 영상 인식만 담당하고, 전략 FSM·모터 출력·바닥 경계 회피·비상정지는 계속 ESP32에서 수행한다. 외부 서버가 좌우 모터 출력을 직접 결정하지 않는다.
카메라
-> 라즈베리파이: 1280x720 저지연 영상 송출
-> 전용 5GHz 공유기
-> 유선 연결된 서버 PC: 상대 검출
-> UDP로 목표 좌표·박스·신뢰도 반환
-> 라즈베리파이: 원격/로컬 결과 선택 및 14바이트 UART 변환
-> ESP32: 기동 선택과 모터 제어초기 시험은 1280x720, 최대 50FPS, H.264 저지연 RTP/UDP 송출을 기준으로 한다. B프레임과 긴 수신 버퍼를 사용하지 않고, 처리 대기열은 최대 한 프레임만 유지한다. 처리가 밀리면 오래된 프레임을 끝까지 처리하지 않고 버린 뒤 최신 프레임으로 넘어간다. 서버는 필요하면 수신한 압축 영상을 재인코딩 없이 저장하고, 검출 결과와 FSM 로그는 별도로 기록한다.
서버가 반환하는 최소 정보는 다음과 같다.
frame_id, capture_time, target_x, target_y,
target_width, target_height, confidence, target_count서버의 1280x720 좌표는 현재 UART 규격인 1920x1080 좌표로 변환한다. 단순 전체 화면 매핑이면
x *= 1.5, y *= 1.5를 적용한다. 원격 검출기와 로컬 검출기가 각자 UART sequence를 만들지 않고,
라즈베리파이의 최종 결과 선택기가 출처와 관계없이 하나의 연속 sequence를 생성한다.
원격 서버 결과를 기본으로 사용하되 라즈베리파이의 로컬 검출기를 폴백으로 유지한다. 원격 정상 상태에서 로컬 검출기를 완전히 종료하면 장애 시 초기화 지연 때문에 즉시 전환할 수 있으므로, 카메라 스트림과 검출기를 준비한 상태로 유지하거나 낮은 주기로 대기시킨다.
REMOTE_ACTIVE
-> 원격 결과 지연 증가 -> REMOTE_DEGRADED
-> 새 원격 결과가 120ms 동안 없음 -> LOCAL_ACTIVE
-> 원격 결과가 5~10프레임 연속 정상 -> REMOTE_ACTIVE전환 기준의 초기값은 다음과 같다.
| 조건 | 처리 |
|---|---|
| 원격 결과 나이 0~60ms | 원격 결과 정상 사용 |
| 60~120ms | 원격 불안정 상태로 기록, 최신 결과만 제한적으로 사용 |
| 120ms 이상 새 결과 없음 | 로컬 검출 결과로 즉시 전환 |
| 1초 이상 응답 없음 | 서버 완전 단절로 기록하되 이미 로컬로 운전 중이어야 함 |
| 원격 결과 5~10프레임 연속 정상 | 복구 후보, 지연과 좌표 일치 확인 후 원격으로 복귀 |
1초는 주행 중 폴백을 시작하는 시간이 아니다. 1m/s 주행에서는 1초 동안 1m를 이동할 수 있으므로 현재 ESP32 영상 신선도와 같은 120ms를 초기 폴백 기준으로 사용한다. 원격 패킷 하나만 도착했다고 즉시 복귀하면 원격과 로컬 사이를 반복 전환할 수 있으므로 연속 정상 프레임과 복구 히스테리시스를 사용한다.
원격과 로컬 출처가 바뀐 직후 약 200ms 동안은 좌표·거리 추정 차이를 고려해 리어리프트 공격과 리어리프트 턴을 금지하고 일반 정렬과 제한된 접근만 허용한다. 바닥 경계 회피, SW1 비상정지, 모터 명령 만료 감시는 영상 출처와 관계없이 항상 우선한다. 원격과 로컬 결과가 모두 오래되면 마지막 표적을 계속 추적하지 않고 목표 상실 상태로 전환한다.
이 구성은 아직 구현·검증되지 않았다. 전용 공유기를 가까이 두고 서버를 유선 연결한 상태에서 다음을 측정한 뒤 생산 전략 채택 여부를 결정한다.
리어리프트의 가속·제동·삽입·회전 단계는 네트워크 왕복으로 하나씩 명령하지 않는다. 서버는 목표 위치와 기동 시작 조건에 필요한 영상 정보만 제공하고, 일단 시작한 시간 기반 기동은 ESP32가 로컬에서 끝낸다. 대회에서 외부 컴퓨터와 무선 통신을 허용하는지는 실제 적용 전에 해당 연도 규정으로 별도 확인한다.
센서 100Hz는 목표이지 현재 실측 달성 결과가 아니다. AS7341 전체 스펙트럼은 두 번의 수광이 필요하다.
실제 브레이크 효과, 시간 기반 기동의 기체 안정성, 바닥과 상대 로봇 표면 구분은 실물 검증이 필요하다.
영상·가상환경·빌드 산출물은 .gitignore에 따라 제외한다.
2026-10-05 추가 작업 반영에는 남은 PCBV2 자료와 파이썬 코드, PNG 실행 화면도 함께 포함했다.
| Qty | Value | Footprint | References |
|---|---|---|---|
| 4 | 10K | Resistor_SMD:R_0603_1608Metric | R2, R15, R16, R17 |
| 4 | 1K | Resistor_SMD:R_0603_1608Metric | R3, R4, R7, R8 |
| 4 | 470 | Resistor_SMD:R_0603_1608Metric | R5, R6, R9, R10 |
| 4 | MountingHole_Pad | MountingHole:MountingHole_3.2mm_M3_DIN965_Pad | H1, H2, H3, H4 |
| 3 | UART | Connector_Molex:Molex_SPOX_5267-04A_1x04_P2.50mm_Vertical | J19, J20, J21 |
| 2 | 10uF | Capacitor_SMD:C_0805_2012Metric_Pad1.18x1.45mm_HandSolder | C1, C2 |
| 2 | 4.7K | Resistor_SMD:R_0603_1608Metric | R12, R14 |
| 2 | 6.8K | Resistor_SMD:R_0603_1608Metric | R11, R13 |
| 2 | Conn_01x06 | Connector_Molex:Molex_SPOX_5267-06A_1x06_P2.50mm_Vertical | J13, J16 |
| 2 | Conn_01x08 | Connector_Molex:Molex_SPOX_5267-08A_1x08_P2.50mm_Vertical | J9, J10 |
| 2 | LOGO | LOGO | G***, G*** |
| 2 | ~ | XL4015:XL4015 | U1, U2 |
| 1 | 0.1uF | Capacitor_SMD:C_0805_2012Metric_Pad1.18x1.45mm_HandSolder | C3 |
| 1 | 100K | Resistor_SMD:R_0603_1608Metric | R1 |
| 1 | AMS1117-3.3 | Package_TO_SOT_SMD:SOT-223-3_TabPin2 | U3 |
| 1 | AS7341_1 | Connector_Molex:Molex_SPOX_5267-04A_1x04_P2.50mm_Vertical | J11 |
| 1 | AS7341_2 | Connector_Molex:Molex_SPOX_5267-04A_1x04_P2.50mm_Vertical | J12 |
| 1 | AS7341_3 | Connector_Molex:Molex_SPOX_5267-04A_1x04_P2.50mm_Vertical | J14 |
| 1 | AS7341_4 | Connector_Molex:Molex_SPOX_5267-04A_1x04_P2.50mm_Vertical | J15 |
| 1 | Conn_01x02 | Connector_Molex:Molex_SPOX_5267-02A_1x02_P2.50mm_Vertical | J6 |
| 1 | Conn_01x02 | Connector_AMASS:AMASS_XT30U-M_1x02_P5.0mm_Vertical | J5 |
| 1 | IR1 | Connector_Molex:Molex_SPOX_5267-03A_1x03_P2.50mm_Vertical | J1 |
| 1 | IR2 | Connector_Molex:Molex_SPOX_5267-03A_1x03_P2.50mm_Vertical | J2 |
| 1 | IR3 | Connector_Molex:Molex_SPOX_5267-03A_1x03_P2.50mm_Vertical | J3 |
| 1 | IR4 | Connector_Molex:Molex_SPOX_5267-03A_1x03_P2.50mm_Vertical | J4 |
| 1 | IR5 | Connector_Molex:Molex_SPOX_5267-03A_1x03_P2.50mm_Vertical | J7 |
| 1 | IR6 | Connector_Molex:Molex_SPOX_5267-03A_1x03_P2.50mm_Vertical | J8 |
| 1 | SW1 | Connector_Molex:Molex_SPOX_5267-02A_1x02_P2.50mm_Vertical | J17 |
| 1 | SW2 | Connector_Molex:Molex_SPOX_5267-02A_1x02_P2.50mm_Vertical | J18 |
| 1 | TCA9548APWR | Package_SO:TSSOP-24_4.4x7.8mm_P0.65mm | U4 |
| 1 | YD-ESP32-S3 | YD-ESP32-S3:YD-ESP32-S3 | A1 |
| 1 | ~ | Library:MPU6050 | U5 |

caconee22/c_robot
처음 사용하는 사람은 펌웨어 구조·사용법 전체 설명을 먼저 읽는다. 파일별 책임, 실제 FSM/안전 흐름, 센서 설정·교정, UART 규격, 모터 API, 주기와 실물 시험 순서를 설명한다. 별도 벤치의 콘솔/CSV는 BENCHTESTS.md, 검토 근거는 VERIFICATION.md에 있다. 아래는 저장소 전체와 영상 프로그램 안내다.


pascallanger/DIY-Multiprotocol-TX-Module
Multiprotocol TX Module (or MULTI-Module) is a 2.4GHz transmitter module which controls many different receivers and models.

fossasia/pslab-hardware
PSLab Hardware Design and Schematics https://pslab.io


MaltWhiskey/Mega-Cube
16x16x16 PL9823 Cube with Teensy 4.0 and FlexIO driver



shamansystems/Cheap-FOCer-2
Low-Cost Motor Controller based on the VESC 6
It measures 65 × 90 mm and has 2 copper layers, 1.6 mm thick.
53 parts, built around the AMS1117-3.3. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.
From the caconee22/c_robot repository on GitHub, at the commit this page was made from: the board is PCBV2/C_ROBOT.kicad_pcb and its schematic PCB/C_ROBOT.kicad_sch. PCBKit opens the board in the browser, with nothing to install.
Its repository states no licence, so its author keeps all rights: ask caconee22 before reusing the design.