李小成 发表于 2015-2-5 17:02:50

我的自平衡小车站不来

前几天我在贴吧看了几个贴,就开始动手做自平衡小车。现在还有很多不懂,PID那几个参数我都是随机调的,每次调完就烧程序进板,没有借用任何什么串口监视之类的东西观察数据变化情况,只能看小车的运行情况,掌握不到大概思路是什么。
现在,硬件部分做好了,开始调程序,我的自平衡小车,刚开始时候(大概持续2s左右),还会在平衡位置不断摆动,但过后就一直往一个方向运动了。(知道的DX请告诉我一下)


一下是我的代码:
#include "Wire.h"
#include "I2Cdev.h"
#include "MPU6050.h"

MPU6050 accelgyro;


#define Gry_offset -20   
   
#define Gyr_Gain 65


#define pi 3.14159

int16_t ax, ay, az;
int16_t gx, gy, gz;


/********** 互补滤波器参数 *********/
unsigned long preTime = 0; // 采样时间
float f_angle = 0.0;       // 滤波处理后的角度值


unsigned long lastTime;         // 前次时间
   float ITerm, lastInput;    // 积分项、前次输入
   float Output = 0.0;      // PID输出值


      int oommm;
   
      int TN1=3;
      int TN2=4;
      int TN3=8;
      int TN4=7;
      int ENA=5;
      int ENB=9;


void setup()
{
    Wire.begin();
    Serial.begin(9600);
    accelgyro.initialize();
    delay(500);
    pinMode(3,OUTPUT);         
    pinMode(4,OUTPUT);
    pinMode(8,OUTPUT);
    pinMode(7,OUTPUT);
    pinMode(5,OUTPUT);
    pinMode(9,OUTPUT);
    delay(100);

}

void loop()
{
    unsigned long now = millis();                           // 当前时间(ms)
    float dt = (now - preTime) / 1000.0;                  // 微分时间(s)
    preTime = now;       // 记录本次时间(ms)
   
   
    float K = 0.8;                                          // 取值权重
    float A = K / (K + dt); // 加权系数

    float TimeCh = (now - lastTime) / 1000.0;               // 采样时间(s)
    float Kp = 0.9, Ki = 26.0, Kd = 5.0;
   
                      // 比例系数、积分系数、微分系数
    float SampleTime = 0.001;                                 // 采样时间(s)
    float Setpoint = -3.8;                                  // 设定目标值(degree)
    float outMin = -150.0, outMax = +150.0;
   
   
    accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
    float angleA= atan2(ax , az) * 180 / pi;
    float omega=(gy +Gry_offset)/Gyr_Gain; // 当前角速度(degree/s)      
   
   

   
   

if (abs(angleA)<45)//这个是误差达到一定程度后的系统关闭开关
{   

      //Kalman_Filter(angleA,omega);
      f_angle = A * (f_angle + omega * dt) + (1-A) * angleA;
      now = millis();
      if(TimeCh >= SampleTime) {                              // 到达预定采样时间时
      float Input = f_angle;                              // 输入赋值
      float error = Setpoint - Input;                     // 偏差值
      ITerm+= (Ki * error * TimeCh);                      // 计算积分项
      ITerm = constrain(ITerm, outMin, outMax);         // 限定值域
      float DTerm = Kd * (Input - lastInput) / TimeCh;    // 计算微分项
      Output = Kp * error + ITerm - DTerm;                // 计算输出值
      Output = constrain(Output, outMin, outMax);         // 限定值域
      PWMB();         
      lastInput = Input;                                  // 记录输入值
      lastTime = now;
      

   }
    else {
   
         analogWrite(5, 0); //PWM调速a==0-255
         analogWrite(9, 0);
         }
    delay(3);
}
}




//-------------电机正反转 PWM输出-----------
void PWMB()
{
if(Output<0)
{/* digitalWrite(3, LOW);
    digitalWrite(4, HIGH);
   digitalWrite(8, LOW);
    digitalWrite(7, HIGH);*/

    digitalWrite(3, HIGH);
    digitalWrite(4, LOW);
    digitalWrite(8, HIGH);
    digitalWrite(7, LOW);

   }
else if(Output>0)
{

    digitalWrite(3, LOW);
    digitalWrite(4, HIGH);
    digitalWrite(8, LOW);
    digitalWrite(7, HIGH);
}
                  
   
   
    //oommm=min(220,abs(40*Output));
    analogWrite(5, Output+35); //PWM调速a==0-220
    analogWrite(9, Output+30);

}


这个程序我是结合两个人的程序写的,有几条我都不明白是怎么得来的:
1:
#define Gry_offset -20   
#define Gyr_Gain 65
float Setpoint = -3.8;                                  // 设定目标值(degree)
(这三个值是如何得到的,还有有什么作用)

2:陀螺仪的静态偏移量是怎么测的,

eagle210@sina 发表于 2015-2-8 19:11:52

本帖最后由 eagle210@sina 于 2015-2-8 19:20 编辑

也想做做试试呢。问题说不好,但是对于角度的偏差,

f_angleA最好用串口看看得到的实际数是多少。也不知道那个公式保险吗,积分会不会出问题了?

另外angleA换个公式试试,比如ATAN(gx/SQRT(gy^2+GZ^2))

13631271989 发表于 2015-3-28 12:11:25

楼主你好!可以问一下你的物品清单么

wenjie 发表于 2015-9-2 12:51:39

上面的数值是你测到的, Gry_offset -20 是你的平衡小车在垂直位置时的零漂值,理想情况下都是为0,但是由于安装配合的误差导致在垂直位置时存在偏移量,不同的小车偏移量时不一样的。Gyr_Gain 65是加速度的比例放大系数,在数据处理中根据自己的需要选择合适的比例放大系数。Setpoint = -3.8是计算中设定的理想值。
页: [1]
查看完整版本: 我的自平衡小车站不来