MANUAL 01 · 新手篇 · LEARN NOTES

收进学习手册 · 2026-09-11 · duck.whatled.com

Microduck 新手上手指南

这是一份给硬件、电路、机械、机器人都刚入门的人的路线图。它按当前
F:\microduck 仓库写,不假定你已经买齐零件。

先给结论

你现在最适合走这条顺序:

先看懂软件和仿真
  → 识别手里的舵机
  → 用树莓派做一个安全的单舵机台架
  → 让 Radxa 只跑软件,不接未知硬件
  → 买/借一只与项目协议匹配的总线舵机做通信实验
  → 最后再做整机、电源、IMU 和步态

当前仓库能直接教你的,是运行时、通信协议、控制闭环、仿真模型、部署脚本和排错方法。
仓库当前没有完整的鸭子原理图、PCB 工程、机械 CAD 装配包或 BOM;kicad-mcp-test/
是 KiCad 路由测试夹具,不是鸭子的电子板。因此,不要把文档中提到的“官方 HAT”、
“imu_to_dxl”或外部复刻仓的图纸当成已经随本仓库提供的文件。

你的第一个目标不是“马上走起来”,而是完成四个可验证的小目标:

  1. 能画出控制数据流;
  2. 能分清 PWM 舵机和总线舵机;
  3. 能用万用表和限流电源安全点亮一只舵机;
  4. 能在没有真机的情况下跑通本仓库的测试和 robotd --fake。

1. 这是什么项目

Microduck 是一只小型双足机器人。它不是用程序逐帧写死“左脚抬起、右脚落下”,而是把
姿态和关节状态输入神经网络,让网络每个控制周期给出关节目标。

当前代码里的最重要数字:

数字 在项目里的含义 代码出处
15 5 个左腿关节 + 5 个颈/头/嘴关节 + 5 个右腿关节 duck-control/src/model.rs
14 步态策略控制的关节数;嘴巴被排除 MOUTH_INDEX = 9
61 → 14 策略输入 61 个观测,输出 14 个动作 docs/design/robotd-design.md
50 Hz 每 20 ms 读传感器、推理、写目标 robotd 控制循环
1 Mbps Dynamixel 协议 V2 总线的波特率 BAUD_RATE
200 IMU 转接板在总线上的设备 ID IMU_DXL_ID

把它想成一个闭环:

身体姿态 + 关节反馈
        ↓
    61 个观测
        ↓
    ONNX 策略
        ↓
    14 个关节目标
        ↓
    舵机和机械结构
        ↓
    真实运动再次变成反馈

当前仓库的目录地图

目录 新手先把它理解成什么
robotd/ 主控制进程:控制循环、状态机、JSON-RPC 服务
duck-control/ 硬件抽象:总线、IMU、观测、策略、安全层
kinematics/ MJCF 模型、正向运动学、头部/手部几何
odometry/ 根据脚和 IMU 估计机器人位移
robotctl/、duckctl/ 命令行控制工具;先不急着改
padd/ 手柄输入转换成机器人意图
tof/、mediad/、sounds/ 深度、相机/媒体、声音;运动闭环前可暂缓
configd/、btd/、updater/ 网络、蓝牙、升级;属于系统运维层
docs/course/ 面向学习的课程草稿
docs/deep-dive/ 对控制、电源、协议和结构的深入笔记
scripts/ 在 Radxa 上配置系统、部署和测试的脚本
kicad-mcp-test/ KiCad 测试夹具,不是鸭子的真实电路板

第一遍只读这四个文件:


2. 先认识你手里的东西

Radxa Zero 3W

它是 Linux 主控,适合运行本仓库的 Rust 守护进程。部署脚本针对 Radxa Zero 3 / RK3566
这一类板子,默认电机串口是 /dev/ttyS2。这块板不是舵机电源,也不是把舵机插进
USB 就能工作的“万能转接板”。

没有电机和 IMU 时,Radxa 可以先做两件事:

  1. 刷系统、SSH 登录、学习 Linux;
  2. 运行假总线模式、编译和测试软件。

真正接电机之前,先读 开发板安装。不要在 Windows 终端里直接运行
setup-board.sh;这些脚本应在目标 Radxa 上执行,或由 provision-board.sh 通过 SSH
执行。

3D 打印外壳件

它们目前只是“待验收的机械零件”,不能因为外形像鸭子就假定与项目模型完全匹配。仓库里
可核对的机械来源是 MJCF 模型,不是一套可直接
打印的 CAD 装配包。

到手后的顺序:

  1. 给每个零件编号并拍照;
  2. 用游标卡尺量舵机腔、轴孔、螺丝孔和板卡空间;
  3. 不装电机,先用螺丝和轴承做“干装配”;
  4. 记录哪些孔过紧、哪些轴线不平行;
  5. 只改一个尺寸,再打印一个小测试件。

不要先把未知舵机硬塞进壳体。舵机的外形、安装孔、输出轴方向和重量都会改变结构。

