STM32平衡小车项目实战:从PID控制到姿态解算的嵌入式系统综合应用

发布时间:2026/9/3 11:54:53
STM32平衡小车项目实战:从PID控制到姿态解算的嵌入式系统综合应用 简介本资源是一套面向高校嵌入式系统课程设计、毕业设计及期末大作业的高完成度平衡小车实践项目基于WHEELTEC B570硬件平台聚焦STM32F1系列主控的传感器融合、PID控制与实时运动调节等核心能力训练。压缩包共315个文件涵盖44个C源文件含HAL库驱动与MPU6050姿态解算、71个头文件定义硬件抽象与算法接口、44个编译中间文件.o/.d及配套Makefile、链接脚本.ld、工程配置.ioc/.mxproject和固件输出.hex/.elf结构完整可直接本地编译下载运行。已有130人学习下载项目经助教审定评审得分98分难度适中且覆盖从底层外设初始化UART/ADC/TIM、DMP运动驱动到闭环平衡控制的全链路实现。读者可获得可复现的高分项目源码、模块化清晰的工程组织、关键传感器MPU6050与电机驱动调试说明以及适用于教学验收与自主拓展的完整技术文档支撑。1. 项目概述从零到一打造一台能“站起来”的智能小车如果你正在学习嵌入式系统尤其是STM32那么“平衡小车”绝对是一个绕不开的经典项目。它不像点个LED灯那么简单也不像做个遥控车那样直观它的核心魅力在于“动态平衡”——让一个只有两个轮子的机器人像我们人类一样能够自主地站立、移动甚至抵抗外界的干扰。这背后是传感器数据采集、姿态解算、PID控制算法和电机驱动等多个嵌入式核心技术的综合应用。我当年做这个项目时从一堆零件到小车稳稳立住的那一刻那种成就感至今难忘。今天我就以WHEELTEC的B570平衡小车套件为例结合我自己的实战经验把这个“高分项目”从里到外、从硬件到软件彻底拆解一遍希望能为你扫清障碍直通高分。WHEELTEC B570是一个相当成熟的平衡小车开源平台它基于STM32F103C8T6俗称“蓝桥杯”或“战舰”同款核心芯片集成了MPU6050六轴传感器、TB6612电机驱动、编码器反馈等关键模块。你拿到的源码和文档就像一份武功秘籍的“总纲”和“招式图”但要想真正练成还得理解内功心法原理和实战技巧调试。这个项目非常适合作为嵌入式课程设计、毕业设计或者电子竞赛的练手项目。它不仅考察你的C语言编程、单片机外设使用能力更是对你系统思维、算法理解和动手调试能力的全面检验。接下来我将带你深入这个项目的每一个环节。2. 核心硬件平台与电路设计解析2.1 主控芯片STM32F103C8T6的选型与资源分配为什么是STM32F103C8T6这颗芯片在平衡小车项目中堪称“性价比之王”。它属于ARM Cortex-M3内核主频72MHz拥有64KB Flash和20KB RAM。对于平衡小车来说其资源绰绰有余。我们需要重点关注它以下几个外设的使用定时器TIM这是项目的“心脏”。我们需要至少3个定时器TIM2/TIM3/TIM4用于编码器模式读取左右电机的转速和方向。这是实现速度闭环控制的基础。TIM1/TIM8高级定时器用于生成驱动电机的PWM波控制电机的转速和转向。一个基本定时器如TIM6/TIM7用于产生系统中断作为整个控制周期的“节拍器”比如我们常说的“5ms控制周期”就是由它来保障的。串口USART用于调试信息输出连接电脑串口助手和后续可能的蓝牙/Wi-Fi模块通信。I2C总线用于与MPU6050姿态传感器通信读取原始的加速度计和陀螺仪数据。ADC非必需但常用可以用于读取电池电压实现低电量报警或保护。注意在规划引脚时一定要对照芯片数据手册和原理图避免功能复用冲突。例如某些定时器的通道引脚可能与串口或I2C引脚复用需要仔细配置。2.2 姿态感知核心MPU6050的工作原理与数据“驯服”MPU6050是这个项目的“眼睛”和“耳朵”它决定了小车能否感知自身的倾斜状态。它内部集成了三轴加速度计和三轴陀螺仪。加速度计测量的是线加速度包括重力加速度。在静止时我们可以通过计算各轴重力分量的夹角来估算姿态角如俯仰角Pitch。但它对运动特别是电机振动非常敏感动态响应差数据会“漂”。陀螺仪测量的是角速度。通过对角速度积分可以得到角度变化。它的动态响应好但积分会引入累积误差时间一长角度就“飘”到不知道哪里去了。所以核心问题就是如何融合这两组各有优劣的数据得到一个稳定、准确的姿态角这就是姿态解算算法要解决的问题。在B570的源码中最常见的是互补滤波和卡尔曼滤波。互补滤波Complementary Filter思路简单粗暴且有效。它利用高通滤波器提取陀螺仪的高频动态信号利用低通滤波器提取加速度计的低频静态信号然后将两者按一定权重相加。公式可以简化为角度 α * (上一角度 陀螺仪角速度 * dt) (1 - α) * 加速度计角度其中α是一个介于0和1之间的系数dt是采样时间。α越大信任陀螺仪越多响应快但易漂移α越小信任加速度计越多静态稳但动态差。通常需要反复调试找到一个平衡点。卡尔曼滤波Kalman Filter这是一种最优估计算法理论更优美抗干扰能力更强。它将系统建模为一个状态方程和观测方程通过预测和更新两个步骤最优地估计出系统状态这里就是姿态角。源码中如果实现了卡尔曼滤波通常会比互补滤波更稳定但理解和调参难度也更大。实操心得对于初学者我强烈建议先从互补滤波入手。它的效果已经足够让小车站起来了而且参数直观主要调α和dt便于理解融合原理。你可以先让小车静止观察融合后的角度是否跟随加速度计角度再快速晃动小车观察角度是否又能快速跟上陀螺仪的变化。2.3 动力与反馈系统电机、驱动与编码器这是小车的“腿”和“肌肉感知”。电机通常使用N20减速电机或类似的直流减速电机。关键参数是减速比和额定电压它们决定了小车的扭矩和速度。驱动芯片TB6612比传统的L298N效率更高、发热更小。它需要两个PWM信号控制一个电机的速度和方向AIN1/AIN2和PWMA。接线务必正确否则电机可能不转或乱转。编码器这是实现速度闭环和位置闭环的关键。增量式编码器输出A、B两相正交脉冲。STM32的定时器编码器接口模式可以自动根据A、B相的相位关系计数轻松得到脉冲数和方向。速度计算在固定的控制周期如5ms内读取编码器计数值的变化量ΔCnt。速度v (ΔCnt / 编码器线数) * (轮周长 / 控制周期)。这个速度值将作为速度环PID的反馈量。电路连接检查清单[ ] MPU6050的SDA、SCL是否正确连接至STM32的I2C引脚如PB6, PB7并接上拉电阻。[ ] 电机驱动TB6612的PWMA、AIN1、AIN2是否连接至STM32的定时器PWM输出通道和普通GPIO。[ ] 编码器的A、B相是否分别接入支持编码器模式的定时器通道如TIM2的CH1、CH2。[ ] 电池电压是否在电机和芯片的允许范围内常用7.4V或12V锂电池且电源模块如LM2596能为STM32稳定提供5V或3.3V。3. 软件架构与核心控制算法深度剖析拿到源码不要急于下载。先花时间理清整个程序的骨架这比盲目调试效率高十倍。一个典型的平衡小车软件架构如下3.1 程序主循环与中断服务例程的分工平衡小车是一个典型的实时控制系统必须保证控制周期的绝对稳定。因此普遍采用“前台后台”系统架构。后台main函数循环负责非实时或实时性要求不高的任务如初始化所有硬件GPIO、定时器、I2C、USART等。读取蓝牙串口指令如果有的話。更新系统状态如待机、运行、故障。一些慢速的数据显示或记录。前台定时器中断服务例程这是控制系统的核心。由一个基本定时器如TIM6触发每隔固定时间如5ms执行一次。在这个中断里必须完成所有实时控制任务顺序至关重要数据采集通过I2C读取MPU6050的原始数据加速度、角速度。姿态解算调用互补滤波或卡尔曼滤波函数计算出当前小车的俯仰角Pitch和角速度。控制算法计算 a.直立环角度环PD控制根据目标角度通常为0度即直立和当前角度的偏差以及角速度计算出一个控制量目的是让小车“站直”。 b.速度环PI控制根据目标速度通常为0即静止和编码器测得的速度偏差计算出另一个控制量目的是消除直立环带来的静差让小车能真正静止。 c.转向环P控制如果小车需要转弯则根据左右轮速度差或遥控指令叠加一个控制量。控制量融合与输出将直立环、速度环、转向环的输出叠加经过限幅处理后转换为PWM占空比通过高级定时器输出给TB6612驱动电机。关键点中断服务函数里的代码必须精简高效不能有延时函数如delay_ms不能进行复杂的浮点运算如果必须确保STM32已启用硬件浮点单元或使用优化后的库。否则会导致中断执行时间过长影响下一个控制周期系统就会失控。3.2 灵魂所在PID控制算法的原理与调参实战PID是让小车保持平衡的“大脑”。我们主要用到两个环直立环角度环和速度环。3.2.1 直立环角度环PD控制器直立环是内环也是最重要的环。它直接响应小车的倾斜。P比例项P_out Kp * angle_error。angle_error是目标角度与实际角度的偏差。Kp就像小车的“反应速度”。Kp太小小车反应慢软绵绵地倒下Kp太大小车会剧烈抖动甚至发散。D微分项D_out Kd * gyro。这里通常直接用陀螺仪测得的角速度作为微分项而不是对角度误差求微分因为噪声大。Kd代表“阻尼”或“预见性”。它能够抑制P项引起的振荡。没有D项小车会在平衡点附近来回摇摆D项太强系统会反应迟钝。直立环输出Vertical_out P_out D_out3.2.2 速度环PI控制器速度环是外环。你会发现如果只有直立环小车虽然能站住但会慢慢地朝一个方向移动无法静止在一点。这是因为电机阻力、地面不平等因素造成了静差。速度环就是为了消除这个静差。P比例项P_out_speed Kp_s * speed_error。响应速度偏差。I积分项I_out_speed Ki_s * speed_error * dt。积分项会累积历史偏差专门消除静差。但积分项太强会导致“积分饱和”引起系统超调或振荡。速度环输出Speed_out P_out_speed I_out_speed3.2.3 调参步骤与口诀“先内后外先P后D最后I”这是调试成败的关键务必耐心。第一步调直立环PD将速度环和转向环的输出置零。先调Kp从小值开始比如1.0用手扶住小车给一个轻微倾斜感受电机是否有正确的抵抗力度小车往前倾电机应该往后转。逐渐增大Kp直到小车能快速响应倾斜但开始出现高频抖动。此时Kp约为临界值的70%-80%。再调Kd加入一个较小的Kd比如0.5观察抖动是否被抑制。增大Kd直到抖动消失小车反应依然迅速。Kd太大小车会变得“僵硬”反应迟钝。目标松开手小车能自己站立2-3秒不倒。此时它会缓慢移动这是正常的。第二步调速度环PI保持直立环参数不变加入速度环。先调Kp_s从小值开始比如0.1。观察小车是否比之前更“粘地”移动趋势减弱。逐渐增大Kp_s直到小车能在你推动后缓慢回到原位置或在一个小范围内稳定。最后调Ki_s如果小车仍有缓慢的漂移加入一个很小的Ki_s比如0.001。Ki_s的作用是精细修正。务必给积分项设置一个输出限幅防止积分饱和例如限制其最大输出为直立环输出的20%。调试神器串口绘图。将关键数据如angle_error,gyro,Vertical_out,speed_error,Speed_out 以及最终的PWM值通过串口发送到电脑使用SerialPlot、VOFA等工具实时绘图。观察波形你能直观地看到每个参数的影响这是盲调无法比拟的。3.3 源码关键函数导读在B570的源码中你需要重点关注以下几个函数函数名可能略有不同MPU6050_Read()I2C读取原始数据函数。Get_Angle()或IMU_update()姿态解算函数里面包含了互补滤波或卡尔曼滤波的实现。TIM6_IRQHandler()或SysTick_Handler()定时中断服务函数整个控制逻辑的核心。Vertical_Control()直立环PD计算函数。Velocity_Control()速度环PI计算函数。Set_Pwm()或Motor_Output()将最终控制量转换为PWM并输出的函数。4. 项目实战从焊接调试到稳定运行4.1 硬件组装与上电前检查焊接确保所有排针、电机线、电源线焊接牢固无虚焊、短路。特别是MPU6050模块引脚细密焊接时注意不要连锡。安装将MPU6050模块水平安装在小车底盘的中心平面上X轴指向小车前进方向。这是姿态解算的物理基础装歪了角度基准就错了。上电前检查万用表蜂鸣档检查电源与地是否短路。检查电池极性是否正确。用手轻轻拨动轮子观察编码器信号线是否连接牢固。4.2 软件调试分步走基础外设测试串口下载一个最简单的串口打印“Hello World”程序确认下载器和串口通信正常。LED/按键测试GPIO输出输入是否正常。传感器测试编写代码读取MPU6050的ID0x68确认I2C通信成功。读取原始加速度和陀螺仪数据通过串口打印静止时观察加速度计Z轴是否约为1g或-1g取决于安装方向转动小车观察陀螺仪数据变化是否灵敏。电机与编码器测试写一个固定占空比的PWM输出程序测试左右电机是否能正反转。开启定时器编码器模式用手转动轮子通过串口打印计数值确认编码器工作正常且方向正确正转递增反转递减。闭环调试按照3.2.3节的步骤先注释掉速度环和转向环只调试直立环PD参数。保护措施调试时用手扶住小车或者将小车放在两个杯子中间防止它突然暴走损坏设备或伤及自身。利用串口绘图边调边看。4.3 稳定运行与功能扩展当小车能稳定站立后你可以尝试蓝牙遥控通过HC-05/06模块用手机APP或电脑发送指令控制小车前进、后退、转向。循迹/避障增加红外对管或超声波模块让小车实现自动循迹或避障功能。上位机监控利用Qt、Matlab或Python如PyQt、Tkinter编写一个简单的上位机实时显示小车角度、速度、PWM等曲线并支持参数在线调节。优化控制算法尝试更高级的算法如串级PID、模糊PID或者将卡尔曼滤波从姿态解算扩展到整个状态估计。5. 常见问题与故障排查实录即使有源码调试过程也绝不会一帆风顺。下面是我和学生们常遇到的“坑”问题现象可能原因排查思路与解决方案小车完全无反应电机不转1. 电源问题电池没电、开关未开、电源线虚焊。2. 主控芯片未正常工作晶振、复位电路、Boot引脚。3. 程序未成功下载或运行。1. 用万用表测量各关键点电压电池电压、5V/3.3V稳压输出、单片机VDD。2. 检查晶振是否起振示波器看波形Boot0/1引脚是否接地。3. 下载一个最简单的LED闪烁程序确认开发环境、下载器、芯片均正常。电机抖动或只朝一个方向转1. 电机驱动芯片TB6612输入逻辑错误。2. PWM输出通道或极性配置错误。3. 控制量计算错误输出始终为正或负。1. 检查AIN1/AIN2控制方向的GPIO电平是否正确。2. 用示波器或逻辑分析仪检查PWM波形是否正常输出占空比是否随控制量变化。3. 在调试中打印最终的PWM控制值看其是否在正负范围内正常变化。小车立不住往一个方向加速倒下1.MPU6050安装方向错误或坐标系定义错误。2. 直立环PID极性错误正反馈。3. 角度零点机械中值未校准。1.这是最高频的问题确认小车前倾时MPU6050测得的俯仰角是正还是负与控制算法的期望是否匹配。最简单的方法将计算出的角度通过串口打印用手前倾/后倾小车看角度值变化方向是否正确。2. 检查直立环输出公式符号。小车前倾角度为正电机应该向后转产生向前的力使小车回正。如果反了将Kp或整个输出取反。3. 将小车放在一个你认为绝对水平的平面上读取此时的俯仰角将此值作为零点偏移量在程序中减去。小车能站但剧烈抖动1. 直立环Kp太大或Kd太小。2. 控制周期不稳定中断被干扰。3. 传感器数据噪声大MPU6050未校准、电源不稳。1.降低Kp增大Kd。这是最主要的调节手段。2. 检查定时器中断优先级是否最高中断服务函数是否执行时间过长。3. 对MPU6050的原始数据进行简单的滑动平均滤波或使用其内置的DLPF数字低通滤波器。确保其供电稳定3.3V最好单独从LDO取电而非电机驱动板上的3.3V。小车站住后缓慢漂移1. 速度环未起作用或参数不当。2. 机械结构不对称重心偏移。3. 电机或齿轮箱存在回差。1. 检查速度环是否已启用Ki_s是否过小或积分限幅是否太小。适当增大Ki_s。2. 尝试微调小车重心如移动电池位置。3. 这是硬件固有特性可在软件中为两个电机设置微小的补偿值。通过蓝牙遥控无反应1. 蓝牙模块未正确配对或接线错误TX/RX接反。2. 串口中断与定时器中断冲突。3. 协议解析错误。1. 先用串口助手测试蓝牙模块透传是否正常。2. 避免在高速定时器中断中处理串口数据。应在主循环或低优先级串口中断中处理。3. 打印接收到的原始数据检查是否符合约定的协议格式如‘f’前进‘b’后退。最后一点个人体会调平衡小车耐心和观察力比盲目修改代码更重要。它是一个软硬件紧密结合的系统任何一个环节的微小偏差都可能导致失败。充分利用好串口打印调试信息和绘图工具让你的调试过程从“盲人摸象”变成“眼见为实”。当你第一次看到自己亲手组装、编程的小车颤颤巍巍又坚定地站立起来时你会觉得之前所有的抓狂和熬夜都是值得的。这份从理论到实践从问题到解决的全过程经验才是这个“高分项目”带给你的最大财富。本文还有配套的精品资源点击获取