🧪 新教程持續更新中 · 由機械臂到傳感器,跟隨教程從零搭建
跳到主要內容

SCS0009 桌面上位機(GUI 與 CLI) ​

本頁是 SCS0009 序列匯流排版的桌面控制教學。網頁控制見 SCS0009 網頁控制,硬體接線見 SCS0009 接線。

快速上手 ​

  1. 安裝 Python 3.10+ 與相依套件:安裝。
  2. 連接匯流排驅動板,確認序列埠:環境需求。
  3. 執行 GUI:amazing-hand-gui 或 python amazing_hand_gui.py。
  4. 按 標定 檢查左右手、角度和中位。
  5. 用逐指滑桿、預設姿態和序列做動作。

AmazingHand Python 控制工具(適用左手和右手) ​

用 Python 編寫的 GUI 與命令列工具,透過序列匯流排伺服馬達驅動板控制 8 個 Feetech SCS0009 伺服馬達,驅動 Pollen Robotics 的 AmazingHand 靈巧手。

左右手都支援。 啟動時選擇右手(伺服馬達 ID 1-8)或左手(伺服馬達 ID 11-18),--hand 可跳過提問。姿勢庫左右手共用,每隻手在 data/config.yaml 裡各自維護伺服馬達映射、安裝偏移和原始值目標。詳見左右手選擇。

AmazingHand 控制工具主介面


專案結構 ​

text
amazing_hand_gui.py   – GUI 主程式
amazing_hand_cmd.py   – 命令列工具
hand_logic.py         – 共用業務邏輯(不依賴 UI)
pyproject.toml        – 套件中繼資料、相依套件、pytest 設定
data/
  config.yaml         – 應用程式設定(序列埠、限位、原始值目標)
  hand_config.yaml    – 已儲存的手勢與序列
docs/
  REQUIREMENTS.md       – 需求與驗收標準
  CONFIG_FORMAT.md      – 設定檔格式說明
  scs_servo_protocol.md – SCS0009 暫存器參考
  CHANGES.md            – 相對原版的改動說明與原因
  user_manual.md        – 已遷移到中央教學的跳轉頁
tests/
  test_hand_logic.py      – hand_logic 單元測試(155 項)
  test_gui_utils.py       – GUI 工具函式單元測試(51 項)
  test_cmd.py             – CLI 單元測試(42 項)
  test_integration.py     – 整合測試(14 項)
  test_system.py          – 子程序系統測試(22 項)
  test_system_hardware.py – 硬體測試(33 項,需 --hardware)
  test_cmd_hardware.py    – CLI 硬體測試(21 項,需 --hardware)

環境需求 ​

  • Python 3.10 或更高版本(GUI 需要包含 Tkinter)
  • 為 8 個伺服馬達提供獨立的 5V 外接電源
  • 已安裝好驅動的 USB 序列匯流排適配器

安裝 ​

建議用 pip 安裝(讀取 pyproject.toml):

bash
pip install -e .

或直接安裝相依套件:

bash
pip install -r requirements.txt

開發與測試環境:

bash
pip install -r requirements-dev.txt

標定 ​

伺服馬達的角度體系、手勢預設和中位都取決於具體的機械手。這些參數全部集中在 data/config.yaml。

左右手選擇 ​

兩隻手用的伺服馬達和機械結構都不同,所以介面彈出之前先選:

text
  AmazingHand — which hand?
    1 = right hand  (servo IDs 1-8)
    2 = left hand   (servo IDs 11-18)
  Enter 1 or 2 [1]:
  LEFT hand — servo IDs 11-18
    Ring (11, 12)  Middle (13, 14)  Pointer (15, 16)  Thumb (17, 18)
    middle position raw: [571, 451, 571, 451, 571, 451, 571, 451]

跳過提問:

bash
python amazing_hand_gui.py --hand left
python amazing_hand_cmd.py --pose victory --hand left

不加 --hand 時用 data/config.yaml 裡的 hand: 值。

為什麼一隻手不只是換組 ID。 除了伺服馬達編號(右手 1-8、左手 11-18,且左手的手指編號是鏡像的 —— 無名指在前),左手還有兩處機械差異,程式都會自動處理:

右手左手
伺服馬達 ID1-811-18
手指 → ID食指 1,2 / 中指 3,4 / 無名指 5,6 / 拇指 7,8無名指 11,12 / 中指 13,14 / 食指 15,16 / 拇指 17,18
廠商 MiddlePos[451, 571, …][571, 451, …]
安裝偏移0°−35.16°(hands.left.angle_offset)
同指雙伺服馬達(a, b)(b, a)(hands.left.mirror_pose)

