arduino 开发板读取mpu6050陀螺仪

https://blog.csdn.net/ling3ye/article/details/51360568

首先感谢csdn大神。

我只是在大神的卡尔曼滤波代码基础上添加了servo库控制舵机,基本上没啥改进,如有错误,欢迎指出。

servo库能够控制180度舵机,360度舵机需要在舵机位置加装传感器,否则会一直自转,没有像180度舵机可以控制角度,270度舵机目前还没入手。

下一步是想要将ppm或者pwm信号输入给遥控器,在凤凰模拟器加密狗上输入ppm信号能够正常控制两通道,在富斯i6遥控器上发现ppm in没有反应,还在摸索中。

最后的成品属于头追云台,在几年前有航模大神就已经做过了。,。

运行环境:arduino ide。代码如下:

#include<Servo.h>      //引入Servo库

Servo sg901;           //定义舵机1

Servo sg902;           //定义舵机2


#include "Wire.h"      //引用Wire库

#include "I2Cdev.h"    //引用I2C库

#include "MPU6050.h"   //引用MPU6050库

 

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轴卡尔曼变量

 

void setup()

{

    Wire.begin();

    Serial.begin(115200);

 

    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; //计算陀螺仪偏移

    sg901.attach(9);     //定义舵机1引脚

    sg902.attach(10);    //定义舵机2引脚

}

 

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;    //MPU6050输入6个值

        

    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;

 

    /* kalman end */  //卡尔曼计算结束

 

    Serial.print(agx);Serial.print(",");    //X轴值在-90到90之间

    Serial.print(agy);Serial.print(",");    //Y轴值在-90到90之间

    Serial.print(agz);Serial.println();     //Z轴值在-90到90之间


    sg901.write(90-agx);     //输出舵机1角度

    sg902.write(90+agy);    // 输出舵机2角度               

    

}


-- --
  • 投诉或建议
评论