1. 项目概述:STM32两轮平衡车核心设计思路
两轮平衡车作为经典的嵌入式控制实践项目,完美融合了传感器技术、电机控制和实时算法。这个基于STM32F103的方案,硬件上采用MPU6050姿态传感器+TB6612电机驱动的经典组合,软件层面则通过位置式PID算法实现直立控制。不同于市面上常见的成品平衡车,这个开源项目最大的价值在于完整公开了从电路设计到代码实现的全部细节。
在实际开发中,平衡车的核心挑战主要来自三个方面:首先是传感器数据的准确获取与融合,MPU6050输出的原始数据需要经过滤波和角度换算;其次是控制算法的实时响应,普通PID算法难以应对车体快速倾倒的动态过程;最后是电机驱动的稳定性,大电流切换带来的电源干扰和MOS管发热问题不容忽视。这个项目针对这些痛点都给出了经过实测的解决方案。
2. 硬件设计详解
2.1 传感器模块设计要点
MPU6050作为姿态感知的核心,其I²C接口通常连接STM32的PB6(SCL)/PB7(SDA)引脚。实际布线时需要注意:
- 传感器下方建议涂抹焊锡膏辅助散热,因为持续工作的陀螺仪芯片会产生一定热量
- I²C总线需配置4.7kΩ上拉电阻,布线长度不宜超过10cm
- 电源引脚必须并联0.1μF去耦电容,放置位置尽量靠近传感器VCC引脚
重要提示:MPU6050的AD0引脚电平决定了器件地址(0x68/0x69),多传感器系统中需特别注意地址分配
2.2 电机驱动电路设计
TB6612是双通道H桥驱动芯片,相比L298N具有更高效率(90%以上)和更低发热量。关键设计参数:
-
电源设计:
- 主电源输入需采用低ESR的100μF钽电容滤波
- 逻辑电源与电机电源必须隔离,建议使用DC-DC模块
- 电源走线宽度≥30mil(2oz铜厚),过孔数量尽量少
-
PWM信号处理:
- 输入引脚需串联100Ω电阻抑制振铃
- 死区时间建议设置为1μs左右
- 刹车功能引脚建议通过跳线可选
-
散热设计:
- 芯片底部散热焊盘必须与大面积铜箔连接
- 持续工作电流>1A时需要添加散热片
- PCB建议采用2oz铜厚以提高载流能力
2.3 PCB布局关键技巧
电机驱动部分的布局直接影响系统稳定性:
- 大电流路径优先布局,遵循"输入电容→芯片→输出电容"的最短路径原则
- 信号地与功率地单点连接,推荐使用0Ω电阻或磁珠隔离
- 敏感信号线(如编码器输入)远离PWM走线,必要时采用包地处理
- 关键参数对比:
| 设计参数 | 推荐值 | 不良后果 |
|---|---|---|
| 电源线宽 | ≥30mil | 电压跌落严重 |
| PWM频率 | 18-20kHz | 电机啸叫/MOS过热 |
| 铜厚选择 | 2oz | 温升过高 |
| 去耦电容 | 0.1μF+10μF | 信号抖动 |
3. 软件实现解析
3.1 传感器数据处理
原始数据需经过多重处理才能用于控制:
c复制// 加速度计数据换算角度(单位:度)
float Accel_angle = atan2(ay, az) * 57.29578f;
// 陀螺仪积分计算角度变化
float Gyro_angle = gx * 0.000532f; // 16.4LSB/(°/s) @2000dps
// 互补滤波融合
Angle = 0.98*(Angle + Gyro_angle) + 0.02*Accel_angle;
滤波参数选择原则:
- 陀螺仪权重(0.98):决定系统响应速度
- 加速度计权重(0.02):修正长期漂移
- 剧烈晃动时可适当提高加速度计权重至0.05
3.2 位置式PID算法实现
c复制typedef struct {
float Target; // 目标角度(如0°)
float Kp,Ki,Kd; // PID参数
float Err,LastErr,PrevErr; // 误差记录
float Output; // 输出PWM值
} PID;
void PID_Calc(PID *pid)
{
pid->Err = pid->Target - Actual_Angle;
// 微分先行计算
float dErr = pid->Err - pid->LastErr;
// 位置式PID公式
pid->Output = pid->Kp * pid->Err
+ pid->Ki * pid->Integral
+ pid->Kd * dErr;
pid->LastErr = pid->Err;
}
调参步骤:
- 初始化Ki=0, Kd=0
- 逐步增加Kp直到车体开始高频抖动
- 加入Kd抑制抖动,通常为Kp的1/10
- 最后加入微小Ki消除静态误差
3.3 电机控制实现
TB6612的PWM驱动代码关键点:
c复制void SetMotorPWM(int moto1, int moto2)
{
// 电机1方向控制
if(moto1>0){
MOTOR1_A = 1;
MOTOR1_B = 0;
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, moto1);
} else {
MOTOR1_A = 0;
MOTOR1_B = 1;
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, -moto1);
}
// 电机2同理...
}
PWM参数配置建议:
- 时钟源:72MHz
- 预分频:72-1
- 自动重载值:800-1
- 频率计算结果:72MHz/(72*800)=12.5kHz
4. 系统保护机制
4.1 硬件看门狗实现
c复制// 初始化独立看门狗
IWDG_HandleTypeDef hiwdg;
hiwdg.Instance = IWDG;
hiwdg.Init.Prescaler = IWDG_PRESCALER_32; // 32分频
hiwdg.Init.Reload = 0xFFF; // 约1.6s超时
HAL_IWDG_Init(&hiwdg);
// 主循环中喂狗
while(1) {
HAL_IWDG_Refresh(&hiwdg);
// ...其他代码
}
4.2 软件保护策略
- 倾角过大保护:
c复制if(fabs(Angle) > 45.0f) {
Motor_Stop();
Error_Handler();
}
- 通信异常检测:
c复制if(HAL_GetTick() - lastMPUTime > 100) {
// MPU6050通信超时
Motor_Stop();
}
- 电源监测:
c复制if(ADC_Value < 3000) { // 电池电压低于7V
LowPower_Warning();
}
5. 调试与优化技巧
5.1 安全调试方法
- 初次测试:
- 用扎带固定车体离地1cm
- 观察电机响应方向是否正确
- 检查PID输出极性
- 参数整定:
- 先调直立环(Kp=3.0起步)
- 再调速度环(比直立环慢10倍)
- 最后调转向环
- 实测工具:
- 手机蓝牙调试助手
- 串口数据可视化
- 激光测距仪校准
5.2 常见问题排查
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 车体单向倾倒 | 电机极性反接 | 交换电机线序 |
| 高频抖动 | Kp过大或Kd过小 | 降低Kp/增加Kd |
| 响应迟钝 | 滤波权重不当 | 调整互补滤波参数 |
| 电机异响 | PWM频率不当 | 调整至18-20kHz |
| 电源崩溃 | 走线过细 | 加粗电源线/增加电容 |
6. 进阶优化方向
- 传感器升级:
- 改用MPU9250(集成磁力计)
- 增加TOF测距传感器
- 添加电流检测芯片
- 算法改进:
- 实现串级PID控制
- 加入模糊PID自适应
- 开发状态观测器
- 功能扩展:
- 蓝牙APP控制
- 路径规划算法
- 自主充电模块
在完成基础功能后,建议通过SD卡记录运行数据,用MATLAB分析控制效果。实际测试表明,加入速度前馈补偿后,车体在快速移动时的稳定性可提升40%以上。