DEEP 108 · 第十辑 · duck-control 逐函数精读 · LEARN NOTES

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

解读 108 · hl2915.rs(一):Hl2915Bus 帧层

解读对象:duck-control/src/hl2915.rs(620 行)
需要的前置:解读 69(代码地图导览)、解读 64(寄存器表出处)

导览见解读 69,本篇逐函数下钻。bus.rs 的帧层在解读 98;HL-2915 的对应物分两篇,本篇管"字节怎么解释":寄存器常量、校准、解码与台架控制器,下一篇管 RobotIo 实现。

1. 常量即协议

文件头 17 行常量(hl2915.rs:16-32)是一张压缩的寄存器表,与 hl2915_bench.py 完全一致:DEFAULT_BAUD_RATE = 1_000_000(:16);状态块从 PRESENT_STATE_ADDR = 56 读(:17),短块 8 字节(:18)、扩展块 15 字节(:19);写目标在 GOAL_POSITION_ADDR = 42(:23),扭矩开关 40(:24),P/D/I 增益在 21/22/23(:25-27),电压温度在 62(:28)。IMU_ADDR = 124(:29)与 XL330 总线读地址相同——IMU 板不换,换的只是舵机协议。POSITION_CENTER = 2048(:20)是 4096 计数中点;DEFAULT_HL2915_IDS = [1..=15](:21-22)与 model::JOINT_IDS 的 10–34 段完全不同。换算常数两个:电流每计数 6.5 mA(:31)、速度每计数 0.229 转/分(:32)——后者与 bus.rs 的 RAD_PER_SEC_PER_COUNT 同源(见解读 98)。

2. 四本错误账与逐关节校准

错误类型按用途分四本:DecodeError::Short(hl2915.rs:43-47)管块太短;IdError(:49-57)管名单——空、广播、重复各一个变体;PositionError(:59-69)管角度换算的计数与弧度两侧;CalibrationError(:71-77)管校准表。FeetechCalibration(:84-97)每关节两样:zero_raw(机械零位的编码器值)与 direction(+1/−1);默认值全是中点与 +1,注释强调这是"刻意的台架起点,打印出来的机器人必须逐关节校准"(:81-83)。两个换算函数互为逆:raw_to_radians(:114-120)先用 rem_euclid(4096) 把差值回卷,超过 2048 就减 4096——跨过 0/4095 接缝走最短路,再乘 2π/4096 与方向;radians_to_raw(:122-132)先拒绝非有限与 −π..π 之外的角度(:127),zero + delta.round() 后再 rem_euclid 回 0..4095。测试 calibration_round_trips_direction_and_zero(:600-609)用零位 1000、方向 −1 钉住往返误差不超过一个计数。

3. 裸字节的翻译官

decode_present_state(:139-150)解 8 字节状态块,布局在注释里(:137-138):position(2)、speed(2)、load(2)、voltage(1)、temperature(1),全部小端;不足 8 字节报 Short。电压每计数 0.1 V(:147),测试(:565-573)用 0x79 解出 12.1 V、0x1e 解出 30 °C。speed_to_rad_per_second(:152-156)值得细看:最高位是符号,幅值要 & 0x7fff 掩出来,再乘 0.229 与 2π/60 换成 rad/s。角度工具两个:raw_to_degrees(:158-160)对越界计数 min(4095) 兜底;degrees_to_raw(:162-167)的区间是半开的 0..360——359.999 合法、360.0 报错(测试 :587-590)。validate_ids(:169-183)用 HashSet::insert 的返回值一行查出重复(:178),并拒绝 254/255 两个广播保留值(:175-177)。

4. Hl2915Bus:台架上的遥控器

Hl2915Bus(:189-192)是"一两只舵机的小而安全的台架控制器",立场写在文档里(:185-188):"刻意先暴露原始寄存器单位……避免悄悄把 XL330 的角度约定套到飞特电机上"。open(:484-500)校验名单后开串口,Sts3215Controller::new().with_protocol_v1()(:493-495)——HL-2915 走飞特磁编码协议 v1。六个方法:ping_all(:506-514)返回应答名单;read_states(:516-524)按 56/8 批量读,逐块过 decode_present_state;set_torque(:526-530)广播扭矩;set_id(:532-536)改 ID 前先校验新 ID;write_positions_raw(:538-557)写前两道检查——数量报 Count,任一值超 4095 报 Range(:548-552),再转成 rustypot STS 接口要的 i16(:553)发出。注意它不在 RobotIo 体系里:这是台架与测试用的"裸层",生产路径在下一篇的 Hl2915RobotIo。

你带走的收获

延伸

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