拿到 Microduck 的板子和打印件那天,我先没急着拧螺丝。开源双足机器鸭这东西,表面看是一堆 3D 打印件加几个舵机,实际上真正的门槛在软件部署和首次上电那一刻——你能不能让它站起来,而且站得正。这就要说到今天的主角:"回中位"。
Microduck 是一台典型的开源双足机器人,主控用 ESP32,左右腿、鸭嘴、尾翼各由一个舵机驱动,结构件全靠 3D 打印。我第一次接触这个项目时被"开源到底"这一点打动了:固件源码、步态参数、调试工具全部躺在 Git 仓库里,不像市面上的玩具机器人只能按预设动作走。软件部署和首次运行是每个新玩家都要过的第一关,而这个阶段里最关键的"回中位",直接决定了鸭子能不能站稳、走姿会不会歪。
这篇内容我按真实操作顺序来写:硬件怎么接线、固件怎么编译烧录、首次上电要注意什么,以及如何用一段简单的回中位程序把所有舵机精确送到中位,让鸭子站直。不管你是嵌入式老手,还是第一次碰 ESP32 的入门玩家,按这个流程走一遍,基本不会卡壳。
1. 项目概览与选型逻辑
1.1 Microduck 的硬件构成与通道分配
先把零件盘一遍。Microduck 的核心硬件通常包括一块 ESP32 开发板、四个 180 度舵机和一套打印结构件。我这里推荐用 MG90S 或 SG90,原因是这两个型号的舵机性价比高、资料多,卡在结构件里无论尺寸还是扭矩都够用。ESP32 选择 WROOM-32 模组的开发板就行,社区版和官方版差异不大,只要能正常识别串口和烧录。
各功能通道建议按下表分配,尽量和官方固件默认引脚保持一致,避免改代码:
| 功能 | 推荐 GPIO | 默认角度 | 作用说明 |
|---|---|---|---|
| 左腿舵机 | GPIO 13 | 90 | 驱动左侧鸭脚前后摆动 |
| 右腿舵机 | GPIO 12 | 90 | 驱动右侧鸭脚前后摆动 |
| 鸭嘴舵机 | GPIO 14 | 90 | 控制鸭嘴开合,用于交互演示 |
| 尾翼舵机 | GPIO 27 | 90 | 控制尾翼偏转,辅助姿态调整 |
选择 ESP32 而不是 Arduino Uno,并不是因为 Uno 跑不动四个舵机,而是因为后续扩展空间差太多。双足机器人做到后面一定会加 IMU 姿态传感器、蓝牙遥控,甚至摄像头视觉识别,ESP32 的双核算力和丰富外设可以让你少折腾很多东西。而且 ESP32 的 PWM 输出由 LEDC 硬件通道管理,稳定性比 Uno 的软件模拟 PWM 高不少,驱动舵机时抖动更小。
结构件方面,PLA 材质打印就够了。鸭身、腿管、鸭嘴都需要预留舵机臂的安装孔位,打印时建议把填充率设到 30% 左右,太低了关节处容易断,太高了浪费材料和时间。打印完先不急着装配,热床翘边和孔位公差是常见问题,用锉刀修一下再进入电路部分。
1.2 为什么首次运行必须做"回中位"
所谓"回中位",就是让每个舵机输出中位 PWM 脉宽,大约 1500 微秒,对应舵机输出轴停在厂商定义的中立角度。对 180 度舵机来说,中位就是物理上的 90 度位置。
这一步为什么重要?我总结成三个理由:
第一,装配对齐必须有一个确定的参考姿态。鸭腿和鸭脚是通过舵机臂固定的,如果舵机不在中位就拧螺丝,腿管可能歪了 20 度你都不知道。后面所有步态参数都以这个姿态为基准,基座歪了,走起来就一定歪。
第二,回中位是软件和硬件之间的"握手"。Microduck 的步态控制是基于角度偏移叠加实现的,比如抬腿就是左腿舵机从中位转到 45 度再回来。如果中位本身不准,叠加出来的动作全都会偏。
第三,回中位是快速诊断手段。每次烧录完固件,先跑一遍回中位程序,能立刻发现舵机接线是否反了、通道映射是否错了、某个舵机是否坏了。这些故障在走步态程序时隐藏得很深,但在静态中位状态下一眼就能看穿。
2. 环境准备与软件部署
2.1 工具链选型:Arduino IDE 还是 PlatformIO
Microduck 的官方固件大多基于 Arduino 框架,所以最省事的选择是 Arduino IDE。我推荐 2.x 版本,界面比 1.x 清爽,而且内置串口监视器和库管理,新手友好度高。PlatformIO 当然也可以,它在写大型项目、管理多平台编译时更专业,但对于"四个舵机加一个回中位程序"这种体量,先用 Arduino IDE 撸一遍,理解整个流程,比一上来就上复杂工具链更有价值。
如果你以后准备长期玩 Microduck,再把 PlatformIO 提上日程,它能把依赖管理、编译缓存做得更顺手。两者可以共存,不影响。我自己的习惯是项目初期用 Arduino IDE 快速验证,等需要加模块化代码时迁到 PlatformIO。
2.2 拉取源码与安装芯片支持包
先把项目仓库拉到本地。Git 是必备工具,命令行执行:
git clone --depth=1 https://github.com/YourAccount/microduck.git cd microduck--depth=1是浅克隆,只拉最新一次提交,项目体积小、速度更快。如果只是为了跑最新固件,这样完全够用;如果要参与开发提 PR,再考虑去掉这个参数拉完整历史。
接下来安装 ESP32 开发板支持包。打开 Arduino IDE,在"首选项-附加开发板管理器网址"里填入:
https://dl.espressif.com/dl/package_esp32_index.json然后到"开发板管理器"搜索esp32 by Espressif Systems,选择安装 2.0.17 左右的稳定版本。为什么强调稳定版?最新版虽然功能更多,但对老仓库的兼容性偶尔会翻车,编译报出一些奇怪的未定义符号错误,排查起来很闹心。先让环境跑通,再考虑升级。
库方面,核心依赖是ESP32Servo,作者 Kevin Harrington,在库管理器里搜索安装即可。如果官方仓库的 README 里还提到蓝牙、网页控制功能,再按需安装对应库。这里有个小技巧:拉完源码后先打开 README 看"依赖清单",别一股脑把网上看过的库全装一遍,装了没用还容易版本冲突。
2.3 编译与烧录要点
接好开发板之后,在 Arduino IDE 里选择开发板型号为ESP32 Dev Module,分区方案保持默认。烧录前不需要手动设置波特率,ESP32 的下载走硬件握手,点上传按钮会自动处理。
有一个大概率会遇到的问题:不断弹出Connecting...然后卡死。这通常是因为开发板的自动下载电路没生效。解决办法很朴素:按住开发板上的 BOOT 键不放,点击"上传",等到串口日志开始滚动几百毫秒后再松手。这个操作几乎能解决九成疑难烧录问题。
烧录成功后打开串口监视器,波特率设置为 115200,复位开发板,能看到固件的启动日志。这里我建议养成一个好习惯:每次烧录前先看一眼串口监视器的端口号,别在多个串口设备同时插着的时候乱点,很容易一包固件写到隔壁的传感器板子上,耽误半小时。
3. 首次运行与回中位实现
3.1 上电之前的安全检查单
第一次上电回中位之前,先过一遍五项检查,表面上是多花五分钟,实际上能帮你避开最难受的返工:
一、检查舵机线序。SG90 和 MG90S 排线颜色基本统一:棕色是 GND,红色是 VCC,橙色是信号线。接错线轻则舵机不动,重则烧舵机驱动芯片。
二、确认供电能力。舵机堵转时瞬时电流能到 1A 以上,普通 USB 口直接带不动。建议舵机用独立的 5V 3A 电源箱供电,ESP32 开发板用 USB 或独立 5V 供电,两路电源的 GND 必须共地。共地是舵机信号稳定的大前提,没有共地,信号线上的电位就没有参考点,舵机会出现各种抽风。
三、紧固结构件但别压线。鸭腿、鸭脚螺丝要拧牢,但走线要留出余量,舵机扭转时千万别把线皮磨破。
四、动作范围预判。回中位本身是绝对安全的动作,但如果你之前手动拧过舵机臂,先拔掉鸭嘴连杆再上电,防止舵机方向异常时连杆把打印件顶裂。
五、确保桌面有足够空间。鸭子回中位时腿会伸直,周围别有杂物挡道,站立区域最好放一块防滑垫。
3.2 回中位程序原理解析
回中位的代码逻辑极其简单,就是把所有舵机都 write 到 90 度,但理解write(90)和脉宽的关系才是重点。
在 ESP32Servo 库中,舵机映射范围默认是 500 到 2500 微秒。Servo.write(90)会按比例算出中位脉宽:
[ 1500 = 500 + \frac{90}{180} \times (2500 - 500) ]
也就是恰好 1500 微秒。这就是舵机的中位信号频率基础:标准模拟舵机看的是脉宽,不是角度。角度只是库帮你算出来的可视化表达。
但实际装配中,舵机个体存在出厂偏差,舵机臂卡齿也可能没对准,单纯写 90 度不一定能让鸭腿垂直。所以我会做一层"装配偏移量"补偿,把偏移值集中放在配置文件里,调参时不用翻主程序代码。
config.h:
#pragma once #define SERVO_MIN_US 500 #define SERVO_MAX_US 2500 #define LEFT_LEG_PIN 13 #define RIGHT_LEG_PIN 12 #define BEAK_PIN 14 #define TAIL_PIN 27 // 装配偏移量,单位:度;正值偏往角度增大方向 #define LEFT_LEG_OFFSET 0 #define RIGHT_LEG_OFFSET 0 #define BEAK_OFFSET 0 #define TAIL_OFFSET 0主程序microduck_center.ino:
#include <ESP32Servo.h> #include "config.h" Servo leftLeg, rightLeg, beak, tail; void setup() { Serial.begin(115200); delay(200); leftLeg.attach(LEFT_LEG_PIN, SERVO_MIN_US, SERVO_MAX_US); rightLeg.attach(RIGHT_LEG_PIN, SERVO_MIN_US, SERVO_MAX_US); beak.attach(BEAK_PIN, SERVO_MIN_US, SERVO_MAX_US); tail.attach(TAIL_PIN, SERVO_MIN_US, SERVO_MAX_US); delay(500); // 等待舵机驱动器稳定 Serial.println("Microduck -> all servos to center"); leftLeg.write(90 + LEFT_LEG_OFFSET); rightLeg.write(90 + RIGHT_LEG_OFFSET); beak.write(90 + BEAK_OFFSET); tail.write(90 + TAIL_OFFSET); Serial.println("center command sent"); } void loop() { // 保持中位,后续调参直接改 config.h 中的 OFFSET delay(1000); }这段代码的要点在Attach时显式指定了最小和最大脉宽,确保write的角度映射符合你的期望。如果不指定,部分库的默认映射范围可能有偏差,导致写 90 度实际输出 100 度,这是很多人忽略的坑。
3.3 让鸭子站起来:现场标定流程
代码上传好之后,别急着把四根轴全锁死。我推荐分步装配标定:
第一步,只装一条腿。让鸭子一侧躺着,接好舵机,上电跑回中位程序。观察舵机臂和腿管是否呈垂直状态。如果不是,改config.h里对应的偏移值,每次按正负 2 到 3 度的步长微调,重新编译烧录。这个过程看着繁琐,实际几分钟就能完成。
第二步,标定另一条腿。两条腿都标定完,再把它们同时装上。此时松开所有关节螺丝,让两条腿在自重下自然下垂,然后逐步上紧螺丝。这样做的好处是,单条腿标定时的残余误差不会在装配时被螺丝锁死放大。
第三步,装鸭嘴和尾翼。回中位时鸭嘴应当闭合居中,尾翼水平。如果鸭嘴闭合不严,多半是连杆长度需要修剪或调整角度偏移;尾翼歪了则和鸭腿同理,加偏移量就行。
这里分享一条经验:关节螺丝必须在通电回中位状态下拧紧。断电状态下舵机虽然还能手动掰动,但那是齿轮箱打滑的位置,不是软件定义的中位位置。你在断电状态下对齐的"看起来垂直",通电后很可能偏了十度。
4. 常见问题与排查技巧
4.1 舵机抖动但不转动
这是新手遇到最多的问题。现象是舵机发出高频滋滋声、输出轴轻微抖动,但角度稳定不下来。
原因几乎都是供电能力不足。舵机在启动瞬间需要电流冲击,4 个舵机同时回中位更是如此,USB 口或 1A 小电源根本喂不饱。解决办法是换 5V 3A 及以上的电源,并在舵机供电端并联一个 470 到 1000 微法的电解电容,用于缓冲电流尖峰。电容极性不能接反,长腿接正极,短腿接负极。
还有一种隐蔽情况:舵机电源和 ESP32 没有共地。信号线上只有 PWM 脉冲,没有统一参考地,舵机控制器无法正确解析信号,表现出来就是随机抖动。检查两路电源的 GND 是否真正连到了同一个节点。
4.2 编译报错的几类典型场景
'Servo' was not declared in this scope这是典型的依赖缺失,ESP32Servo 库没有安装成功。回到库管理器,搜索ESP32Servo,作者是 Kevin Harrington,安装后再编译。
avr/pgmspace.h: No such file or directory说明你直接拿 Arduino Uno 的示例代码跑在了 ESP32 上,代码里包含 AVR 芯片专用头文件。找一下项目里有没有#include <avr/pgmspace.h>之类的内容,删掉,或者换成官方的 ESP32 示例代码。这类报错本质上不是环境问题,是源码目标平台不匹配。
如果编译时卡在内存溢出上,检查是否用了大量String拼接或过大的全局数组。ESP32 的 320KB RAM 看着很大,但 Arduino 框架本身占了不少,别拿它当电脑内存用。
4.3 串口识别不到或一直连接不上
Windows 下最常见的情况是设备管理器里压根没出现COMx。这通常不是板子坏了,而是 USB 转串口芯片驱动没装。Microduck 常用的开发板大多使用 CP2102 或 CH340,去对应芯片官网装驱动即可。
如果你能看到 COM 口但一上传就卡在Connecting...,按我前面说的:按住 BOOT 键再点上传,等日志开始烧写后松手。还有一种情况是板子在你手里被刷过其他固件,自动下载模式被禁用,这时候长按 EN 复位键再尝试。
排查这些的时候记得先把串口监视器关掉,因为串口监视器会占用 COM 端口,IDE 上传时会因为端口被占而连续报错。
4.4 上电后鸭子还是歪的
如果回中位程序已经在跑,鸭子还是歪,需要区分是硬件还是软件问题。
一种可能是装配偏移量没标定。很多新手觉得回中位是固定动作,写完代码烧进去就完事,忽视了舵机臂卡齿角度和打印件孔位公差。这时候回到 3.3 的标定流程,诚实地一步步调偏移值,不要嫌烦。
另一种可能是左右腿舵机装反了,表现为一只脚向前一只脚向后,但单看角度又都"在中位附近"。检查舵机插头是否插在了错误的 GPIO 排针上,对照通道表逐一确认即可。
4.5 电源过流保护导致反复重启
如果你用带过流保护的电源适配器,上电瞬间可能会触发保护断电,鸭子还没站稳就瘫了。原因还是启动电流峰值太高。
解决办法是给舵机加软启动逻辑——在代码里不要一上来就四个舵机同时写角度,而是一个一个来,中间加 200 到 500 毫秒的延时。虽然中位程序跑完只差零点几秒,但在供电条件不理想的环境下,顺序启动能显著降低瞬时电流压力。
顺带提一个长期运行建议:Microduck 摆桌上演示时可以一直插电,但注意舵机在中位附近长期通电是堵转状态,会持续发热。演示完最好断电,否则舵机寿命会明显缩水。
5. 从回中位到步态:下一步调试方向
5.1 步态参数从哪里开始调
回中位跑通后,鸭子已经具备"站姿基线",接下来自然想让它走。步态调参的核心是三个量:抬腿高度、步长、步频。这三个量在官方仓库里一般就是几个宏定义或配置文件里的常量。
刚开始我建议把步频调到较慢的 0.5 到 1 秒一步,观察两条腿是否交替正常。第一版参数跑起来像鸭子喝醉了很正常,关键是看动作是否在左右腿之间对称。步长先给一个保守的 5 到 10 度摆动,别一上来就追求大步流星,双足系统最容易在重心转移瞬间翻车。
调步态时让鸭子在防滑垫或硬质桌面上跑,先不要在光滑地板上测试。桌面的抓地力反应直接,你很容易分辨是参数问题还是重心的物理问题。光滑地面则会把摩擦不足伪装成参数错误,白白浪费调试时间。
5.2 加 IMU 和不加 IMU 的玩法差异
很多开源双足项目在步态调试一段时间后会感到瓶颈:鸭子走一段就偏航。这本质上是开环控制的问题,脚下每一步的微小误差都在累积。
这时候可以给 Microduck 加 IMU 模块,比如 MPU6050 或 ICM42688,采集俯仰和偏航角,在固件里做简单的姿态闭环。加 IMU 之后不只是"走得直"这么简单,还能让鸭子在受到轻微推力时主动调整姿态,互动感强很多。ESP32 的 I2C 接口接 IMU 很方便,接线只需要 VCC、GND、SDA、SCL 四根线,共享 I2C 总线还能同时挂显示屏。
如果你不想升级硬件,也可以用串口或蓝牙发指令,让鸭子执行固定的点头、张嘴、扇翅膀动作组合,做一个桌面互动玩具也绰绰有余。仓库里通常自带串口指令解析的示例,找一下cmd开头的文件就能扩展。
我实际操作下来最大的体会是,Microduck 这类开源项目真正的价值不在打印件和螺孔,而在"回中位"这个简单动作背后教会你的整套调试方法论:设定可重复的基线、逐项隔离变量、再在这个基线上做叠加。每次换舵机、换打印件、甚至换场地,我都会重新跑一遍回中位程序,确保这个基线没有被悄悄破坏。调试到后期你会习惯这个过程,它不再是个"首次运行步骤",而是整个项目最可靠的锚点。