机器狗舵机

先不要猜型号。拍清楚铭牌、插头和线色,量一只的重量,记录:

观察项 可能是 PWM 舵机 可能是总线舵机
接线 3 线:信号、正极、地 3 线总线或专用插头,常有 DATA 标识
控制方式 一只舵机占一个 PWM 信号脚 多只舵机共用一条数据总线,每只用 ID 区分
反馈 通常不能读真实位置 通常能读位置、电压、温度
现在能否接本项目 只能做 PWM 学习台架 还要核对协议、电压、尺寸和控制模式

如果不能确认型号和额定电压,就不要上电。项目的 duck-control 明确按 Dynamixel
XL330 协议、ID 和寄存器工作;“能转”不等于“能被本项目控制”。

小智 ESP32 硬件

当前仓库没有 xiaozhi-esp32/ 目录,也没有现成的小智协议适配器。因此它现在是一个
独立语音项目,不是 Microduck 的即插即用模块。

正确的接入顺序是:先让鸭子本地动作稳定,再设计一条明确的接口,例如:

ESP32 识别“坐下” → 串口/Wi‑Fi 发一个高层命令 → robotd → 安全层 → 动作

不要让 ESP32 直接抢占舵机总线;总线必须由 robotd 单一拥有。

树莓派 Pi 2 Model B

Pi 2 可以当作低成本的 PWM 实验台或 Linux 练习机。它没有本项目所需的官方控制栈,也
不能替代 Radxa 的 ARM 主控。它没有板载 Wi‑Fi,联网通常要插网线。

Pi 2 做 PWM 实验时,只有在数据手册确认舵机额定为 5–6 V 后,才使用独立、限流的
5–6 V 电源;不能从 Pi 的 5 V 脚给多只舵机供电。总线舵机要按自己的数据手册供电,不能
套用这个电压。信号地必须共地。当前仓库没有 Pi PWM 台架脚本,所以不要把某个外部教程
里的脚本路径当成仓库文件。


3. 十个必须先懂的概念

  1. 舵机:带齿轮和控制器的电机总成。你给目标,它负责转到目标。
  2. PWM 舵机:靠脉冲宽度控制,一只一根信号线,通常没有位置反馈。
  3. 总线舵机:多只设备共用数据线,靠 ID 寻址,可以读回位置等状态。
  4. UART:串行通信接口;项目用它连接舵机总线。
  5. 半双工:同一根数据线既发送又接收,但同一时刻只能一个方向说话。
  6. IMU:陀螺仪和加速度计,用来知道身体是否倾斜、正在怎样运动。
  7. 观测:网络看到的数字;本项目的 alpha 策略是 61 维。
  8. 动作:网络输出的关节目标;本项目的步态策略输出 14 个数。
  9. 推理:使用已经训练好的 ONNX;不等于重新训练神经网络。
  10. sim2real:把仿真里的策略迁移到真机;仿真能走不代表真机一定能走。

最重要的区分是:PWM 和总线不是“便宜版与贵版”的区别,而是系统接口不同。没有
反馈的 PWM 舵机不能直接满足当前 61→14 的闭环假设;它仍然非常适合拿来学供电、脉冲和
机械负载。


4. 控制代码如何对应硬件

打开 duck-control/src/model.rs,你会看到当前运行时的硬件契约:

左腿:ID 20 21 22 23 24
颈/头/嘴:ID 30 31 32 33 34
右腿:ID 10 11 12 13 14
IMU 转接板:ID 200

这不是建议值,而是代码查找设备时使用的地址。舵机顺序也不能随意交换,因为数组下标
同时决定了关节名字、观测位置和写入目标。

这里显示的是原版 XL330/Dynamixel 路线的 ID。你现在使用 HL-2915-C001 时,现场台架和
HL 后端暂时采用另一套更容易管理的编号:第一只设为 ID=1,第二只设为 ID=2,完整 15 只
时再按关节顺序使用 ID=1..15,IMU 仍保留 ID=200。不要把上面的 10/20/30 直接写给
HL-2915;也不要在只有两只舵机时启动要求 15 只设备的 robotd。

duck-control/src/bus.rs 展示了一次控制周期做什么:

一次 sync_read:读 IMU + 15 只舵机
一次策略推理:观测 → ONNX → 14 个动作
一次 sync_write:写 15 个目标(嘴巴位置单独处理)
每秒一次:读电压和温度

robotd 还规定了三个很重要的安全行为:

这就是为什么你的 ESP32、手柄、浏览器和语音程序都应该发高层意图,而不是自己向
串口写舵机包。阅读顺序建议是:

  1. duck-control/src/model.rs:设备、ID、HOME 姿态;
  2. duck-control/src/bus.rs:总线读写;
  3. robotd/src/control.rs:观测、策略、目标;
  4. duck-control/src/safety.rs:最后一道安全边界;
  5. docs/design/robotd-design.md:把上述文件串成一张图。

5. 小白如何看懂电路图