上述後兩項漏掉任何一個手勢都會走形:安裝偏移會讓每根手指偏 35°,少了同指互換則張開方向整個反過來(V 字手勢兩指併攏、該併攏的三指反而張開)。

data/hand_config.yaml 是左右手共用的,儲存的永遠是右手序;左手在讀取時轉換、儲存時換回。

標定一隻新手。 以 hands.left 裡的值為範本,然後按這個順序核驗:

  1. 按 Middle position,看 Current (0-1023) 那行是否讀到預期的原始值
  2. 按 Open All / Close All —— 行程應該到機械限位且不堵轉
  3. 試一個張開手勢(victory 張成 V 字、greeting 三指併攏)

哪一項不對,該調哪個參數:

現象改哪裡
Middle position 讀數不對hands.<名稱>.raw_positions.middle
張開方向反了hands.<名稱>.mirror_pose
行程不夠或過頭hands.<名稱>.raw_positions.open / close

角度體系 ​

GUI 和 CLI 都使用角度值,由 rustypot 驅動換算成伺服馬達內部的原始值:

text
raw = 1024 × angle / 300° + 511        (0.29297°/step,原始值範圍 0–1023)
角度含義
−35°完全張開(伸直)
0°中位,手指自然微屈
+75°完全握緊(拳)

每根手指的兩個伺服馬達並排、軸心共線:同向旋轉產生側擺,反向旋轉產生屈伸。偶數 ID 伺服馬達相對奇數 ID 取反,所以同一個開合值就會讓兩個伺服馬達朝相反方向運動;這一點由程式自動處理,你不需要手動換算。

限位 ​

text
limits:
  servo_min: -75      # 任何伺服馬達指令的絕對行程上下限
  servo_max: 75
  base_min: -75       # 開合滑桿範圍
  base_max: 75
  side_min: -35       # 左右滑桿範圍
  side_max: 35

side_min/side_max 控制左右張開。由於程式做了歸一化(u = |side_offset| / |side_min|),只改這個範圍不會改變實際張開幅度,只是把滑桿刻度壓縮了。要真正改變手指張開的角度,必須同時修改 auto_extremes。

原始值目標 ​

三個全域位置按鈕把伺服馬達驅動到精確的原始值,不經過角度模型:

text
raw_positions:              # 下標 0 -> 伺服馬達 ID 1 …… 下標 7 -> 伺服馬達 ID 8
  open:   [260, 760, 260, 760, 260, 760, 260, 760]
  close:  [760, 260, 760, 260, 760, 260, 760, 260]
  middle: [451, 571, 451, 571, 451, 571, 451, 571]
  • open / close —— 機械行程兩端。用廠商的 Feetech 調校工具單獨驅動伺服馬達測出來。
  • middle —— 標定後的機械中位(即廠商 Arduino 演示程式裡的 MiddlePos)。注意它不是 open 和 close 的中點,而是偏離 raw 511 約 ±60 raw(±17.6°)。

這些是每隻手各自的標定值。廠商原話是 "replace values by your calibration results"。

如何校驗: Servo Feedback 面板有一行 Current (0-1023),即時顯示原始位置。按下 Middle position 按鈕後,這一行應該讀到 451, 571, 451, 571, …。

控制項範圍速查 ​

控制項範圍
開合滑桿(縱向)−75 … +75
左右滑桿(橫向)−35 … +35
速度1(慢) … 6(快)

速度值會由驅動當作 rad/s 傳給伺服馬達,所以 1–6 大致對應 57–344 °/s。帶載後實際速度約為該值的 70% —— 排序列延時時要把這一點算進去。


執行 GUI (amazing_hand_gui.py) ​

AHC 主介面:逐指控制、全域按鈕、遙測與日誌

介面分為四塊:

  • 左欄:四根手指的逐指控制面板,含開合/側擺滑桿、Auto/Raw 模式、速度、Open/Close/Center。
  • 中欄:全域控制按鈕(Open All / Close All / Center All / Middle position)和姿態管理。
  • 右欄:遙測曲線與 Servo Feedback 回饋表(位置、負載、溫度、電壓)。
  • 底部:執行日誌與狀態列,顯示連線狀態、動作進度和錯誤資訊。

pip 安裝後可直接呼叫:

text
amazing-hand-gui
amazing-hand-gui --port /dev/ttyUSB0

或直接執行:

bash
python amazing_hand_gui.py
python amazing_hand_gui.py --port /dev/ttyUSB0

埠下拉框會列出本機實際存在的序列埠(優先使用 pyserial,沒有則讀 Windows 登錄檔),所以編號靠後的適配器也能顯示出來。下拉框可以直接手輸埠號。設定裡的預設埠沒插時,GUI 會自動從第一個真實埠啟動;想固定埠就明確傳 --port。

功能 ​

逐指控制面板:Auto/Raw 模式、速度與 Open/Close/Center 快捷按鈕

  • 逐指滑桿控制開合與左右,支援 Auto(開合 + 左右)和 Raw(直接控制兩個伺服馬達角度)兩種模式

    Auto 模式的兩個滑桿是控制軸,程式自動做差動合成;Raw 模式才是直接給兩個伺服馬達角度。每根手指的兩個伺服馬達並排、軸心共線:同向旋轉產生側擺,反向旋轉產生屈伸。

  • 逐指 Open / Close / Center 快捷按鈕

  • 逐指速度選擇(1–6),另有全域速度同步下拉框

  • 鍵盤快速鍵,便於精確微調

  • 全域位置按鈕:Open All、Close All、Center All、Middle position

  • 基於 data/hand_config.yaml 的手勢與序列管理

  • 可直接在介面上刪除已儲存的手勢(🗑 Delete 按鈕)

  • 即時伺服馬達遙測曲線(位置、負載、溫度、電壓)

  • Servo Feedback 表格,含即時原始位置(0–1023),可用於標定校驗

鍵盤操作 ​

  • 1-4:選擇手指(Ring 無名指、Middle 中指、Pointer 食指、Thumb 拇指)
  • 方向鍵:移動選中的手指
    • 上/下:握緊 / 張開
    • 左/右:左右移動
  • 修飾鍵:
    • 無:每次 1°(精調)
    • Shift:每次 5°(常規)
    • Ctrl:每次 10°(快速)
  • 快捷動作:
    • Q:選中的手指完全握緊
    • E:選中的手指完全張開
    • C:左右位置回正

全域按鈕 ​

按鈕開合左右
✋ Open All所有手指到原始值 open回正
✊ Close All所有手指到原始值 close回正
⊙ Center All保持不變回正
⊙ Middle position所有手指到原始值 middle回正

Global Speed 下拉框(1–6)會立刻把選定速度套用到所有手指控制項,並同步各指的滑桿顯示。

三個原始值按鈕(Open All、Close All、Middle position)繞過了角度模型,因此執行後滑桿顯示的是最接近的可表示值,而不是精確值。之後再碰滑桿,手會偏離原始目標最多約 0.3° —— 這是為了精確命中標定位置的刻意取捨。

已知問題:Center All 不會跳過處於 Raw 模式的手指,會覆蓋你手動設定的原始角度。單指的 ⊙ Center 按鈕則不會。


執行 CLI (amazing_hand_cmd.py) ​

獨立的命令列工具,無需啟動 GUI 即可套用手勢和播放序列。它讀取與 GUI 相同的 data/hand_config.yaml,並逐字發送儲存的姿勢值 —— 與 GUI 發出的完全一致。

Linux:序列埠權限 ​

USB 序列埠適配器通常表現為 /dev/ttyACM0(Waveshare / CDC-ACM)或 /dev/ttyUSB0(FTDI / CH340)。

查找方式:

bash
ls /dev/ttyACM* /dev/ttyUSB* 2>/dev/null
# 或者
dmesg | grep -E 'ttyACM|ttyUSB' | tail -5

如果報 Permission denied,把目前使用者加入 dialout 群組後重新登入:

bash
sudo usermod -aG dialout $USER

pip 安裝後 ​

text
amazing-hand-cmd --list
amazing-hand-cmd --pose open
amazing-hand-cmd --sequence demo --loop
amazing-hand-cmd --pose open --speed 6
# 需要時覆蓋序列埠:
amazing-hand-cmd --pose open --port /dev/ttyUSB0

直接執行 ​

bash
python amazing_hand_cmd.py --list
python amazing_hand_cmd.py --pose open
python amazing_hand_cmd.py --pose close --speed 6
python amazing_hand_cmd.py --sequence demo
python amazing_hand_cmd.py --sequence wave --loop
python amazing_hand_cmd.py --port /dev/ttyUSB0 --pose open
python amazing_hand_cmd.py --list --config /path/to/hand_config.yaml

