
1. 这只鸭子凭什么火出圈第一次刷到 Microduck 的演示视频时我盯着屏幕看了三遍。一只用 3D 打印件、舵机和树莓派拼出来的双足机器鸭摇摇晃晃地在地上走遇到障碍会自己调整重心用蓝牙手柄一推摇杆还能原地转圈。评论区一堆人问“这玩意儿能上街遛吗”我当时的反应是能但得先把几个坑填了。Microduck 是一个完全开源的桌面级双足机器人项目核心定位是“低成本、可复现、可扩展”。它不像那些动辄上万的科研级双足平台而是把物料成本压到了千元以内用最常见的树莓派作为主控配合舵机驱动板和 3D 打印结构件让任何一个有基础动手能力的人都能在周末搭出一只属于自己的机器鸭。它解决的问题很具体让双足机器人的入门门槛从“实验室级别”降到“车库级别”。适合谁来参考嵌入式爱好者、机器人方向的学生、想给孩子做 STEM 项目的家长以及所有对双足步态算法好奇但不想一上来就啃论文的开发者。我前后搭过三只 Microduck第一只摔断了腿第二只烧了一个舵机第三只才真正能稳定地“上街遛”。这篇文章就把我踩过的坑、调过的参数、以及从零到能走能转的完整路径拆开讲清楚。你不需要有机器人学背景但需要会拧螺丝、会烧录系统、能看懂简单的 Python 代码。2. 整体设计思路与方案选型拆解2.1 为什么是双足而不是轮式或四足双足机器人的魅力在于它的“不稳定”。轮式平台永远倒不了四足平台静态稳定但双足必须靠动态平衡才能站住。Microduck 选择双足路线核心考量是教学价值和趣味性。你让一个轮式小车走直线没人会觉得惊讶但一只鸭子摇摇晃晃地迈出两步然后站稳那种“活过来”的感觉是完全不同的。从技术角度看双足平台强迫你面对三个核心问题重心投影点CoM与支撑多边形的关系、舵机扭矩与关节角度的映射、以及步态周期中的相位切换。这些概念在轮式平台上根本不会出现。Microduck 用最简化的 6 自由度结构每条腿 3 个关节髋、膝、踝来呈现这些问题既不会复杂到让人放弃也不会简单到学不到东西。另一个现实原因是成本。四足需要至少 8 个舵机双足只需要 6 个而且四足的结构件打印量几乎是双足的两倍。对于想先试试水的人来说双足是更友好的起点。2.2 主控为什么选树莓派而不是单片机这是被问得最多的问题。用 Arduino 或者 STM32 不能做吗能但会很难受。Microduck 的步态算法需要实时计算逆运动学、处理蓝牙手柄输入、同时还要留出扩展接口给摄像头或传感器。树莓派的 Linux 环境让你可以用 Python 快速迭代numpy 做矩阵运算scipy 做插值这些库在单片机上要么没有要么得自己移植。更重要的是调试体验。树莓派可以 SSH 进去改代码、看日志、甚至跑一个 Flask 服务用手机浏览器监控关节角度。单片机每次改代码都要重新烧录调试效率差了一个数量级。当然代价是树莓派的实时性不如单片机但 Microduck 的步态频率在 1-2 Hz 左右Linux 的调度延迟完全在可接受范围内。我实测过树莓派 4B 和树莓派 5两者都能跑但树莓派 5 的 PWM 输出更稳舵机抖动明显小一些。如果手头只有 4B也没问题把步态周期稍微放慢一点就行。2.3 舵机选型与扭矩计算Microduck 官方推荐的是 MG996R 金属齿轮舵机扭矩标称 9.4 kg·cm6V。为什么是这个规格我们来算一笔账。假设鸭子总重 800g每条腿承担 400g。髋关节到地面的力臂大约是 8cm那么髋关节需要的静态扭矩是 0.4kg × 8cm 3.2 kg·cm。但双足行走时动态载荷可能是静态的 2-3 倍所以需要 6.4-9.6 kg·cm 的扭矩。MG996R 在 6V 下刚好卡在这个区间留了一点余量。如果你用 SG90 那种 1.8 kg·cm 的小舵机静态都撑不住一通电就直接趴下。我第一只鸭子就是用了便宜的塑料齿轮舵机走了三步就扫齿了。后来换成 MG996R连续走半小时也只是温热。注意MG996R 有假货标称扭矩可能只有 5 kg·cm。买的时候看齿轮是不是全金属用手拧一下输出轴阻力均匀且没有虚位的基本靠谱。2.4 结构件打印的关键参数3D 打印件是 Microduck 的骨架强度直接决定能走多久。官方 STL 文件在 GitHub 上可以下载但打印参数得自己调。我试过三种材料PLA、PETG 和 ABS。PLA 最硬但脆摔一次就断腿。PETG 韧性好层间结合力强是首选。ABS 强度够但打印时翘边严重不推荐新手。层高建议 0.2mm壁厚至少 3 层填充率 40% 以上。关键受力部位髋关节支架、脚掌连接件可以单独把填充率提到 60%。还有一个细节打印方向。髋关节支架如果竖着打印层间受力方向刚好和行走时的弯矩垂直容易分层。应该横着打印让层纹方向与受力方向平行。这个细节官方文档没写是我断了两次腿之后才悟出来的。3. 核心细节解析与实操要点3.1 硬件清单与成本拆解先把账算清楚免得做到一半发现预算超了。以下是我第三只鸭子的实际采购清单价格按国内电商平台常见价位估算。部件型号/规格数量单价元小计元主控板树莓派 4B 2GB1350350舵机MG996R625150舵机驱动板PCA9685 16路11515蓝牙手柄通用安卓手柄16060锂电池2S 7.4V 2000mAh14545降压模块LM2596 可调25103D 打印件PETG 约 200g14040螺丝轴承等M3 套装13030杜邦线若干11010合计710如果你已经有树莓派成本直接降到 360 左右。这个价格在双足机器人里算是地板价了。3.2 舵机驱动板与树莓派的接线逻辑PCA9685 通过 I2C 和树莓派通信只需要两根线SDA 接树莓派的 GPIO2物理引脚 3SCL 接 GPIO3物理引脚 5。VCC 接 3.3VGND 共地。舵机的电源单独走锂电池经过降压模块到 6V不要从树莓派取电否则一走动树莓派就会重启。这里有个坑PCA9685 的 V 引脚是给舵机供电的但板子上的 VCC 是给芯片供电的两者不能混。我第一次接线时把 6V 直接灌到了 VCC芯片瞬间冒烟。正确的做法是 VCC 接树莓派 3.3VV 接降压模块输出的 6VGND 全部共地。树莓派 5 的引脚定义和 4B 基本兼容I2C 引脚位置一样。但树莓派 5 的 GPIO 电平是 3.3V和 4B 相同所以不需要额外电平转换。3.3 逆运动学求解的简化方法双足行走的核心是逆运动学给定脚掌的目标位置反推髋、膝、踝三个关节的角度。Microduck 用的是解析法把腿简化为二维平面上的两连杆机构。设大腿长度 L16cm小腿长度 L26cm脚掌目标位置相对于髋关节的坐标为 (x, y)。那么膝关节角度 θ_knee 可以通过余弦定理求出d sqrt(x^2 y^2) cos(θ_knee) (L1^2 L2^2 - d^2) / (2 * L1 * L2) θ_knee acos(cos(θ_knee))髋关节角度 θ_hip 则需要先求出目标方向角θ_hip atan2(y, x) - atan2(L2 * sin(θ_knee), L1 L2 * cos(θ_knee))踝关节角度 θ_ankle 用来保持脚掌水平通常是 θ_ankle -(θ_hip θ_knee) 再加上一个补偿角。这套公式在 Python 里用 math 库就能实现不需要任何机器人学库。我实测下来只要 L1 和 L2 测量准确角度误差在 1 度以内鸭子走起来就不会有明显的内八或外八。提示L1 和 L2 不是打印件的理论长度而是舵机输出轴到下一个关节中心的实际距离。用游标卡尺量别信图纸。3.4 蓝牙手柄的映射策略Microduck 用蓝牙手柄控制左摇杆控制前后和转向右摇杆控制身体高度和俯仰。映射逻辑在 Python 里用 evdev 库读取手柄事件然后转换成步态参数。关键参数有三个步幅stride、步频frequency和转向偏置turn_offset。左摇杆的 Y 轴映射到步幅范围 -3cm 到 3cmX 轴映射到转向偏置范围 -15 度到 15 度。右摇杆的 Y 轴映射到身体高度范围 8cm 到 12cm。我试过用 pygame 读手柄延迟比 evdev 高不少而且树莓派上 pygame 的 joystick 模块偶尔会丢事件。evdev 直接读 /dev/input/eventX稳定得多。4. 实操过程与核心环节实现4.1 系统烧录与基础环境配置树莓派系统用 Raspberry Pi OS Lite 64 位版本不需要桌面环境省资源。烧录用官方 Imager配置好 WiFi 和 SSH插电就能连。第一次启动后先做三件事改源、更新、装依赖。国内网络环境下默认源速度感人换成清华源或者阿里源会快很多。具体操作是编辑 /etc/apt/sources.list 和 /etc/apt/sources.list.d/raspi.list把 deb 地址替换掉。然后安装核心依赖sudo apt update sudo apt install -y python3-pip python3-numpy python3-smbus i2c-tools pip3 install adafruit-circuitpython-pca9685 evdev启用 I2C 接口sudo raspi-config # 选择 Interface Options - I2C - Enable重启后用i2cdetect -y 1检查 PCA9685 是否被识别地址应该是 0x40。如果显示的是--说明接线有问题先查 SDA 和 SCL 有没有接反。4.2 舵机中位校准与角度映射舵机上电之前先把所有舵机拧到机械中位。MG996R 的中位是 1.5ms 脉宽对应 PCA9685 的计数值大约是 30750Hz 下。但每个舵机的机械中位都有偏差需要逐个校准。校准方法是先给舵机一个 1.5ms 的信号然后松开舵盘螺丝手动把舵盘转到腿伸直的位置再拧紧。这样电信号的中位就和机械中位对齐了。然后在代码里建立角度到脉宽的映射表。MG996R 的有效角度范围是 0-180 度对应脉宽 0.5ms-2.5ms。PCA9685 在 50Hz 下的计数值范围是 102-512。映射公式def angle_to_pulse(angle): pulse_min 102 pulse_max 512 return int(pulse_min (angle / 180.0) * (pulse_max - pulse_min))我建议在代码里给每个舵机单独存一个偏移量因为六个舵机的机械中位不可能完全一致。校准的时候用input()手动输入角度观察腿的实际位置记下偏差值。4.3 步态生成与相位控制Microduck 的步态是周期性的一个完整步态周期分四个相位左腿支撑右腿摆动、双腿支撑、右腿支撑左腿摆动、双腿支撑。每个相位持续的时间由步频决定。我用一个状态机来实现class GaitState: def __init__(self): self.phase 0 self.cycle_time 0.8 # 秒 self.t 0 def update(self, dt): self.t dt if self.t self.cycle_time: self.t 0 self.phase self.t / self.cycle_time然后根据 phase 的值计算左右脚的目标位置。摆动腿的轨迹用贝塞尔曲线支撑腿保持直线。贝塞尔曲线的控制点决定了抬脚高度和落地缓冲我调了大概二十次才找到不摔跤的参数。关键心得抬脚高度不要超过 2cm落地时脚掌要有一个轻微的下压动作模拟真实行走的足跟落地。这个下压角度大概是 5 度能显著减少前倾摔倒的概率。4.4 蓝牙手柄配对与实时控制树莓派自带蓝牙用 bluetoothctl 配对手柄bluetoothctl scan on # 找到手柄的 MAC 地址 pair XX:XX:XX:XX:XX:XX connect XX:XX:XX:XX:XX:XX trust XX:XX:XX:XX:XX:XX配对成功后手柄会出现在 /dev/input/eventX。用 evdev 读取事件from evdev import InputDevice, categorize, ecodes gamepad InputDevice(/dev/input/event3) for event in gamepad.read_loop(): if event.type ecodes.EV_ABS: if event.code ecodes.ABS_X: turn_offset (event.value - 128) / 128 * 15 elif event.code ecodes.ABS_Y: stride (event.value - 128) / 128 * 3这里要注意手柄的摇杆中位值不一定是 128可能是 127 或 129。我建议在启动时先读一次中位值后续用相对值计算。注意树莓派 5 的蓝牙模块和 4B 不同配对某些手柄时可能需要先power off再power on才能被扫描到。这是固件层面的问题不是配置错误。4.5 上街遛鸭的实战记录第一次带 Microduck 出门是在小区楼下。地面是水泥砖接缝处有 5mm 左右的高差。鸭子走了大概十米在第三个接缝处绊了一下前倾摔倒右腿舵机扫齿。复盘原因脚掌的离地高度不够只有 1.5cm遇到 5mm 的凸起时摆动腿的脚尖会刮到地面。后来把抬脚高度加到 2.5cm同时在步态里加了一个“探测-调整”逻辑如果某个舵机的电流突然增大堵转就立即抬高该腿并缩短步幅。第二次出门换了平整的沥青路面走了五十米没摔。但转弯时如果速度太快离心力会让鸭子向外侧倾倒。解决办法是转弯时自动降低步频同时把身体重心向内侧偏移 2-3 度。第三次我试着让它走盲道那种条纹凸起反而成了优势因为脚掌的橡胶垫能卡进条纹里抓地力更好。但走到盲道尽头时有一个 3cm 的台阶鸭子直接撞上去摔了。所以上街遛鸭的前提是路面高差不超过 1cm没有超过 3cm 的垂直障碍。5. 常见问题与排查技巧实录5.1 舵机抖动与供电不足的排查舵机抖动是最常见的问题表现是静止时舵机嗡嗡响或者走动时突然抽一下。九成原因是供电不足。排查步骤先用万用表量降压模块的输出电压空载应该是 6V接上舵机后如果掉到 5V 以下说明降压模块的电流不够。LM2596 标称 3A但实际持续输出 2A 就很烫了。六个 MG996R 同时动作的峰值电流可能到 5A所以要么换大电流的降压模块要么在电源端并一个大电容1000uF 以上缓冲。另一个原因是 I2C 通信干扰。舵机的 PWM 信号和 I2C 走线如果平行且距离近会产生串扰。把舵机线束和 I2C 线分开走垂直交叉能明显改善。5.2 步态不稳的常见原因速查现象可能原因解决方法走路时向一侧偏左右腿的 L1/L2 长度不一致重新测量并修正代码中的长度参数前倾摔倒重心投影点超出支撑多边形降低步频减小步幅增加脚掌下压角度后仰摔倒髋关节角度过大减小髋关节的摆动幅度检查中位校准原地踏步不前进脚掌与地面的摩擦力不足在脚掌底部贴橡胶垫增加摩擦系数转弯时外侧腿拖地转向偏置没有配合步频调整转弯时自动降低步频 20%走几步就重启树莓派供电不足树莓派单独供电不要和舵机共用电池5.3 树莓派系统层面的坑树莓派 4B 和 5 在 GPIO 和 I2C 上基本兼容但有一个坑树莓派 5 的 I2C 时钟频率默认是 100kHz而 4B 是 100kHz 但实际可能跑在 400kHz。如果你的 PCA9685 在 5 上工作不稳定可以在 /boot/firmware/config.txt 里加一行dtparami2c_arm_baudrate100000强制降速。还有一个问题是树莓派 5 的散热。跑步态算法时 CPU 占用大概 30%但如果你同时开了摄像头或者跑了其他服务温度会飙到 80 度以上然后触发降频步态就会卡顿。加一个散热片或者小风扇成本不到二十块但稳定性提升明显。5.4 蓝牙手柄断连的处理蓝牙手柄在树莓派上断连是家常便饭尤其是树莓派 4B 的蓝牙模块和 WiFi 共用天线2.4G 频段拥挤时容易丢包。我的解决方案是写一个守护脚本每 5 秒检查一次手柄设备是否还在 /dev/input/ 下如果不在就自动重连#!/bin/bash while true; do if ! ls /dev/input/event* | xargs -I {} udevadm info {} | grep -q Gamepad; then bluetoothctl connect XX:XX:XX:XX:XX:XX fi sleep 5 done另外手柄的电池电量低时也会频繁断连换新电池或者插 USB 线供电能解决。5.5 进阶扩展的方向Microduck 的扩展性很好树莓派的 GPIO 还剩不少I2C 总线也可以挂多个设备。我试过加一个 OV5647 摄像头模块做视觉巡线用 OpenCV 识别地面上的黑色胶带然后把手柄控制切换成自动跟随。效果还行但树莓派的算力有限帧率只有 10fps 左右走快了会跟丢。另一个方向是加超声波传感器做避障。HC-SR04 接在 GPIO 上检测到前方 20cm 内有障碍就自动停下并后退。这个逻辑很简单但很实用尤其是在室内遛鸭的时候。还有人把 Microduck 的步态算法移植到了其他双足平台上比如用 STM32 做底层控制树莓派只负责高层决策。这种架构的实时性更好但开发复杂度也上去了。如果你已经能把 Microduck 走稳可以试试这个方向。我个人在实际操作中的体会是Microduck 最大的价值不是它本身能走多好而是它把双足机器人的所有核心问题都暴露出来了供电、通信、机械校准、步态规划、实时控制。每一个问题你都得亲手解决一遍解决完了你对双足机器人的理解就不再是纸上谈兵了。最后分享一个小技巧调试步态的时候把鸭子吊在一个支架上让脚悬空这样你可以安全地观察每个关节的运动轨迹不用追着它满屋子跑。