STM32平衡小车进阶调试(调参篇)
📅 2026/7/15 23:51:36
👁️ 阅读次数
📝 编程学习
1. PID调参前的准备工作
调参前需要确保硬件和基础代码已经就绪。我遇到过不少同学直接开始调PID,结果发现是电机极性接反或者MPU6050数据异常导致的"假故障"。这里分享几个必查项:
- 机械中值校准:将小车放在绝对水平面上,用OLED显示MPU6050的俯仰角(Pitch),这个值就是机械中值。我的经验值是-3.2°,你的可能不同
- 电机极性测试:分别给左右电机正电压,观察车轮转向。正确的转向应该是:正电压对应车轮向前转(编码器值增加)
- 传感器数据验证:用串口打印以下数据:
当车体前倾时,Pitch应增大,gyroY为正值;车轮向前时编码器值为正printf("Pitch:%.1f GyroY:%.1f EncL:%d EncR:%d\n", Pitch, gyroy, Read_Speed(2), Read_Speed(4));
注意:建议先用胶带固定小车,防止调试时突然失控摔倒。我当年第一个平衡车就是在调试时从桌上飞出去,电机轴都摔弯了...
2. 直立环调试(PD控制)
直立环是平衡车的核心,采用PD控制。公式很简单:
直立环输出 = Kp×角度偏差 + Kd×角速度2.1 比例系数Kp调试
初始值设定:根据经验,Kp初始值=车身重量(g)×车轮半径(cm)×0.3。我的小车重300g,轮径6.5cm,所以Kp=300×6.5×0.3≈600
调试方法:
- 先将Kd设为0
- 手持小车倾斜10度左右突然放手
- 观察现象:
- Kp过小:小车缓慢倒下,像"慢动作"
- Kp适中:小车快速回正但有轻微振荡(这是我们想要的)
- Kp过大:剧烈振荡甚至"跳舞"
实测技巧:用手机慢动作录像观察振荡次数。理想状态是2-3次振荡后稳定
2.2 微分系数Kd调试
Kd用于抑制振荡,相当于"阻尼力"。
初始值:Kd=Kp/10。我的Kp=600,所以Kd初始值60
调试现象:
- Kd过小:小车持续摆动(欠阻尼)
- Kd适中:快速稳定无振荡(临界阻尼)
- Kd过大:反应迟钝像"老年痴呆"
特殊技巧:用指尖轻敲车身,好的参数下小车应该像不倒翁一样快速回正
3. 速度环调试(PI控制)
速度环用于消除静态误差,防止小车缓慢移动。公式:
速度环输出 = Kp×速度偏差 + Ki×速度偏差积分3.1 比例系数Kp调试
- 初始值:Kp=直立环Kp×0.1。我的直立环Kp=600,所以速度环Kp=60
- 调试方法:
- 给小车一个轻微推力
- 观察现象:
- Kp过小:推力导致持续移动
- Kp适中:移动1-2cm后停止
- Kp过大:出现"抽搐"现象
3.2 积分系数Ki调试
Ki用于消除静态误差,但容易导致积分饱和。
- 初始值:Ki=Kp/200。我的Kp=60,所以Ki=0.3
- 调试技巧:
- 在代码中加入积分限幅:
if(Encoder_S > 10000) Encoder_S = 10000; if(Encoder_S < -10000) Encoder_S = -10000; - 观察长时间运行后小车是否出现"自发运动"
- 在代码中加入积分限幅:
4. 转向环调试(P控制)
转向环相对简单,主要控制Z轴角速度:
转向环输出 = Kp×Z轴角速度- 初始值:Kp=直立环Kp×0.05。我的Kp=600,转向环Kp=30
- 调试方法:
- 手持小车悬空,手动旋转
- 观察车轮转向是否与旋转方向相反(产生抵抗旋转的力)
- 在地面测试时,好的参数下小车应该能保持直线行驶
5. 常见问题排查
5.1 小车单方向跑偏
可能原因:
- 机械中值不准(重新校准)
- 电机输出不对称(在Load函数中加入补偿值)
- 地面不平(换个场地测试)
5.2 高频抖动
解决方案:
- 降低Kd值(每次减5)
- 检查MPU6050的DLPF设置(推荐配置为5Hz)
MPU6050_SetDLPF(MPU6050_DLPF_BW_5);
5.3 响应迟钝
优化建议:
- 提高控制频率(建议200-500Hz)
- 检查MPU6050数据更新时间(DMP输出频率建议≥100Hz)
调试过程中建议保存多组参数备用。我的习惯是用Excel记录参数和现象:
| 参数组 | Kp直立 | Kd直立 | Kp速度 | Ki速度 | Kp转向 | 现象描述 |
|---|---|---|---|---|---|---|
| 组1 | 600 | 60 | 60 | 0.3 | 30 | 轻微振荡 |
| 组2 | 550 | 65 | 50 | 0.2 | 25 | 响应略慢但稳定 |
最后分享一个实用技巧:用蓝牙模块实时调参。在代码中添加:
if(USART_RX_BUF[0]=='P') Vertical_Kp = atof(&USART_RX_BUF[1]);这样通过手机串口APP发送"P550"就能实时修改Kp值
编程学习
技术分享
实战经验