5.1 先接受当前仓库的限制

当前仓库没有 Microduck 完整的原理图 PDF。你能可靠读取的是软件对硬件的接口假设:

Radxa UART (/dev/ttyS2)
        │ 1 Mbps,Dynamixel Protocol V2
        ▼
单线 TTL 半双工总线
   ├─ IMU 板,ID 200
   └─ 15 个总线舵机,ID 10–14 / 20–24 / 30–34

供电部分不能从 Rust 代码“脑补”出来。代码能读到舵机报告的总线电压,但电池、保险丝、
降压器、插座和 PCB 具体怎么连,必须以你手里真实的板卡和舵机数据手册为准。

5.2 原理图与 PCB 图的区别

不要把原理图里的线条位置当成真实物理走线;同名网络(例如 GND、SDA、SCL、
UART_TX)才是电气连接的关键。

5.3 通用五步读图法

拿到任何一张图,按这个顺序:

  1. 找电源入口:输入电压是多少,正负极在哪里;
  2. 找 GND:所有模块是否有共同参考地;
  3. 找主控:哪颗 MCU/SoC,电源脚是否有去耦电容;
  4. 沿信号走:UART、I²C、SPI、PWM 分别连到谁;
  5. 看保护:保险丝、反接保护、TVS、限流和急停在哪里。

对每个连接器写一张小卡片:

连接器 J?
1: GND
2: 电源(多少伏,谁提供)
3: DATA / TX / SDA(方向是什么)
4: 未使用或保留

这样比一上来认电阻、电容的符号更有效。先知道“电从哪来、数据往哪走”,再研究元件值。

5.4 你第一次该画的草图

先不要画 PCB,只用纸画四个框:

[电池/电源] ──> [舵机供电总线] ──> [15 个舵机]
                       ▲
                       │ DATA(半双工)
[Radxa UART] ──────────┘
      │
      ├─ [IMU 总线设备 ID 200]
      └─ [上层软件、网络、语音命令]

在图旁边标出三个“未知项”:舵机额定电压、总线转接/方向切换电路、Radxa 与电源的共地
方式。未知项没有数据手册前不要填数字;这正是工程记录的一部分。

深入阅读顺序:

这些是解释性笔记,不是你当前硬件的接线批准书。真正上电仍以实物手册和万用表测量为准。


6. 小白如何看懂和设计结构

6.1 先看运动链,再看外壳

打开 robot_walk.xml,先只找 body、joint、
inertial 三类标签:

trunk_base
├─ 左腿:left_hip_yaw → left_hip_roll → left_hip_pitch → left_knee → left_ankle
├─ 颈头:neck_pitch → head_pitch → head_yaw → head_roll
└─ 右腿:right_hip_yaw → right_hip_roll → right_hip_pitch → right_knee → right_ankle

这份 MJCF 是仿真模型,不是可直接打印的 CAD。它能告诉你运动链、坐标系、质量和关节
范围,不能告诉你螺丝怎么拧、打印件能否承受冲击。

6.2 结构设计的最小方法

每做一个零件,按这七问检查:

  1. 它固定谁、允许谁动?
  2. 旋转轴线在哪里?左右是否对称?
  3. 舵机输出轴和外壳是否有硬限位?
  4. 螺丝受的是拉力、剪切还是反复振动?
  5. 轴承是否承担了侧向载荷,而不是让舵机输出轴硬扛?
  6. 电线有没有弯折半径、夹线和可拆空间?
  7. 维护时能不能只拆一层,而不是拆完整只鸭子?

6.3 你的打印件验收流程

不要直接打印或装完整机器。先做一个“最小闭环”:

量舵机 → 量打印腔体 → 空装 → 单关节手动活动 → 单舵机低负载 → 再扩大

验收记录至少包括:

项目 记录什么
外形 长、宽、高,是否翘曲
孔位 螺丝能否顺利穿过,是否需要修孔
轴线 两个关节轴是否平行/垂直
刚度 手捏、轻推时是否明显变形
走线 线会不会碰转动件或被夹住
维护 能否取出舵机、电池和控制板

打印公差没有一个对所有打印机都正确的数字。先打测试片,再根据测量结果调整;不要把
网上的“统一补偿 0.2 mm”直接套用。

6.4 换舵机为什么会牵动结构和训练

舵机变化会同时影响:

所以机器狗舵机最多先用来学台架。不要期待“把同样数量的舵机塞进去”就能直接运行官方
步态策略。


7. 现在就能做的学习路线

第 0 阶段:不通电,建立地图

按下面顺序读,每篇只写三句话笔记:它解决什么问题、输入是什么、输出是什么。

  1. 第 00 课:这只鸭子是什么
  2. 第 01 课:浏览器仿真
  3. 第 02 课:十个必懂概念
  4. 第 04 课:61 到 14
  5. 第 08 课:看懂电路图
  6. 第 09 课:3D 打印测试片

验收标准:你能不看文档解释“摇杆为什么不是直接控制某一只腿”。

