STM32F103六自由度机械臂拖动示教与轨迹复现实战解析

发布时间:2026/9/4 3:14:27
STM32F103六自由度机械臂拖动示教与轨迹复现实战解析 六自由度机械臂搭配 STM32F103最值得先跑通的功能不是花式动作而是“把人对机械臂的拖动过程记录下来再让机械臂自动复现同一段轨迹”。这类教学项目听起来复杂真正拆开以后其实分三块机械结构、角度采集、轨迹回放。对学习嵌入式或者机器人控制的人来说用这套小机械臂做示教操作能把单片机 PWM 输出、ADC 采样、状态机切换、数据存储全部串起来完成度比单纯点灯和呼吸灯高很多。这篇内容面向正在组装、或者已经装好六轴机械臂但还没有打通“拖动示教 轨迹复现”的开发者。如果你手里的机械臂也使用 STM32F103 控制板下面的思路可以直接套用如果你还没确定材料包里有没有角度反馈机构那更要先把系统架构看清楚再决定要不要为示教功能增加传感器。1. 拖动示教到底在做什么它和普通舵机控制有什么区别1.1 六个自由度不是简单“六个舵机”而是从底座到手腕的姿态链很多初学者会把六自由度机械臂直接理解为“给六个舵机发 PWM 就行”这个理解在复现固定动作时勉强够用但一进入示教操作就会出问题。六自由度的“自由度”指的是机械臂末端在空间中能完成独立运动方向的个数。要让夹爪末端到达某个位置同时保持一个特定姿态通常需要六个旋转关节参与底座负责水平回转肩部和肘部负责把手臂抬到不同高度手腕部分负责末端姿态调整。每一个关节都影响末端所以只是按固定时间顺序转动六个舵机很容易出现末端位置偏差。拖动示教里的四个字“拖动示教”实际含义是人用手直接移动机械臂的各个关节机械臂系统实时记录每个关节的角度之后播放给执行器让机械臂重新走一遍同样的轨迹。1.2 拖动示教与遥控示教的本质区别实时读取关节角度普通舵机控制流程非常单向单片机计算目标角度输出 PWM 脉宽舵机转到对应位置。系统只关心“我发了什么角度”不关心“关节实际在哪”。拖动示教反过来首先要能感知“关节在哪”。也就是说每个自由度除了执行舵机还必须有一个角度反馈源比如电位器、霍尔角度传感器、编码器或者舵机内部的可反馈角度数据。人手动拖动关节时关节角度发生变化STM32F103 通过 ADC 或通信接口读取到这些角度把它们记录下来。这跟遥控示教不同遥控示教是操作者用按键、摇杆给目标角度机械臂自己移动拖动示教则是操作者直接改变机械臂姿态系统跟随记录。正是这个差异决定了硬件选型。如果材料包里的机械臂只有舵机没有独立的关节角度反馈那它能做的是“设定路径复现”而不是“拖动示教”。想补足常见做法是在每个活动关节处加装一个电位器把角度变化转换成电压变化再交给 STM32F103 的 ADC 通道读取。1.3 记录轨迹和复现轨迹的最小工作流程完整的最小流程可以拆成三步。第一步是进入示教模式。此时舵机不主动驱动或者只保持很小的阻尼操作者用手拖动机械臂到起点。第二步是边拖边记录。系统以固定采样周期读取角度把六路角度打包成一条轨迹数据放入缓冲区或者写入存储。第三步是退出示教进入复现模式。STM32F103 从轨迹第一条数据开始把存储的关节角度逐点发送给对应舵机让机械臂按同样的顺序走一遍。这里要特别注意复现不可能做到逐采样点立即到达。舵机存在物理转动时间轨迹中相邻两个点角度差太大舵机就追不上表现出来就是轨迹被拉平或者爆音抖动。所以记录时最好控制拖动速度复现时给每段运动留足执行时间。2. 用 STM32F103 组装机械臂先别急着焊电路先算清关节和接口2.1 控制核心选择STM32F103 什么时候够用什么时候必须换STM32F103 是六自由度机械臂里非常常见的主控。它带有多路定时器、多路 ADC、UART、SPI、Flash处理这种微型桌面机械臂的控制循环足够。但先说清楚边界如果只是做拖动示教和轨迹复现STM32F103 很合适。它不需要 Linux 那样复杂的文件系统不依赖大内存。普通工程里用片内 Flash 保存几条轨迹用定时器产生多路 PWM用 ADC 读取角度完全符合轻量控制器的定位。如果后续要做视觉识别、路径规划、逆运动学实时解算、三维模型渲染还要同时处理摄像头画面那 STM32F103 的资源会非常紧张。这时候建议把上位机逻辑放到 PC、树莓派或者 ESP 之类的通信模块上STM32F103 只做底层舵机控制和数据采集。主控不是越强越好关键是任务分层清楚。2.2 每个关节的两类组件角度反馈与执行驱动在设计电路之前先给机械臂的六个关节做一张表格把每个关节的反馈方式和驱动方式标出来。下面是我常用的规划格式自由度典型位置运动方向角度反馈执行部件需要采集/输出接口J1底座水平旋转电位器/编码器舵机1 路 ADC1 路 PWMJ2肩部前后俯仰电位器/编码器舵机1 路 ADC1 路 PWMJ3肘部上下俯仰电位器/编码器舵机1 路 ADC1 路 PWMJ4前臂旋转绕臂轴旋转电位器/编码器舵机1 路 ADC1 路 PWMJ5腕部俯仰上下摆动电位器/编码器舵机1 路 ADC1 路 PWMJ6夹爪末端旋转/夹取电位器/编码器舵机1 路 ADC1 路 PWM这张表不是机械结构图而是控制系统设计图。你不需要在第一次接线时把六个电位器和六个舵机全部接满可以先用 J1、J2、J3 三个轴做 Demo确认信号方向和角度映射正确再扩展到六轴。直接一口气接完一旦某个方向的电压接反会花大量时间排查。2.3 舵机、供电、信号线最容易烧板的三个细节我在实际测试中踩过最多的问题不是代码逻辑而是供电和信号接线。第一舵机供电和单片机供电要分开。六自由度机械臂的动作集中在瞬间启动和停止电流峰值明显。如果舵机直接从 STM32F103 最小系统的 3.3V 取电电压一旦被拉低单片机大概率复位。常见做法是外部电源给舵机供电STM32F103 通过稳压模块单独供电两边共地。第二舵机信号线不能随意接到 5V 单片机的 IO 口。STM32F103 的普通 GPIO 是 3.3V 电平很多航模舵机信号端能兼容 3.3V但部分舵机在信号高电平低于某个阈值时工作不稳定或者需要电平转换。接之前一定看舵机规格。对输入角度反馈的电位器也是一样如果电位器供电是 5VADC 输入引脚不一定能直接承受 5V 电压要确认 IO 是否容忍 5V或者用分压电路把电压降到 3.3V 以内。很多“角度漂移”“读数乱跳”问题源头不是 ADC 代码而是引脚输入电压超过手册范围。第三信号线尽量短。舵机 PWM 信号频率不高但如果把舵机信号线跟舵机电源线捆在一起穿过关节会受到电机启停干扰导致舵机偶尔抽动。组装时我习惯让信号线和电源线分走两侧或者至少用双绞方式减少噪声。3. 机械装配顺序与拖动示教矛盾的处理3.1 先把基座固定好再往上装肩、肘、腕机械装配的顺序直接影响示教手感。如果底座还放在桌面上晃拖动机械臂时整个结构都会偏记录到的角度数据自然不稳定。我的建议是从底座固定开始装。底座是整个力传递的起点可以先安装到底板或桌面夹具然后依次装肩部、大臂、肘部、前臂、腕部、夹爪。每一步装完都做一次手动转动测试确认关节转动顺畅没有螺丝顶死、齿轮卡顿、线材缠绕。这里要注意一个反直觉点组装时如果把所有螺丝都拧到最紧关节摩擦会很大演示记录时手感很生硬如果太松关节会下垂复现轨迹时舵机要额外出力去补偿重力。合适的松紧度是机械臂静止时能保持住当前姿态但操作者用手推动时不需要用很大力气。3.2 让关节有“顺手可拖动”的状态不是所有舵机都能在马达停止时被轻松反向转动。有些舵机带有减速齿轮箱内部阻力很大强行拖动容易损坏齿轮。这时候就需要在机械设计上留出手动拖动通道。常见的方案有两种。一种是在每个关节上安装独立的角度传感器舵机驱动结构可以脱开另一种是给舵机设计一个离合器结构。如果材料包本身不支持这两种结构那“拖动示教”就要改为“逐关节设定模式”也就是操作者不直接同时拖动整条手臂而是通过上位机发送角度驱动舵机逐轴运动记录路径点。如果你手里的机械臂是可以直接拖动的类型请先小角度测试捏住末端轻轻移动观察舵机有没有异常卡顿。如果听到齿轮打滑或者咔咔声马上停下检查执行机构是否与减速齿轮已经脱离。3.3 手动拖动之前必须做限位检查和配平六自由度机械臂在自由拖动状态下人手可以把它摆到很多极限位置比如手腕向后翻转超过 180 度或者大臂压到桌面。机械限位如果存在强行拖过去会损坏结构件。所以在接通演示模式之前先手动把所有关节从最小位置转到最大位置记录每一路 ADC 读数在软件里设置角度限制。如果某个关节在自然状态下会往下垂说明重心没有平衡好。对桌面级小机械臂来说最直接的办法是把舵机回程扭矩调低或者在结构设计中把大臂保持在一个既不会低垂又不会过重的区间。硬件装配阶段不要追求“零下垂”那是复杂工业机械臂才需要仔细配平的内容。小型舵机本身有保持扭矩复现模式下伺服闭环可以维持姿态。4. STM32F103 端功能拆解角度采集、舵机输出、主流程切换4.1 ADC 采样的六个通道如何映射成关节角度假设每个关节使用电位器作为角度反馈电位器两端接参考电压中间抽头接 STM32F103 的 ADC 通道。电位器转到一个位置ADC 读到对应的电压程序把这个裸 ADC 值换算成角度。换算公式并不复杂float angle (float)adc_value / 4096.0f * 300.0f - 150.0f;这个式子只是示意。具体乘以多少、减去多少取决于电位器量程和机械臂关节的实际角度范围。很多 DIY 项目会直接用 ADC 原始值作为记录数据后续播放时也发送同样的比较值。这种方法能跑通演示但代码可读性差也不方便做限位和轨迹缩放。建议第一次调试就做“ADC 值到关节角度”的标定。标定方法很简单把该关节手动转到机械零点记录一次 ADC 值再转到已知角度比如 90 度记录一次 ADC 值。用两组数据算出比例和偏移量。最少两点标定就能工作如果电位器线性度一般可以用三点标定中间点用来修正非线性。4.2 舵机控制信号用定时器 PWM不推荐靠延时翻转 GPIO很多人会用延时函数模拟舵机脉冲让 PA1、PA3 这类引脚不断翻转。这个办法看起来容易实际很占 CPU还会让你没法稳定做 ADC 采样。因为舵机需要周期性收到 50Hz 左右的脉冲信号一旦主循环被其他延时阻塞舵机信号会出现抖动。STM32F103 上有多个定时器输出比较通道可以产生独立 PWM。用定时器做主时钟每个通道各输出一路脉宽完全不需要在主循环里计算每个引脚的翻转时间。如果接了六路舵机可以选一个定时器的六个通道或者两个定时器各接三路。从这次项目的角度考虑推荐按这样安排功能模块推荐接口说明6 路舵机 PWM定时器 CH1~CH6 或两个定时器50Hz 左右比较值控制脉宽6 路电位器 ADCADC1 的 6 个通道若使用 DMA可以连续采集示教按钮/模式切换GPIO 输入带软件消抖或外部上拉串口调试USART1向上位机发送当前角度/状态如果你对定时器输出占空比的理解还不熟练可以先只给一个舵机做 PWM 输出测试用逻辑分析仪观察周期和脉宽再扩展到多路。4.3 三种任务模式待机、示教记录、复现播放机械臂主程序建议设置成清晰的模式状态不要把所有逻辑写进一个大 while 循环。代码里可以抽象出三个模式typedef enum { MODE_IDLE, MODE_TEACH, MODE_PLAY } SystemMode;待机模式下机械臂不执行轨迹但系统仍然周期读取角度主要用于初始化和手动校准。示教模式下系统把 ADC 读取到的当前角度写入缓冲区。此时如果你直接用舵机驱动需要注意进入示教前要把舵机驱动目标和当前角度同步否则舵机会强行跳到某个目标值跟人手动拖动的力对抗。我的做法是示教时关闭舵机输出或者让舵机进入低功耗保持状态只依靠角度反馈采集数据。复现模式下系统从缓冲区读取轨迹点形成 PWM 目标值平滑发送给舵机。这里要有“当前舵机角度”和“目标舵机角度”两种状态不能直接把缓冲区的历史值一次性发送。5. 示教数据该怎么记记完怎样才能完整复现5.1 记录关节角还是记录笛卡尔坐标选择决定后续难度轨迹复现不是只能记“末端在空间里的直线路径”。对多数教学项目来说更简单有效的方法是记录每个关节的角度。关节角记录方式的优点是采集容易。你只需要在每一采样周期读六个 ADC 值存成一条六维数据。复现时同样按照六路角度发送给舵机即可。因为舵机是旋转关节本身接收的就是角度目标所以这种记录方式天然匹配底层执行单元。如果要记录笛卡尔坐标比如让机械臂末端走一条直线、画一个圆那就必须引入正运动学和逆运动学。正运动学可以根据关节角度求末端位置逆运动学要根据末端位置反推六路关节角。六自由度机械臂的逆运动学解算需要处理多解、奇异点问题复杂度明显高很多。对这个工程演示阶段来说先不要把问题扩大化。5.2 采样周期、缓冲区和存储策略记录轨迹时采样周期不是越小越好。下面是我常用的判断思路拖动速度采样频率建议单次 10 秒轨迹的数据量很慢手把手调姿态10~20 Hz约 100~200 条记录正常演示速度30~50 Hz约 300~500 条记录快速连续动作100 Hz 以上1000 条以上单片机的缓冲区如果只写在 RAM 数组里掉电后数据会丢失。如果想实现“记录一段轨迹断电重启后还能复现”就需要把数据写入非易失存储。STM32F103 没有专门的模拟 EEPROM但可以通过片内 Flash 模拟 EEPROM 用法把一条轨迹分成固定大小的扇区保存。要注意 Flash 擦写次数和写入方式。不要每次采样都直接写 Flash高频擦写会缩短寿命更好的做法是先把一段轨迹缓存到 RAM等操作者按下“结束记录”后批量写入 Flash。5.3 复现时给舵机加平滑过渡不要让轨迹突然跳变直接播放录制轨迹最常见的现象是机械臂开局狂抖或者从当前姿态瞬间跳到轨迹第一帧。原因是录制起点和播放时的机械臂当前姿态不一致。如果当前机械臂停在 0 度而轨迹第一帧是 45 度复现代码直接把 45 度发给舵机舵机会猛冲看起来就像突然抽搐。解决办法是先做一个“回零”或“回到起始点”的过渡过程。可以设定一个较慢的步进速度从当前角度逐渐逼近轨迹第一帧再开始播放实际轨迹。同样在播放最后一段后不要立刻中断输出要让舵机保持最后一帧角度避免回复到初始状态导致突然弹回。平滑过渡处理示例for (float t 0; t 1.0f; t step) { output current_angle (target_angle - current_angle) * t; setServoAngle(channel, output); delay(10); }这只是基础线性插值实际工程还可以用梯形速度规划或者 S 曲线。对桌面六轴来说线性插值加适当延迟通常已经足够。关键在两段之间不要出现角度跳变。5.4 如果需要多段轨迹先设计好编号有些复现任务不只是播放一段而是要把“拿起物件”“移动到高点”“放到另一边”三段轨迹串起来。这种情况建议先规定每个轨迹段的编号、结束条件、下一段跳转目标而不是把所有点堆成一个长数组。我习惯把轨迹抽象成一个小结构typedef struct { uint8_t id; uint8_t point_count; uint16_t sample_rate; uint16_t joint_angles[6][MAX_POINTS]; } Trajectory;工程里用结构体管理比较直观。每段轨迹保存时要同时保存采样率因为回放时只有知道每两个点的间隔时间才能控制舵机动作速度。6. 把最小 Demo 扩展成可连续运行的桌面机械臂6.1 用 Flash 存储多段轨迹实现掉电保存最小闭环跑通后你要问自己的下一个问题是这段轨迹能不能在断电后继续使用如果只存 RAM演示时一拔电就丢。想保存先把 STM32F103 的 Flash 划分看明白。不同容量的 F103 芯片 Flash 大小不同页大小和地址布局也不一样。写 Flash 前必须确认具体型号。建议先把项目放到真实芯片上读出其容量再做存储规划。写入 Flash 过程有几个容易踩的坑。第一执行 Flash 写操作时不能同时从同一块 Flash 取指令所以部分情况下需要把写入函数放在 RAM 中执行。第二擦除最小单位是页不能像 RAM 那样单字节随便改。如果轨迹数据不大可以分配固定大小的一块区域每段轨迹从区域开头依次写入而不是频繁擦写。对多数演示场景可以把存储做成“简易日志”第一段写在地址 A第二段写在地址 A偏移。如果用户重新记录新轨迹先擦除整块区域再从头写。这种模式实现简单还能避免 Flash 频繁擦写。6.2 增加上位机串口调试帧格式、校验、启停命令机械臂拖动演示时如果没有任何上位机界面你很难知道当前 MCU 处于哪个模式也不方便查看每一路角度值。这时最简单的方法是添加一条 UART 调试链路。把角度数据、当前模式、采样状态通过串口输出到电脑可以快速判断是采集端问题还是舵机端问题。串口消息建议设计成带帧头、长度、数据、校验的形式不要直接把裸 ADC 值用 printf 无限打印。因为高频率打印会占用主循环时间可能导致采样周期不稳定。封装一个简单的命令行输入teach start进入示教输入teach stop停止并保存输入play 1播放第一段轨迹。从工程角度看这个命令行比把模式切换全部放在按钮上更容易调试。因为按钮需要消抖、状态指示、长按/短按区分命令行把这些逻辑统一到了串口层。6.3 如果需要逆运动学主控只做运动执行更合理当你不再满足于点对点复现而是希望机械臂末端能从 A 点自动经过 B 点和 C 点绘制出直线或者圆弧时就要考虑加入逆运动学。但 STM32F103 直接跑实时逆运动学不是不可能而是容易让代码变得很紧。比较好的方案是把逆运动学放在 PC 端上位机完成然后用统一的关节角度协议下发给 STM32F103。MCU 端只处理 DAC 采集和舵机播放不再承担复杂运动学解算。这样做还有一个好处上位机可以显示 3D 模型实时反馈机械臂姿态方便观察轨迹是否合理。STM32F103 作为执行控制器仍然保持高实时性。对学习 Robotic 的人来说这套“上位机方案 下位机执行”的架构更接近实际项目结构。7. 常见问题与排查链路先看现象再查输入/输出7.1 启动后机械臂乱动先查供电和初始化状态机械臂启动瞬间乱动很多人的第一反应是代码 bug但实际更常见的是供电不足和初始化顺序不对。先看供电如果用 USB 线给 STM32F103 供电再通过 3.3V 引脚拉舵机开机瞬间电压跌落会把控制系统拉复位。表现就是舵机“咔咔”响或者机械臂突然运动一下又停止。再看初始化顺序舵机 PWM 输出是否在 GPIO 配置和 ADC 配置完成之前就开启了如果 PWM 先开启而舵机目标角度数组还是全 0 或者随机值机械臂就会朝一个意想不到的角度猛转。规范做法是先把所有角度变量初始化成当前机械姿态再开启 PWM 输出。这里也可以使用“先让舵机进入不输出状态完成所有校准后再使能”的机制。7.2 角度读取跳动 / 复现轨迹偏移先查定位与映射复现轨迹偏移并不代表记录数据坏了。它往往是示教时 ADC 映射关系和复现时 PWM 映射关系不一致造成的。演示教时我们记录电位器 ADC 值然后乘以系数得到关节角度播放时又把关节角度转换成舵机脉宽。这个“ADC 值→角度→脉宽”链路里有两个映射需要同时校准。如果只校准了采集端没校准输出端机械臂位置就会偏。排查步骤可以是先手动设置一个固定关节角度检查舵机是否转到肉眼可见的同一位置。比如让肩部关节变成 90 度再用尺子或量角器确认。如果读数一直接近但差一点优先怀疑 PWM 最小脉宽和最大脉宽设置不正确。不同舵机的脉宽范围有差异不能拿 0.5ms~2.5ms 直接套用在所有舵机上。7.3 舵机 PWM 输出不到满量程先确认定时器周期和比较值范围有朋友用 STM32F103 定时器输出 PWM调试时发现舵机角度怎么也到不了 180 度看起来像 PWM 始终只输出到一部分量程。这个问题的重点不在舵机而在定时器定时和占空比计算。PWM 高电平时间由“比较值 / 自动重载值 * 定时器周期”决定。如果自动重载值设置得不合适比较值写到最大也到不了 2.5ms。先不要直接加大比较值应该按照以下链路排查确认定时器时钟频率。确认自动重载值计算 PWM 周期是否约 20ms。确认比较值范围换算成高低电平时间。用逻辑分析仪在舵机信号引脚上直接测脉宽。逻辑分析仪测量时如果转动目标角度 0 度到 180 度高电平时间能在 0.5ms 到 2.5ms 范围均匀变化那代码就没问题。如果最大输出只有 1.5ms说明自动重载值和比较值映射没有拉开范围。这个排查同样适用于 DMA 方式输出多路 PWM引脚换了但计算逻辑一样。7.4 拖动记录一段时间后卡死或掉数据先查缓冲区与存储节奏如果记录刚开始正常十几秒后 STM32F103 不再响应大概率不是舵机问题而是存储或者缓冲区设计问题。先检查缓冲区是否越界。记录过程中每采样一次就往数组里写一组六路数据。如果数组上限是 200 条你却记录了 500 条写指针越界后可能把其他变量覆盖掉造成各种诡异现象。解决办法是先固定缓冲区最大点数采样时检查索引到达上限就自动停止记录或者覆盖最旧数据。如果采样时不写数组而是每采一个点就擦写一次 Flash卡死概率会更高。Flash 擦除和写入耗时较久主循环一直等待就会错过后面的采样。建议的节奏是“高速采集进 RAM停止记录后一次性写入 Flash”。这样既保证采样连续性也避免频繁擦写。7.5 示教模式时舵机仍跟手阻力大确认进入模式后的驱动状态最后一个常见误区是示教记录时舵机仍然需要用力反推才能移动。很多人以为把舵机目标值设为当前角度就够但实际上舵机的闭环控制器仍会试图回到目标角人一推它它就会反推。让关节进入手动可拖状态关键是让舵机停在一个“被控制但不主动回正”的状态或者完全切断驱动。通道的电平不能是高阻抗噪声必须稳定在 0V 或者一个安全电平。某些舵机对低电平和高电平的响应不同直接悬空会导致舵机抽搐这种状态不能被当作示教模式。如果机械结构不支持脱开另一种方案是采用“虚拟示教”在电脑上位机里拖动三维模型系统算出关节运动轨迹再发给单片机执行。严格说这不是物理拖动示教但同样可以达到“记录—复现”的教学目标而且不需要改动机械结构。六自由度机械臂这个项目真正有价值的地方并不是让几个舵机按顺序转而是让你理解机器人控制中的“感知、决策、执行”闭环。STM32F103 适合承担这个闭环里的执行层拖动示教则是连接人和机器人最直观的交互方式。如果你正在做这类组装项目建议先把单轴校准做完再做三轴记录最后扩展成六轴整体复现。每一步都能确认结果后面的故障就会少很多。