新手教程:烧录系统、开机与配置
做完这份教程,你的机器鸭能站起来、用手柄走路、听懂自己的名字。整个过程约 2–3 小时(不含组装),只需要一台 Windows 电脑,加上在浏览器里使用的 DuckBuddy 工作台(装机工具)。
顺序是:烧卡 → 开机连网 → 电脑免密登录 → 打开工作台 → 板级测试 → 关节映射 → 零位标定 → 打开服务、站起来 → 手柄和名字。每一步做完再做下一步:前一步没过,后面都会出问题。
教程适用于两种鸭子:HL-2915 舵机 + 3S 电池,和 HD-1910 舵机 + 2S 电池。两种的流程一样,只有几处不同。文中标「HD-1910 版」的地方要多看一眼;做 HD-1910 版之前,请先读完后面的「HD-1910 版要注意」一节。
准备什么
| 类别 | 东西 | 说明 |
|---|---|---|
| 机器人 | 组装好的机器鸭 | Orange Pi Zero 3W + HAT + PDB,15 只 HL-2915 或 HD-1910 舵机,舵机 ID 已设好(1–15)。零件见 物料清单 |
| 机器人 | 锂电池 | HL-2915 用 3S,充满 12.6 V(LiHV 13.05 V);HD-1910 用 2S,充满 8.4 V,别用 LiHV 充到 8.7 V。节数不对时,舵机不会上力 |
| 存储 | TF 卡 16 GB 以上 + 读卡器 | 镜像约 9.5 GB |
| 电脑 | Windows 10/11 | 和机器鸭连在同一个 WiFi 里 |
| 电脑 | 系统镜像 | DuckBuddy-opizero3w-trixie-日期.img 和它的 .sha256,从百度网盘下载(提取码 nway)。网盘里的 Orange Pi 官方原版镜像用不到 |
| 电脑 | balenaEtcher | 烧卡软件,etcher.balena.io |
| 电脑 | Python 3.11 以上 | 装好后运行 pip install pyserial mujoco numpy Pillow |
| 电脑 | DuckBuddy 仓库 | 从 github.com/Animan-AI/DuckBuddy 下载:用 git clone,或点 Code → Download ZIP 后解压。工作台在 tools/bringup,零位标定还要用到 tools/joint_align |
| 网络 | 2.4 GHz WiFi | 路由器或手机热点都行 |
| 备用 | mini HDMI 线 + 显示器 + USB 键盘 | 只在连不上 WiFi 时用 |
| 备用 | 蓝牙手柄 | Xbox 模式的手柄(如北通 BSP-G6) |
机器鸭要用的软件,镜像里已经全部装好,不用另外安装。
第一步:烧录系统卡
烧一张卡约 10–15 分钟。
-
核对镜像没有下坏。 在镜像所在的文件夹里打开 PowerShell,运行:
Get-FileHash .\DuckBuddy-opizero3w-trixie-*.img -Algorithm SHA256把输出的一长串和
.sha256文件里的对一下,完全一样才继续。 -
插卡、打开 balenaEtcher。 依次点 Flash from file(选镜像)→ Select target(选 TF 卡,看清容量,别选成移动硬盘)→ Flash。
- 等它写完并校验完。 界面显示 Flash Complete 才算成功。
- Windows 弹出“需要格式化磁盘”时,点取消。 卡里是 Linux 分区,Windows 读不了,点了格式化就白烧了。
- 弹出读卡器,取下卡。
一张卡对应一只鸭子。用过的卡里存着那只鸭子的标定和名字,不要直接插到另一只上用。
第二步:第一次开机与连网
第一次开机要 2–3 分钟,中间可能自己重启一次,别断电。这次开机它会做三件事:
- 把分区扩到整张卡;
- 按芯片序列号给自己起名
duck-XXXX(XXXX 是 4 位字母数字); - 生成这只鸭子自己的叫声。
- 把卡插进 Orange Pi,电池接上 PDB。这时舵机还不上力,鸭子是软的,躺在桌上就行。
- 让它连上 WiFi。 有三种情况:
- 镜像文件名带
-wifi(课程会场用的):开机会自动连上会场 WiFi,直接看第 3 条。 - 普通镜像:接 mini HDMI 显示器和 USB 键盘,屏幕上会出现
duck-XXXX login:(顺便记下这个名字)。用户名和密码都是orangepi。登录后运行sudo nmtui,选 Activate a connection,挑你的 WiFi,输入密码。连上后运行ip -4 a show wlan0,inet后面就是 IP。 - 没有显示器:用 USB 串口调试板接板子的调试口,在电脑上用串口工具(波特率 115200)登录,后面的操作同上。
- 镜像文件名带
-
在电脑上找到它。 打开 PowerShell:
ping duck-XXXX.local能通就用这个名字。如果不知道 XXXX,或者
.local不通,就去路由器管理页的设备列表里,找名字以duck-开头的设备,用它的 IP。 -
第一次登录并改密码。
ssh orangepi@duck-XXXX.local问是否信任时输入
yes,密码是orangepi。所有鸭子的初始密码都一样,进去后马上运行passwd改成你自己的密码。
HD-1910 版:告诉它舵机型号。 镜像默认按 HL-2915 设置。HD-1910 的鸭子登录后,先运行一次:
duck-model hd1910
它会先备份原配置,再把电流单位、电池(2S、最高 8.4 V)、走路策略和关节方向改成 HD-1910 的。不带参数运行 duck-model,可以看现在设的是哪种。HL-2915 的鸭子跳过这一条。
后面凡是写 duck-XXXX.local 的地方,都换成你这只鸭子的名字,或者直接写 IP。
第三步:让电脑免密登录
工作台通过 ssh 和鸭子通信,过程中不会弹窗问密码,所以要先把电脑的公钥放到鸭子上。每台电脑、每只鸭子各做一次就行。
-
电脑上还没有密钥的话,先生成一对(一路回车):
ssh-keygen -t ed25519 -
把公钥放到鸭子上(这一步会问一次鸭子的密码):
type $env:USERPROFILE\.ssh\id_ed25519.pub | ssh orangepi@duck-XXXX.local "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys" -
确认免密生效:
ssh -o BatchMode=yes orangepi@duck-XXXX.local hostname没有问密码、直接打印出
duck-XXXX,就成功了。报Permission denied,说明第 2 步没做对。
第四步:打开 DuckBuddy 工作台
工作台是在你电脑上运行的网页工具,通过 ssh 指挥鸭子做测试和标定,鸭子上不用装任何东西。
-
在 DuckBuddy 仓库的文件夹里打开 PowerShell,运行:
python tools/bringup/app.py --host orangepi@duck-XXXX.local -
在浏览器里打开
http://localhost:8780。 - 点「总览」里的 刷新,页头显示出
duck-XXXX就是连上了。新卡上 robotd 显示“未运行”是正常的:标定完之前,镜像里的服务都不会打开。
工作台有五个页签,每个页签顶上都有一段可以展开的图文说明:
| 页签 | 做什么 | 本教程哪一步用 |
|---|---|---|
| 总览 | 连接状态、启动 / 停止 robotd、选 USB 调试板串口 | 每一步 |
| 整机测试 | 舵机总线、IMU、麦克风、喇叭、ToF、摄像头六项检测 | 第五步 |
| 舵机 | 扫描、改 ID、摆动、关节映射 | 第六步 |
| 零位标定 | 核对关节方向、记录零位、站在 home 姿势上精调 | 第七步 |
| IMU 固件 | 用 ST-Link 给 PDB 上的 IMU 烧固件 | 板子没烧过固件时才用 |
页头右边红色的「全部卸力」随时都能按。 舵机乱动、发烫或有焦味时,先按它,再拔电池。
第五步:板级测试
六项全部通过才能往下做。打开「整机测试」,确认 robotd 没在运行(新卡本来就没运行),然后逐项点测试。每项都会给出通过 / 不通过和测量值。
| 项目 | 你要做的 | 通过的标准 |
|---|---|---|
| 舵机总线 | 点测试就行 | 15 只全部应答,错误率 ≤ 0.5%,没有红色的多圈读数 |
| IMU | 让鸭子静止放着 | 融合输出 90–150 Hz,陀螺噪声 < 1 dps |
| 麦克风 | 在录音的 4 秒里拍拍手或说说话 | 两路都有声音,没有削顶 |
| 喇叭 | 听到 1 kHz 的“嘟”声后点“听到了” | 录到的声音高出 ≥ 15 dB,并且人耳听得到 |
| ToF | 点测试就行 | ≥ 10 Hz,64 个点里至少 32 个有效 |
| 摄像头 | 镜头前别挡着 | ≥ 10 fps,缩略图是正常画面 |
不通过时,先对照下面几种常见情况:
- 舵机总线、IMU、麦克风、ToF 一起不通过,连 IMU(ID 200)都不应答:HAT 的 3.3 V 没有电。断电后检查 HAT 上的 U5(正面,印 TJ)和 U7(背面,印 SH)是不是装反了。
- 每个 ID 都回
ff ff 00:HAT 和 PDB 之间那根线的 GND 和 DATA 接反了。 - 只有 IMU 不应答:PDB 上的 IMU 还没烧固件,用「IMU 固件」页烧。
- ToF 0 帧:多半是插头没插实,断电重插。
- 只有少数舵机不应答:检查这几只的串线和插头。
- HD-1910 版:某只舵机读数小于 0 或大于 4095:这是多圈计数,关节被掰过了 0/4095 那一点。重启 Orange Pi 清不掉,要拔电池给舵机断电。上力之前,15 只的读数都要在 0–4095 之间,否则它会多转一圈去找目标。
全部通过后点“导出报告”,存一份 JSON,以后维修时可以对照。
第六步:关节映射
这一步告诉鸭子:哪个 ID 的舵机装在哪个关节上。装配时很少按顺序装,所以每只鸭子都要做一次,约 10 分钟。
- 让鸭子平躺在桌上,腿和头都悬空,能自由摆动。
- 确认「总览」里 robotd 是停着的。robotd 运行时,舵机页会拒绝操作。
- 打开「舵机」页的 关节映射 卡片,点开始。工具会让舵机一只一只地左右摆动 ±8°,你看哪个关节在动,就在页面上点那个关节。嘴也算一个关节。
- 15 只都点完后,做一遍 左右对照:左右成对的关节一起摆,确认没有点反左右。
- 选 不改 ID,写入配置。工具会先备份,再把对应关系写进鸭子上
~/robot/duck.toml的joint_ids。
另一个选项“按关节顺序批量改 ID”也能用,但会改写 15 只舵机的内存,第一次做不建议用。
第七步:零位标定
这一步确定每个关节的方向和“零度”位置,决定鸭子能不能站稳。它是整个流程里最需要耐心的一步,约 30–60 分钟。
先做准备:
- 关掉工作台(在 PowerShell 里按 Ctrl+C),再用同一条命令重新打开。刚写进配置的映射要重开后工作台才会读到;不重开,标定页会把旧值写回去。
- 在「总览」里点 启动 robotd。标定页读的是 robotd 给出的关节角。这时配置里还没有步态策略,它不会走路。
- 让鸭子平躺或托在手里,打开「零位标定」,点 开始标定(全身会卸力)。
核对方向(舵机不上力,用手掰):
- 在表格里点一个关节,第三张图会画出它的正方向。
- 把实机的这个关节往同一个方向掰。前两张图里的模型应该跟着同向转,读数变大。
- 转反了,就点这一行的 反向,再掰一次确认。
- 15 个关节都做一遍。左右成对的关节要两边一起掰,只掰一边容易看反。嘴没有模型:张嘴时读数应该变大。
记录零位:
- “参考”选 零位,照着参考图把鸭子摆好:腿伸直、头摆正、嘴闭到底。
- 点 全部设为零位,再点 写入配置。工具会先备份,再重启 robotd。
- 如果某个关节在零位的读数很靠近 0 或 4095,说明舵盘装偏到了舵机的跳变点。不用拆舵盘:停掉 robotd,在「舵机」页选中那只舵机,点 当前位置设为中位,再回来重标这个关节。
站在 home 姿势上精调:
- 托好鸭子,点 写入并回 home。它会上力,平滑地摆成站姿。
- 放到桌上检查:脚底贴平;躯干的俯仰、横滚接近 0(页面上有 IMU 读数);头和地面平行;脚尖朝正前;左右对称;能自己站住。
- 哪个关节偏了,就点那一行的 − / +(每次 0.5°),再点 写入并回 home 看效果。反复几轮。
调好后,先停掉 robotd,在「整机测试」里再跑一遍“舵机总线”,导出报告存档。
第八步:打开服务、第一次站起来
标定完成后,用一条命令打开鸭子的全部服务:舵机控制、手柄、生命层、语音、视觉、ToF 和手机网页。以后开机,这些服务会自动运行。
- 让鸭子躺下。
-
ssh 登录鸭子,运行:
duck-services on它会把走路、起立、坐站三个策略加进配置,重启 robotd(重启前会问你鸭子躺好了没有,输入
y),再启动全部服务。如果零位还全是 0,它会拒绝执行,提醒你先标定。 -
等 20 秒左右,运行
duck-services status,七个服务都应该是active。 - 第一次站立。 让鸭子躺在平地上,双手托住它的身体,对它说“豆豆,站起来”(还没起名字时它叫豆豆)。它会上力站起来,第一次站的时候手不要离开。说“豆豆,坐下”,它会坐下;说“豆豆,睡觉”,它会坐下并卸力。
HD-1910 版还没有坐下的动作。 说“坐下”或“睡觉”时,它会继续站着。要让它停下,先双手扶住它,再按手柄的 Start 或工作台的「全部卸力」。走路要先放在地上(垫上软垫)试,不要托在手里或悬在空中试。
安全规矩,每一条都要做到:
- 只在平整、不滑的地面上站和走,周围留出 1 米,不要在桌边。
- 第一次站、第一次走时,人要蹲在旁边,手随时能接住它。
- 出了问题,先点工作台的「全部卸力」(HL-2915 版也可以说“豆豆,睡觉”),再拔电池。
- 头部舵机到 70 °C 时,它会自己停下来休息。这是正常的保护,等它凉下来就好。
- 要回去重新标定:先让它躺下,运行
duck-services off,再用工作台。
第九步:手柄与名字
用工作台配对手柄
已刷 -r2 的用户可以保留现有系统。 -r2 已有蓝牙驱动和兼容设置,需要先在鸭子上安装一次配对服务,再用最新版工作台操作。
- 让电脑和鸭子连到同一局域网,按第三步配置 SSH 登录。用
ssh orangepi@鸭子的IP登录,在鸭子的终端执行以下命令。已有仓库时,在现有仓库更新到最新版后,从sudo apt install开始执行。
git clone https://github.com/Animan-AI/DuckBuddy.git
cd DuckBuddy
sudo apt install bluez python3-dbus python3-gi
sudo install -m 755 deploy/opi-image/duck-gamepad-pair.py /usr/local/sbin/duck-gamepad-pair
sudo install -m 644 deploy/opi-image/duck-gamepad-pair.service /etc/systemd/system/
sudo systemctl enable --now duck-gamepad-pair.service
- 在电脑上更新 DuckBuddy 仓库,按第四步重新打开工作台。把手柄切到 Xbox 模式并让灯快闪,再在「总览」点「配对新手柄」,等待页面显示结果。服务刚启动时可能已经在扫描,此时按钮会显示本轮配对结果。
- 配对后,鸭子下次开机时按手柄的 Home 键回连。手柄控制功能按第八步完成标定后启用。
已刷 -r3 的用户可以在首次开机的约 90 秒扫描窗口内直接让手柄快闪。换手柄或错过窗口时,使用工作台「配对新手柄」。自动配对和重启回连仍待实机验证。
用终端手动配对
配对手柄(只需做一次)。 把手柄切到 Xbox 模式并进入配对状态(灯快闪),然后在鸭子上运行 bluetoothctl,依次输入:
power on
agent on
default-agent
menu scan
transport bredr
back
scan on
等列表里出现手柄的名字,记下它前面的地址(形如 83:26:09:02:6A:A0),再输入:
scan off
pair 手柄地址
trust 手柄地址
exit
之后按手柄的 Home 键,它会自动连上鸭子。以后每次开机,也是按 Home 键回连。
| 按键 | 作用 |
|---|---|
| Start | 上力并站起来 / 卸力。按之前先扶住鸭子 |
| 左摇杆 | 前后左右走(最快 0.2 m/s) |
| 右摇杆 | 原地转向 |
| Select 按住 2 秒 | 关机 |
| 十字键上 按住 3 秒 | 切到翻滚模式,不要按 |
给它起名字。 名字和性格写在鸭子上的 ~/.config/duck/persona.json 里,只需要写和例子不一样的部分(完整的例子在 ~/persona/example.json)。用 nano ~/.config/duck/persona.json 新建这个文件,比如:
{
"name": "小鸭",
"name_pinyin": "xiao3 ya1",
"name_aliases": ["小丫", "小雅", "晓鸭"],
"description": "小鸭是一只二十厘米高的小机器鸭子。它会走路、坐下、转头、嘎嘎叫,听得懂中文,用鸭叫和动作回应。",
"character": "你是小鸭,一只小机器鸭子,性格温和、好奇,喜欢和人待在一起。"
}
name_aliases:语音识别把名字听错时会写成的词。先空着,叫它几次名字,再用tail -n 30 ~/robot/recs/voiced-service.log看它听成了什么,把听错的词加进来。不要加单个字。- 保存后重启三个服务才会生效:
systemctl --user restart lifed-dev voiced-dev duckweb-dev。
手机网页。 手机和鸭子连同一个 WiFi,在浏览器里打开 http://鸭子的IP:8088,能看到它听到了什么、说了什么,以及它现在的状态。安卓手机大多不认 .local 名字,要用 IP。
用语音连新 WiFi。 对它说“(名字)连网”,把手机上 WiFi 或个人热点的分享二维码举到它脸前 20–30 厘米,它连上后会念出自己的网页地址。之后问“(名字)你的地址”,它会再念一遍。带鸭子去新地方时就用这个办法。
HD-1910 版要注意
这些是装第一只 HD-1910 鸭子时踩过的坑,HL-2915 版不用管。
- 只能用 2S 电池。 舵机由电池直接供电,插上 3S 会直接烧坏舵机,软件拦不住。2S 和 3S 电池要用不同的插头,免得插错。
- 扩展板要先换一颗电阻。 把 HAT 上的 R11 从 130 kΩ 换成 91 kΩ(只换 R11,R6 别动),不然 2S 下 HAT 起不来。
- PDB 的舵机座要反向焊。 HD-1910 原装线的针序和 PDB 相反,所以 J4/J6 座子要反过来焊(线的 1 号针对丝印 3/D)。第一片焊完,先测一下通断。焊完后用异丙醇刷洗干净:助焊膏残留会导电,让总线成片出错。
- 新舵机先过向导。 HD-1910 出厂是模式 4,直接用会失控。在工作台「舵机」页用新舵机向导,选 HD-1910,它会写好 ID、500k 波特率、模式 0 和卸载条件。只改了 ID 的舵机不能用。
- 多圈计数。 关节被掰过 0/4095 后,读数会变成负数或大于 4095,要拔电池断电才能清掉。上力前先看一眼(见第五步)。
- 电量低于约 30% 时,别让它起身。 2S 电压掉得快,起一次身就可能把扩展板的电压拉到关断线以下,导致整机重启。尽量用内阻小的电池。
- 系统里要先运行
duck-model hd1910(见第二步)。它会换成为 HD-1910 重新训练的走路策略和更强的航向保持;这个版本还没有坐下的动作。 - 重量。 策略按 806 g 的整机训练。外壳或电池明显更重时,站立和走路的余量会变小。
常见问题
| 现象 | 多半是 | 怎么办 |
|---|---|---|
| 插卡后 Windows 要求格式化 | 卡里是 Linux 分区 | 点取消,不影响使用 |
ping duck-XXXX.local 不通 |
网络不支持这种名字,或鸭子没连上 WiFi | 去路由器设备列表找 IP;找不到就接显示器,用 nmtui 重连 |
| 工作台报连不上机器人 | 免密没做好,或 IP 变了 | 重做第三步的第 3 条测试;用 --host 带上新地址重开工作台 |
| 舵机页拒绝操作 | robotd 占着总线 | 在「总览」里停掉 robotd;服务已经打开的用 duck-services off |
| 零位页没有读数 | robotd 没在运行 | 在「总览」里启动 robotd |
| 标定写入后又变回旧值 | 改过配置后没重开工作台 | 每次写完映射,或在鸭子上手动改过配置,都要重开工作台 |
| 某个关节读数显示红色(多圈) | 舵机转过了 0/4095 跳变点 | 断一次电池清掉,再用「当前位置设为中位」把零位挪开 |
| 叫名字没反应 | 语音识别把名字听成了别的字 | 看 voiced 日志,把听错的词加进 name_aliases |
| 走着走着不听摇杆了 | 头部舵机到了 70 °C,在休息 | 等它凉到 45 °C 以下自己恢复 |
| 电池一接上就报电压不对 | 电池节数和舵机不配(HL-2915 要 3S、HD-1910 要 2S),2S 充到了 8.4 V 以上,或者电量太低 | 换节数对、充满的电池;HD-1910 版确认运行过 duck-model hd1910 |
| 手柄连不上 | 没切到 Xbox 模式,或配对时没选 transport bredr |
在 bluetoothctl 里 remove 手柄地址,重做配对 |
| 摄像头测试报“被占用” | visiond 在用摄像头 | systemctl --user stop visiond-dev 后再测 |
附录:常用命令
以下命令都在 ssh 登录鸭子后运行,除了关机都不用 sudo。
| 命令 | 作用 |
|---|---|
duck-services status |
看七个服务是否在运行、策略加了没有 |
duck-services on |
标定完后打开全部服务,开机自启 |
duck-services off |
停掉全部服务,回到标定状态(先让它躺下) |
duck-model |
看 / 切换舵机型号(hl2915 或 hd1910) |
systemctl --user restart lifed-dev voiced-dev duckweb-dev |
改完名字后让它生效 |
tail -n 30 ~/robot/recs/robotd-service.log |
看舵机控制的日志;把 robotd 换成 lifed / voiced / padd,看对应服务的日志 |
cat /var/lib/duck/firstboot.log |
看第一次开机时起名和生成叫声有没有成功 |
ip -4 a show wlan0 |
看 IP |
sudo nmtui |
连别的 WiFi |
passwd |
改登录密码 |
sudo poweroff |
关机。等 10 秒再拔电池;直接拔电可能丢掉最近 10 分钟写的文件 |
工作台的更多用法(新舵机配置向导、IMU 烧录、各项测试的判据)见仓库里的 tools/bringup/README.md。