双STM32六足机器人:舵机PWM控制与步态算法实现解析
2026/9/16 12:37:29 网站建设 项目流程

简介:基于 STM32 的六足机器人控制系统完整设计资料,涵盖结构分析、步态控制、多模式交互与软硬件协同实现,可作为单片机、嵌入式方向课程设计或毕业设计的综合参考。系统采用主控板与舵机控制板分离的双板架构,主控 STM32F103VET6 负责数据处理与显示,舵机控制板 STM32F103R8T6 负责角度控制,两板通过串口通信;同时引入无线网络、蓝牙、语音识别、手势识别及云端服务器,可针对不同应用场景选择不同控制方案。压缩包共 944 个文件、约 101.91MB,涵盖 C 语言源码与头文件、Keil 工程、Altium Designer 原理图与 PCB、制板文件、安卓工程与手机安装包、PDF 说明等,能够支撑从源码阅读、电路打样、焊接测试到移动端验证的完整流程。目前已有 314 人学习。配套资料中还提供可直接安装调试的手机 APP、云端平台 C# 服务端代码及完整机器人工程文件,方便核对硬件连接、复现步态算法并扩展语音/手势控制逻辑,适合需要一手项目资料或二次开发的学习者。

1. 双核驱动的六足机器人:为什么一块 STM32 不够用

六足机器人最容易翻车的地方不是算法本身,而是舵机一多,单片机的中断和时序就全面失控。常见配置六条腿各带 3 个舵机,共 18 路 PWM 要持续刷新,与此同时还要处理蓝牙、WiFi、语音和手手势识别数据,单颗 STM32F103C8T6 的资源在真实负载下非常吃紧。BlackPearlRobot 工程给出的方案是把系统拆成主控板和舵机控制板:主控板用 STM32F103VET6 负责通信决策与指令仲裁,舵机板用 STM32F103R8T6 专职输出 PWM,两块板之间通过串口交换数据。这个架构把实时性要求高的舵机刷新和实时性要求高但频率低的控制逻辑解耦,适合课程设计,也适合作为量产前验证的原型。

2. 双 STM32 硬件分工与舵机板 PWM 资源设计

2.1 为什么把控制权拆成两块板

单芯片方案不是不能跑,一块高主频 STM32F4 也能同时完成 18 路 PWM 和通信处理,但 103 系列定位下,把负载分开是性价比最高的做法。舵机 PWM 刷新周期通常 20ms,即 50Hz;在一个周期里 18 路舵机的脉宽要精确到微秒级,任意一路的中断延迟抖动都会让舵机表现为抖动或异响。当主控板同时在做步态计算、串口解析、语音指令识别和 WiFi 数据转发时,中断嵌套会让 PWM 输出的 jitter 明显增大。

舵机控制板的任务被压缩到只剩两个:解析串口协议、更新 PWM 比较寄存器。这样舵机刷新不依赖操作系统和复杂逻辑,十六条物理链路的数据流是确定的。主控板则把精力放在步态状态机和工作模式切换上,两边各干各的,出问题时也更容易通过串口日志定位是通信层还是控制层的问题。

2.2 舵机控制板的 PWM 定时器映射

舵机控制板选用 STM32F103R8T6,它提供 TIM1、TIM2、TIM3、TIM4 四个可输出 PWM 的定时器,每个定时器 4 个通道,共 16 路。对于 18 自由度六足机器人,直接映射还差两路,工程上常见三种补法:一是减少死重舵机,把六足设计成 12 路舵机(每条腿 2 个自由度);二是通过 I2C 外扩 PCA9685;三是把两条步态同步的腿部舵机并联在同一通道。第三种做法在测试中容易出现堵转电流叠加烧驱动器,我一般不会用。更稳妥的是保留 16 路定时器 PWM,剩余两路用一个独立小舵机板或 PCA9685 补足。

一个常规的通道分配表格如下,实际编号按工程中的 BLackPearlRobot 舵机索引即可。

