1. 平衡车项目概述与核心需求
平衡车作为典型的机电一体化项目,本质上是一个倒立摆控制系统。十年前我第一次接触这类项目时,就被其精妙的控制算法所吸引。基于STM32的方案之所以成为创客和工程师的首选,主要得益于其出色的实时性能和丰富的外设资源。
这个项目需要同时解决三个核心问题:姿态感知、运动控制和动力输出。其中最关键的是在5ms内完成从传感器数据采集到电机控制的完整闭环,这对处理器的计算能力和中断响应提出了严苛要求。STM32F4系列芯片的168MHz主频和硬件浮点单元恰好能满足这一需求,这也是我选择它的主要原因。
2. 硬件系统设计详解
2.1 主控选型与电路设计
经过多次迭代测试,最终选定STM32F405RGT6作为主控芯片。这款芯片的优势在于:
- 自带硬件浮点运算单元(FPU)
- 12个定时器通道支持6路PWM输出
- 3个USART和2个SPI接口
- 运行FreeRTOS时仍有充足资源余量
电源部分采用两级稳压设计:第一级LM2596将锂电池电压降至5V,第二级AMS1117-3.3为MCU供电。实测中这个方案能有效抑制电机启停造成的电压波动。特别提醒:稳压芯片必须加装散热片,我在初期测试中就因过热烧毁过两个AMS1117。
2.2 传感器模块选型
MPU6050是最常用的姿态传感器,但直接使用其DMP输出存在20ms左右的延迟。我的改进方案是:
- 关闭DMP功能
- 通过I2C直接读取原始数据
- 在STM32上实现互补滤波算法
这样能将延迟控制在3ms以内,具体接线方式如下:
code复制MPU6050 STM32
VCC → 3.3V
GND → GND
SCL → PB6
SDA → PB7
INT → PA0(外部中断)
2.3 电机驱动电路
采用双TB6612FNG驱动模块的方案,相比L298N具有以下优势:
- 效率提升30%以上
- 工作温度降低15-20℃
- 支持1.2A持续电流输出
特别注意:电机电源必须与控制系统电源隔离!我曾在初期将两者共用一组锂电池,结果电机启动瞬间导致MCU复位。后来改用独立的18650电池组供电,问题彻底解决。
3. 软件算法实现
3.1 姿态解算优化
传统卡尔曼滤波在STM32F4上需要2.3ms计算时间,经过优化后采用以下方案:
c复制// 简化版互补滤波实现
void IMU_Update(float dt) {
// 加速度计数据归一化
float acc_norm = sqrt(ax*ax + ay*ay + az*az);
ax /= acc_norm; ay /= acc_norm; az /= acc_norm;
// 陀螺仪积分
gx += gyro_x * dt;
gy += gyro_y * dt;
// 互补滤波
float tau = 0.98;
angle_x = tau*(angle_x + gyro_x*dt) + (1-tau)*atan2(ay, az);
angle_y = tau*(angle_y + gyro_y*dt) + (1-tau)*atan2(-ax, sqrt(ay*ay + az*az));
}
实测显示该算法仅需0.8ms即可完成计算,且角度误差在±1°以内。
3.2 PID控制算法实现
采用位置式PID与速度PID的双环控制结构:
c复制typedef struct {
float Kp, Ki, Kd;
float integral;
float prev_error;
} PID;
float PID_Calculate(PID* pid, float error, float dt) {
pid->integral += error * dt;
float derivative = (error - pid->prev_error) / dt;
pid->prev_error = error;
return pid->Kp*error + pid->Ki*pid->integral + pid->Kd*derivative;
}
调试时发现几个关键点:
- 先调速度环再调角度环
- Ki参数过大会引起剧烈振荡
- 输出限幅必须设置(建议±200)
3.3 电机控制策略
使用定时器输出PWM配合GPIO控制方向,关键配置如下:
c复制// PWM频率设为10kHz
TIM_TimeBaseInitTypeDef TIM_Init;
TIM_Init.TIM_Prescaler = 84-1; // 84MHz/84=1MHz
TIM_Init.TIM_Period = 100-1; // 1MHz/100=10kHz
TIM_TimeBaseInit(TIM1, &TIM_Init);
// 设置占空比
#define PWM_SetDuty(ch, duty) TIM1->CCR##ch = (uint16_t)(duty)
实测发现当PWM频率低于8kHz时,电机会发出可闻噪音。而高于15kHz会导致MOS管发热明显增加。
4. 系统调试与优化
4.1 传感器校准流程
MPU6050必须进行以下校准:
- 水平静置10秒采集陀螺仪零偏
- 旋转各轴检查数据连续性
- 通过以下代码补偿零偏:
c复制gyro_x -= gyro_x_offset;
gyro_y -= gyro_y_offset;
gyro_z -= gyro_z_offset;
常见陷阱:校准过程中设备必须保持绝对静止,我曾因桌面轻微震动导致校准失败。
4.2 PID参数整定方法
推荐采用"阶跃响应法"进行调试:
- 先将所有参数设为0
- 逐步增加Kp直到出现小幅振荡
- 取振荡临界值的50%作为最终Kp
- 以相同方法调整Kd
- Ki最后调整,通常为Kp的1/100
我的实测参数范围参考:
- 角度环:Kp=25, Ki=0, Kd=0.5
- 速度环:Kp=100, Ki=2, Kd=0
4.3 抗干扰设计
三个关键改进点:
- 在电机电源线上加装磁环
- 所有信号线使用双绞线
- ADC采样端口添加0.1uF去耦电容
特别提醒:PWM信号线要远离模拟信号线!我曾因布线不当导致MPU6050数据出现周期性跳变。
5. 全套资料说明
提供的工程包含以下关键文件:
/Hardware:Altium Designer格式原理图+PCB/Software:Keil MDK完整工程bsp_mpu6050.c:优化后的传感器驱动control.c:双环PID实现motor.c:带死区补偿的电机控制
/Documents:中文开发文档- 焊接注意事项
- 参数测量方法
- 故障排查指南
资料使用建议:
- 先阅读《硬件组装指南》
- 使用预编译的测试固件验证各模块
- 逐步修改算法参数
6. 常见问题解决方案
问题1:上电后电机剧烈抖动
- 检查PID参数是否过大
- 确认MPU6050安装方向是否正确
- 测量电机供电电压是否稳定
问题2:平衡车偏向一侧
- 重新校准陀螺仪零偏
- 检查机械结构是否对称
- 调整电机死区补偿参数
问题3:运行一段时间后失控
- 检查稳压芯片温度
- 监测堆栈使用情况(FreeRTOS)
- 添加看门狗定时器
我在开发过程中总结的黄金法则:出现异常时首先断开电机供电,用LED指示灯或串口输出调试信息,绝对不要在电机运转时进行电路修改!
7. 进阶改进方向
对于想进一步提升性能的开发者,可以考虑:
- 改用STM32H7系列提升运算能力
- 实现基于Q格式的定点数运算优化
- 添加蓝牙遥控功能(推荐HC-05模块)
- 移植到CubeMX+FreeRTOS环境
最后分享一个实用技巧:在调试时可以用手机充当简易示波器,通过ADC采集关键信号后用串口发送,再使用SerialPlot等工具可视化。这个方法帮我快速定位了三个隐蔽的算法缺陷。