參數 ​

參數預設值說明
--pose NAME–套用指定名稱的手勢
--sequence NAME–播放指定名稱的序列
--list–列出所有手勢與序列
--loop關循環播放序列,直到 Ctrl+C
--speed N3伺服馬達速度 1(慢)… 6(快)
--port PORTLinux /dev/ttyACM0
Windows COM9
序列埠的埠號
--baudrate N1000000鮑率
--config PATHdata/hand_config.yaml指定其他設定檔
--handconfig.yaml 的 hand指定使用哪隻手(右手 1-8,左手 11-18)

腳本結束時(包括 Ctrl+C)會自動關閉所有伺服馬達的力矩。

CLI 沒有對應 data/config.yaml 的 --config 參數,該檔案始終從專案目錄載入。


設定檔 ​

data/config.yaml ​

段落用途
serial各平台預設序列埠、鮑率、可選鮑率列表
servos每根手指對應的伺服馬達 ID
limits伺服馬達與兩個滑桿的角度範圍
speeds1–6 速度刻度的預設值/最小/最大值
auto_extremes左右滑桿到極限時的伺服馬達位置
raw_positions全域位置按鈕的精確原始值目標
paths手勢/序列檔案的位置

伺服馬達與手指的對應關係 ​

手指伺服馬達 ID姿勢陣列下標
Pointer 食指1, 24, 5
Middle 中指3, 42, 3
Ring 無名指5, 60, 1
Thumb 拇指7, 86, 7

姿勢陣列的順序是 無名指、中指、食指、拇指,不是按伺服馬達 ID 排列。 手動編輯 hand_config.yaml 時這是最容易搞錯的一點。

amazing_hand_cmd.py 頂部的註解寫著 "index 0→servo1 … 7→servo8",那個註解是錯的,上表才是程式的真實行為。


手勢與序列 ​

姿態管理面板

所有手勢和序列都儲存在 data/hand_config.yaml。檔案不存在時 GUI 會自動建立。

儲存手勢 ​

  1. 用滑桿或鍵盤把手擺到目標姿勢
  2. 在 "Name:" 輸入框填入名稱
  3. 點擊 Pose Management 區域的 "➕ Add New"

速度只影響滑桿的移動快慢;儲存的手勢只記錄 8 個伺服馬達位置。

載入 / 刪除手勢 ​

  • 從下拉框選擇後點擊 ✓ Apply 讓手移動到該姿勢
  • 點擊 Apply 右側的 🗑 Delete,確認後永久刪除

序列管理 ​

  1. 在 Sequence Player 中點擊 "🔧 Manage" 開啟序列管理器
  2. Saved Sequences(左欄)
  • 檢視、執行、編輯或刪除已有序列
  • 雙擊或點擊 "▶ Execute" 執行一次
  1. Sequence Builder(右欄)
  • 雙擊 "Available Poses" 中的手勢即可加入為一步
  • 可為每一步單獨設定 8 個伺服馬達的速度和延時;步驟以 "pose:s1,s2,...,s8|delay" 形式儲存
  • 用 ↑/↓ 調整順序,或用 "⏱ Delay" 按鈕插入獨立暫停
  • 填好名稱後點擊 "💾 Save Sequence" 儲存;點 "▶ Execute" 可先試跑不儲存
  1. 回到主視窗,需要連續播放時勾選 Sequence Player 裡的 Loop

序列編輯器

步驟格式 ​

text
pose_name:speed1,speed2,...,speed8|delay
  • speed1..speed8 —— 按姿勢順序排列的 8 個伺服馬達速度(1–6)
  • delay —— 距離下一步的等待時間,如 0.6s。可省略;省略時 GUI 會退回到固定的自動等待
  • 獨立暫停寫作 SLEEP:1.0s(沒有逗號分隔的速度列表)

延時的選取。 驅動本身能讀到達伺服馬達是否停止,但序列播放用的是固定延時。大致按 行程角度 / (速度 × 57.3 × 0.7) 秒來估算,並留出餘量 —— 在帶載的手上,超過約 130° 的動作在速度 3 下需要 1.0 秒以上。

YAML 格式範例 ​

text
poses:
  open:
    positions: [-35, -35, -35, -35, -35, -35, -35, -35]
  close:
    positions: [75, 75, 75, 75, 75, 75, 75, 75]
  ring_close:                 # 無名指握緊,其餘張開
    positions: [75, 75, -35, -35, -35, -35, -35, -35]

