03-PWM サーボバージョン-使用マニュアル
目次
概要
ハードウェア配線
ファームウェアのビルドと書き込み
シリアル通信プロトコル
コマンドリファレンス
上位機の使用方法
ジェスチャートラッキング
ジェスチャーパラメータの微調整
よくある質問
1. 概要
本ファームウェアは ESP32-S3 開発ボード上で動作し、PWM 信号で 8 チャンネルのサーボを制御して器用なハンドにジェスチャーを実行させます。上位機(PC/Raspberry Pi/その他の MCU)は USB シリアルでバイナリフレーム命令を送信し、ESP32 が解析して対応するジェスチャーを実行し応答を返します。
プロジェクトは 2 セットのファームウェア実装を提供します:
| ファームウェア | ディレクトリ | 特徴 |
|---|---|---|
| ESP-IDF 版(推奨) | esp-idf/AmazingHand_Serial/ | コンポーネント化された工程構造、FreeRTOS デュアルタスク、実運用に対応 |
2 セットのファームウェアは同じシリアルプロトコルと同じコマンドセットを共有し、ジェスチャーパラメータは相互に参考にできます。
対応するジェスチャー(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 開発ボード(優信 YX-ESP32-S3 または同等品) |
| サーボ | 8 チャンネル PWM アナログサーボ (SG90 または同等品) |
| アダプタボード | PWM サーボアダプタボード |
ESP32-S3 開発ボードには 2 つの Type-C インターフェースがあります:
内蔵 USB Serial/JTAG:ESP32-S3 チップ内蔵の USB コントローラに直結
外付け FT232:FT232 シリアル変換チップを介して通信
両方のインターフェースをシリアル通信に使用でき、いずれか一方を選べばよいです。上位機は対応するシリアルデバイス名を選択します。
サーボ → アダプタボード
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 | 必ずコモングランドにすること、少なくとも 1 本接続 |
左右の手は同じ GPIO マッピングを共有します。「左手」モードに切り替えると、ファームウェアがジェスチャー内で親指の運動方向をミラーリングし、ピンは変わりません。
電源供給
アダプタボードには 2 組の 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 の 2 タスク + 初期化(グルー層)
└── 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 キャリブレーション(任意、初回使用を推奨)
サーボの中心位置とパルス幅は実際の機構に合わせてキャリブレーションする必要があります。2 つの方法があります:
- 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、1 フレームの開始を識別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 以内に 1 フレームを受信し終えないと自動的に破棄します(バイト欠落による恒久的な同期ずれを防ぐ)
チェックサムが一致しないフレームは静かに破棄され、上位機はタイムアウト再送を実装すべきです
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
8 個の同じ 0x5A を 2 つずつ 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. 上位機の使用方法
プロジェクトのルートディレクトリには 2 つの上位機ツールを提供しています:
| ツール | ファイル | 種類 | 用途 |
|---|---|---|---|
| グラフィカルインターフェース | 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°)
指の差動制御(推奨):各指に 2 つのプログレスバー——屈曲/伸展 はその指の 2 つのサーボを逆方向に差動制御(屈曲・伸展)、右スイング/左スイング は同方向のスイングを制御します。2 つの自由度は独立しており、同期して駆動
繰り返し / 停止:前回のジェスチャーを繰り返す / 現在のジェスチャーを即座に中断
通信ログ:下部に送受信フレームと応答状態をリアルタイム表示
指の差動制御の説明
各指は2 つのサーボの差動駆動で、2 つの自由度は直交しています:
| プログレスバー | 作用 | 機械的効果 |
|---|---|---|
| 屈曲◀▶伸展 | 2 つのサーボが逆方向に回転(差動) | 指を曲げるか伸ばす |
| 右スイング◀▶左スイング | 2 つのサーボが同方向に回転 | 指を左右に振る |
屈曲/伸展スライダーの範囲 -70 ~ +70(0 = 中立、+70 = 完全伸展、-70 = 完全屈曲)
左右スイングスライダーの範囲 60 ~ 120(90 = 中立、60 = 右へスイング、120 = 左へスイング)
サーボ角度 =
スイング ± 屈曲、2 つのサーボは同期して更新され直接駆動コマンドを送信
例(人差し指 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°)を基準とする差動構造:2 つのサーボのオフセットの差 = 伸展/収縮、同方向成分 = 左右の偏り
8.3 パラメータ調整手順
対応するジェスチャーの
#defineマクロを見つける数値を変更(増加 → 振幅が大きくなる;減少 → 振幅が小さくなる)
再ビルド・書き込みし、上位機で効果をテスト
動作が自然になるまで繰り返し微調整
9. よくある質問
Q1: 上位機がシリアルポートに接続できない?
ESP32 が Type-C でパソコンに接続されていることを確認
デバイスマネージャーの COM ポート番号が GUI の選択と一致しているか確認
ボーレートが 115200 であることを確認
シリアルポートを占有している他のソフトウェアを切断
Q2: コマンドを送信しても反応がない?
まず
AA 00 00 00(NOP)を送信し、BB 00 00 00を受信するはずファームウェアが書き込み済みで、ターゲットチップが ESP32-S3 であることを確認
配線を確認(GND がコモングランドになっているか)
Q3: ジェスチャーの動作振幅が正しくない、または方向が逆になった?
ジェスチャーパラメータの微調整(第 7 節参照)に入り、対応するマクロを調整します。
Q4: 左右手モードはどのジェスチャーに影響しますか?
グー/チョキ/サムズアップ/OK/ピンチなど親指を含むジェスチャーで、左右手を切り替えると親指のミラー方向が変わります。
Q5: 指が引っかかって伸びない?
すべての収縮系ジェスチャーは実行前に自動的に「まず手全体を展開してから収縮」します。これにより指が前のジェスチャーに邪魔されるのを防ぎます。それでも引っかかる場合は、機械的な組立を確認するか収縮の振幅を小さくしてください。