第 1 阶段:在电脑上验证软件

先确认 Rust 版本满足仓库的 rust-version = "1.89",再在开发机上运行:

cargo test
cargo test -p kinematics

如果报 requires rustc 1.89,不是项目代码坏了,而是本机工具链太旧;先用 rustup
安装 1.89 或更新版本,再重跑。

这两步不需要 Radxa、不需要舵机,也不需要电池。然后阅读 测试和仿真部署说明。

如果想观察运行时而不接总线,可以编译后使用 robotd --fake;它的意义是“没有总线、
没有真实机器人”,不是模拟一个完整的物理世界。命令帮助以当前代码为准:

cargo run -p robotd -- --help

验收标准:测试通过,并能说清“假总线测试”和“MuJoCo 物理仿真”的区别。

第 2 阶段:用 Pi 2 学一只 PWM 舵机

只有在你确认舵机型号和额定电压后再做:

  1. Pi 2 刷 Raspberry Pi OS,插网线,先只练 SSH;
  2. 准备独立的、带限流的 5–6 V 电源;
  3. 信号线接一个 GPIO,电源正负接外部电源,Pi 与外部电源共地;
  4. 只接一只、只做小角度动作;
  5. 观察堵转、电压下跌、重启和发热。

这阶段的学习目标不是做鸭子,而是亲手体会:PWM 舵机通常没有真实位置反馈,外力把轴
掰走后,程序并不知道。

验收标准:能安全地让一只舵机来回小角度运动,能解释为什么电源不能取自 Pi 的 5 V 脚。

第 3 阶段:让 Radxa 只跑软件

在 Radxa 上按 install-dev.md 做系统安装,重点观察:

没有总线硬件时,先不要追求 robotd 健康通过;使用 --fake 和单元测试学习软件路径。

第 4 阶段:一只总线舵机的实验

如果你的机器狗舵机经确认是 Dynamixel/Feetech 一类总线舵机,再购买或借一个匹配的 USB
调试器,并且只接一只。验证顺序:

  1. 查数据手册的额定电压、协议、电平和默认波特率;
  2. 独立给舵机供电,调试器只负责通信;
  3. 万用表测电源正负和空载电压;
  4. 扫描、读取位置、电压、温度;
  5. 只有确认通信稳定后,才改 ID;
  6. 改 ID 后断电、贴标签、回读确认。

对于当前项目,代码使用 1 Mbps、Dynamixel Protocol V2 和分段 ID。Feetech 或其它协议
需要适配层,不能只改一个 ID 就当成兼容。

第 5 阶段:整机前的硬件门槛

满足以下条件前,不要上官方步态:


8. 第一个月计划

第 1 周:只学习和盘点

第 2 周:Pi 2 和结构干装

第 3 周:Radxa 软件

第 4 周:决定是否进入总线阶段


9. 上电和调试安全卡

每次上电前逐项打勾:

出现以下任意现象,立刻断电:异常嗡鸣、快速发热、反复重启、冒烟、明显卡死、电源压降
过大。先断电,再查线;不要带电“试一下”。

robotd 正在运行时,不要同时用另一个程序或 USB 调试器打开同一条电机总线。需要做底层
扫描时,先停掉占用总线的服务,并确认没有 serial-getty 抢占 /dev/ttyS2。


10. 常见误区

误区 正确理解
“Radxa 有 GPIO,所以能直接带舵机” GPIO 只表示信号能力,不代表电源、电平、协议和保护都匹配
“舵机能转,就能跑官方模型” 还要匹配反馈、协议、尺寸、质量、齿隙、增益和电压
“3D 打印件外形一样就能装” 轴线、孔位、限位、刚度和走线空间都要实测
“先把 15 只都接上,再慢慢改 ID” 出厂同 ID 的总线设备会互相抢答;总线阶段一次只接一只未配置设备
“把 ESP32 直接接到舵机总线更简单” 会破坏单一总线所有者和安全层;ESP32 应发高层命令
“仿真里能走,真机只要调个速度” 真机还会遇到电压、延迟、摩擦、回差、装配误差和跌倒
“先买齐再研究” 先做便宜、可逆的验证;每个采购都由上一个门槛解锁

11. 下一步该读什么

目的 当前仓库里的文件
看全局 README、architecture.md
学控制闭环 robotd-design.md、第 04 课
学电路思路 电控架构、电源树、半双工总线
学协议和 ID 舵机协议、ID 与模式
学结构 MJCF 模型、kinematics/src/
学 Radxa 开发板安装、手工安装
学日常命令 robotctl cheat sheet
学仿真/训练 进阶学习文档、学习工具(工作区文件)
评估更便宜舵机 低成本舵机替换决策表(工作区文件)
学排错 第 07 课、testbench 验证

读代码时的一条捷径

遇到一个新模块,不要从第一行顺读。先回答四个问题:

  1. 它读什么输入?
  2. 它输出给谁?
  3. 它是否能直接写电机?
  4. 出错时是停、保持、降级,还是继续运行?