定时器通道 1通道 2通道 3通道 4
TIM1左前腿髋左前腿大腿左前腿小腿左中腿髋
TIM2左中腿大腿左中腿小腿左后腿髋左后腿大腿
TIM3右前腿髋右前腿大腿右前腿小腿右中腿髋
TIM4右中腿大腿右中腿小腿右后腿髋右后腿大腿

PWM 初始化时要把定时器分频和重装载值算准。以 72MHz 系统时钟为例,输出 50Hz 的 PWM,预分频 PSC 设为 71,这样计数频率是 72MHz / (71+1) = 1MHz,即每计数一次为 1 微秒。自动重装载值 ARR 设为 19999,得到 1MHz / 20000 = 50Hz。舵机脉宽 0.5ms 到 2.5ms 对应 CCR 值 500 到 2500。初始化代码里要把定时器的 PWM 模式配成向上计数、输出极性为高,这样逻辑分析仪观察到的波形和舵机实际响应一致。

2.3 双板串口通信协议设计

主控板与舵机控制板之间采用串口进行数据交互,波特率 115200 在 20ms 的控制周期内足够传输完整的舵机角度帧。协议帧的格式是:帧头 0xAA 0x55,命令字,18 路角度数据(每路 2 字节,高位在前),最后加一个累加和校验。帧头防止串口错位,校验字节防止干扰导致舵机误动作。

typedef struct { uint8_t head[2]; uint8_t cmd; uint16_t angle[18]; uint8_t checksum; } ServoFrame; uint8_t calc_checksum(const ServoFrame* f) { uint8_t sum = 0; for (uint16_t i = 0; i < 38; i++) { sum += ((uint8_t*)f)[i]; } return sum; }

代码里的angle[18]存放舵机目标角度值,单位是 0.1 度,所以 900 代表 90 度。calc_checksum把整个帧结构按字节累加,帧尾的checksum字段与累加值相等时才执行角度更新。实测中出现舵机随机抖动时,先看校验失败的帧占比,如果校验失败率高,优先排查串口共地问题和舵机大电流对逻辑电源的冲击,而不是改协议。

3. 原理图与 PCB 实现:Altium Designer 16 的布板细节与打样调试

3.1 最小系统四件套:启动、晶振、复位、下载

主控板在 Altium Designer 16 中完成原理图和 PCB 设计,围绕 STM32F103VET6 的最小系统有四块电路必须画对。启动电路用 BOOT0 和 BOOT1 跳线组合,正常运行时 BOOT0 拉低选择 Flash 启动,需要 ISP 升级时拉高。晶振电路给主控提供 8MHz 主频和 32.768kHz 的 RTC 时钟源,两个负载电容各取 20pF 左右,布局时晶振尽量贴近 MCU 引脚,走线要短且对称。复位电路使用 RC 复位,10kΩ 电阻上拉到 3.3V,100nF 电容对地,复位时间常数约 1ms,按下复位按键时能产生可靠的低电平复位信号。

下载接口直接引出 SWD 四线:SWDIO、SWCLK、GND、3V3。相比串口 ISP,SWD 在板子调试阶段更实用,不占用串口资源,也不受 BOOT 跳线状态影响。原理图绘制时,STM32 每个电源引脚旁边都要放一个 100nF 去耦电容,并且电容物理位置要尽量靠近对应电源引脚;如果打样回来发现程序跑飞或 ADC 采样跳动,先检查是不是去耦电容离引脚太远。

3.2 电源树与模块接口的噪声控制

整版电源树从外部 5V 输入开始,5V 直接供给舵机电源轨,逻辑部分经 AMS1117-3.3 稳压到 3.3V。舵机属于大电流脉冲负载,瞬间电流可达 2A 级别,所以舵机电源和逻辑电源要完全分开走线,只在输入端共地。ESP8266 在 WiFi 发射时电流尖峰明显,必须在模块电源引脚就近放置 1000μF 电解电容和 0.1μF 陶瓷电容并联,否则 WiFi 透传时主控板会随机复位。

