六自由度机械臂做到第二期,重点就不是“转不转得动”了,而是“能不能按你的动作干活”。这篇教程的主角是一台基于 STM32F103 单片机的小型六轴机械臂,核心玩法是拖动示教和轨迹复现:你可以用手把机械臂摆成想要的姿态,让单片机把这段轨迹记下来,然后机械臂自己把动作重复出来。这个思路非常接近工业现场里的示教编程,但门槛低得多,用一块 STM32F103 加几个舵机就能跑。
做这类 DIY 机械臂,大家关心的通常不是控制理论有多深,而是三件事:第一,硬件怎么装、线怎么接;第二,拖动示教到底怎么实现,是硬拖还是用传感器读角度;第三,轨迹记录与复现怎么做,停电能不掉、回放顺不顺。这篇文章会把这几条主线拆开讲,包括 STM32F103 的 PWM 输出、串口调试、角度采样、轨迹存储和复现流程,也会给出一套面向初学者的排错思路。如果你想拿单片机做毕业设计,或者想理解机械臂最核心的“示教-回放”闭环,这篇文章可以直接当操作笔记看。
需要先说明的是,机械臂的具体结构件、舵机型号和驱动板不是每家都一样,文中涉及接线和代码的地方会给通用思路和模板,实际使用时请以你手上的材料包和电路原理图为准。下面进入正式内容。
1. 核心能力速览
| 项目能力 | 说明 |
|---|---|
| 机械臂结构 | 六自由度关节型机械臂,适合完成简单空间轨迹复现 |
| 主控芯片 | STM32F103 系列单片机,Cortex-M3 内核,72MHz 主频 |
| 核心功能 | 拖动示教、轨迹记录、自动复现 |
| 示教方式 | 手动拖动关节或使用电位器/编码器采集角度,记录后回放 |
| 执行机构 | 常见 PWM 舵机或总线舵机,具体以材料包为准 |
| 需要外设 | 多路 PWM 输出、ADC 模拟量采集、串口、按键/拨码开关 |
| 启动方式 | 上电自检后进入待机,通过按键切换“示教/记录/复现”模式 |
| 是否支持批量任务 | 常规固件以单条轨迹为主,可扩展多段轨迹存储 |
| 是否支持接口 API | 通过串口可与上位机通信,适合二次开发 |
| 典型应用场景 | 单片机课程设计、机械臂入门、示教复现演示、小型自动化测试 |
这里最值得关注的功能就是“拖动示教”。它把复杂的轨迹规划问题简化成了“把动作录下来再播出去”。对于 STM32F103 这种 MCU 来说,不需要跑什么逆解算法,只要处理好角度采样、时间序列存储和 PWM 输出,就能实现一台低成本机械臂的示教复现。
2. 适用场景与使用边界
这类 STM32F103 六轴机械臂适合的人群很明确:学过单片机基础、想接触机械臂控制、需要做课设或毕业设计的人。它能帮你理解几个工程问题:多路舵机怎么同时控制、关节角度怎么测量、非实时系统和实时系统在轨迹复现上的差异、夹爪和关节的运动顺序怎么编排。
但它也有很明显的能力边界。第一,如果你要求机械臂进行复杂路径规划,比如在三维空间里避障、自动插补直线和圆弧,STM32F103 裸机方案会非常吃力,应该优先考虑 ROS 配合上位机,或者用带 FPU 和更多资源的芯片。第二,低成本 PWM 舵机的精度通常有限,回放时会出现微小抖动,不能和工业伺服机械臂比重复定位精度。第三,拖动示教依赖角度反馈传感器,如果你的机械臂只是由普通 PWM 舵机组成且没有安装任何位置反馈,直接“拖”舵机轴并不能让单片机读到角度,这一点必须提前搞清楚。
使用边界方面还要提醒合规问题:如果机械臂上安装了夹爪、摄像头或其他执行器,请确保操作对象是合法测试物料,不要用来夹取或搬运任何可能造成人身伤害、财产损失的物品;如果后续把拖动示教技术用于仿生动作采集、远程操作等场景,要确认使用对象已获得合法授权,避免采集到他人肖像、隐私信息或受版权保护的运动内容。整个项目应在安全的桌面环境下进行测试,机械臂运动速度不宜过高。
3. STM32F103 机械臂硬件组成与选型思路
六自由度机械臂听起来复杂,拆开看就是六个关节电机加上底座和臂杆。对 STM32F103 而言,硬件设计最需要考虑的是三个部分:主控板、舵机驱动、角度反馈。
主控板可以直接用 STM32F103 最小系统板,也可以用集成度更高的开发板。关键不是板子本身,而是需要引出足够的定时器通道和 ADC 引脚。以常见的 STM32F103C8T6 为例,它有三个通用定时器 TIM2、TIM3、TIM4,每个定时器有 4 个通道,理论上最多可以输出 12 路 PWM,覆盖六个自由度没有问题。需要注意的是,如果六路舵机都是 PWM 舵机,每个舵机都需要独立的信号引脚,并且要求 50Hz 左右的更新频率,配置时要保证同一组关节的 PWM 周期一致。
舵机选择上有两条路线:
第一种是普通 PWM 舵机。它价格低、资料多,适合入门,控制方式简单:给一个 20ms 周期的脉冲信号,高电平宽度从 0.5ms 到 2.5ms 对应不同转角。但普通的模拟舵机或低端数字舵机没有角度反馈,堵转时电流大,长期使用容易发热;机械臂六个关节同时受力时,如果电源跟不上,还会造成单片机复位。
第二种是串行总线舵机。总线舵机内部集成了驱动、控制、反馈电路,可以返回当前位置、温度和电压,也能通过总线协议控制多台舵机,只需要一根信号线连成菊花链,布线比 PWM 舵机省非常多。总线舵机通常还支持“松脱”或“力矩模式”,可以让关节在外力作用下被拖动,同时通过总线把位置变化读回来,这对拖动示教方案非常有利。
如果你的材料包采用的是普通 PWM 舵机,那么实现拖动示教需要额外安装角度传感器,常见方案包括在每个关节处安装电位器或磁编码器,把机械角度转换为电压信号,再送入 STM32F103 的 ADC 引脚。
除了电机和控制信号,机械臂还需要一块可靠的电源。STM32F103 的逻辑部分可以用 USB 或 3.3V LDO 供电,但六个舵机千万不要全部从单片机的 5V 引脚取电。一个标准做法是使用独立的 5V/6V 舵机电源,比如 2S 锂电池、带降压模块的外置电源,或至少是额定电流充足的开关电源,并且把舵机电源地和控制板地单点相连。舵机瞬时启动电流可能很高,如果出现屏幕闪烁、舵机抽搐、单片机反复重启,优先怀疑电源功率不足。
4. 项目环境准备与开发工具链
软件层面的环境准备相对标准。如果你从零开始写 STM32F103 机械臂固件,推荐下面的工具组合:
- 代码生成工具:STM32CubeMX,用于初始化时钟、GPIO、定时器、ADC、串口。
- 编译调试环境:Keil MDK 或者 STM32CubeIDE,两者都可以编译 STM32F103 工程。
- 烧录方式:ST-Link / J-Link 下载器,或者使用串口 ISP 烧录。
- 串口工具:USB 转 TTL,用于调试输出和上位机通信。
- 上位机:如果你希望把记录的轨迹导出到电脑分析,可以用串口助手或自定义 Qt/Python 上位机。
在使用 STM32CubeMX 做初始化时,需要特别核对下面的几个配置点。
时钟部分,STM32F103 外部晶振通常为 8MHz,PLL 倍频后系统时钟为 72MHz,APB1 外设时钟为 36MHz,APB2 外设时钟为 72MHz。定时器如使用内部时钟,要确保舵机 PWM 的周期正确。PWM 全周期为 20ms 时,如果定时器时钟是 72MHz,预分频器和自动重装值的设置要满足:
PWM_Frequency = Timer_Clock / ((PSC + 1) * (ARR + 1))要让 PWM_Frequency 接近 50Hz,可以把 PSC 设为 71,这样定时器计数频率为 1MHz,再让 ARR 等于 19999,就得到 20ms 周期。然后通过修改比较寄存器 CCR 的值,输出不同脉宽。
GPIO 部分,每个舵机 PWM 输出引脚要配置为复用推挽输出;ADC 角度采样引脚配置为模拟输入;按键引脚配置为上拉输入或下拉输入,根据硬件决定。
串口部分,建议预留一路 UART 作为调试口,输出机械臂当前模式、关节角度和错误码。这样在拖动示教时,你不用一直盯着物理臂的位置,通过串口就能确认角度是否被读到。
开发环境不复杂,但第一次做的人经常忽略一件事:下载器、串口模块和舵机电源的“地”必须共地。ST-Link 通过 SWD 接口下载,如果下载器和目标板、舵机电源各用各的电源,烧录和通信都可能失败。正确做法是把所有电源的负极接到同一个参考点。
5. 安装组装与电气接线要点
进入第二期教程,机械结构通常已经基本成型,这里重点讲电控这一侧的组装检查。接线前先画一张接线表,把每个关节的 PWM 引脚、ADC 采样引脚、舵机电源正负极标清楚,避免通电后把线插错。
如果机械臂使用 6 个 PWM 舵机,主控板和舵机之间需要传输 6 路信号线。STM32F103 的 GPIO 输出电压是 3.3V,而部分舵机工作在 5V 或 6V 电压下,对信号高电平的要求不完全一致。更稳妥的方案是使用电平转换模块,或选择明确支持 3.3V 逻辑电平的舵机。如果你直接用 3.3V 单片机驱动 5V 舵机,距离短、舵机少时常能工作,但抗干扰能力差,长线传输时可能出现抖动,不建议在正式项目里长期这样接。
ADC 角度反馈部分的接线要特别注意。常见电位器两端接电源和地,中间抽头输出到 STM32F103 的 ADC 引脚。如果电位器供电是 3.3V,抽头电压范围就是 0V 到 3.3V,可以直接接 ADC;如果供电是 5V,抽头电压可能超过 STM32F103 的模拟输入上限,必须串联分压电阻或使用电压跟随器把电压缩放到 3.3V 以内。很多 STM32F103 芯片的 GPIO 并不耐 5V,不是“能插就能用”的。
强电和弱电要分开布线。舵机的电源线比较粗,如果与角度采样线、串口线绑在一起,舵机转动时产生的大电流变化会干扰 ADC 采样值,表现为拖动时角度数值跳变。建议舵机电源线和信号采样线分开走,必要时在 ADC 引脚前加一个 100nF 电容滤波,在软件里也可以做多次采样求平均。
组装完成后,先不要急着写复杂固件,做一次“最小通电检查”:只给主控板供电,确认下载器能识别芯片;再单独给一个舵机供电,用一个简单的测试程序让舵机回中。确认单路舵机工作正常后,再逐步扩展到六个自由度。这样可以大大降低排错难度。
6. 拖动示教功能实现原理
拖动示教在工业机器人里叫“直接示教”,操作者抓住机械臂末端,带着它走一遍期望路径,机器人实时记录关节角度变化,之后回放路径。这个功能落到 STM32F103 方案上,核心不是“拖”这个动作,而是“单片机怎么知道每个关节被拖到了哪里”。
如果你的机械臂使用带位置反馈的总线舵机,拖动示教会比较直接。让舵机进入松脱或力矩模式,舵机输出轴可以被外力转动,同时内部反馈角度不断改变,主控通过总线周期读取每个舵机的角度,就完成了关节角度采集。回放时把记录的角度写入舵机,让它跟随目标位置即可。
如果你的机械臂使用普通 PWM 舵机,实现拖动示教要复杂一些,常见做法是加装角度传感器。每个关节安装一个与舵机轴同步旋转的电位器,舵机轴转动时电位器阻值变化,输出电压也变化,STM32F103 用 ADC 读取电压并换算为角度。拖动时,舵机是否真的能被自由拖动,取决于减速齿轮结构和舵机驱动器的状态。如果是未通电状态下硬掰,很多舵机因为齿轮减速比大会很吃力,甚至可能损坏齿轮。比较稳妥的做法是让舵机处于通电但处于“无力矩”状态,或在机械结构上设计离合器,让关节可以脱开驱动。动手前先看一下材料包里舵机的结构和安装方式。
一个更容易实现的变通方案是“主从示教”:另外搭建一台结构相同但关节数量相同的小型机械臂,每个关节只装电位器不装舵机,作为操作手柄。主臂和从臂的关节角度一一对应。用手摆动主臂,STM32F103 采集主臂各关节角度,换算后输出 PWM 控制从臂复现同样动作。这样既做到了“拖动示教”,又避免了大扭矩舵机被反向硬拖的问题,是目前 DIY 项目里比较推荐的做法。
不管采用哪种方案,拖动示教都需要定义好角度单位。你可以把每个关节的原始 ADC 值直接保存为 0 到 4095 的整数,也可以先标定,将 ADC 值转换为真实的物理角度。直接保存原始值实现简单,后续如果想在回放路径中间插入插补或修改某个点,就会比较麻烦;转换为角度后再存储,数据处理更友好。但对于一个以演示为主的六轴机械臂项目,直接从 ADC 原始值起步没有太大问题。
轨迹记录部分的核心是一个周期性采样任务。可以设置采样周期为 20ms 或 50ms,也就是每 20ms 读一次六个关节的角度,并把它们作为一组数据写入存储区。拖动得越快,相邻两组数据之间的角度变化越大;采样周期越短,记录越细腻,占用的存储空间也越多。建议用按键切换模式:空闲状态按下“示教模式”按键后开始实时采样,再按一次或等串口指令结束记录。
6.1 角度采集标定
在开始记录轨迹之前,先做一些标定。把每个关节都手动转到机械零位,记录下该位置的 ADC 读数;再把关节转到最大角度位置,记录另一个读数。这样就能计算出 ADC 读数与关节角度的线性关系。如果只是在关节范围内摆动,也可以不做全范围标定,直接按下式的比例映射:
angle = (adc_value - adc_min) * angle_max / (adc_max - adc_min);实际标定时要注意:电位器旋转范围小于 360 度,安装位置必须和关节转轴机械限位对齐。装反了或没对准,拖动时数据会到极限然后跳变,导致复现轨迹错误。这里值得花时间多看几次串口输出的原始值。
6.2 状态机设计
拖动示教虽然功能不复杂,但状态很清晰,适合用一个简单状态机管理:待机、示教记录中、回放中、暂停。不同状态对应不同按键功能,避免用户误触。
| 状态 | 说明 | 进入方式 |
|---|---|---|
| IDLE | 机械臂待机,舵机保持零位或松脱 | 上电默认 |
| TEACH | 正在读取关节角度并按周期存储 | 空闲时按下示教按键 |
| PLAY | 按存储轨迹自动输出关节角度 | 空闲或示教结束后按下回放按键 |
| HOLD | 停止在某个轨迹点,不继续输出 | 任意状态触发暂停 |
状态机不需要跑操作系统,在主循环里用一个 switch 结构就能完成。如果后续还要同时处理串口指令、按键扫描和舵机刷新,才需要考虑定时器中断或者 FreeRTOS。
7. 轨迹记录与复现的存储策略
轨迹复现效果好不好,很大程度上取决于记录的数据格式和回放方式。最简单的做法是把轨迹点按时间顺序存在一个数组里。
每个轨迹点包含 6 个关节角度值,如果角度用 uint16_t 表示,一个点就是 12 字节。采样 500 个点需要 6000 字节,这个容量对于 STM32F103 内部 RAM 来说偏大,因为常见的 STM32F103C8T6 只有 20KB RAM,如果数组开太大,会影响运行稳定性。更稳妥的做法是把轨迹存入外部 Flash 芯片,或者用串口发送到上位机保存。如果只是短时间演示,在 RAM 中放一个几百点的环形缓冲区也够用,但要注意数组越界。
项目中如果有多段轨迹需求,可以设计成下面这样的结构体:
#define JOINT_NUM 6 #define MAX_TRACK_POINTS 300 typedef struct { uint16_t joint_angle[JOINT_NUM]; } TrajectoryPoint; TrajectoryPoint g_track_buffer[MAX_TRACK_POINTS]; uint16_t g_track_len = 0;记录轨迹时,把实时采样到的点位写入 g_track_buffer[g_track_len],然后 g_track_len 自增。回放时,用 for 循环按顺序取出每个轨迹点,换算成 PWM 比较寄存器值并输出。
这种直接回放方式有一个明显问题:如果记录时拖动速度不稳定,或者你只采样了 30 个点,复现时机械臂的动作会一顿一顿,不够平滑。解决办法是提高采样频率,或者在回放时对相邻轨迹点做线性插值。例如记录周期是 50ms,回放时细分为每 5ms 向前推进一个中间角度的 1/10,这样机械臂运动更平顺。
回放时也不能只输出角度就完事,还要考虑舵机的物理响应速度。六个舵机从当前角度转到目标角度需要时间,如果代码连续飞快地更新目标值,舵机跟不上也会导致动作变形。在轨迹回放任务里加一个延时或者定时器等待,让每个轨迹点之间有稳定的时间间隔,是一个容易被忽视但非常重要的小细节。
如果要做“断电保持轨迹”的版本,可以把轨迹数据通过串口写到上位机保存,或者接外部 SPI Flash。用内部 Flash 保存轨迹虽然可行,但要处理擦写均衡和写入次数问题,不建议作为主要方案。更简单的实用方案是在演示时把轨迹缓存到 RAM 中,断电后重新录一遍即可,对于学习演示项目已经足够。
8. 固件开发框架与代码骨架
下面给出一套固件逻辑骨架,不依赖具体硬件库,重点说明控制流程。如果你使用 STM32CubeMX + HAL 库,可以把对应部分替换成自己的外设句柄。
8.1 主循环框架
int main(void) { // 初始化时钟、GPIO、定时器PWM、ADC、串口 system_init(); // 使能六个舵机信号输出,默认回中 servo_reset_all(); while (1) { key_scan(); switch (system_state) { case STATE_IDLE: // 舵机保持零位,等待开始示教 break; case STATE_TEACH: // 读取6个ADC采样值,换算角度,写入轨迹缓冲 record_track_point(); delay_ms(20); break; case STATE_PLAY: // 根据当前轨迹点输出对应PWM脉宽 replay_track_point(); delay_ms(10); break; default: break; } } }8.2 PWM 舵机角度输出函数
假设每个自由度对应一路定时器通道,输入 0 到 180 的角度值,输出对应占空比。以定时器周期 20ms、中心位置算法为例:
void servo_set_angle(TIM_HandleTypeDef *htim, uint32_t channel, float angle) { // 将0~180度映射到500us~2500us, // 具体脉宽范围需要根据舵机手册和机械安装调整 float pulse_width_us = 500.0f + angle / 180.0f * 2000.0f; float compare = pulse_width_us / 20000.0f * 20000.0f; __HAL_TIM_SET_COMPARE(htim, channel, (uint32_t)compare); }这段代码里的脉宽范围和定时器周期都是示意值。不同舵机的脉宽范围差异很大,比如有些舵机是 500us 到 2500us,有些是 1000us 到 2000us。务必对照舵机手册修改。
8.3 轨迹记录与回放函数
void record_track_point(void) { if (g_track_len >= MAX_TRACK_POINTS) { // 轨迹缓冲区已满,停止记录 system_state = STATE_IDLE; return; } TrajectoryPoint *point = &g_track_buffer[g_track_len]; for (int i = 0; i < JOINT_NUM; i++) { uint16_t adc = read_adc(i); point->joint_angle[i] = adc_to_angle(adc, i); } g_track_len++; } void replay_track_point(void) { static uint16_t replay_index = 0; if (replay_index >= g_track_len) { replay_index = 0; system_state = STATE_IDLE; return; } TrajectoryPoint *point = &g_track_buffer[replay_index]; for (int i = 0; i < JOINT_NUM; i++) { servo_set_angle(&htim[i], pwm_channel[i], point->joint_angle[i]); } replay_index++; }这里展示的是最直接的点到点回放逻辑。如果你希望轨迹更平滑,可以在 replay_track_point 里加入对当前值和目标值的插值,每 5ms 移动一小步。回放结束后让机械臂回到初始零位,也是一个很实用的设计。
9. 功能测试与效果验证
固件写好并且机械臂组装完成后,不要直接进入完整轨迹复现,而是按下面的顺序分层测试。
9.1 单关节角度回读测试
在示教模式下,手动缓慢转动第一个关节,在串口调试助手里观察对应 ADC 值和角度值是否连续变化,没有跳变。如果数据忽大忽小,检查电位器接线是否松动、ADC 采样是否悬空,或者在软件里增加滤波。这步通过后,再逐个检查其余五个关节。
9.2 单路舵机输出测试
把某一自由度的目标角度固定为 0 度、90 度、180 度,观察舵机是否能准确到达对应位置。如果到了位置仍然“嗡嗡”响,说明 PWM 脉宽对应的角度可能超出机械限位,或舵机在死角位置堵转,需要减小角度范围。
9.3 六轴联动测试
让六个自由度依次从零位偏转到最大角度再回中,确认机械上不存在干涉、抖动、异响。这一步很重要,因为六轴机械臂在空间运动时可能发生相邻关节碰撞。如果出现明显干涉,需要缩小软件角度限位。
9.4 短轨迹示教复现测试
手动拖动或通过主臂操作机械臂,走一条简单路径,比如从零位抬起到前方再放回,记录 5 秒钟轨迹,然后按下回放键。观察机械臂能否按顺序完成同样动作。如果回放时动作速度比示教时快很多,说明回放时每个轨迹点的延时不够,需要把延时时间调整为和记录时一致。
9.5 长轨迹复现与稳定性测试
逐步增加拖动过程的复杂度和时长,例如加入圆弧动作或夹爪开合动作,重点观察三个问题:轨迹缓冲区是否溢出、回放末尾是否出现卡顿、多次连续回放后是否产生位置偏移。位置偏移主要由舵机精度和机械间隙造成,如果偏移量在可接受范围内就可以,不需要追求工业级重复定位。
10. 接口调试与上位机联动思路
除了按键控制,串口是这套系统最值得扩展的接口。你可以把 STM32F103 的串口连接到上位机,用 Python 或串口工具发送简单指令,例如:
| 串口指令 | 功能 |
|---|---|
MODE_IDLE | 进入待机 |
MODE_TEACH | 开始示教记录 |
MODE_PLAY | 开始回放 |
GET_ANGLE | 读取当前六个关节角度 |
SET_ANGLE | 设置某个关节目标角度 |
下面是一个用 Python 调用串口控制机械臂的通用模板,需要根据实际串口号和命令格式调整:
import serial import time ser = serial.Serial( port="COM3", baudrate=115200, timeout=1 ) def send_command(cmd: str): ser.write((cmd + "\n").encode("utf-8")) time.sleep(0.1) res = ser.read_all().decode("utf-8", errors="ignore") print(res) send_command("MODE_TEACH") time.sleep(5) send_command("MODE_PLAY")串口功能如果不做上位机,也可以只用来打印调试信息。在实际项目里,最好的调试习惯是每 100ms 打印一次当前状态、采样点数、当前正在执行的轨迹点索引,这样一帧一帧地检查,能很快定位问题。
11. 资源占用与性能观察
STM32F103 做六自由度机械臂示教,核心瓶颈通常不是 CPU 算力,而是 RAM、定时器资源和 PWM 更新逻辑。
如果你用的是裸机主循环,六个自由度只是每周期更新 6 个定时器的比较寄存器,CPU 占用并不高。大部分时间其实花在了延时和等待舵机动作完成上。因此除非要同时处理复杂视觉算法、云端通信、多自由度实时轨迹插补,否则没必要一上来就用 FreeRTOS。但如果项目后期要同时管理按键扫描、OLED 屏幕显示、串口通信、多段轨迹调度,再用 RTOS 会让任务边界更清晰。
RAM 占用方面,轨迹缓冲区是最大消耗项。上面一个点 12 字节,如果开 1000 个点就需要 12KB,这对于 20KB RAM 的芯片来说已经非常紧张。更合理的做法是限制记录时长,比如采样周期 20ms、记录 10 秒,只需要 500 个点,也就是 6KB 左右,相对安全。如果你希望记录几分钟的动作,建议把轨迹数据放到外部 Flash 或 SD 卡中。
串口输出也会占用时间。调试时如果每 50ms 输出一条完整角度信息,可能会影响主循环的采样节奏。建议在正式录轨迹时关闭日志输出,或者只在按键切换状态时打印一次状态摘要。
12. 常见问题与排查方法
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| 舵机完全不动 | 电源未接 / 信号线接错 / PWM未初始化 | 检查舵机供电电压,确认信号线接到对应定时器通道 | 按接线表逐一核对,用示波器或逻辑分析仪看 PWM 波形 |
| 舵机上电后抖动 | 电源电流不足 / PWM周期不对 | 测量舵机电源电压是否被拉低 | 换大电流电源,分清舵机电源和逻辑电源 |
| 记录的角度值跳变 | 电位器接线不良 / ADC采样悬空 / 参考电压抖动 | 串口打印原始 ADC 值,观察变化规律 | 检查接线,增加滤波电容,多次采样取平均 |
| 拖动关节很费力 | 舵机齿轮自锁 / 减速比太大 | 检查机械结构,确认舵机是否断电 | 增加离合器结构或改用总线舵机松脱模式 |
| 回放速度比示教快 | 轨迹点之间延时太短 | 对比记录周期和回放周期 | 在回放循环里加与记录周期一致的延时 |
| 回放动作一顿一顿 | 轨迹点太少 / 插值不够 | 查看轨迹缓冲区点数 | 提高采样频率,或在回放时做线性插值 |
| 六轴运动时相互碰撞 | 软件角度限位没设置 | 逐个自由度检查最大最小角度 | 为每个关节设置单独的角度上下限 |
| 单片机反复重启 | 舵机堵转导致电源跌落 | 观察舵机卡死位置和大电流 | 减小角度范围,增加电源电容或换大功率电源 |
| 串口乱码 | 波特率不一致 / 电平不匹配 | 确认上位机波特率和代码一致 | 使用 115200 8-N-1,检查共地 |
| Flash 存储轨迹失败 | 写入擦除不规范 | 先单独测试 Flash 读写 | 使用外部 Flash 时按页擦除,避免跨页写 |
13. 最佳实践与安全使用建议
从这套六自由度机械臂项目中,可以总结出几条比较通用的经验。
第一次跑通功能之前,不要把目标算法和机械结构都做到最复杂。先固定一个关节,用最简 PWM 输出程序确认舵机方向正确、脉宽范围和机械限位一致;然后固定两个关节,测试让两个轴同时运动是否存在干涉;最后再扩展到六个自由度。这样每增加一个变量,出问题时都能快速定位。
角度限位一定要在每个关节单独设置。六个自由度的机械结构里,每个关节的机械零位、运动方向、最大角度都不完全相同。用一个全局 MAX_ANGLE 限制所有关节,并不安全。更合理的方式是给每个关节定义一个结构体,里面存最小角度、最大角度、舵机脉宽零点、方向标志。
轨迹数据的管理也值得一开始就规范化。示教记录文件、回放代码、角度标定参数不要散落各处。如果使用串口把轨迹上传到电脑,建议用带时间戳的 CSV 文件保存,方便后期用 Python 分析或绘制角度曲线。
安全方面,机械臂属于运动设备,通电调试时不要把手伸到关节运动范围内,特别是要小心夹爪和底座旋转关节。舵机力矩虽然不大,但被夹到手指依然会痛,六轴运动时末端的线速度也不低。不要让机械臂在无人看管状态下长时间自动运行,防止舵机发热或结构松动后发生意外。对使用总线舵机、带角度传感器的方案,调试时尽量先让机械臂处在低速状态,确认轨迹无误后再提高回放速度。
如果项目后续用于毕业设计,可以考虑在现有“示教-回放”基础上增加视觉识别、串口远程控制、多段轨迹自动拼接等功能。如果用总线舵机,还可以读取电压、温度、堵转状态,直接把机械臂做成一个小型实验平台。
14. 总结与下一步
这台 STM32F103 六自由度机械臂最值得试的点,就是把“拖动示教”这样听起来偏工业的功能,用单片机加舵机实现了闭环。你不需要先搞懂复杂的机械臂运动学,就能实际操作一遍“记录动作、回放动作”的完整流程,这对理解机器人控制的基础非常有帮助。
拿到手之后建议先做第 9 节里的单关节测试,确认每个自由度的 ADC 采样和 PWM 输出都稳定,再进入完整六轴轨迹复现。最容易踩的坑集中在三个地方:电源功率不足导致单片机复位、ADC 角度读数跳动、回放速度和记录速度不一致。这三个问题解决了,项目基本就稳了。
下一步可以继续往两个方向扩展:一是从固定轨迹回放走向实时轨迹规划,加入插补算法,让机械臂走直线或圆弧;二是通过串口接上位机,把轨迹文件、参数标定和记录/回放状态全部可视化。这套体系跑通之后,你对单片机外设的理解和机械臂的整体认知,会比单纯看教程提升一个台阶。建议把整套工程文件、接线图和标定参数一起整理好留档,后面做毕设或二次开发都会用到。