03-PWM 서보 버전-사용 매뉴얼
목차
개요
하드웨어 배선
펌웨어 컴파일 및 플래싱
시리얼 통신 프로토콜
명령 레퍼런스
호스트 PC 사용 튜토리얼
제스처 추적
제스처 파라미터 미세 조정
자주 묻는 질문
1. 개요
본 펌웨어는 ESP32-S3 개발 보드에서 실행되며, PWM 신호를 통해 8채널 서보를 제어하여 로봇 손이 제스처를 수행하도록 구동합니다. 호스트 PC(PC/라즈베리파이/기타 MCU)는 USB 시리얼로 바이너리 프레임 명령을 전송하고, ESP32가 해석한 후 해당 제스처를 실행하고 응답을 반환합니다.
프로젝트는 두 세트의 펌웨어 구현을 제공합니다:
| 펌웨어 | 디렉터리 | 특징 |
|---|---|---|
| ESP-IDF 버전(권장) | esp-idf/AmazingHand_Serial/ | 컴포넌트화된 프로젝트 구조, FreeRTOS 듀얼 태스크, 프로덕션 준비 완료 |
두 펌웨어는 동일한 시리얼 프로토콜과 동일한 명령 집합을 공유하며, 제스처 파라미터는 서로 참고할 수 있습니다.
지원 제스처(제스처 명령 11개)
| 제스처 | 명령 | 설명 |
|---|---|---|
| 바위 | 0x01 | 가위바위보: 모든 손가락 주먹 |
| 가위 | 0x02 | 가위바위보: 검지+중지를 펼쳐 V자 |
| 보 | 0x03 | 가위바위보: 모든 손가락 펼침 |
| 엄지 척 | 0x04 | 엄지를 세우고 나머지는 주먹 |
| 도발1 | 0x05 | 검지 흔들기("아니아니아니") |
| 도발2 | 0x06 | 약지를 펼쳐 흔들기(새끼손가락 대체) |
| 펼치기 | 0x07 | 모든 손가락 펼침 |
| 주먹 | 0x08 | 모든 손가락 닫기 |
| OK | 0x09 | OK 제스처 |
| 핀치 | 0x0A | 핀치 제스처 |
| 가리키기 | 0x0C | 검지를 펼쳐 "가리키기" 동작 |
| 직접 구동 | 0xF0 | 8채널 서보 각도를 직접 제어 |
| 좌우손 설정 | 0xF1 | 왼손/오른손 모드 전환 |
| 반복 | 0xFE | 마지막 제스처를 반복 실행 |
| 정지 | 0xFF | 현재 제스처를 즉시 종료 |
| NOP | 0x00 | 링크 테스트 |
참고: 명령 0x0B는 사용 중지되었습니다(기존 "엄지 아래로"가 "엄지 척" 동작과 중복되어 제거됨).
2. 하드웨어 배선
적용 하드웨어
| 항목 | 모델 |
|---|---|
| 메인 컨트롤러 | ESP32-S3 개발 보드(Youxin YX-ESP32-S3 또는 동급) |
| 서보 | 8채널 PWM 아날로그 서보 (SG90 또는 동급) |
| 어댑터 보드 | PWM 서보 어댑터 보드 |
ESP32-S3 개발 보드에는 두 개의 Type-C 인터페이스가 있습니다:
내장 USB Serial/JTAG: ESP32-S3 칩 내장 USB 컨트롤러에 직접 연결
외장 FT232: FT232 USB-시리얼 변환 칩을 통해 통신
두 인터페이스 모두 시리얼 통신에 사용할 수 있으며, 어느 하나를 선택하면 됩니다. 호스트 PC에서 해당 시리얼 장치 이름을 선택하세요.
서보 → 어댑터 보드
8개 서보의 3P 플러그를 ID 번호에 따라 어댑터 보드의 서보 1-8 핀 헤더에 꽂습니다.
어댑터 보드 → ESP32-S3
| 어댑터 보드 | ESP32-S3 GPIO | 설명 |
|---|---|---|
| PWM1 | 4 | 검지 관절1 |
| PWM2 | 5 | 검지 관절2 |
| PWM3 | 6 | 중지 관절1 |
| PWM4 | 7 | 중지 관절2 |
| PWM5 | 15 | 약지 관절1 |
| PWM6 | 16 | 약지 관절2 |
| PWM7 | 17 | 엄지 관절1 |
| PWM8 | 18 | 엄지 관절2 |
| 5V | 5V | 전원 공급(어댑터 보드에서 인출) |
| GND | GND | 반드시 공통 접지, 최소 한 가닥 연결 |
좌우손은 동일한 GPIO 매핑을 공유합니다. "왼손" 모드로 전환하면 펌웨어가 제스처 내에서 엄지 운동 방향을 미러링하며, 핀은 변경되지 않습니다.
전원 공급
어댑터 보드에는 두 세트의 5V/GND 전원 포트가 있습니다:
한 세트는 Type-C 케이블로 인출되어 5V 3A 전원 어댑터에 연결
다른 한 세트는 ESP32-S3의 5V 핀에 전원을 공급하기 위해 인출(개발 보드는 더 이상 Type-C로 전원을 공급할 필요 없음)
3. 펌웨어 컴파일 및 플래싱
3.1 ESP-IDF 버전(권장)
경고: 경로 요구 사항: ESP-IDF 컴파일은 중국어 경로를 지원하지 않습니다. 프로젝트가 위치한 경로가 완전히 영문인지 확인하세요(사용자 폴더, 상위 디렉터리 포함).
프로젝트 구조
esp-idf/AmazingHand_Serial/
├── CMakeLists.txt # 최상위 프로젝트 구성
├── sdkconfig.defaults # 기본 Kconfig 구성
├── main/
│ ├── CMakeLists.txt
│ └── main.c # FreeRTOS 이중 태스크 + 초기화(글루 레이어)
└── components/
├── hand_servo/ # 서보 구동(LEDC PWM + 캘리브레이션 데이터)
├── hand_gestures/ # 제스처 파라미터 매크로 + 제스처 함수 + 좌우손 제어
└── hand_protocol/ # 시리얼 프레임 파싱 + 명령 분배빌드 환경
ESP-IDF v6.0.1
대상 칩: ESP32-S3
idf.py환경 변수 설정 완료
컴파일 및 플래싱
cd esp-idf/AmazingHand_Serial
# 1. 대상 칩 설정 (최초 또는 칩 교체 시)
idf.py set-target esp32s3
# 2. 컴파일
idf.py build
# 3. 플래시 (Windows: COM 포트 사용, 예: COM3)
idf.py -p COM3 flash
# 4. 시리얼 모니터 (선택 사항, 보드레이트 115200)
idf.py -p COM3 monitor
components/또는main/아래의 소스를 수정한 후에는idf.py build && idf.py -p COM3 flash를 다시 실행하면 됩니다.
3.3 캘리브레이션(선택 사항, 최초 사용 시 권장)
서보 중심 위치와 펄스 폭은 실제 기구에 맞게 캘리브레이션해야 합니다. 두 가지 방법이 있습니다:
- ESP-IDF 버전:
components/hand_servo/hand_servo.c의middle_pos[8](40번째 줄)와min_pw/mid_pw/max_pw[8](45-47번째 줄)를 편집
캘리브레이션 후 다시 컴파일 및 플래싱해야 합니다.
4. 시리얼 통신 프로토콜
4.1 물리 계층
| 파라미터 | 값 |
|---|---|
| 인터페이스 | USB Serial (UART0) |
| 보드레이트 | 115200 |
| 데이터 비트 | 8 |
| 패리티 비트 | 없음 (None) |
| 정지 비트 | 1 |
| 흐름 제어 | 없음 |
4.2 프레임 형식
호스트 → ESP32(명령 프레임)
┌────────┬────────┬──────────┬────────────────┬──────────┐
│ 0xAA │ CMD_ID │ DATA_LEN │ DATA[0 .. N-1] │ CHECKSUM │
│ 1 Byte │ 1 Byte │ 1 Byte │ N Bytes │ 1 Byte │
└────────┴────────┴──────────┴────────────────┴──────────┘
帧头 命令ID 数据长度 数据负载 校验和프레임 헤더: 고정
0xAA, 한 프레임의 시작을 식별CMD_ID: 명령 번호(명령 레퍼런스 참조)
DATA_LEN: 데이터 페이로드의 바이트 수(0-8, 8을 초과하는 프레임은 무효)
DATA: 데이터 페이로드, 길이는 DATA_LEN에 의해 결정
CHECKSUM:
CMD_ID ^ DATA_LEN ^ DATA[0] ^ ... ^ DATA[N-1](XOR 체크섬)
DATA_LEN = 0이면 CHECKSUM = CMD_ID입니다.
ESP32 → 호스트(응답 프레임)
┌────────┬────────┬────────┬──────────┐
│ 0xBB │ CMD_ID │ STATUS │ CHECKSUM │
│ 1 Byte │ 1 Byte │ 1 Byte │ 1 Byte │
└────────┴────────┴────────┴──────────┘
帧头 命令ID 状态码 校验和프레임 헤더: 고정
0xBBCMD_ID: 원래 명령 번호
STATUS: 상태 코드(아래 표 참조)
CHECKSUM:
CMD_ID ^ STATUS
상태 코드
| STATUS | 의미 | 설명 |
|---|---|---|
| 0x00 | OK | 명령이 수락되어 실행 시작 |
| 0x01 | 유효하지 않은 명령 | CMD_ID가 명령 테이블에 없음 |
| 0x02 | 파라미터 오류 | 데이터 길이 또는 내용이 올바르지 않음 |
| 0x03 | 바쁨 | 제스처 실행 중, 새 명령을 일시적으로 받지 않음 |
| 0x10 | 완료 | 제스처 실행 완료 |
4.3 통신 타이밍
主机 ESP32
│ │
│──── [AA 01 00 01] ────────→│ 发送"石头"命令
│ │
│←─── [BB 01 00 01] ─────────│ ACK: 命令已接受
│ │
│ (执行手势中)
│ │
│←─── [BB 01 10 11] ─────────│ 完成: 手势执行完毕
│ │
│──── [AA 02 00 02] ────────→│ 发送"剪刀"命令
│ │
│←─── [BB 02 00 02] ─────────│ ACK
│ │4.4 제스처 정지 & 프레임 타임아웃
[AA FF 00 FF]를 전송하면 실행 중인 제스처를 언제든 중단할 수 있음ESP32는 200ms 내에 한 프레임을 다 받지 못하면 자동으로 폐기(바이트 손실로 인한 영구적 동기 상실 방지)
체크섬이 일치하지 않는 프레임은 조용히 폐기되며, 호스트 PC는 타임아웃 재전송을 구현해야 함
4.5 좌우손 모드
기본은 오른손 모드입니다. [AA F1 01 02 F2]를 전송하면 왼손으로 전환, [AA F1 01 01 F1]을 전송하면 오른손으로 복귀합니다. 좌우손은 엄지의 운동 방향에 영향을 줍니다(바위/가위/엄지 척/OK/핀치 등 엄지가 포함된 제스처).
5. 명령 레퍼런스
5.1 제스처 명령 (0x01-0x0A, 0x0C)
이 명령들은 데이터 페이로드가 필요 없으며 (DATA_LEN=0), ESP32는 수신 후 즉시 해당 제스처를 실행합니다.
| 명령 | HEX 프레임 | 응답 | 설명 |
|---|---|---|---|
| 바위 | AA 01 00 01 | BB 01 00 01 → BB 01 10 11 | 모든 손가락 주먹 |
| 가위 | AA 02 00 02 | BB 02 00 02 → BB 02 10 12 | 검지+중지 펼침 |
| 보 | AA 03 00 03 | BB 03 00 03 → BB 03 10 13 | 모든 손가락 펼침 |
| 엄지 척 | AA 04 00 04 | BB 04 00 04 → BB 04 10 14 | 엄지 세우기 |
| 도발1 | AA 05 00 05 | BB 05 00 05 → BB 05 10 15 | 검지 흔들기(약 2.5s) |
| 도발2 | AA 06 00 06 | BB 06 00 06 → BB 06 10 16 | 약지 흔들기(약 2.5s) |
| 펼치기 | AA 07 00 07 | BB 07 00 07 → BB 07 10 17 | 모든 손가락 펼침 |
| 주먹 | AA 08 00 08 | BB 08 00 08 → BB 08 10 18 | 모든 손가락 닫기 |
| OK | AA 09 00 09 | BB 09 00 09 → BB 09 10 19 | OK 제스처 |
| 핀치 | AA 0A 00 0A | BB 0A 00 0A → BB 0A 10 1A | 핀치 제스처 |
| 가리키기 | AA 0C 00 0C | BB 0C 00 0C → BB 0C 10 1C | 검지를 펼쳐 "가리키기" 동작 |
5.2 직접 구동 명령 (0xF0)
8채널 서보 각도를 직접 제어하며, 8바이트 데이터가 각각 서보 1-8에 대응하고 각 바이트의 값 범위는 0-180입니다.
예시: 모든 서보를 중립 위치(90°)로
发送: AA F0 08 5A 5A 5A 5A 5A 5A 5A 5A F8
│ │ │ └── 8 个 0x5A (90°) ──┘ │
│ │ │ └── CHECKSUM
│ │ └── DATA_LEN = 8
│ └── CMD_DIRECT_DRIVE
└── 帧头체크섬 = F0 ^ 08 ^ 5A ^ 5A ^ 5A ^ 5A ^ 5A ^ 5A ^ 5A ^ 5A = F8
동일한 0x5A 8개를 둘씩 XOR하면 0x00이 되고, 최종적으로
0xF0 ^ 0x08 ^ 0x00 = 0xF8
예시: 검지 펼치기(서보1=170°, 서보2=10°), 나머지는 중립(90°)
发送: AA F0 08 AA 0A 5A 5A 5A 5A 5A 5A 58
└─170° └─10°5.3 좌우손 설정 (0xF1)
1바이트 데이터: 0x01 = 오른손, 0x02 = 왼손.
设右手: AA F1 01 01 F1
设左手: AA F1 01 02 F25.4 제어 명령
| 명령 | HEX 프레임 | 설명 |
|---|---|---|
| NOP | AA 00 00 00 | 링크 테스트, 즉시 BB 00 00 00 반환 |
| 반복 | AA FE 00 FE | 마지막 제스처를 반복 실행 |
| 정지 | AA FF 00 FF | 현재 제스처를 즉시 종료 |
5.5 응답 빠른 조회
유효하지 않은 명령을 수신했을 때(존재하지 않는 명령 0xFC를 예로):
发送: AA FC 00 FC
响应: BB FC 01 FD (STATUS=0x01 无效命令)체크섬 검증:
FC ^ 00 = FC, 응답FC ^ 01 = FD
6. 호스트 PC 사용 튜토리얼
프로젝트 루트 디렉터리는 두 개의 호스트 PC 도구를 제공합니다:
| 도구 | 파일 | 유형 | 용도 |
|---|---|---|---|
| 그래픽 인터페이스 | hand_gui.py / 패키지 exe | 시각화 | 버튼 클릭으로 제스처, 슬라이더 직접 구동, 로그 |
| 명령줄 테스트 | serial_test.py | 명령 방식 | 제스처/단일 서보/스윕 전송, 자동화 테스트 |
둘 다
pyserial에만 의존합니다. 설치:pip install -r requirements.txt
6.1 시각화 GUI(권장)
방식 A: 패키지된 exe 실행(고객용)
AmazingHand控制台.exe를 받습니다(또는 압축 해제된 디렉터리)exe를 두 번 클릭하여 바로 실행, Python 설치 불필요
아래 단계에 따라 연결하고 사용합니다
방식 B: 소스에서 실행
# 1. 의존성 설치
pip install -r requirements.txt
# 2. 실행
python hand_gui.pyGUI 사용 단계
시리얼 포트 선택: 상단 드롭다운에서 ESP32에 해당하는 COM 포트를 선택(Windows 장치 관리자에서 확인)
"연결" 클릭: 상태등이 녹색으로 변하고 로그 영역에 "연결됨"이 표시되며, 자동으로 NOP 링크 테스트를 전송
제스처 명령: 「바위」「가위」「보」「엄지 척」「OK」… 등의 버튼을 클릭하면 로봇 손이 해당 제스처를 실행
좌우손: 「오른손」/「왼손」을 체크하여 엄지 미러 방향 전환
서보 직접 구동: 슬라이더 8개를 드래그하여 개별 서보 각도를 실시간 제어(0-180°)
손가락 차동 제어(권장): 손가락마다 두 개의 진행 막대——굴곡/신전은 해당 손가락의 두 서보를 역방향 차동(굴곡 신전)으로 제어하고, 오른쪽/왼쪽은 동일 방향 흔들기를 제어합니다. 두 자유도는 독립적이며 동기 구동됩니다
반복 / 정지: 마지막 제스처 반복 / 현재 제스처 즉시 중단
통신 로그: 하단에 송수신 프레임과 응답 상태를 실시간 표시
손가락 차동 제어 설명
각 손가락은 두 개의 서보가 차동 구동하며, 두 자유도는 직교합니다:
| 진행 막대 | 역할 | 기계적 효과 |
|---|---|---|
| 굴곡◀▶신전 | 두 서보 역방향 회전(차동) | 손가락 굴곡 또는 신전 |
| 오른쪽◀▶왼쪽 | 두 서보 동일 방향 회전 | 손가락 좌우 흔들기 |
굴곡/신전 슬라이더 범위 -70 ~ +70(0 = 중립, +70 = 완전 신전, -70 = 완전 굴곡)
좌우 흔들기 슬라이더 범위 60 ~ 120(90 = 중립, 60 = 오른쪽으로, 120 = 왼쪽으로)
서보 각도 =
흔들기 ± 굴곡, 두 서보를 동기 갱신하고 직접 구동 명령을 전송
예(검지 GPIO4/5): 굴곡 슬라이더를 +70으로 드래그, 흔들기를 90 유지 → 서보4=160°, 서보5=20°(완전 신전); 굴곡을 -70으로 드래그 → 서보4=20°, 서보5=160°(완전 굴곡).
6.2 명령 방식 테스트(serial_test.py)
명령줄 사용법
# 도움말 보기
python serial_test.py
# 링크 테스트
python serial_test.py COM3 nop
# 제스처 전송
python serial_test.py COM3 rock # 바위
python serial_test.py COM3 thumbs_up # 엄지 척
python serial_test.py COM3 index # 가리키기
python serial_test.py COM3 open # 펼치기
python serial_test.py COM3 close # 주먹
# 단일 서보 직접 구동
python serial_test.py COM3 servo 1 90 # 서보1 → 90°
# 모두 중앙으로 복귀
python serial_test.py COM3 mid
# 좌우 손 설정
python serial_test.py COM3 hand L # 왼손
python serial_test.py COM3 hand R # 오른손
# 스윕 / 자가 진단
python serial_test.py COM3 sweep 1 # 서보1 스윕
python serial_test.py COM3 test # 모든 서보 순차 테스트대화형 모드
python serial_test.py COM3REPL에 진입하여 축약 명령을 직접 입력합니다(예: servo 3 180, rock, mid, quit).
6.3 시리얼 도구 수동 테스트(선택 사항)
CoolTerm (macOS/Windows/Linux):
CoolTerm을 열고,
Options→ 보드레이트 115200, 8N1 설정Connection→Send String→Hex선택AA 01 00 01을 입력 → 전송 → 로봇 손이 "바위" 실행응답 영역에
BB 01 00 01 ... BB 01 10 11이 표시되는지 확인
SerialTool (macOS):
brew install serialtool
echo -ne '\xAA\x01\x00\x01' > /dev/cu.usbserial-00016.4 Python 제어 스크립트(사용자 정의 개발)
#!/usr/bin/env python3
"""灵巧手串口控制 - Python 上位机示例"""
import serial
import time
SERIAL_PORT = "/dev/cu.usbserial-0001" # 실제 포트로 수정
BAUD_RATE = 115200
# 명령 정의 (펌웨어 명령 세트와 일치)
CMD = {
"nop": 0x00,
"rock": 0x01,
"scissors": 0x02,
"paper": 0x03,
"thumbs_up": 0x04,
"taunt1": 0x05,
"taunt2": 0x06,
"open": 0x07,
"close": 0x08,
"ok": 0x09,
"pinch": 0x0A,
"index": 0x0C,
"direct": 0xF0,
"set_side": 0xF1,
"repeat": 0xFE,
"stop": 0xFF,
}
def calc_checksum(cmd_id, data=b""):
"""计算 XOR 校验和 (CMD ^ LEN ^ DATA[0..N])"""
result = cmd_id ^ len(data)
for b in data:
result ^= b
return result & 0xFF
def send_command(ser, cmd_id, data=b""):
"""发送命令帧,返回 (ack_status, completion_status)"""
data_len = len(data)
checksum = calc_checksum(cmd_id, data)
frame = bytes([0xAA, cmd_id, data_len]) + data + bytes([checksum])
ser.write(frame)
print(f"发送: {frame.hex(' ').upper()}")
def read_response(ser, timeout=1.0):
"""读取一个响应帧 [0xBB CMD STATUS CKSUM]"""
ser.timeout = timeout
while True:
b = ser.read(1)
if not b:
return None
if b[0] == 0xBB:
buf = ser.read(3)
if len(buf) == 3:
expected = buf[0] ^ buf[1]
if expected == buf[2]:
return bytes([0xBB]) + buf
return None
def set_side(ser, side):
"""设置左右手: side='R' 右手, side='L' 左手"""
val = 0x01 if side.upper() == 'R' else 0x02
send_command(ser, CMD["set_side"], bytes([val]))
def direct_drive(ser, angles):
"""直驱 8 路舵机: angles 为 8 个 0-180 的角度列表"""
data = bytes([min(180, max(0, a)) for a in angles[:8]])
send_command(ser, CMD["direct"], data)
# ===== 사용 예시 =====
if __name__ == "__main__":
ser = serial.Serial(SERIAL_PORT, BAUD_RATE, timeout=1)
time.sleep(1) # ESP32 리셋 완료 대기
# 1. 링크 테스트
print("=== NOP 链路测试 ===")
send_command(ser, CMD["nop"])
# 2. 가위바위보 게임
print("\n=== 猜拳: 石头 → 剪刀 → 布 ===")
for name in ["rock", "scissors", "paper"]:
send_command(ser, CMD[name])
time.sleep(0.5)
# 3. 좋아요 제스처
print("\n=== 真棒 ===")
send_command(ser, CMD["thumbs_up"])
# 4. 테스트 중지
print("\n=== 停止测试 ===")
send_command(ser, CMD["taunt1"]) # 검지 흔들기 시작
time.sleep(0.3)
send_command(ser, CMD["stop"]) # 즉시 정지
# 5. 직접 구동 모드: 모두 중앙으로 복귀
print("\n=== 直驱: 归中 ===")
direct_drive(ser, [90] * 8)
ser.close()7. 제스처 추적
카메라로 손바닥을 실시간 인식하여 로봇 손의 손가락 굴곡/신전 및 좌우 흔들기를 구동합니다. 공식 AmazingHand의 손 추적 알고리즘 기반(MediaPipe 21개 키포인트 + 3D 월드 좌표 회전).
7.1 원리
카메라를 손바닥에 향함 → MediaPipe가 21개 손 키포인트 인식
손의 로컬 좌표계를 구성하고 4개 손가락 끝의 3D 벡터를 계산
손가락 끝 벡터 → 각 손가락의 (flex, base) 차동 파라미터 → 직접 구동 프로토콜을 재사용하여 서보로 전송
7.2 환경 요구 사항
제스처 추적은 64비트 Python + mediapipe 0.10.14에 의존합니다(구버전 solutions API, 이것만이 3D 월드 좌표를 처리할 수 있음):
| 의존성 | 버전 |
|---|---|
| Python | 64비트 3.12 |
| mediapipe | 0.10.14 |
| numpy | <2.0 |
| scipy | >=1.9 |
| opencv-python | >=4.10 |
| Pillow | >=10.0 |
주의: 현재 기본 환경은 32비트 Python이라 mediapipe를 설치할 수 없습니다. 64비트 Python 3.12를 별도로 설치해야 합니다(D 드라이브, 예:
D:\Python312-64에 설치, 기존 32비트와 완전히 공존하며 충돌 없음).
7.3 원클릭 배포
64비트 Python 3.12 설치(python.org에서 64비트 installer 다운로드,
D:\Python312-64에 설치)프로젝트 루트 디렉터리의 **
setup_tracking.bat**을 두 번 클릭하여 실행64비트 Python 자동 검색
tracking_env가상환경 생성mediapipe 0.10.14 등 의존성 설치
설치 검증
7.4 사용 단계
- 추적 환경으로 GUI 시작:
tracking_env\Scripts\python hand_gui.py시리얼 포트 연결(ESP32에 해당하는 COM 포트 선택)
"제스처 추적" 패널에서 카메라 번호 선택(기본 0)
"추적 시작" 클릭 → 카메라 화면이 패널에 표시됨
손바닥을 카메라에 향함:
손가락 굴곡/신전 → 로봇 손의 해당 손가락이 굴곡/신전
손바닥 좌우 회전 → 로봇 손 손가락이 좌우로 흔들림
"추적 정지" 클릭하여 종료
손이 감지되지 않으면 패널에 "손이 감지되지 않음"이 표시되고, 감지되면 "손 감지됨: Right/Left"가 표시됩니다.
7.5 파라미터 캘리브레이션
매핑 계수는 hand_tracking.py 하단(FLEX_SCALE / BASE_SCALE)에 있습니다:
FLEX_SCALE = 80.0 # 손끝 z 성분 → 굽힘/폄 (flex)
BASE_SCALE = 30.0 # 손끝 x 성분 → 좌우 회전 (base)굴곡/신전 폭이 부족하거나 방향이 반대이면 FLEX_SCALE을 조정하고; 좌우 흔들기 폭이 부족하거나 반대이면 BASE_SCALE을 조정합니다(부호로 방향 조정).
8. 제스처 파라미터 미세 조정
8.1 파라미터 위치
각 제스처의 각도 오프셋은 #define 매크로로 정의되며, 로직 코드를 수정할 필요 없이 값만 조정합니다.
- ESP-IDF 버전:
components/hand_gestures/hand_gestures.c상단 "제스처 파라미터(사용자 조정 가능)" 영역
8.2 파라미터 의미
// 예: 바위 제스처
#define ROCK_IDX_OFF1 70 // 검지 관절1 오프셋
#define ROCK_IDX_OFF2 -70 // 검지 관절2 오프셋양수 = 굴곡하여 쥠, 음수 = 펴서 염
각 손가락 2개의 오프셋,
middle_pos기준(기본 90°)차동 구조: 두 서보 오프셋의 차이 = 신전/수축, 동일 방향 성분 = 좌우 편향
8.3 파라미터 조정 단계
해당 제스처의
#define매크로를 찾습니다값을 수정합니다(증가 → 폭이 커짐; 감소 → 폭이 작아짐)
다시 컴파일 및 플래싱하고 호스트 PC로 효과를 테스트
동작이 자연스러울 때까지 반복적으로 미세 조정
9. 자주 묻는 질문
Q1: 호스트 PC가 시리얼 포트에 연결되지 않음?
ESP32가 Type-C로 컴퓨터에 연결되었는지 확인
장치 관리자의 COM 포트 번호가 GUI 선택과 일치하는지 확인
보드레이트 115200 확인
시리얼 포트를 점유하는 다른 소프트웨어 연결 해제
Q2: 명령을 보내도 반응이 없음?
먼저
AA 00 00 00(NOP)을 전송하면BB 00 00 00을 수신해야 함펌웨어가 플래싱되었고 대상 칩이 ESP32-S3인지 확인
배선 확인(GND 공통 접지 여부)
Q3: 제스처 동작 폭이 맞지 않거나 방향이 반대?
제스처 파라미터 미세 조정(7장 참조)으로 해당 매크로를 조정합니다.
Q4: 좌우손 모드가 어떤 제스처에 영향을 주나요?
바위/가위/엄지 척/OK/핀치 등 엄지가 포함된 제스처는 좌우손 전환 후 엄지 미러 방향이 바뀝니다.
Q5: 손가락이 걸려서 펴지지 않음?
모든 수축 계열 제스처는 실행 전에 자동으로 "먼저 손 전체를 펼친 후 오므림"하여 손가락이 이전 제스처에 막히는 것을 방지합니다. 그래도 걸리면 기계 조립을 점검하거나 수축 폭을 줄이세요.