PCB 布线时注意几个关键规则:

信号类型最小线宽间距要求说明
舵机电源 5V40mil与信号线 10mil载流决定线宽,可铺铜加厚
3.3V 逻辑电源20mil与地间距 8mil电源平面扇出
串口/USB 信号10mil与电源线 8mil差分对等长
晶振走线10mil包地处理走线下方不要铺其他信号

在 Altium Designer 16 里,除了在 Rule 菜单里设定这些线宽和间距规则,还要给 GND 做铺铜。打样回来后焊接顺序也有讲究:先焊电源部分,上电用万用表量 3.3V 是否正常;再焊晶振和复位电路,用示波器确认 8MHz 波形起振;最后焊 STM32 和 SWD 接口,连接 ST-Link 能读到芯片 ID 才算最小系统通过,再逐个焊接外设接口。一次把所有元件焊完再上电的做法在小批量调试中很容易烧板,不推荐。

4. 步态算法与多控制模式:从三脚步态到云端指令链

4.1 六足结构自由度与舵机转角约束

六足机器人的腿部机构采用三条腿各 3 个自由度的构型:基节舵机负责腿部前后摆动,大腿舵机负责抬腿高度,小腿舵机负责足端着地姿态。每个舵机有机械限位,典型范围是基节 -90° 到 90°,大腿 -45° 到 135°,小腿 -30° 到 150°,超出范围就会堵转。步态算法输出的角度必须经过限幅,避免舵机齿轮打齿。

运动学逆解的目标是把足端坐标映射成三个舵机角度。基节角由足端位置在水平面上的投影和机器人身体中心的连线与正前方夹角决定,大腿和小腿角则由两点距离配合余弦定理求解。

4.2 三脚步态的时序编排

六足机器人最基本的稳定步态是三脚步态:六条腿分成两组,第一组是右前、左中、右后,第二组是左前、右中、左后,两组交替支撑和摆动。任意时刻至少有三条腿着地,组成一个三角形支撑面,重心落在三角形内就能保持静止或缓慢移动稳定。步态周期参数放在步态结构体里,通过调整抬腿高度、步幅和周期来适配不同的地面条件。

