# ubtech_servo_firmware **Repository Path**: wight3/ubtech_servo_firmware ## Basic Information - **Project Name**: ubtech_servo_firmware - **Description**: 优必选舵机固件:自研 SAMD10 固件(飞特 SCS 协议兼容)+ 跨平台上位机 + 一键烧录工具 - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 6 - **Created**: 2026-09-29 - **Last Updated**: 2026-09-29 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # MicroDuck 总线舵机 —— 固件 · 上位机 · 烧录工具 把一颗便宜的 **SAMD10 总线舵机**(原厂驱动板)刷成我们自己的固件,让它对上位机 **完全表现为一颗飞特 SCS 系列舵机**(帧格式 / 指令集 / 控制表地址全部对齐), 再配一套**跨平台图形上位机**:单舵机调试 / 总线总览 / 一键烧录。 > 完整的**使用说明书**(产品参数、接线、短接、协议、寄存器全表、报错对照)在 > **[`舵机使用说明书.md`](舵机使用说明书.md)**(网页版 [`舵机使用说明书.html`](舵机使用说明书.html), > 双击就能看)。本 README 只讲"这个仓库怎么用"。 --- ## 一、这个仓库里有什么 | 文件 / 目录 | 说明 | |---|---| | `scs_gui.py` | **上位机本体**(三页:单舵机调试 / 总线总览 / 烧录固件) | | `flash_gui.py` | **烧录器**:上位机第 3 页复用的逻辑,也能单独跑(网页版 `http://127.0.0.1:8777`) | | `run_gui.command` | macOS 双击启动(会先检查 tkinter / pyserial 缺不缺) | | `run_gui.bat` | Windows 双击启动(同上) | | `requirements.txt` | 上位机依赖(只有 `pyserial`;tkinter 随 Python 装) | | `舵机使用说明书.md` / `.html` | **完整说明书**(界面右上角【📖 说明书】打开的就是它) | | `README_上位机.md` | 脚本版的使用说明 + 别人用之前要装什么 | | `README_免安装.md` | 免安装版(`.app` / `.exe`)的使用说明 | | `firmware/` | **固件源码**:`main.c`(v5.55,单文件约 3400 行)+ `link.ld` + `ours.bin` + `README_固件.md` | | `ours.bin` | 当前固件(和 `firmware/ours.bin` 同一份,13682 字节) | | `setid.py` `setreg.py` `cfgsnap.py` `fwcheck.py` `restore_cfg.py` | 命令行小工具(设 ID / 读写寄存器 / 快照 / 校验固件 / 恢复出厂配置) | | `loopback_test.py` | 总线回环自测(把适配器 TX-RX 短接后跑) | | `flash_bin.sh` `flash_bin_stlink.sh` | 命令行烧录(CMSIS-DAP / ST-Link) | | `dsu_erase.tcl` `fix_userrow2.tcl` `samd_local.cfg` | **原厂锁片解锁**用(整片擦除 + 写熔丝),被 `flash_gui.py` 调用 | | `md2html.py` | 改完 `说明书.md` 重新生成 html:`python3 md2html.py 舵机使用说明书.md` | | `build/` | 打包脚本(在 Mac / Windows 上重打发行包) | | `dist/` | 已经打好的 4 个发行包(见下) | | `docs/` | 额外的开发/原理笔记(`烧录与解锁原理.md`) | --- ## 二、上位机长什么样 三页,最上面那条工具栏(串口 / 波特率 / 连接 / ID / PING)三页共用。 | 页 | 干什么 | |---|---| | **① 单舵机调试** | 调一颗:实时位置、目标位置滑条(可勾"拖动即发送")、速度与加速度、力控(力矩模式 / 重力前馈 / 碰撞检测)、LED、整张寄存器表(点一行就显示该行的完整说明) | | **② 总线总览** | 一次看**总线上所有舵机**:每颗一行(版本 / 模式 / 当前位置+进度条 / 速度 / 负载 / 电流 / 电压 / 温度),每行一个目标位置滑条;还有**随机同步发送**(一条 `SYNC_WRITE` 让所有舵机同时动,演示很直观) | | **③ 烧录固件** | 一键烧录:连接 →(必要时)整片擦除 → 写熔丝 → 断电重上电 → 烧录 → 校验 → 设 ID + 写标准配置 → 配置快照 | --- ## 三、快速开始 ### 方式 A:免安装(推荐给不搞开发的人) 下载 `dist/` 里对应的包,解压双击,**不用装 Python**: | 系统 | 包 | 备注 | |---|---|---| | macOS(Apple Silicon) | `microduck_servo_gui_mac_app.zip` | 第一次可能被 Gatekeeper 拦 → 右键【打开】→ 再点【打开】 | | Windows | `microduck_servo_gui_win_exe.zip` | 第一次可能弹 SmartScreen → 更多信息 → 仍要运行 | > 只有"**烧录固件**"这一页还需要系统里有 **openocd**(它是独立程序,没打进去): > mac `brew install open-ocd`;Windows 把 openocd 目录放到程序旁边 > (`openocd\bin\openocd.exe`)或设环境变量 `MICRODUCK_OPENOCD=...\openocd.exe`。 > 前两页(调试 / 总线总览)什么都不用装。 ### 方式 B:脚本版(能改代码,用这个) | 系统 | 包 | |---|---| | macOS | `microduck_servo_gui_mac.zip` → 双击 `run_gui.command` | | Windows | `microduck_servo_gui_win.zip` → 双击 `run_gui.bat` | 别人要用之前得先装(详细版见 [`README_上位机.md`](README_上位机.md)): ```bash # macOS python3 -m pip install --user pyserial # 串口 brew install python-tk # 只有 Homebrew 的 python 才需要; brew install open-ocd # 只有烧录才需要 # Windows python -m pip install pyserial # 装 python.org 版时勾上 tcl/tk ``` ### 方式 C:直接从这个仓库跑 ```bash git clone <这个仓库> cd microduck_servo python3 -m pip install --user -r requirements.txt python3 scs_gui.py # macOS python scs_gui.py # Windows ``` > ⚠ `scs_gui.py` 依赖**同目录**的 `flash_gui.py` / `fwcheck.py` / `setid.py` / > `restore_cfg.py` / `cfgsnap.py` 和 `舵机使用说明书.*` —— > **请保持这些文件在同一层**,不要只挑几个文件拷走。 --- ## 四、接线(先看这个,不然连不上) 舵机侧面那个**方形 5 针口**: | 针 | 含义 | |---|---| | **GND** | 地(和调试器共地) | | **VCC** | 舵机电源 **6~9 V**(不要接调试器的 3.3 V) | | **DIO** | 半双工单总线数据 / 也是 SWD 的 **SWDIO** | | **CLK** | 总线时钟口 / 也是 SWD 的 **SWCLK** | | **RST** | 复位 | * **平时用**(调试、跑策略):`GND + VCC + DIO` 接 USB-TTL 总线适配器,波特率 **1 Mbps**。 * **烧录固件**:`GND + DIO + CLK` 接调试器(**RST 可不接,VCC 千万别接**)。 * **连不上时的关键一招**:把 **CLK 和 GND 短接 → 上电 → 松开**,再点烧录 (原理见说明书 §3.3)。 --- ## 五、烧录固件 打开上位机**第 3 页**,选模式 → 点【▶ 一键烧录】: | 模式 | 什么时候用 | 会不会动熔丝 | |---|---|---| | **自动(默认)** | 通用 | 已解锁 → 不动,直接烧;未解锁 → 自动解锁 | | **只烧录** | 给自己刷过的舵机升级固件 | 绝不动熔丝 | | **强制解锁 + 烧录** | **全新原厂舵机**第一次刷我们的固件 | **整片擦除**,不可恢复 | 步骤条:`① 连接 → ② 整片擦除 → ③ 写熔丝 → ④ 断电重上电 → ⑤ 烧录 → ⑥ 校验 → ⑦ 设 ID + 写配置 → ⑧ 快照` * 第 ①~③ 步只在需要解锁时做,已解锁的舵机会显示"— 跳过"; * 走到第 ④ 步要**手动断电重上电**(User Row 熔丝只在 POR 时重载),程序会停下来等你点【继续】; * 第 ⑦ 步自动设 ID 并写**标准台架配置**(P=20 / D=8 / I=0、限位 540~3800、PWM 20 kHz、上电位置=保持当前位置…); * 烧录时程序会**自动把串口断开**(SWD 会把内核停住,串口不能同时用),烧完自动接回。 > ⚠ **给原厂锁片解锁只能用 CMSIS-DAP**(free-dap,免驱):那一步要直写 DSU 寄存器, > ST-Link 走 HLA 通道拿不到这种底层访问。已经解锁过的舵机,ST-Link 一样能烧。 原理、坑和排查(BOOTPROT / DSU / WDT 熔丝 / User Row 写入顺序)都记在 **[`docs/烧录与解锁原理.md`](docs/烧录与解锁原理.md)**;现象→处理见说明书 §5.4。 --- ## 六、固件 一颗 **ATSAMD10D14AMU**(16 KB Flash / 4 KB RAM)上的单文件固件,**v5.55**。 在 macOS 上编译(Homebrew clang + lld): ```bash brew install llvm lld export PATH=/opt/homebrew/opt/llvm/bin:/opt/homebrew/bin:$PATH cd firmware clang --target=arm-none-eabi -mcpu=cortex-m0plus -mthumb -Os \ -ffreestanding -fno-builtin -Wall -Wextra -nostdlib -nostartfiles \ -fuse-ld=lld -T link.ld -Wl,--gc-sections -o fw.elf main.c llvm-objcopy -O binary fw.elf fw.bin ``` 编译命令和接线要点也写在 [`firmware/README_固件.md`](firmware/README_固件.md)。 **只改注释不会改变二进制**(编完对比 sha256 就知道了)。 固件特性(相对原厂):飞特 SCS 协议兼容、力控(电流估计 / 力矩模式 / 重力前馈 / 碰撞检测)、 状态 LED、**上电目标位置可设**(默认不归中)、参数掉电保存。 --- ## 七、命令行小工具 | 脚本 | 用法 | 干什么 | |---|---|---| | `setid.py` | `python3 setid.py <串口> <新ID> [当前ID]` | 改 ID(ID 254 = 广播) | | `setreg.py` | `python3 setreg.py <串口> <地址> <值>` | 写一个寄存器 | | `cfgsnap.py` | `python3 cfgsnap.py <串口> ` | 把所有配置读出来存成快照 | | `fwcheck.py` | `python3 fwcheck.py ` | 校验固件文件 | | `restore_cfg.py` | `python3 restore_cfg.py <串口> ` | 恢复出厂/标准配置 | | `loopback_test.py` | `python3 loopback_test.py <串口>` | 总线回环自测 | | `flash_bin.sh` / `flash_bin_stlink.sh` | `bash flash_bin.sh` | 命令行烧 `ours.bin` | --- ## 八、重新打发行包 ```bash # macOS:一键重打脚本版 zip + 免安装 .app zip(并自检、拷到桌面) bash build/rebuild_mac_pkg.sh # 只把某个目录打成 mac 能双击运行的 zip(保留可执行位) python3 build/make_mac_zip.py --src <目录> --out ``` **为什么 Mac 的包要在 Mac 上打**:Windows 上生成的 zip,macOS 的 Finder(Archive Utility / `ditto`)**不认** `external_attr` 里的 Unix 权限位,解压出来 `run_gui.command` 是 0644, 双击会报"没有正确的访问权限"。在 Mac 上用 `zip` 打就没这个问题(已验证)。 --- ## 九、常见问题(速查,详细版见说明书 §8) | 现象 | 处理 | |---|---| | 双击 `run_gui.command` 说没有权限 | `chmod +x run_gui.command` | | `ModuleNotFoundError: tkinter` | 用 python.org 的 Python,或 `brew install python-tk` | | 界面里连接串口报错 | `python3 -m pip install --user pyserial` | | 烧录页说找不到 openocd | `brew install open-ocd`,或设 `MICRODUCK_OPENOCD` | | PING 没反应 | 波特率先确认是 **1 Mbps**、信号线接在 **DIO**、舵机有独立 6~9 V 供电 | | 总线上一颗都不应答 | 检查总线驱动模式=1、波特率、共地 | | 上电舵机自己抽一下 | 上电目标位置被设成固定角度了 → 【取消上电位置】(写 0xFFFF) | | 烧录后 `NVM lock error` | 熔丝还没重载 → **断电重上电**再来一次 | --- ## 十、版本 | 项 | 值 | |---|---| | 固件 | **v5.55**(`firmware/main.c` 顶部 `FW_VER_MAJOR/MINOR`,寄存器 3/4 读出来就是它) | | 文档 | 2026-09-27 | | 默认波特率 | 1 Mbps(可切 500 kbps) | | 默认 ID | 0(广播)—— 新舵机第一次上电要先设 ID | | 角度范围 | 0~4095 counts(≈0.088°/count),出厂限位 540~3800 | | 工作电压 | 6~9 V(8~9 V 性能最好) | --- ## 十一、参考 协议与内存表按飞特官方文档的格式编写: * 《SCS 通信协议》 * 《SCSCL 舵机内存表手册》 --- ## 许可 Apache License 2.0,见 [LICENSE](LICENSE)。