平衡车PID控制系统(豆包版本)

两轮平衡车的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. 软件准备(先跑通基础)

  1. MPU6050驱动:读出加速度、陀螺仪
  2. 姿态解算:得到稳定的 Pitch(倾角)、Gyro_Pitch(俯仰角速度)、Yaw_Z(偏航角速度)
  3. 编码器读取:左右轮实际转速
  4. PWM输出:控制电机正反转、转速
  5. 串口/蓝牙:实时打印角度、PID输出、PWM(调试必备)

三、第一步:确定机械中值(最关键!)

机械中值:小车自然平衡、重力合力为零的倾角(不是绝对0°)。

操作步骤

  1. 小车放在平地,断电、手轻扶
  2. 缓慢向前推,直到小车自己向前倒下,记下此时Pitch角(如 +8°)
  3. 缓慢向后拉,直到小车自己向后倒下,记下此时Pitch角(如 -6°)
  4. 机械中值 = (前倒角度 + 后倒角度) / 2
    • 例:(8 + (-6))/2 =
  5. 代码中:目标倾角 = 机械中值(不是0°)

错误后果:中值不准,车永远往一边溜、无法静止


四、第二步:调直立环(PD)------ 先让车"能站住"

顺序:先关速度环、转向环(参数=0),只调直立环

1. 确定Kp极性(最容易错)

  • 初始:Kp=100, Kd=0, Ki=0
  • 上电,轻推车身前倾(Pitch>中值)
    • ✅ 正确:车轮向前转,试图把车身拉回直立
    • ❌ 错误:车轮向后转 ,加速倾倒 → Kp取反(Kp=-100)

2. 调Kp大小(从0往上加)

  • 步骤:
    1. Kp=0→50→100→150→200...每次+50
    2. 观察:
      • Kp太小:反应慢、一推就倒
      • Kp适中:推一下能回弹、小幅晃动
      • Kp太大:剧烈低频震荡(前后摆、摆幅大)
  • 终点:加到刚出现明显低频震荡 ,再**×0.6~0.8**(降为稳定值)
  • 典型范围:Kp = ±150 ~ ±400(依车架、电机)

3. 确定Kd极性

  • Kd作用:阻尼、抑制震荡、防抖动
  • 测试:
    • 拿起小车,快速绕电机轴前后摆动
    • ✅ 正确:车轮跟随摆动方向转动(有阻力感)
    • ❌ 错误:车轮反向转动、无阻尼Kd取反

4. 调Kd大小

  • 步骤:
    1. Kd=0→0.5→1.0→1.5→2.0...每次+0.5
    2. 观察:
      • 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(分步)

  1. 先Ki=0,只调Kp
    • 0.1→0.2→0.3→0.4...每次+0.1
    • 现象:
      • Kp太小:仍缓慢漂移、回位慢
      • Kp适中:推一下能回到原位、不怎么漂移
      • Kp太大:高频抖动、平衡被破坏
  2. 再加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即可)

  1. 确定Kd极性
    • 拿起小车绕Z轴左旋
    • ✅ 正确:产生向右纠正力(抵抗旋转)
    • ❌ 错误:助力旋转Kd取反
  2. 调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);
}

八、调试顺序总结(黄金步骤)

  1. 测机械中值 → 代码设为目标倾角
  2. 关速度、转向环 → 调直立环Kp极性→Kp大小→Kd极性→Kd大小
  3. 开速度环(关转向) → 调Velocity_Kp→Velocity_Ki+积分限幅
  4. 开转向环 → 调Turn_Kd极性→大小
  5. 整体细调:小步修改,观察现象

九、典型问题与参数修正(一看就会)

现象 原因 修正
一推就倒、反应慢 直立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

每台车机械、电机、传感器不同,参数必须自己重调,不能直接抄。


十一、进阶建议

  1. 用上位机(如Vofa+):实时画角度曲线,直观看震荡/超调
  2. 控制频率 :PID**100200Hz**(510ms调用一次)
  3. 滤波 :角速度、角度做一阶低通,减少噪声
  4. 保护 :倾角>±30°时切断PWM,防飞车烧电机

需要我把以上内容整理成一份可直接照着做的平衡车PID调试清单+参数记录表吗?你可以边调边填,快速定位最优参数。




平衡车三环PID整合方法(核心:串级结构 + 叠加规则)

你现在的困惑是绝大多数人做平衡车的卡点:单独会调,一合就乱、抖、倒、冲

我直接给你最标准、最稳定、不会出错的三环整合方案一步一步照做就能完美融合,不用猜、不用试错。


一、先记住:三环整合的核心逻辑(必须背下来)

平衡车三环不是随便加一起,而是固定串级结构

1. 层级关系(从上到下)

  1. 速度环(外环) → 给直立环提供动态目标角度
  2. 直立环(内环) → 执行平衡,输出基础PWM
  3. 转向环(独立环) → 左右轮差速,不影响平衡

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)

直接给你完整可编译的三环整合工程,你只需要填传感器和电机驱动就能跑!

相关推荐
sno_guo2 小时前
直播抠图技术100谈之25---调色中曲线是最优解
人工智能·算法·机器学习·直播·内容运营·obs抠图·直播技术
故事和你912 小时前
洛谷-【图论2-2】最短路1
开发语言·数据结构·c++·算法·动态规划·图论
Simple-Soft2 小时前
指针的高级应用与技巧 - C语言的灵魂
c语言·数据结构·算法
南宫萧幕2 小时前
Simulink 从零搭建 HEV ECMS 环境:模块解析、排坑指南与智能算法接口预留
人工智能·算法·matlab·汽车·控制
子豪-中国机器人2 小时前
词云与条形码答案
算法
闲人编程2 小时前
Agent的评估体系(AgentEval):如何判断一个Agent好坏?
大数据·人工智能·python·算法·agent·智能体·swe
沫璃染墨2 小时前
红黑树完全指南:从核心原理到插入验证全实现
开发语言·c++·算法
拉拉拉拉拉拉拉马2 小时前
Windsurf 最新版进阶讲解:从 Cascade 到 Devin Local,重新理解 AI 编程工作流
人工智能·算法
Mr_pyx2 小时前
面试题记录
jvm·数据结构·算法·spring·mybatis