flymaple PID 的 输出 问题

2012-10-111万
AI 快速预览详细 收起
本文讨论了自平衡小车中Flymaple PID输出值异常的问题。通过调整一阶互补滤波器和PID控制器参数,特别是积分项和微分项,解决了输出值异常的问题。文章详细介绍了具体步骤,包括设定目标值、输出上限和下限等关键参数。这对于自平衡小车开发者来说是一个实用的调试指南。

  1. #include <Wire.h>
  2. #define Gry_offset 15   // 陀螺仪偏移量
  3. #define Gyr_Gain 0.07     // 满量程2000dps时灵敏度(dps/digital)
  4. #define pi 3.14159
  5. float Com_angle;
  6. float Y1;
  7. float Com2_angle;
  8. float Klm_angle;
  9. #define Q_angle 0.01      // 角度数据置信度
  10. #define Q_omega 0.0003    // 角速度数据置信度
  11. #define R_angle 0.01      // 方差噪声
  12. float bias = 0;
  13. float P_00 = 0, P_01 = 0, P_10 = 0, P_11 = 0;
  14. float angleG;
  15. long timer = 0;  // 采样时间
  16. void lvbo(void)
  17. {
  18. /********** 互补滤波器参数 *********/
  19. unsigned long preTime = 0; // 采样时间
  20. float f_angle = 0.0;       // 滤波处理后的角度值
  21. /*********** PID控制器参数 *********/
  22. unsigned long lastTime;           // 前次时间
  23. float ITerm, lastInput;    // 积分项、前次输入
  24. float Output = 0.0;        // PID输出值
  25. unsigned long now = millis();                           // 当前时间(ms)
  26.     float dt = (now - preTime) / 1000.0;                    // 微分时间(s)
  27.     preTime = now;                                          // 记录本次时间(ms)
  28. /********** 读取姿态传感器 *********/
  29.     int16 acc[3];
  30.     getAccelerometerData(acc);
  31.     int16 gyro[4];
  32.     getGyroscopeData(gyro);    //读取陀螺仪
  33.     float Y_Acc =acc[1];      //(Acc, 1);                             // 获取向前的加速度(digite)
  34.     float Z_Acc =acc[2];       // (Acc, 2);                             // 获取向下的加速度(digite)
  35.     float angleA = atan(Y_Acc / Z_Acc) * 180 / pi;          // 根据加速度分量得到的角度(degree)
  36.     float omega =  Gyr_Gain * (gyro[1]+  Gry_offset); // 当前角速度(degree/s)
  37. /*********** 一阶互补滤波 **********/
  38.     float K = 0.8;                                          // 取值权重
  39.     float A = K / (K + dt);                                 // 加权系数
  40.     f_angle = A * (f_angle + omega * dt) + (1-A) * angleA;  // 互补滤波算法
  41. /************ PID控制器 ***********/
  42.     now = millis();                                         // 当前时间(ms)
  43.     float TimeCh = (now - lastTime) / 1000.0;               // 采样时间(s)
  44.     float Kp = 10.0, Ki = 0.0, Kd = 0.0;                    // 比例系数、积分系数、微分系数
  45.     float SampleTime = 0.1;                                 // 采样时间(s)
  46.     float Setpoint = -3.8;                                  // 设定目标值(degree)
  47. <font color="#ff0000">    float outMin = -80.0, outMax = +80.0;                   // 输出上限、输出下限</font>
  48. <font color="#ff0000">    if(TimeCh >= SampleTime) {                              // 到达预定采样时间时</font>
  49. <font color="#ff0000">        float Input = f_angle;                              // 输入赋值</font>
  50. <font color="#ff0000">        float error = Setpoint - Input;                     // 偏差值</font>
  51. <font color="#ff0000">        ITerm+= (Ki * error * TimeCh);                      // 计算积分项</font>
  52. <font color="#ff0000">        ITerm = constrain(ITerm, outMin, outMax);           // 限定值域</font>
  53. <font color="#ff0000">        float DTerm = Kd * (Input - lastInput) / TimeCh;    // 计算微分项</font>
  54. <font color="#ff0000">        Output = Kp * error + ITerm - DTerm;                // 计算输出值</font>
  55. <font color="#ff0000">        Output = constrain(Output, outMin, outMax);         // 限定值域</font>
  56. <font style="background-color:yellow">       // servoL.write(Output + servoL_offset);               // 控制左驱</font>
  57. <font style="background-color:yellow">       // servoR.write(Output + servoR_offset);               // 控制右驱</font>
  58.         lastInput = Input;                                  // 记录输入值
  59.         lastTime = now;                                     // 记录本次时间
  60.     }
  61. /************ 参数上传 ***********/
  62.     SerialUSB.print(now);          // 计算时间
  63.     SerialUSB.print(", ");
  64.     SerialUSB.print(f_angle, 6);   // 偏离角度
  65.     SerialUSB.print(", ");
  66.     SerialUSB.print(Output, 6);    // PID输出值
  67.     SerialUSB.print("; ");
  68.     SerialUSB.println("  ");  
  69. // 控制微分时间
  70.     delay(100);
  71. }
复制代码
这是 来自极客工坊 的 一段 自平衡小车 的程序








创作许可协议

本项目采用 None(不开放任何权利,保留所有权利) 进行许可。

评论(4)
夏斌
夏斌
刚看了下时间,原来好久的事啦:(
夏斌
夏斌回复金笑雨
我刚拿到板子时间不长,还没来得及研究算法呢,不过是做了点类似膝跳反射的响应程序。
金笑雨
金笑雨
作者
回复夏斌
我 这个 都 放下 好久 了 一直也没进行 算法那块 我是 小白 编程 也 不好。。。
夏斌
夏斌
你旋转一下板子
金笑雨
金笑雨
作者
求助呀 :'(
金笑雨
金笑雨
作者
标记 部分 是 控制小车的 电机的 PID 的输出 是怎么 与 我控制 电调 相连的 我不知道 怎么写了 还有 这个 输出 一直 是 这样


一直是 80 ???为什么 ?
- 没有更多了 -