typedef struct { uint8_t swing_phase; // 0 表示支撑相,1 表示摆动相 uint16_t cycle_time_ms; // 完整步态周期,如 600ms int16_t step_height; // 抬腿高度,单位 0.1mm int16_t step_length; // 步幅,单位 0.1mm int16_t body_height; // 机身高度,单位 0.1mm } GaitParam; int16_t leg_angle[6][3]; void update_gait(GaitParam* gait, uint16_t elapsed_ms) { for (int leg = 0; leg < 6; leg++) { int phase = ((elapsed_ms * 2 / gait->cycle_time_ms) + leg) % 2; if (phase == 0) { // 支撑相:足端相对身体后移,推动身体前进 joint_trajectory(leg, 0, -gait->step_length / 2); } else { // 摆动相:足端抬起并向前摆动 joint_trajectory(leg, gait->step_height, gait->step_length / 2); } } }

update_gait按时间递进,每组三条腿交叉进入摆动相。phase的计算把腿编号偏移加入时间轴,避免所有腿同时切换导致重心失稳。摆动相里的joint_trajectory负责把足端轨迹平滑转换到舵机角度,如果直接阶跃切换角度,机器人会像抽搐一样前进。控制周期建议 10ms 一帧,步态周期 600ms 时一个周期内更新 60 次,舵机运动曲线足够平滑。

4.3 WiFi、蓝牙、语音、手势的指令汇聚

4.3.1 本地链路的优先级仲裁

系统支持 WiFi、蓝牙、语音识别和手势识别四种控制方式。WiFi 采用 ESP8266 透传模块,默认 AT 固件,主控通过串口发送 AT 指令配置为 STA 模式连接路由器,手机 APP 通过 TCP 连接模块的 8080 端口下发动作指令。蓝牙使用经典蓝牙透传模块,配对后 APP 直接用虚拟串口发送数据。语音识别选用离线模块,通过串口输出识别到的关键词编号。手势识别则是把惯性传感器佩戴在手腕上,板载姿态解算输出手势标签。

主控板串口规划:USART1 接 ESP8266,USART2 接蓝牙,USART3 接舵机控制板,语音和手势分别占用 USART4 和 USART5。多路指令同时到达时必须有仲裁机制,实际操作中把指令按优先级分级:

控制源优先级典型指令
语音急停最高“停止”触发立即停车
蓝牙手柄前进、后退、转弯
手势识别向左、向右
云端 APP路径规划、远程巡检

这些指令统一进入主控命令队列,高优先级可以直接抢占低优先级指令,例如语音急停在任何状态下都要立刻置零舵机目标角度,不能让云端指令把当前状态覆盖掉。

4.3.2 云端指令流与 C# 服务端

云端平台采用 C# 实现常见做法是使用 ASP.NET Core 建一个 WebSocket 或者 SignalR 服务,把手机 APP 和机器人端的 ESP8266 连接在一起。手机通过 WiFi 或 4G 访问云端,云端再把控制指令推送到机器人的 TCP 长连接上。信号从请求产生到舵机动作的链路是:APP 按下前进按钮,发起 HTTP 或 WebSocket 请求,云端收到后查寻在线设备表,把指令转发给对应设备,ESP8266 收到后经串口交给主控,主控调步态更新,再由串口把角度帧给舵机板。

public class CmdHub : Hub { public async Task SendCmd(string deviceId, string cmd) { // 设备端通过 RegisterDevice 加入设备组 await Clients.Group(deviceId).SendAsync("cmd", cmd); } }

deviceId是每一台六足机器人的唯一标识,比如BLACKPEARLROBOT_01SendCmd把指令投递到对应 SignalR 分组,ESP8266 端的客户端库负责接收并回传给主控。这里要注意只控制指令若走公网,云端和机器人之间必须做设备鉴权和指令合法性校验,否则任何连上网的人都能控制你的机器人。

5. 上位机联调技巧:串口抓包、参数标定与工程文件规范

很多六足机器人调试到最后才发现问题全出在舵机角度和通信帧错位上,所以建议先把上位机联调工具链跑通再整机测试。用 Android Studio 开发的应用可以实时下发指令,但我在整机测试时习惯先做一个 Python 串口回放脚本,直接通过 USB 转串口连接主控板,把要测试的步态数据逐帧发出去,避免手机端的问题倒灌到机器人端。

import serial, struct, time ser = serial.Serial('COM5', 115200, timeout=0.1) for i in range(100): frame = bytes([0xAA, 0x55, 0x01]) + struct.pack('>36H', *angles) + bytes([0xFF]) ser.write(frame) time.sleep(0.01)

angles是 18 个舵机角度列表,代码里使用大端序打包成帧。这个脚本的价值在于可以通过修改angles直接验证舵机正反向、限位是否一致,同时用串口打印主控返回的应答帧来判断协议是否闭环。测试步态时建议先把所有舵机置于中位,用手按压机器人身体确认每个关节的物理方向与逻辑方向一致,避免反转错误被放大成步态错乱。

舵机标定要逐个通道进行,记录实测脉宽和理论值的偏差:

通道中位脉宽/μs最小脉宽/μs最大脉宽/μs死区修正
115055102495+12
214985052490-6

死区修正是把实测中位与理论 1500μs 的偏差写入主控的参数表里,角度计算时统一补偿,否则六条腿在空载时看起来位置一致,负载后整体往一侧偏。标定完成后把参数表导出成头文件,和固件一起打 tag 归档。工程文件从 YS-V0.3 到 YS-V0.7 的版本演进过程里,固件、AD 工程和 APP 源码的版本号需要保持同步,建议每次改动硬件布局或舵机映射时同步更新BLACKPEARLROBOT.apr对应的宏定义文件,并在源码仓库里写清楚改动点。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询