能回答这四个问题,就已经是在读机器人系统,而不只是读 Rust 语法。

最后记住:你现在不需要同时学会电路、机械、Rust、Linux 和强化学习。每次只验证一个小
闭环,并记录“接了什么、测到了什么、下一步是什么”。这比一次打印整机、一次接满 15
只舵机更快,也更安全。


12. 已确定使用 HL-2915-C001 时的复刻路线

这一节专门针对飞特 HL-2915-C001。它不是 XL330 的直接替换件,而是一套新的执行器适配。

装机主线更新:当前 15 只装机舵机是 4–8.4 V 的 HD-1910-C001(2S 母线友好),不是
本节的 12 V HL-2915。接线、只读探针、官方关节 ID 表与标定门控见
URT2 + HD-1910 接线、组装与测试指南;
仿真侧的参数迁移与训练见HD1910 仿真迁移与 PPO 训练教程。
本节的"协议适配层 + 逐任务验收"方法两者通用,但电压、线序、模式和寄存器不能互套。

12.1 先把型号资料钉死

下面是根据飞特 HL-2915-C001 官方产品页、2026-01-18 规格书和磁编码内存表整理的工作表。
实物标签和随货最新版手册仍然优先;同系列其他型号不能直接替代 C001 的电压、电流或寄存器单位。

官方 HLS 产品列表把 C001 的默认 Mode 0 列为 0–360°绝对位置控制,因此它不是普通的连续旋转
PWM 舵机;但本项目仍需要以随货手册确认位置模式、回读单位和目标位置地址。确认前只运行
Ping/只读命令,不要运行 --move-center 或摆锤记录器。如果实物固件与资料不一致,先停在协议
适配层,不能靠软件把它伪装成位置舵机。

项目 HL-2915-C001
工作电压 9–14 V,典型 12 V
堵转扭矩 14.2 kg·cm @ 12 V
空载电流 160 mA @ 12 V
堵转电流 1.5 A @ 12 V
额定电流 500 mA @ 12 V
官方过热保护 规格书写 80 °C;内存表的默认温度限制可能不同,第一次台架仍采用更保守的软件门槛
外形 34 × 20 × 23 mm
重量 27.8 ± 2 g
输出轴 25T,外径 4.95 mm
位置 0–4095,中心 2048,0.088°/步
接头 PH1.25-3P:1=GND,2=Vcc,3=Signal/TTL
默认 ID 1
默认波特率 1 Mbps
信号电平 高电平 2–5 V,低电平 0–0.45 V

资料入口:

先分清两颗 IMU:官方 Robot HAT 上的 BMI088 走 I²C,当前步态不用它;控制闭环使用另一块
imu_to_dxl 板,通过 Dynamixel Protocol v2 占用 ID 200。看到 BMI088 不代表步态 IMU 已通过。
如果暂时只有 imu_to_dxl、还没有 15 只舵机,可先用仓库里的 imu_probe 单独验收 ID=200:

cargo run -p duck-control --bin imu_probe -- /dev/ttyUSB0 --watch-seconds 10

它只读取 IMU,不启动 robotd,也不会给舵机上扭矩。

两只 HL-2915 和 IMU 已经接到同一个半双工串口后,用混合探针验证协议切换:

cargo run -p duck-control --bin hl2915_mixed_probe -- /dev/ttyUSB0 1 2 --watch-seconds 60

最后一行必须同时满足 samples>=25、errors=0、imu_ready=true、
0 <= max_stale_run <= stale_imu < samples、max_stale_run < 25,以及四项舵机故障计数都是 0;
旧日志没有 max_stale_run 时必须用当前探针重跑,不能人工补字段;
只要出现欠压、过热、接近堵转或舵机状态故障,混合探针也会返回失败,不可继续启动整机。

这仍然是只读台架程序;完整 robotd 需要 15 只 HL-2915 和完成关节标定。

第一次接线应以 HL-2915-C001 的产品参数表、实物标签和卖家确认结果为准,先用 12 V 限流电源,
不要照抄通用接口图,也不要因为同系列型号写了其他电压就擅自放宽保护范围。仓库探针里的
9–14 V、55 °C、1.4 A 是保守的项目台架门槛:55 °C 低于官方过热保护值,1.4 A 低于约 1.5 A
堵转电流,目的是在第一次空载测试时宁可误停也不把舵机推到保护边缘。确认到实物固件和测试数据后,
再单独修改门槛和测试。

12.2 通信寄存器速查

飞特协议包格式是:

FF FF | ID | Length | Instruction | Parameters... | Checksum

校验:Checksum = ~(ID + Length + Instruction + Parameters) & 0xFF。

HL-2915-C001 磁编码内存表中,复刻最先需要这些地址:

地址(十进制) 含义 长度 用途
5 ID 1 逐只设置唯一 ID
6 Baud Rate 1 0=1 Mbps,其余值按内存表映射
40 Torque Enable 1 0=关闭,1=打开,128=当前位置设为 2048
42 Goal Position 2 目标位置
46 Goal Speed 2 目标速度
48 Goal Torque 2 目标扭矩
56 Present Position 2 实际位置
58 Present Speed 2 实际速度;HLS 内存表按约 0.732 RPM/计数换算,收到的型号内存表优先
60 Present Load 2 实际负载;HLS 磁编码表通常用 bit10 表示方向、bit0..9 表示幅值,原始值不要直接当百分比
62 Present Voltage 1 单位 0.1 V
63 Present Temperature 1 单位 °C
65 Status 1 过载、温度、电压、舵机异常
66 Moving 1 是否运动
69 Present Current 2 单位约 6.5 mA/计数

磁编码协议支持:PING=0x01、READ=0x02、WRITE=0x03、SYNC_READ=0x82、
SYNC_WRITE=0x83。协议示例用从地址 56 读取 8 字节,一次拿到位置、速度、负载、电压、
温度。这正好可以替代当前项目 XL330 的连续寄存器读取,但地址和数据单位不能照搬。

12.3 复刻任务清单

第一次实际通电前,先完整阅读URT2 + HL-2915 接线、组装与测试指南,
实际操作时使用两只舵机现场验收表(工作区文件),边操作边记录电源、ID、
温升、通信错误和 CSV 路径;不要只保存终端里最后一行输出。

Task HL2915-001:单舵机资料确认

Task HL2915-002:单舵机台架通信

Task HL2915-003:替换底层总线驱动

Task HL2915-004:重做供电和线束

Task HL2915-005:打印一个关节适配件

Task HL2915-006:一条腿和动力学辨识

Task HL2915-007:整机、悬空、落地

12.4 现有硬件的分工

第一步只做 HL2915-001:拿到官方内存表,买一只舵机和调试器,完成单舵机 PING/读写。
没有这个结果,不进入打印整机、批量买舵机和训练策略。


13. 两只 HL-2915-C001 的实际落地步骤(代码已放入仓库)

本仓库现在已经有一个“只做台架验证”的最小程序:

13.1 先准备硬件

你至少需要:两只 HL-2915-C001、一个支持单线半双工 TTL 的 Feetech 调试器(本项目使用官方 FE-URT-2/FE-URT2-C001)、
一个可限流的 12 V 电源、万用表和一根 USB 线。Radxa 的 5 V 电源不能直接接到舵机 Vcc,
树莓派和小智 ESP32 也先不要接舵机总线。

URT2 的 USB-C 只负责给调试器逻辑供电并建立 COM 口;舵机电源接 TTL 侧 G/V1,HL-2915
接 TTL-Bus,不要接 RS485 侧 V2。完整接线和 FD 首次调试顺序见
两只舵机现场验收表(工作区文件)。

舵机 PH1.25-3P 的线序按官方资料核对:

1 = GND(电源负极、调试器 GND、Radxa GND 共地)
2 = Vcc(先用 12 V,限流)
3 = Signal/TTL(调试器的半双工数据线)

两只新舵机通常都为 ID=1。因此,第一次不能把两只同时接上,否则它们会同时回答同一个
ID,通信必然冲突。

13.2 在电脑上先测第一只

在仓库根目录打开 PowerShell。把 COM3 换成调试器在设备管理器显示的端口:

Get-CimInstance Win32_SerialPort | Format-Table DeviceID,Caption
cargo test -p duck-control hl2915
cargo check -p duck-control --bin hl2915_probe
cargo run -p duck-control --bin hl2915_probe -- COM3 1

最后一条命令的默认行为是:打开 1 Mbps、Ping ID 1、读取位置/速度/负载/状态/运动标志/电流/电压/温度,然后退出。
看到 响应=[1] 才算通信链路成立。若报“没有响应”,先断电,再按 GND/Vcc/Signal、12 V、ID、
半双工转接器顺序排查;不要先改程序。

13.3 给第二只改成 ID=2

只接第二只舵机(第一只必须断开),仍然使用它出厂的 ID=1:

cargo run -p duck-control --bin hl2915_probe -- COM3 1 --set-id 2

程序只在显式写出 --set-id 时改 EEPROM。看到成功提示后,给舵机断电再上电,然后验证:

cargo run -p duck-control --bin hl2915_probe -- COM3 2

必须看到 响应=[2]。如果没有,停止继续接线,重新只接这一只并检查供电;不要用广播命令“碰运气”。

13.4 两只一起做只读验证

确认一只 ID=1、另一只 ID=2 后,才把两只并联到同一条 12 V/GND/Signal 总线:

cargo run -p duck-control --bin hl2915_probe -- COM3 1 2

预期输出中 响应=[1, 2],并各有一行状态。这个步骤只读,不会让两只舵机转动;建议先连续运行
几次并记录电压和温度。

要做第一轮稳定性验收,可以让程序连续只读 10 分钟:

