NeuralNexus Arm:从 CAD 到数字孪生的自研 6 自由度机械臂
📌 本分册目标
这一台和前几册的路线都不同:不是复刻现成开源臂,而是从零手工做一台——机械结构、嵌入式固件、运动学求解、数字孪生、视觉抓取全部自研,没买套件、也没拼现成方案。它的核心命题只有一句话:一条指令,让真实机械臂与 3D 数字孪生体同步运动。
作者团队(Lasan Perera 等 5 人)把整条链路打通得很完整,所以它特别适合当作「一台机械臂到底由哪些层组成」的活教材:SolidWorks 建模 → Simscape Multibody 数字孪生 → MATLAB 逆运动学求解 → USB CDC 115200 → STM32H743 实时伺服 → 6 路步进 + 舵机夹爪 → AS5047P 绝对编码器反馈。
本分册按 系统链路 → 硬件栈 → 关节传动 → 控制与协议 → 数字孪生 → 视觉 → 资料下载 → 踩坑要点 八段走。它的价值不在于「照着装一台」,而在于学习每一层之间怎么接口、怎么验收。
🧭 第一段:系统链路(先理解数据怎么流)
抓住这条链路,后面每一节都能对号入座:上位机算运动学 → 串口下发关节角 → 下位机做实时伺服。中间用一条极简的文本协议解耦,两侧可以独立开发、独立调试。
SolidWorks CAD → Simscape Multibody 数字孪生 → MATLAB 逆运动学求解器
│
USB CDC @ 115200 baud(关节角文本协议)
▼
STM32H743 @ 420 MHz → 6 路步进电机 + 夹爪舵机(2 kHz 控制环)
│
AS5047P 绝对编码器(SPI 反馈,14 bit)
│
浏览器 Web Serial 控制面板(Chrome / Edge,无需 MATLAB 授权)
- 几何层:SolidWorks 出实体,导入 Simscape Multibody 得到可仿真的刚体树(
importrobot('Assem1')),连杆尺寸与关节限位在这一层定义。 - 规划层:MATLAB 用 Robotics System Toolbox 的
inverseKinematics解逆运动学,得到 6 个关节角。 - 传输层:6 个逗号分隔的角度值 + 换行,走 USB CDC 虚拟串口,115200 8N1。
- 执行层:STM32H743 在 TIM6 中断里以 2 kHz 统一推进 6 轴脉冲,夹爪走 50 Hz PWM。
- 反馈层:6 片 AS5047P 通过 SPI1 读绝对角度(mode 1,14 bit),用于校验与后续闭环。
- 替代入口:不想装 MATLAB?官方提供纯浏览器控制面板,用 Web Serial API 直接连串口下发角度。
🔧 第二段:硬件栈(选型逻辑比参数更重要)
| 类别 | 配置 |
|---|---|
| MCU | STM32H743VITx(Cortex-M7 @ 420 MHz,25 MHz HSE → PLL:M=5 / N=168 / P=2) |
| 步进电机 | 2 × NEMA 24(J2 / J3)· 1 × NEMA 23(J1)· 3 × NEMA 17(J4 / J5 / J6) |
| 驱动器 | 2 × CL57T 闭环(J2 / J3)· 1 × DM542 开环(J1)· 3 × TMC2209 板载 1/8 细分(J4 / J5 / J6) |
| 编码器 | 6 × AS5047P 磁绝对编码器,14 bit(16384 计数/圈),SPI1 mode 1 |
| 夹爪 | 舵机 · TIM1_CH3 · 50 Hz PWM(930 µs 开 / 1100 µs 合) |
| 外设分配 | TIM1_CH3 夹爪 · TIM2_CH2 蜂鸣器 · TIM6 步进 ISR @ 2 kHz · USB CDC 虚拟串口 |
| 控制环 | TIM6 ISR @ 2 kHz(PSC 74 / ARR 499),tick 周期 500 µs |
| 接线拓扑 | M1~M3 共阳(STEP+/DIR+/ENA+ 接外部 +5V,STM32 开漏吸收)· M4~M6 推挽 3.3V 直连 |
OUTPUT_PP(3.3V 直驱),外部 CL57T / DM542 用开漏 OUTPUT_OD(共阳接法,低有效)。因此固件里 Stepper_SetEnableM4M5M6(false) 恰恰是「使能」外部驱动器的动作——代码审阅时看起来像 bug,但它不是。改这一处之前先想清楚极性。⚙️ 第三段:关节传动与脉冲当量(写控制器前先抄下来)
| 关节 | 角色 / 电机 / 减速比 / 脉冲每圈 |
|---|---|
| J1 | 底座旋转 · NEMA 23(DM542)· 1:7 · 2800 |
| J2 | 肩 · NEMA 24(CL57T 闭环)· 1:30 · 5000 |
| J3 | 肘 · NEMA 24(CL57T 闭环)· 1:30 · 5000 |
| J4 | 腕俯仰 · NEMA 17(TMC2209 1/8)· 1:1 · 设计值 1600 |
| J5 | 腕滚转 · NEMA 17(TMC2209 1/8)· 1:1 · 设计值 1600 |
| J6 | 末端旋转 · NEMA 17(TMC2209 1/8)· 1:1 · 设计值 1600,实测 3200 |
| 关节限位 | J1 ±180° · J2 −70°~70° · J3 120°~240° · J4 ±180° · J5 60°~300° · J6 ±180° |
| 索引映射 | jointToMotor[6]——逻辑关节编号 ≠ 电机接线顺序,映射表集中在固件里,改接线必须同步改这张表 |
pulsesPerJointRev 填错,整机角度会等比偏移——这也是「绝对定位目前只在 1:1 腕关节可行」的直接原因。🖥️ 第四段:通信协议与控制方式
| 指令 | 格式与含义 |
|---|---|
| 关节移动 | 6 个逗号分隔的角度值(度)→ 0,-50,60,-80,-90,50;固件换算成脉冲并回显 steps: ... |
| 夹爪 | G,1 闭合 / G,0 打开(TIM1_CH3 舵机 PWM) |
| 归零 | HOME——编码器零点标定 |
| 测试 | TEST——30° 编码器标定流程 |
| 工作模式 | 相对模式:每条指令都是相对当前位置的增量;绝对定位与 J3/J5 的 180° 偏移已写好但暂时禁用,等编码器归零完成后再启用 |
上位机侧有两种用法:MATLAB 会话(算 IK + 驱动仿真 + 串口下发)或浏览器控制面板(Chrome / Edge 打开 HTML,点 Connect 选串口即可操控,不需要 MATLAB 授权)。MATLAB 会话的标准开场如下,第一步必须先建 jointData——Simscape 的 From Workspace 模块依赖它:
% 每次开新会话都先跑这一段
jointData = zeros(2,7); % 必须最先执行
load_system('Assem1');
robot = importrobot('Assem1');
robot.DataFormat = 'row';
limitsDeg = [-180 180; -70 70; 120 240; -180 180; 60 300; -180 180];
for i = 1:6
robot.Bodies{i}.Joint.PositionLimits = deg2rad(limitsDeg(i,:));
end
ik = inverseKinematics('RigidBodyTree', robot);
weights = [1 1 1 1 1 1];
q0 = homeConfiguration(robot);
s = serialport("COM9", 115200); % 实际端口以设备管理器为准
% 常用动作
armIK(robot, ik, weights, q0) % 交互式 IK 滑块工具
goToXYZ(robot, ik, weights, q0, [-0.15 0.30 0.10], s) % XYZ → 真机 + 同步孪生
moveBoth(s, [0 10 0 0 0 0]) % 真机与仿真同时相对移动
armWave(s) % 挥手动作
writeline(s, "HOME") % 编码器归零
enc | ... 会淹没串口,导致 MATLAB 的 readline() == "END" 永久等待,仿真与真机一起冻住。同一时间只能选一种模式,或给读取方加超时。🧪 第五段:数字孪生与演示(这台机器的招牌)
Simscape Multibody 的 Mechanics Explorer 里放着一台与真机同尺寸的实体臂,MATLAB 每次解完 IK 就把关节角写进 jointData,From Workspace 模块读这个两列时间表驱动 6 个转动副——点 Run,屏幕上的仿真臂与桌面上的真机会走同一个动作。
- 位置锁定(Position Lock):末端点固定在空间一点,工具姿态扫过一圈——看连杆如何在保持端点不动的前提下流动。
- 姿态锁定 + XYZ 扫掠(Orientation Lock + XYZ Sweep):工具角度锁定,末端沿 X / Y / Z 各扫一遍。
- 动作库:垂直方形、挥手、抓取放置等序列已录好(
drawSquare.m/armWave.m/objectPicking.m等)。 - 零空间演示:
nullspaceDemo.m——同一末端位姿下改变关节配置,理解 6 轴臂的冗余自由度。 - 手动驱动:
set_param('Assem1','SimulationCommand','start')可在脚本里直接启动仿真,方便批量验证。
👁️ 第六段:视觉子系统(像素 → 世界坐标 → IK)
| 环节 | 做法与指标 |
|---|---|
| 相机内参 | 20 张棋盘格标定图 → 重投影误差 0.6863 px(calibrate.py / calibrate picam.py) |
| 相机安装 | 刚性固定,高度 41 cm(外参标定以该位姿为前提) |
| 外参映射 | 3×3 单应矩阵(homography)把像素坐标换成毫米级世界坐标(homography.py) |
| 目标识别 | 颜色分割(segmentation.py)与 YOLO 检测(自定义训练模型:纸箱、糖果等) |
| 闭环 | 识别结果 → 世界坐标 → 送进逆运动学求解器 → 关节角下发 → 夹爪抓取 |
📥 资料下载(官方全量镜像 · 免翻墙)
下列文件均为官方仓库原文件的本站镜像,按用途分目录存放,可直接右键另存。全部资源共 248 个文件 / 约 27.7 MB。
docs · 报告与演示(EDR Documentation)
| 文件 | 大小 | 说明 |
|---|---|---|
| Neural_Nexus_Final_Report.pdf | 3.8 MB | 最终技术报告,机械 / 电气 / 固件 / 运动学 / 视觉全链路文字说明,最值得先读的一份 |
| Neural_Nexus_Final_Presentation.pdf | 6.9 MB | 最终答辩演示,含整机照片、结构爆炸图与结果截图 |
| Neural_Nexus_Project_Pitch.pdf | 0.4 MB | 立项方案(Project Pitch),讲清设计目标与选型思路 |
schematics · 电气原理图
| 文件 | 大小 | 说明 |
|---|---|---|
| MCU_Schematic.pdf | 0.3 MB | 主控板原理图(STM32H743 最小系统、驱动器接口、电源) |
| Encoder_Schematic.pdf | 0.12 MB | AS5047P 编码器板原理图(SPI 菊花链 / 磁铁安装位置) |
gerber · PCB 制造文件
| 文件 | 大小 | 说明 |
|---|---|---|
| MCU.rar | 0.24 MB | 主控板 Gerber 包,可直接送厂打样 |
| nema17.rar | 21 KB | NEMA 17 电机安装 / 转接板 |
| nema17pancake.rar | 20 KB | NEMA 17 扁电机(pancake)转接板 |
| nema23.rar | 22 KB | NEMA 23(J1)安装板 |
| nema24.rar | 22 KB | NEMA 24(J2 / J3)安装板 |
eda · 嘉立创 EDA 工程(本站补充 · 可编辑源文件)
| 文件 | 大小 | 说明 |
|---|---|---|
| NeuralNexus_Arm.eprj2 | 1.3 MB | 嘉立创 EDA 专业版工程包:含 1 张原理图(Schematic1 / P1)与 1 块 PCB(PCB1),下载后「文件 → 打开 → 本地工程」即可继续修改并直接下单打样 |
| preview_schematic.webp · preview_pcb.webp | 23 KB / 112 KB | 工程内置的原理图与 PCB 缩略图,下载前可先预览 |
.eprj2 是嘉立创 EDA 专业版(EasyEDA Pro)的工程格式(本质是一个 SQLite 数据库),标准版无法打开。⚠️ 该工程为本站自制补充资料,不属于官方仓库内容,与官方原理图可能存在差异,实际打样请以
gerber/ 官方文件为准。ik-matlab · MATLAB / Simscape 工程与模型
| 文件 | 大小 | 说明 |
|---|---|---|
| GUIDE.txt | 6 KB | 命令速查卡:会话初始化、IK 求解、滑块工具、真机下发、两个演示的完整调用顺序 |
| REQUIREMENTS.txt | 0.6 KB | MATLAB 版本与工具箱要求(Robotics System Toolbox 等) |
| Assem1.slx | 0.24 MB | Simscape Multibody 数字孪生模型,含 6 个转动副与 From Workspace 数据入口 |
| Assem1_DataFile.m | 10 KB | 模型自动生成的参数文件(连杆尺寸 / 质量 / 惯量),改结构后由 Simscape 重新导出 |
| Part1.STL ~ Part6.STL、endeff.STL | 共 0.9 MB | 7 个连杆 / 末端 STL 网格,仿真可视化用 |
| Part1~Part6 / endeff · STEP | 共 0.58 MB | 同上的 STEP 实体,可用于改结构或转其他格式(本站的 在线 STL→STP 转换工具也能处理这类模型) |
| armIK.m · goToXYZ.m · moveBoth.m | 1~2 KB | 交互式 IK 工具、XYZ 目标点下发、真机 + 仿真同步相对移动 |
| drawSquare.m · armWave.m · objectPicking.m | 1~3 KB | 动作库:垂直方形、挥手、抓取放置序列 |
| demoPositionLock.m · demoOrientationLock_XYZsweep.m | 1.5~1.7 KB | 两个锁定演示:位置锁定与姿态锁定 + XYZ 扫掠 |
| nullspaceDemo.m · findDemoPoint.m | 1.4~1.8 KB | 零空间冗余演示与可达点搜索 |
vision · 视觉脚本与标定数据
| 文件 | 大小 | 说明 |
|---|---|---|
| calibrate.py · calibrate picam.py | 5.6~6.2 KB | 棋盘格内参标定(普通相机 / 树莓派 PiCam 两版) |
| homography.py | 3.7 KB | 单应矩阵求解:像素坐标 → 世界坐标 |
| segmentation.py · detect_picam.py | 4.6~4.8 KB | 颜色分割与目标检测主程序(含 YOLO 调用) |
| camera_matrix.npy · dist_coeffs.npy | 200 / 168 B | 标定结果:3×3 内参矩阵与畸变系数 |
| candy.yaml | 183 B | 颜色阈值参数(糖果检测示例) |
| calib_photos/(20 张) | 共 1.4 MB | 用于复现标定的棋盘格照片 |
firmware · STM32H743 固件工程(170 文件 / 11.8 MB)
| 路径 | 说明 |
|---|---|
| REQUIREMENTS.txt | 构建与硬件说明:工具链、引脚映射表、脉冲当量、USB CDC 三个必要条件、串口协议全文 |
| Test1.0.ioc | STM32CubeMX 配置(时钟树、TIM6 2 kHz、USB CDC、SPI1 等) |
| Core/Src/main.c | 主程序:步进推进、夹爪 PWM、协议解析、编码器读取都在这里 |
| Core/Inc/main.h · stm32h7xx_it.c | 引脚定义与中断服务函数 |
| NeuralNexusArm1.0 Debug.launch | STM32CubeIDE 烧录 / 调试配置,导入后可直接编译下载 |
| STM32H743VITX_FLASH.ld · Drivers/ + Middlewares/ + USB_DEVICE/ | 链接脚本与 ST HAL / CMSIS / USB 中间件(工程开箱可编译,无需另装固件包) |
firmware/REQUIREMENTS.txt(一页讲清全部分配),再看 Core/Src/main.c 里的步进推进与协议解析,最后对照 ik-matlab/GUIDE.txt 理解上位机怎么调它。🚀 第七段:快速开始(三步跑通)
- 固件:STM32CubeIDE 导入
firmware/工程(含.launch配置)→ 编译 → ST-Link 烧录 → 确认板子枚举出 USB 虚拟串口。若从 CubeMX 重新生成代码,必须重新注释掉MX_SDMMC1_SD_Init()——没插 SD 卡时它会直接陷进Error_Handler()导致开机死机。 - 上位机:MATLAB 打开
ik-matlab/,按GUIDE.txt第 0 节初始化(jointData→importrobot→ 关节限位 → IK 求解器 → 串口),再跑goToXYZ或armIK。 - 免 MATLAB 路径:用 Chrome / Edge 打开官方控制面板 HTML → Connect arm → 选串口 → 直接下发角度。接管前先
clear s释放 MATLAB 占用的串口,否则打不开。
RCC_USBCLKSOURCE_HSI48);② HAL_PWREx_EnableUSBVoltageDetector() 是否在 MX_USB_DEVICE_Init() 之前调用;③ 用的是板载 USB-C(PA11 / PA12)而不是 ST-Link 的 USB 口、且线材支持数据。COM 号乱跳就去设备管理器卸载隐藏设备后重插。🐛 第八段:踩坑要点(这一节最省时间)
- 编码器「幽灵漂移」的根因是 -1 哨兵值:读函数失败时返回
-1,这些值被混进 30 次采样均值,导致静止关节读数摆动 60~70°——传感器一直是好的。求均值前过滤掉-1,重复精度立刻回到 ±0.01°。关键线索是「降速反而更糟」:真实的信号完整性问题永远随降频而改善。 - ISR 重定时会缩放错一倍多:从 50 kHz 改到 2 kHz 时,
dt = 0.00002与stepInterval = 50000/speed错了 25 倍,表现为所有电机爬行。正确值是dt = 0.0005、stepInterval = 2000/speed。 - 归零必须用原始电机索引:
Stepper_MoveAll()(不加jointDir)才是对的,用关节索引会出现「双向符号翻转」bug。 - 10° 分块发送:长距离移动拆成小块,既不丢动作也不用改固件。
- 遥测与命令二选一:周期性打印会把握手包冲掉,别让两者同时占用串口。
- Simscape 每个关节只留一对配合:多一个平行 / 垂直配合就把转动副锁死。
- 挪动相机必须重标外参:单应矩阵只在标定时的相机位姿下成立,内参可以继续用。
- 脉冲当量必须逐轴实测:J6 实测 3200 而非设计 1600,说明细分设置与实际驱动不总是一致。
- 别把它当成品设备:官方 README 标注 Status: Active Development,可能存在 bug,使用风险自担。
📊 项目当前状态(官方自评)
| 子系统 | 状态 |
|---|---|
| 6 轴步进控制 / USB CDC / 关节映射 /方向符号 | ✅ 完成 |
| MATLAB IK 流水线 / 同步数字孪生 / 夹爪舵机 | ✅ 完成 |
| 编码器读取(AS5047P,重复精度 ±0.01°) | ✅ 完成 |
| 动作库(5 个序列 + 挥手 + 方形)与浏览器控制面板 | ✅ 完成 |
| 归零 J4 / J5 / J6 | 🟡 可用,标度验证中 |
| 归零 J1 / J2 / J3 | 🔴 受阻(编码器安装比例导致多义性) |
pulsesPerJointRev 标定 | 🟡 J6 实测 3200(非设计 1600),其余待测 |
| 绝对定位 | 🟡 目前仅 1:1 腕关节可行 |
| 3.3 V LDO 更换 | 🔴 需先测 LDO 焊盘处实际 VIN |
| 闭环步进修正 / 视觉抓取联调 | ⚪ 计划中 |
⚖️ 许可与使用提示
- 许可证:仓库以 Apache-2.0 许可发布(见仓库根目录 LICENSE)。允许商用与修改,但需保留版权与许可声明、并说明修改内容。
- 第三方组件:固件工程中的
Drivers/(ST HAL / CMSIS,含LICENSE.txt)、Middlewares/、USB_DEVICE/版权归 STMicroelectronics,另有第三方许可(部分为 BSD-3-Clause),再分发时不要删除其许可文件。 - 本站角色:本站为资料镜像与中文讲解,不是项目作者、也不对文件内容做修改;如与官方仓库不一致,请以 官方仓库为准。
- 安全提示:这是一台自重与扭矩都不小的机器,调试时务必限制关节速度与工作空间,先小角度点动再整段运动,旁边不要站人、不要放易损物。
🔗 官方资料直达
- GitHub · 6-dof-arm-neuralnexus主仓库:README 全文、报告、原理图、Gerber、固件、MATLAB 与视觉脚本
- GitHub · NeuralNexusArm_CodeBase(固件仓库)STM32H743 固件的独立代码库,README 徽章指向同一套固件
- 本站镜像 · README.md37 KB 官方说明全文(电机选型、传动、仿真、硬件、软件架构、快速开始)
- 本站镜像 · 固件构建与协议说明引脚映射、脉冲当量、USB CDC 三个必要条件、串口协议
- 本站镜像 · MATLAB 命令速查卡从会话初始化到两个锁定演示的完整命令序列
❓ 常见问题
这台臂适合照着复刻吗?
它更适合当作全栈学习范本而不是「照抄即可」的复刻项目:固件、仿真与视觉都在活跃开发中,绝对定位尚未完成。如果你想要一台资料成熟、装完就能稳定用的六轴臂,可以先看本站的 Faze4 / PAROL6 分册;想学「一台机械臂每一层怎么写」,NeuralNexus 的链路完整度很高。
没有 MATLAB 授权能玩吗?
能操作真机——官方提供基于 Web Serial API 的浏览器控制面板,Chrome / Edge 打开 HTML 就能连串口下发角度。但数字孪生与逆运动学部分依赖 MATLAB(Robotics System Toolbox + Simscape Multibody);想绕开可以用 Python 自己实现 IK,成本在于模型参数要自己量。
为什么运动是「相对」的?
绝对定位需要可靠的零位,而零位依赖 AS5047P 编码器的归零标定;J1~J3 因为编码器安装比例带来的多义性问题尚未完成归零,所以固件目前只开放相对增量模式。J4~J6 的归零已经可用。
编码器读数乱跳,是传感器坏了吗?
按官方经验,先怀疑软件而不是硬件:读函数失败时返回的 -1 哨兵值被计入采样均值,会让静止关节显示 60~70° 的漂移。过滤掉这些值后再平均,重复精度可达 ±0.01°。
能把这套代码用到别的机械臂上吗?
架构可以直接借鉴:2 kHz 统一步进 ISR + 文本协议 + 上位机求解 IK 的分层设计比较通用。但要改的参数不少——关节↔电机映射、每轴脉冲当量、关节限位与连杆尺寸,还要把 Simscape 模型换掉或重新标定。Apache-2.0 允许这么做,保留许可声明即可。
✅ 下一步
建议顺序:先读 docs/Neural_Nexus_Final_Report.pdf 建立整体印象 → 用 ik-matlab/GUIDE.txt 在 MATLAB 里跑通仿真与 IK → 再刷固件连串口试相对移动 → 最后才碰视觉标定。每一步只动一层,出了问题容易定位。