加载中
加载中
表情图片
评为精选
鼓励
加载中...
分享
加载中...
文件下载
加载中...
修改排序
加载中...
基于ARDUINO使用卡尔曼滤波解算MPU6050
vanguard_Marx
Vanguard_Marx2022/04/05原创 航天技术 IP:福建
关键词
固体火箭C++卡尔曼arduino
C++
/* +------------------------------+ |       Solid rocket DIP控制程序    | |          语言:Arduino C++              | |          2022-04-04-V1.0             | |     Copy right:Vanguard_Marx   |  |      QQ:1533363319                   | |          开源协议:GPL                  | +------------------------------+ */ #include "Wire.h" #include "I2Cdev.h" #include "MPU6050.h"   MPU6050 accelgyro;   unsigned long now, lastTime = 0; float dt;                                   //微分时间   int16_t ax, ay, az, gx, gy, gz;             //加速度计陀螺仪原始数据 float aax=0, aay=0,aaz=0, agx=0, agy=0, agz=0;    //角度变量 long axo = 0, ayo = 0, azo = 0;             //加速度计偏移量 long gxo = 0, gyo = 0, gzo = 0;             //陀螺仪偏移量   float pi = 3.1415926; float AcceRatio = 16384.0;                  //加速度计比例系数 float GyroRatio = 131.0;                    //陀螺仪比例系数   uint8_t n_sample = 8;                       //加速度计滤波算法采样个数 float aaxs[8] = {0}, aays[8] = {0}, aazs[8] = {0};         //x,y轴采样队列 long aax_sum, aay_sum,aaz_sum;                      //x,y轴采样和   float a_x[10]={0}, a_y[10]={0},a_z[10]={0} ,g_x[10]={0} ,g_y[10]={0},g_z[10]={0}; //加速度计协方差计算队列 float Px=1, Rx, Kx, Sx, Vx, Qx;             //x轴卡尔曼变量 float Py=1, Ry, Ky, Sy, Vy, Qy;             //y轴卡尔曼变量 float Pz=1, Rz, Kz, Sz, Vz, Qz;             //z轴卡尔曼变量  const int MPU = 0x68// MPU6050 I2C address float AccX, AccY, AccZ; float GyroX, GyroY, GyroZ; float accAngleX, accAngleY, gyroAngleX, gyroAngleY, gyroAngleZ; float roll, pitch, yaw; float AccErrorX, AccErrorY, GyroErrorX, GyroErrorY, GyroErrorZ; float elapsedTime, currentTime, previousTime; int c = 0; void setup() {     Serial.begin(19200);   Wire.begin();                      // Initialize comunication   Wire.beginTransmission(MPU);       // Start communication with MPU6050 // MPU=0x68   Wire.write(0x6B);                  // Talk to the register 6B   Wire.write(0x00);                  // Make reset - place a 0 into the 6B register   Wire.endTransmission(true);        //end the transmission            accelgyro.initialize();                 //初始化       unsigned short times = 200;             //采样次数     for(int i=0;i<times;i++)     {         accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz); //读取六轴原始数值         axo += ax; ayo += ay; azo += az;      //采样和         gxo += gx; gyo += gy; gzo += gz;          }          axo /= times; ayo /= times; azo /= times; //计算加速度计偏移     gxo /= times; gyo /= times; gzo /= times; //计算陀螺仪偏移 }   void loop() {     unsigned long now = millis();             //当前时间(ms)     dt = (now - lastTime) / 1000.0;           //微分时间(s)     lastTime = now;                           //上一次采样时间(ms)       accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz); //读取六轴原始数值       float accx = ax / AcceRatio;              //x轴加速度     float accy = ay / AcceRatio;              //y轴加速度     float accz = az / AcceRatio;              //z轴加速度       aax = atan(accy / accz) * (-180) / pi;    //y轴对于z轴的夹角     aay = atan(accx / accz) * 180 / pi;       //x轴对于z轴的夹角     aaz = atan(accz / accy) * 180 / pi;       //z轴对于y轴的夹角       aax_sum = 0;                              // 对于加速度计原始数据的滑动加权滤波算法     aay_sum = 0;     aaz_sum = 0;        for(int i=1;i<n_sample;i++)     {         aaxs[i-1] = aaxs[i];         aax_sum += aaxs[i] * i;         aays[i-1] = aays[i];         aay_sum += aays[i] * i;         aazs[i-1] = aazs[i];         aaz_sum += aazs[i] * i;          }          aaxs[n_sample-1] = aax;     aax_sum += aax * n_sample;     aax = (aax_sum / (11*n_sample/2.0)) * 9 / 7.0//角度调幅至0-90°     aays[n_sample-1] = aay;                        //此处应用实验法取得合适的系数     aay_sum += aay * n_sample;                     //本例系数为9/7     aay = (aay_sum / (11*n_sample/2.0)) * 9 / 7.0;     aazs[n_sample-1] = aaz;      aaz_sum += aaz * n_sample;     aaz = (aaz_sum / (11*n_sample/2.0)) * 9 / 7.0;       float gyrox = - (gx-gxo) / GyroRatio * dt; //x轴角速度     float gyroy = - (gy-gyo) / GyroRatio * dt; //y轴角速度     float gyroz = - (gz-gzo) / GyroRatio * dt; //z轴角速度     agx += gyrox;                             //x轴角速度积分     agy += gyroy;                             //x轴角速度积分     agz += gyroz;          /* kalman start */     Sx = 0; Rx = 0;     Sy = 0; Ry = 0;     Sz = 0; Rz = 0;          for(int i=1;i<10;i++)     {                 //测量值平均值运算         a_x[i-1] = a_x[i];                      //即加速度平均值         Sx += a_x[i];         a_y[i-1] = a_y[i];         Sy += a_y[i];         a_z[i-1] = a_z[i];         Sz += a_z[i];          }          a_x[9] = aax;     Sx += aax;     Sx /= 10;                                 //x轴加速度平均值     a_y[9] = aay;     Sy += aay;     Sy /= 10;                                 //y轴加速度平均值     a_z[9] = aaz;     Sz += aaz;     Sz /= 10;       for(int i=0;i<10;i++)     {         Rx += sq(a_x[i] - Sx);         Ry += sq(a_y[i] - Sy);         Rz += sq(a_z[i] - Sz);          }          Rx = Rx / 9;                              //得到方差     Ry = Ry / 9;                             Rz = Rz / 9;        Px = Px + 0.0025;                         // 0.0025在下面有说明...     Kx = Px / (Px + Rx);                      //计算卡尔曼增益     agx = agx + Kx * (aax - agx);             //陀螺仪角度与加速度计速度叠加     Px = (1 - Kx) * Px;                       //更新p值       Py = Py + 0.0025;     Ky = Py / (Py + Ry);     agy = agy + Ky * (aay - agy);      Py = (1 - Ky) * Py;        Pz = Pz + 0.0025;     Kz = Pz / (Pz + Rz);     agz = agz + Kz * (aaz - agz);      Pz = (1 - Kz) * Pz;  // === Read acceleromter data 加速度计=== //   Wire.beginTransmission(MPU);   Wire.write(0x3B); // Start with register 0x3B (ACCEL_XOUT_H)   Wire.endTransmission(false);   Wire.requestFrom(MPU, 6true); // Read 6 registers total, each axis value is stored in 2 registers   //For a range of +-2g, we need to divide the raw values by 16384, according to the datasheet   AccX = (Wire.read() << 8 | Wire.read()) / 16384.0// X-axis value   AccY = (Wire.read() << 8 | Wire.read()) / 16384.0// Y-axis value   AccZ = (Wire.read() << 8 | Wire.read()) / 16384.0// Z-axis value   accAngleX = (atan(AccY / sqrt(pow(AccX, 2) + pow(AccZ, 2))) * 180 / PI) - 0.58// AccErrorX ~(0.58) See the calculate_IMU_error()custom function for more details   accAngleY = (atan(-1 * AccX / sqrt(pow(AccY, 2) + pow(AccZ, 2))) * 180 / PI) + 1.58// AccErrorY ~(-1.58)   // === Read gyroscope data陀螺仪 === //   previousTime = currentTime;        currentTime = millis();              elapsedTime = (currentTime - previousTime) / 1000;   Wire.beginTransmission(MPU);   Wire.write(0x43);   Wire.endTransmission(false);   Wire.requestFrom(MPU, 6true);   GyroX = (Wire.read() << 8 | Wire.read()) / 131.0;    GyroY = (Wire.read() << 8 | Wire.read()) / 131.0;   GyroZ = (Wire.read() << 8 | Wire.read()) / 131.0;   GyroX = GyroX; // GyroErrorX ~(-0.56)     GyroY = GyroY; // GyroErrorY ~(2)   GyroZ = GyroZ - 0.775// GyroErrorZ ~ (-0.8)//调参   gyroAngleX = gyroAngleX + GyroX * elapsedTime; // deg/s * s = deg   gyroAngleY = gyroAngleY + GyroY * elapsedTime;   yaw =  yaw + GyroZ * elapsedTime;   //gyro-陀螺仪 角速度     Serial.print(agx);Serial.print(",");     Serial.print(agy);Serial.print(",");     Serial.println(yaw);     delay (20); }


来自:航空航天 / 航天技术
1
4
新版本公告
~~空空如也
白沫0001
1年10个月前 IP:天津
926268

现在有个6050的库文件,里面好像写好了滤波算法,晚些我会测试一下lz的算法效果🙏

引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论

想参与大家的讨论?现在就 登录 或者 注册

所属专业
上级专业
同级专业
插入公式
评论控制
加载中...
文号:{{pid}}
投诉或举报
加载中...
{{tip}}
请选择违规类型:
{{reason.type}}

空空如也

笔记
{{note.content}}
{{n.user.username}}
{{fromNow(n.toc)}} {{n.status === noteStatus.disabled ? "已屏蔽" : ""}} {{n.status === noteStatus.unknown ? "正在审核" : ""}} {{n.status === noteStatus.deleted ? '已删除' : ''}}
  • 编辑
  • 删除
  • {{n.status === 'disabled' ? "解除屏蔽" : "屏蔽" }}
我也是有底线的