cargo run -p duck-control --bin hl2915_probe -- COM3 1 2 --watch-seconds 600

它每 100 ms 读一次,遇到一次读错误会记录并继续,结束时以非零状态退出;因此可以把它当作
“两只舵机通信是否稳定”的自动门槛。没有错误时应看到 errors=0,并记录 min_voltage 和
max_temperature;如果出现非零 status、电压不在 9–14 V、温度达到 55°C 或电流达到约
1.4 A,程序也会以非零状态退出。这样“能通信”不会被误判成“舵机健康”。

如果要保存后续标定/重训用的原始数据,使用只读记录器:

New-Item -ItemType Directory -Force .\artifacts | Out-Null
cargo run -p duck-control --bin hl2915_record -- COM3 1 2 `
  --seconds 600 --output .\artifacts\hl2915-bench.csv --hz 50

CSV 每个采样点为每只舵机写一行,字段包括时间、位置、速度、负载、状态、运动标志、电流、电压和温度。
它不会写寄存器、不会开扭矩、不会主动运动;出现任何通信错误时以非零状态退出,
不能把不完整的日志当成辨识数据。

13.5 第一次运动只做“回中”

先把舵盘拆下或让输出轴完全悬空,确认周围没有夹手和撞壳风险。然后才执行:

cargo run -p duck-control --bin hl2915_probe -- COM3 1 2 --move-center

程序会打开扭矩、给两只写入原始位置 2048、等待 1 秒、读取状态、关闭扭矩。位置 2048 是协议定义的
中心,不代表已经对齐你的机械零位;机械装配完成后还要单独记录“舵机中心 ↔ 关节零位”的偏移。

13.6 再装到打印件,顺序不要跳

  1. 不通电,把一只舵机放进打印支架,确认 34×20×23 mm 外形、安装孔、线缆弯曲半径和 25T 舵盘都不干涉。
  2. 手动转动关节全行程,确认先碰到机械硬限位,而不是舵机齿轮或线缆先受力。
  3. 只装一只,悬空运行 --move-center,观察支架变形、异响和线缆拉扯。
  4. 两只装好后仍悬空测试;再放到软垫上,只给静态小角度目标。
  5. 在这五步都通过前,不接 Radxa 控制循环,不写行走策略。

13.7 这次代码验证了什么、没有验证什么

已经在无硬件环境自动验证:8 字节状态的小端解析、短报文拒绝、角度和原始位置换算、ID 唯一性、
以及二进制能编译。每次改代码后重复:

cargo test -p duck-control hl2915
cargo check -p duck-control --bin hl2915_probe

真实舵机的供电压降、丢包率、温升、回差、安装强度和“是否真的转到正确机械角度”,只能按 13.2–13.6
的台架顺序现场验证。仓库现在已有显式选择的 HL-2915 RobotIo:它用协议 v1 访问舵机,用协议 v2
访问 ID=200 的 IMU;原 bus.rs 仍只负责 XL330。混合后端尚未经过实体 HAT/IMU
验证,而且默认零位 2048、方向 +1 只是台架起点,因此现在仍不能运行行走策略。

13.8 通过后再搬到 Radxa Zero 3W

电脑上的 COM3 只是第一次调试用的端口。Radxa 上通常会显示成 /dev/ttyUSB0 或 /dev/ttyACM0,
程序本身不需要改:

sudo apt update
sudo apt install -y build-essential pkg-config
# 按仓库要求准备 Rust 1.89;然后把仓库放到 Radxa,例如 ~/microduck
cd ~/microduck
cargo test -p duck-control hl2915
cargo build --release -p duck-control --bin hl2915_probe
ls /dev/ttyUSB* /dev/ttyACM*
./target/release/hl2915_probe /dev/ttyUSB0 1

第一次在 Radxa 上仍然只接一只、只读。等 1 和 2 都能独立 Ping,再做两只并联验证;小智 ESP32、
Pi 2 和行走策略继续保持断开,避免多个程序同时抢同一条半双工总线。

Radxa、官方 Robot HAT 和相机到位后,依次生成三份互不替代的证据:

python tools/microduck_learning/board_readonly_report.py --json-out artifacts/board-readonly-report.json
python tools/microduck_learning/hat_smoke.py --run --confirm-official-hat --json-out artifacts/hat-smoke-first.json
python tools/microduck_learning/media_smoke.py --run --frames 60 --json-out artifacts/media-smoke.json

HAT 命令会录两秒临时音频并播放低音量提示音,退出后删除音频内容。确认第一次确实听到声音,
才重跑并加 --confirm-audible --json-out artifacts/hat-smoke.json。三个 JSON 缺任何一个,S6 都不会通过。

13.9 为 HL-2915 重新辨识 BAM 执行器

只读 CSV 只能回答“舵机现在是否健康”,不能得到执行器的电机常数、等效惯量、摩擦和延迟。
这些参数必须在独立摆锤台架上重新采集;不能把 XL330 的 BAM M6 参数直接套给 HL-2915。

台架要求:舵机刚性固定、摆臂和配重质量用秤测量、舵机轴到配重质心距离用卡尺测量,摆臂竖直向下
作为零位,四周无遮挡,手边有断电开关。第一次只用 ±10°、P=16;没有通过小幅度测试前不要增大幅度。

程序会显式写入 P/I/D、打开扭矩、采集轨迹,结束时自动关闭扭矩;它不是 hl2915_record 那种只读程序。

New-Item -ItemType Directory -Force .\artifacts\bam\raw | Out-Null
cargo +1.89.0 run -p duck-control --bin hl2915_bam_record -- `
  COM3 1 `
  --mass-kg 0.050 `
  --arm-mass-kg 0.010 `
  --arm-length-m 0.100 `
  --center-raw 2048 `
  --direction 1 `
  --kp 16 `
  --vin 12 `
  --amplitude-deg 10 `
  --duration-seconds 6 `
  --hz 100 `
  --output .\artifacts\bam\raw\kp16-a10.json `
  --confirm-motion

