1. STM32平衡车项目概述
平衡车作为嵌入式系统开发的经典项目,完美融合了传感器技术、控制算法和电机驱动等核心要素。使用STM32单片机开发平衡车,不仅能深入理解PID控制原理,还能掌握嵌入式实时系统设计方法。这个项目特别适合有一定STM32基础的开发者进阶学习,也常被用作电子类专业毕业设计的选题。
我去年用STM32F103C8T6做过一个迷你平衡车,从电路设计到代码调试踩过不少坑。平衡车的核心在于通过陀螺仪和加速度计获取车身姿态,然后通过PID算法计算出电机控制量,最终实现自主平衡。整个过程涉及传感器数据融合、实时控制、PWM输出等多个关键技术点。
2. 硬件设计与选型
2.1 主控芯片选择
STM32F103系列是平衡车项目的性价比之选:
- 72MHz主频足够处理传感器数据和PID运算
- 内置定时器可生成PWM信号控制电机
- 丰富的外设接口方便连接各类传感器
- 开发资源丰富,社区支持完善
提示:初学者建议使用STM32F103C8T6最小系统板,价格约15-20元,烧录方便且引脚引出完整。
2.2 姿态传感器选型
MPU6050是最常用的6轴传感器:
- 三轴加速度计测量重力方向
- 三轴陀螺仪测量角速度
- 内置DMP可输出融合后的姿态角
- I2C接口与STM32通信方便
实际使用中发现MPU6050的零点漂移问题需要注意:
c复制// 校准代码示例
void MPU6050_Calibrate()
{
int32_t sum[6] = {0};
for(int i=0; i<1000; i++){
MPU6050_GetData();
sum[0] += gyro.x; sum[1] += gyro.y; sum[2] += gyro.z;
sum[3] += acc.x; sum[4] += acc.y; sum[5] += acc.z;
delay(2);
}
offset.gx = sum[0]/1000; // 存储校准值
// 其他轴类似...
}
2.3 电机驱动方案
TB6612FNG是理想的直流电机驱动芯片:
- 双路H桥设计,可驱动两个电机
- 最大1.2A持续电流,满足小型平衡车需求
- 支持PWM调速和正反转控制
- 内置短路保护和过热保护
接线示意图:
code复制STM32 PWM1 -> TB6612 PWMA
STM32 PWM2 -> TB6612 PWMB
STM32 GPIO -> TB6612 AIN1/AIN2 (控制方向)
STM32 GPIO -> TB6612 BIN1/BIN2 (控制方向)
3. 软件架构设计
3.1 系统任务划分
平衡车需要实时处理多个任务:
- 传感器数据采集(100Hz)
- 姿态解算(100Hz)
- PID控制计算(100Hz)
- 电机PWM输出(100Hz)
- 用户交互(10Hz)
使用定时器中断实现多任务调度:
c复制void TIM3_IRQHandler()
{
static uint8_t cnt = 0;
if(TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET){
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
MPU6050_GetData(); // 每1ms执行
Angle_Calculate(); // 姿态解算
Motor_Output(); // 电机输出
if(++cnt >= 10){ // 每10ms执行
cnt = 0;
Key_Scan(); // 按键扫描
OLED_Refresh(); // 显示刷新
}
}
}
3.2 姿态解算实现
互补滤波是最实用的姿态融合算法:
c复制void Angle_Calculate()
{
// 加速度计计算倾角
float acc_angle = atan2(acc.y, acc.z) * 180/PI;
// 陀螺仪积分计算角度
gyro_angle += gyro.x * dt; // dt为采样周期
// 互补滤波融合
angle = 0.98*(angle + gyro.x*dt) + 0.02*acc_angle;
}
注意:dt值需要精确计算,建议使用定时器捕获实际时间间隔。我实测发现dt误差超过10%会导致控制不稳定。
3.3 PID控制器设计
位置式PID算法实现:
c复制typedef struct {
float Kp, Ki, Kd;
float err, last_err, integral;
} PID;
float PID_Calculate(PID* pid, float target, float feedback)
{
pid->err = target - feedback;
// 积分限幅防止windup
pid->integral += pid->err;
if(pid->integral > 500) pid->integral = 500;
if(pid->integral < -500) pid->integral = -500;
// PID计算
float output = pid->Kp * pid->err
+ pid->Ki * pid->integral
+ pid->Kd * (pid->err - pid->last_err);
pid->last_err = pid->err;
return output;
}
参数整定经验:
- 先调Kp使车体能快速响应但不振荡
- 再调Kd抑制超调和振荡
- 最后调Ki消除静差
- 典型初始值:Kp=20, Ki=0.5, Kd=1.0
4. 系统调试与优化
4.1 传感器校准技巧
MPU6050校准注意事项:
- 校准时保持传感器水平静止
- 采集1000个样本取平均值
- 温度变化时需重新校准
- 存储校准值到Flash避免每次上电校准
4.2 PID参数整定方法
我的参数整定步骤:
- 先将Ki和Kd设为0,逐渐增大Kp直到车体开始振荡
- 取振荡临界值的50%作为Kp初始值
- 增加Kd直到超调量减小到可接受范围
- 最后加入少量Ki消除静差
4.3 常见问题排查
-
车体向一侧倾斜:
- 检查电机接线是否一致
- 确认两个轮子转速相同
- 重新校准MPU6050
-
剧烈振荡无法平衡:
- 降低Kp和Kd值
- 检查传感器数据是否异常
- 确认控制周期稳定
-
响应迟钝:
- 适当增大Kp
- 检查电池电压是否充足
- 确认PWM频率合适(建议8-10kHz)
5. 进阶优化方向
5.1 速度闭环控制
在平衡控制基础上增加速度环:
- 通过编码器测量轮速
- 设计外环速度PID控制器
- 速度环输出作为平衡环的角度设定值
5.2 无线遥控功能
添加蓝牙或2.4G模块实现:
- 手机APP遥控控制
- 参数无线调整
- 状态实时监控
5.3 低功耗优化
针对电池供电的优化措施:
- 动态调整CPU频率
- 传感器间歇工作模式
- 电机驱动休眠功能
我在实际项目中发现,使用STM32的STOP模式可以降低约60%的功耗,但需要注意唤醒后的传感器重新初始化。