sequences:
  demo:
    steps:
      - "open:3,3,3,3,3,3,3,3|2.0s"
      - "close:6,6,6,6,6,6,6,6|2.0s"
      - "ok:3,3,3,3,3,3,3,3|1.0s"
      - "victory:3,3,3,3,3,3,3,3|1.0s"
      - "greeting:3,3,3,3,3,3,3,3|1.5s"
      - "close:6,6,6,6,6,6,6,6|2.0s"
  wave:
    steps:
      - "open:6,6,6,6,6,6,6,6|0.8s"
      - "wave_r:5,5,5,5,5,5,5,5|0.6s"
      - "wave_l:5,5,5,5,5,5,5,5|0.6s"
      - "open:5,5,5,5,5,5,5,5|0.8s"
  finger_roll:
    steps:
      - "open:6,6,6,6,6,6,6,6|0.5s"
      - "ring_close:5,5,5,5,5,5,5,5|0.6s"
      - "open:5,5,5,5,5,5,5,5|0.5s"
      - "middle_close:5,5,5,5,5,5,5,5|0.6s"
      - "open:5,5,5,5,5,5,5,5|0.5s"

循環播放由執行時控制(GUI 的核取方塊),不再寫入 YAML。


測試 ​

專案包含 284 項單元/整合/系統測試,以及 54 項硬體測試。

執行全部測試(無需硬體) ​

text
pytest

執行 GUI + CLI 硬體測試(需要連接伺服馬達) ​

text
pytest tests/test_system_hardware.py --hardware --port /dev/ttyACM0
pytest tests/test_cmd_hardware.py --hardware --port /dev/ttyACM0
# 或兩個一起:
pytest tests/test_system_hardware.py tests/test_cmd_hardware.py --hardware

test_system_hardware.py 驗證連線、手勢套用、遙測讀取、單指張合/揮手、速度控制、序列執行與運動偵測。

test_cmd_hardware.py 端到端驗證 CLI 層:姿勢位置、速度參數、序列步驟、wait_for_motion、--list 輸出,以及結束時關閉力矩。

完整的驗收標準見 驗收需求與測試。

注意:非硬體測試斷言的是 hand_logic.py 裡的兜底預設值,那套預設值仍是原版的 −40…110 尺度。執行時 data/config.yaml 會覆蓋它們,所以無論你怎麼標定,測試都能通過 —— 但也意味著測試並不會校驗你目前的標定參數。


伺服馬達 ID 設定 ​

用 Feetech 官方軟體配合序列匯流排驅動設定伺服馬達 ID 的教學: https://www.robot-maker.com/forum/tutorials/article/168-brancher-et-controler-le-servomoteur-feetech-sts3032-360/

Feetech 軟體下載: https://github.com/Robot-Maker-SAS/FeetechServo



遙測與回饋 ​

  • 指標選擇:位置、負載、速度、溫度、電壓、運動旗標。
  • 圖表模式:Multi-Servo(多伺服馬達曲線)與 Scope(單通道示波器)。
  • 縮放/平移:Y Zoom / Pan、Time Zoom / Pan。
  • 回饋表:Goal、Position、Speed、Load、Voltage、Temperature、Status、Moving。

遙測曲線

伺服馬達回饋表

序列編輯器 ​

  1. 在 Sequence Player 中點擊 Manage。
  2. 用 Available Poses 新增步驟,調整逐指速度、步驟延時或插入休眠。
  3. 用 ↑/↓ 調整順序,輸入名稱儲存;也可先 Execute 試運行。
  4. 回到主視窗選擇序列並 Play;啟用 Loop 連續播放。

序列定義位於 data/hand_config.yaml 的 sequences 鍵下。

疑難排解 ​

現象建議
未列出序列埠重新插拔 USB 適配器、安裝驅動或重新啟動 GUI。
Connect 按鈕變灰已連線,先點 Disconnect。
調整視窗卡頓關閉不必要視窗;resize 已做防抖/限流。
序列未驅動所有手指檢查每步速度,確保每個姿態包含全部 8 個伺服馬達值。
阻塞指示持續檢查機械卡阻;目標與實際位置差異大且無運動會觸發阻塞。

相關開發文件 ​

致謝 ​

原始專案:Betatester777 硬體與參考韌體:Pollen Robotics