先分别用 --kp 8、--kp 16、--kp 32 采集至少三份小幅度日志;每次改变 P 值都要在文件名和记录表中写清楚。
如果要做更可靠的拟合,再重复 --amplitude-deg 20,但只有摆锤不撞任何物体、温度和电流都正常时才允许。

在 Linux/WSL2 的 microduck_rl 固定 commit 中处理日志。bam.process 会把不规则采样插值到固定时间步,
HL-2915 需要本仓库的轻量 BAM 适配入口;先用少量 trial 验证流程,再做正式拟合:

validate_bam_log.py 会拒绝 motor 不是 hl2915 的日志;其他候选舵机必须单独建立型号记录和拟合流程,不能混入 C001 数据。

python tools/microduck_learning/validate_bam_log.py \
  artifacts/bam/raw/kp16-a10.json
cd ~/microduck_rl
# 基础 uv sync 不装 BAM 拟合器的可选依赖;只需在最终 sync 后补装一次
uv pip install --python .venv/bin/python "optuna>=4,<5" "wandb>=0.24,<0.25" cmaes
uv run python -m bam.process \
  --raw /mnt/f/microduck/artifacts/bam/raw \
  --logdir /mnt/f/microduck/artifacts/bam/processed \
  --dt 0.01
uv run python /mnt/f/microduck/tools/microduck_learning/fit_hl2915_bam.py \
  --error-gain <实测值> \
  --logdir /mnt/f/microduck/artifacts/bam/processed \
  --output /mnt/f/microduck/artifacts/bam/hl2915-m6.json \
  --method cmaes --model m6 \
  --trials 2000 --workers 1
uv run python /mnt/f/microduck/tools/microduck_learning/check_bam_model.py \
  /mnt/f/microduck/artifacts/bam/hl2915-m6.json \
  --json-out /mnt/f/microduck/artifacts/bam-model-hl2915-m6.json
uv run python -c "from bam.model import load_model; print(load_model('/mnt/f/microduck/artifacts/bam/hl2915-m6.json').get_parameters())"

--error-gain 是 HL-2915 固件中“位置误差 × P 增益 → PWM 占空比”的换算,必须来自示波器实测
或飞特书面资料;不能抄 STS3215 的数值。适配入口以 C001 的 110 RPM、9.3 kgf·cm/A 作为可优化
起点,不把它们当成拟合结果。不要手改上游训练源码;本仓库的入口会注入 fitted JSON 和
HL-2915 的 12V/增益参数:

export MICRODUCK_RL_DIR=/home/<user>/microduck_rl
export MICRODUCK_BAM_JSON=/mnt/f/microduck/artifacts/bam/hl2915-m6.json
bash /mnt/f/microduck/tools/microduck_learning/run_5_iteration_smoke.sh

5 轮结束后会生成 BAM 合同、ONNX 合同和 training-lineage-lesson-01-repro.json。
其中 purpose=smoke 的意思只是“管线能跑”,不能证明会走。等阶跃记录测出端到端延迟和电压
下陷后,再逐步调整训练参数,完成正式训练、仿真回放和最终 ONNX 导出。随后封存候选模型:

python /mnt/f/microduck/tools/microduck_learning/check_training_lineage.py \
  --bam-contract /mnt/f/microduck/artifacts/bam-model-hl2915-m6.json \
  --onnx-contract /mnt/f/microduck/artifacts/onnx-contract-hl2915-candidate.json \
  --training-repo /home/<user>/microduck_rl \
  --purpose candidate \
  --json-out /mnt/f/microduck/artifacts/training-lineage-hl2915-candidate.json

它会拒绝脏训练仓库、被替换的 BAM/ONNX 文件和错误维度。通过后仍不能直接落地行走:先仿真回放,
再三只舵机单腿、15 只只读、整机悬空、软垫静态站立,最后才做手扶小步态。

什么鸭 WHATDUCK · 复刻学习笔记 ← 全部手册 · 首页