两轮平衡车的PID控制,核心是三环串级PID(直立环+速度环+转向环),通过传感器姿态解算、PID计算、电机输出,实现动态平衡。以下从原理、代码、分步调试、现象分析,给你完整可落地的操作步骤。
一、原理:平衡车为什么要用三环PID?
平衡车本质是倒立摆系统,不稳定、易倾倒,必须用闭环控制。
1. 三环分工(标准串级结构)
-
直立环(PD,核心内环)
-
输入:目标倾角(机械中值,一般≈0°) - 实际倾角(Pitch)
-
输出:期望车轮转速
-
作用:让车身快速回正,不倒下
-
公式:
Balance_Out = Kp * Angle_Err + Kd * Gyro_Pitch (角速度) -
为什么不用I?直立环加I易超调、震荡,一般只PD
-
-
速度环(PI,外环)
-
输入:直立环输出的期望转速 - 实际电机转速(编码器)
-
输出:电机PWM修正量
-
作用:让车静止时不漂移、不缓慢前冲/后溜,消除稳态误差
-
公式:
Speed_Out = Kp * Speed_Err + Ki * Sum(Speed_Err)
-
-
转向环(PD/单D)
- 输入:目标偏航角 - 实际偏航角(Yaw)/Z轴陀螺仪
- 输出:左右轮差速PWM
- 作用:保持直线、遥控转向
2. 总输出合成(左右轮PWM)
PWM_L = Balance_Out + Speed_Out - Turn_Out
PWM_R = Balance_Out + Speed_Out + Turn_Out
- 直立+速度:负责平衡+定速
- 转向:左右差速实现转向
二、硬件与软件准备(必须先做)
1. 硬件清单
- 主控:STM32F1/F4/ESP32
- 姿态传感器:MPU6050(必须做姿态解算:互补滤波/卡尔曼/DMP,输出Pitch倾角+Pitch角速度)
- 电机+驱动:直流减速电机+L298N/DRV8833
- 编码器:测速(速度环必需)
- 电源:7.4V锂电、5V稳压
2. 软件准备(先跑通基础)
- MPU6050驱动:读出加速度、陀螺仪
- 姿态解算:得到稳定的 Pitch(倾角)、Gyro_Pitch(俯仰角速度)、Yaw_Z(偏航角速度)
- 编码器读取:左右轮实际转速
- PWM输出:控制电机正反转、转速
- 串口/蓝牙:实时打印角度、PID输出、PWM(调试必备)
三、第一步:确定机械中值(最关键!)
机械中值:小车自然平衡、重力合力为零的倾角(不是绝对0°)。
操作步骤
- 小车放在平地,断电、手轻扶
- 缓慢向前推,直到小车自己向前倒下,记下此时Pitch角(如 +8°)
- 缓慢向后拉,直到小车自己向后倒下,记下此时Pitch角(如 -6°)
- 机械中值 = (前倒角度 + 后倒角度) / 2
- 例:(8 + (-6))/2 = 1°
- 代码中:目标倾角 = 机械中值(不是0°)
错误后果:中值不准,车永远往一边溜、无法静止。
四、第二步:调直立环(PD)------ 先让车"能站住"
顺序:先关速度环、转向环(参数=0),只调直立环。
1. 确定Kp极性(最容易错)
- 初始:
Kp=100, Kd=0, Ki=0 - 上电,轻推车身前倾(Pitch>中值)
- ✅ 正确:车轮向前转,试图把车身拉回直立
- ❌ 错误:车轮向后转 ,加速倾倒 → Kp取反(Kp=-100)
2. 调Kp大小(从0往上加)
- 步骤:
- Kp=0→50→100→150→200...每次+50
- 观察:
- Kp太小:反应慢、一推就倒
- Kp适中:推一下能回弹、小幅晃动
- Kp太大:剧烈低频震荡(前后摆、摆幅大)
- 终点:加到刚出现明显低频震荡 ,再**×0.6~0.8**(降为稳定值)
- 典型范围:
Kp = ±150 ~ ±400(依车架、电机)
3. 确定Kd极性
- Kd作用:阻尼、抑制震荡、防抖动
- 测试:
- 拿起小车,快速绕电机轴前后摆动
- ✅ 正确:车轮跟随摆动方向转动(有阻力感)
- ❌ 错误:车轮反向转动、无阻尼 → Kd取反
4. 调Kd大小
- 步骤:
- Kd=0→0.5→1.0→1.5→2.0...每次+0.5
- 观察:
- Kd太小:震荡大、来回摆、停不下来
- Kd适中:晃动快速衰减、平稳
- Kd太大:高频抖动、电机抽搐、噪声大
- 典型范围:
Kd = ±1 ~ ±4
直立环调试完成标志
- 手扶松开,能独立站立2~5秒
- 轻推:快速回弹、不剧烈震荡、不立刻倒下
五、第三步:调速度环(PI)------ 让车"站住不动"
直立环只能"站住",但会缓慢漂移、前冲/后溜 → 加速度环PI抑制。
1. 速度环原理
- 目标:静止时期望速度=0
- 误差 = 0 - 实际车速
- 输出:修正PWM,让车回到原位、不漂移
2. 确定Kp极性
- 初始:
Velocity_Kp=0.1, Velocity_Ki=0 - 手动向前推车轮 :
- ✅ 正确:车轮产生反向力、抗拒推动
- ❌ 错误:车轮加速向前 → Kp取反
3. 调Kp与Ki(分步)
- 先Ki=0,只调Kp
- 0.1→0.2→0.3→0.4...每次+0.1
- 现象:
- Kp太小:仍缓慢漂移、回位慢
- Kp适中:推一下能回到原位、不怎么漂移
- Kp太大:高频抖动、平衡被破坏
- 再加Ki(消除静差)
-
初始:
Ki = Kp / 100 ~ Kp / 200(经验值) -
例:Kp=0.6 → Ki=0.003~0.006
-
作用:长时间静止完全不漂移、彻底回中
-
注意:积分限幅! (必须加,否则积分饱和、一松车猛冲)
c// 积分限幅示例 if(Speed_Integral > 300) Speed_Integral = 300; if(Speed_Integral < -300) Speed_Integral = -300;
-
速度环完成标志
- 小车长时间静止不漂移
- 推走后自动回到原位
- 无前冲、后溜、抖动
六、第四步:调转向环(PD/D)------ 走直线、可控转向
1. 转向控制逻辑(差速)
-
输入:Z轴陀螺仪(Yaw角速度)
-
输出:
Turn_Out -
左右PWM:
PWM_L = 直立+速度 - Turn_Out PWM_R = 直立+速度 + Turn_Out
2. 调转向环(一般单D即可)
- 确定Kd极性
- 拿起小车绕Z轴左旋
- ✅ 正确:产生向右纠正力(抵抗旋转)
- ❌ 错误:助力旋转 → Kd取反
- 调Kd大小
- 0.5→1.0→1.5...
- 太小:走曲线、无法直线
- 太大:转向生硬、抖动
- 典型:
Turn_Kd = ±0.5 ~ ±2
转向环完成标志
- 小车自然走直线
- 遥控转向灵活、不抖、回正稳
七、完整PID代码框架(C语言,可直接套用)
c
// -------------- 1. 参数定义 --------------
// 直立环PD
float Balance_Kp = -200; // 按你极性调整
float Balance_Kd = -2.5;
// 速度环PI
float Velocity_Kp = 0.5;
float Velocity_Ki = 0.003;
float Speed_Integral = 0; // 积分累加
float Speed_Integral_Max = 300; // 积分限幅
// 转向环D
float Turn_Kd = -0.8;
// 目标值
float Target_Angle = 1.2; // 你的机械中值
float Target_Speed = 0; // 静止目标速度
// -------------- 2. PID计算函数 --------------
void PID_Calculate(void)
{
// 1. 读取传感器(你自己实现)
float Pitch_Angle = MPU_Get_Pitch(); // 俯仰角
float Pitch_Gyro = MPU_Get_Gyro_Pitch();// 俯仰角速度
float Yaw_Gyro = MPU_Get_Gyro_Yaw(); // 偏航角速度
float Motor_Speed = Get_Motor_Speed(); // 实际车速(编码器)
// ---------------- 直立环PD ----------------
float Angle_Err = Target_Angle - Pitch_Angle;
float Balance_Out = Balance_Kp * Angle_Err + Balance_Kd * Pitch_Gyro;
// ---------------- 速度环PI ----------------
float Speed_Err = Target_Speed - Motor_Speed;
Speed_Integral += Speed_Err;
// 积分限幅(关键!)
if(Speed_Integral > Speed_Integral_Max) Speed_Integral = Speed_Integral_Max;
if(Speed_Integral < -Speed_Integral_Max) Speed_Integral = -Speed_Integral_Max;
float Velocity_Out = Velocity_Kp * Speed_Err + Velocity_Ki * Speed_Integral;
// ---------------- 转向环D ----------------
float Turn_Out = Turn_Kd * Yaw_Gyro;
// ---------------- 合成PWM ----------------
float PWM_L = Balance_Out + Velocity_Out - Turn_Out;
float PWM_R = Balance_Out + Velocity_Out + Turn_Out;
// PWM限幅(防过流)
if(PWM_L > 7200) PWM_L = 7200;
if(PWM_L < -7200) PWM_L = -7200;
if(PWM_R > 7200) PWM_R = 7200;
if(PWM_R < -7200) PWM_R = -7200;
// 输出到电机(你自己实现)
Motor_Set_PWM(PWM_L, PWM_R);
}
八、调试顺序总结(黄金步骤)
- 测机械中值 → 代码设为目标倾角
- 关速度、转向环 → 调直立环Kp极性→Kp大小→Kd极性→Kd大小
- 开速度环(关转向) → 调Velocity_Kp→Velocity_Ki+积分限幅
- 开转向环 → 调Turn_Kd极性→大小
- 整体细调:小步修改,观察现象
九、典型问题与参数修正(一看就会)
| 现象 | 原因 | 修正 |
|---|---|---|
| 一推就倒、反应慢 | 直立Kp太小 | 增大Kp |
| 剧烈前后摆(低频) | Kp太大 / Kd太小 | 减小Kp / 增大Kd |
| 高频抖动、电机抽搐 | Kd太大 | 减小Kd |
| 静止缓慢前冲/后溜 | 速度Kp太小 / 无Ki | 增大Velocity_Kp / 加Ki |
| 一松手就猛冲/猛退 | 积分饱和 | 加积分限幅 / 减小Ki |
| 走不直、总拐弯 | 转向Kd太小/极性错 | 修正转向Kd极性 / 增大 |
| 轻碰就倒、抗干扰差 | 整体参数偏小 | 适当加大Kp、Kd、Velocity_Kp |
十、最终参考参数(仅作起点)
- 直立环:
Kp=±180~±300, Kd=±1.5~±3 - 速度环:
Kp=0.4~0.6, Ki=0.002~0.005 - 转向环:
Kd=±0.5~±1.0
每台车机械、电机、传感器不同,参数必须自己重调,不能直接抄。
十一、进阶建议
- 用上位机(如Vofa+):实时画角度曲线,直观看震荡/超调
- 控制频率 :PID**100200Hz**(510ms调用一次)
- 滤波 :角速度、角度做一阶低通,减少噪声
- 保护 :倾角>±30°时切断PWM,防飞车烧电机
需要我把以上内容整理成一份可直接照着做的平衡车PID调试清单+参数记录表吗?你可以边调边填,快速定位最优参数。
平衡车三环PID整合方法(核心:串级结构 + 叠加规则)
你现在的困惑是绝大多数人做平衡车的卡点:单独会调,一合就乱、抖、倒、冲。
我直接给你最标准、最稳定、不会出错的三环整合方案 ,一步一步照做就能完美融合,不用猜、不用试错。
一、先记住:三环整合的核心逻辑(必须背下来)
平衡车三环不是随便加一起,而是固定串级结构:
1. 层级关系(从上到下)
- 速度环(外环) → 给直立环提供动态目标角度
- 直立环(内环) → 执行平衡,输出基础PWM
- 转向环(独立环) → 左右轮差速,不影响平衡
2. 一句话总结整合规则
速度环输出 = 直立环的目标角度
直立环输出 = 电机基础动力
转向环输出 = 左右轮差值
二、三环整合标准公式(直接套用)
这是全球平衡车通用的最终正确合成公式:
1. 速度环PI计算 → 输出:Speed_Out(动态目标倾角)
2. 直立环PD计算 → 输入目标角 = 机械中值 + Speed_Out
输出:Balance_Out(平衡PWM)
3. 转向环D计算 → 输出:Turn_Out(差速值)
最终电机PWM:
左轮 = Balance_Out - Turn_Out
右轮 = Balance_Out + Turn_Out
为什么要这样?
- 速度环不直接控制PWM ,而是控制车身微微前倾/后仰
- 直立环看到角度变了,就会自动前进/后退,实现不漂移
- 转向环只做差速,完全不破坏平衡
这就是串级PID的精髓!
三、三环整合分步操作(最安全的融合方法)
我给你不会翻车、不会乱抖的标准整合步骤,照做必成:
第1步:保持【直立环已调好】,速度环、转向环全部关闭
Velocity_Kp = 0
Velocity_Ki = 0
Turn_Kd = 0
此时车能站稳 2~5 秒,会漂移,但不会倒。
第2步:把速度环接入直立环的目标角度(关键融合点)
原来直立环:
目标角度 = 机械中值
整合后:
目标角度 = 机械中值 + 速度环输出(Speed_Out)
这一步就是外环控制内环。
第3步:打开速度环,从小到大慢慢加参数
Velocity_Kp = 0.1 → 0.2 → 0.3 → 0.4 → 0.5
Velocity_Ki = Velocity_Kp / 200
整合后正常现象:
- 车不再漂移
- 推它会自动回位
- 平衡依然稳定
- 不会抖动、不会冲
如果出现问题:
- 冲出去/后退 :速度环Kp反了,加负号
- 抖动:Kp太大,减小
- 还漂移:Kp太小,加大
- 一松就猛冲 :没加积分限幅
第4步:加入转向环(最后加,最简单)
转向环完全独立,不影响平衡:
Turn_Out = Turn_Kd * 偏航角速度(Z轴GYRO)
左轮 = 直立环输出 - Turn_Out
右轮 = 直立环输出 + Turn_Out
加完后车能走直线,遥控可转向。
四、整合后的完整代码(可直接复制)
这是真正能跑的成品代码,不是演示版:
c
//========= 三环整合完整版 =========
float Mechanical_Mid = 1.2f; // 机械中值
// 直立环PD
float Balance_Kp = -220;
float Balance_Kd = -2.6f;
// 速度环PI
float Velocity_Kp = 0.5f;
float Velocity_Ki = 0.0025f;
float speed_integral = 0;
float integral_max = 15; // 积分限幅(很小!因为是角度)
// 转向环D
float Turn_Kd = -0.7f;
void PID_Calc(void)
{
// 1. 读取数据
float pitch = MPU_Get_Pitch(); // 实际倾角
float gyro_p = MPU_Get_Gyro_Pitch(); // 俯仰角速度
float gyro_z = MPU_Get_Gyro_Yaw(); // 偏航角速度
float speed = Get_Encoder_Speed(); // 电机速度
// ==================== 1. 速度环(外环)=====================
float speed_err = 0 - speed; // 目标静止
speed_integral += speed_err;
// 积分限幅(关键!必须加)
if(speed_integral > integral_max) speed_integral = integral_max;
if(speed_integral < -integral_max) speed_integral = -integral_max;
float Speed_Out = Velocity_Kp * speed_err + Velocity_Ki * speed_integral;
// ==================== 2. 直立环(内环)=====================
// 【整合核心】速度环输出 → 变成直立环的目标角度
float target_angle = Mechanical_Mid + Speed_Out;
float angle_err = target_angle - pitch;
float Balance_Out = Balance_Kp * angle_err + Balance_Kd * gyro_p;
// ==================== 3. 转向环(独立环)=====================
float Turn_Out = Turn_Kd * gyro_z;
// ==================== 最终PWM合成 ====================
float PWM_L = Balance_Out - Turn_Out;
float PWM_R = Balance_Out + Turn_Out;
// PWM限幅
if(PWM_L > 8000) PWM_L = 8000;
if(PWM_L < -8000) PWM_L = -8000;
if(PWM_R > 8000) PWM_R = 8000;
if(PWM_R < -8000) PWM_R = -8000;
// 输出到电机
Motor_Set(PWM_L, PWM_R);
}
五、整合最容易犯的 4 个致命错误(一定要避开)
1. 错误:速度环直接加在PWM上(90%的人在这里翻车)
// ❌ 错误写法
PWM = 直立环 + 速度环
这样一定会抖、冲、震荡、无法平衡
// ✅ 正确写法
目标角度 = 机械中值 + 速度环输出
直立环根据这个角度计算PWM
2. 错误:速度环积分没有限幅
一松手就猛冲/猛退,必炸
3. 错误:三个环极性不统一
会出现:
- 能站稳
- 一加速度环就倒
- 一加转向就歪
解决:所有环的极性必须统一,要么都正,要么都负
4. 错误:整合后参数乱改
整合时只能动速度环,不能动直立环!
六、整合成功的标准现象
- 静止完全不漂移
- 轻推自动回弹回正
- 行走平稳不抖
- 转向不影响平衡
- 长时间站立纹丝不动
七、我给你总结最简单的整合口诀
速度环控制角度,
直立环控制平衡,
转向环控制差速,
三环叠加不冲突。
如果你愿意,我可以根据你的主控(STM32/ESP32/Arduino)
直接给你完整可编译的三环整合工程,你只需要填传感器和电机驱动就能跑!