传感器部分-MPU6050六轴模块

六轴模块采用高精度的陀螺加速度计 MPU6050,通过处理器读取 MPU6050 的测量数据然后通过串口输出,免去了用户自己去开发 MPU6050 复杂的 I2C 协议, 同时精心的 PCB布局和工艺保证了 MPU6050 收到外接的干扰最小,测量的精度最高。
模块内部自带电压稳定电路,可以兼容 3.3V/5V 的嵌入式系统,连接方便。
模块保留了 MPU6050 的 I2C 接口,以满足高级用户希望访问底层测量数据的需求。
采用先进的数字滤波技术,能有效降低测量噪声,提高测量精度。
模块内部集成了姿态解算器, 配合动态卡尔曼滤波算法, 能够在动态环境下准确输出模块的当前姿态,姿态测量精度 0.01 度,稳定性极高,性能甚至优于某些专业的倾角仪!

MPU6050是什么?
MPU6050是一个6轴运动处理组件,包含了3轴加速度和3轴陀螺仪。
加速度传感器是干嘛用的?
这个要结合图片来说明,大家可以看这里:
http://download.csdn.net/download/feixiangtiakongn/4545536
总而言这,加速度传感器,其实是力传感器。用来检查上下左右前后哪几个面都受了多少力(包括重力)
陀螺仪是干嘛用的?
简而言之,陀螺仪就是角速度检测仪。比如,一块板,以X轴为轴心,在一秒钟的时间转到了90度,那么它在X轴上的角速度就是 90度/秒 (DPS, 角速度单位,Degree Per Second的缩写°/S ,体现了转动的快慢)
4.MPU6050分辨率是多少?
3轴加速度 和3轴陀螺仪分别用了3个16位的ADC, 也就是说,加速度有3个16位ADC,其中每个轴使用了一个。也是说,每个轴输出的数据,是2^16 也就是 -32768 —- +32768。陀螺仪也是一样。
5. 单位换算
上面说的-32768 — +32768 ,那么这个数字到底代表了什么呢?比如陀螺仪 32768 到底是指角速度达到多少度/秒 ?
这个其实是根据MPU6050设置的量程来决定的,量程不一样,32768代表的值就不一样。
MPU6050的量程设置,在 MPU6050::initialize() (MPU6050.cpp库)初始化函数中进行了设置:
setFullScaleGyroRange(MPU6050_GYRO_FS_250);
setFullScaleAccelRange(MPU6050_ACCEL_FS_2);
分别设置为,250度/秒 , 2g
按陀螺仪来说,MPU6050 有四个量程可选:
±250,±500,±1000,±2000 度/s
比方说,设置了是 ±250 , 那么-32768  —- +32768 就代表了 -250 —- +250 。此时它的LSB(拉傻B,最低有效位) 是 131 LSB/(度/s)

主要参数

1、电压:3V~6V
2、电流:<10mA
3、体积:15.24mm X 15.24mm X 2mm
– 2 –
4、焊盘间距:上下 100mil(2.54mm),左右 600mil(15.24mm)
5、测量维度:加速度:3 维,角速度:3 维,姿态角:3 维
6、量程:加速度:±2g,角速度:±250°/s。
7、分辨率:加速度:6.1e-5g,角速度:7.6e-3°/s。
8、稳定性:加速度:0.001g,角速度 0.02°/s。
9、姿态测量稳定度:0.01°。
10、数据输出频率 100Hz。
11、数据接口:串口(TTL 电平),I2C(直接连 MPU6050,无姿态输出)
10、波特率 115200kps。

 

硬件需求

Arduino板

MPU6050六轴模块

跳线

连接线

Arduino板+加速度计

 

MPU6050                                   Arduino
VCC                                          3.3V-5V
GND                                            GND
SDA                                               A4
SCL                                               A5

电路

image

你的Arduino或Genuino板必须接上电脑,以便在串口监视器看到结果。

 

代码

打开Arduino IDE的串口监视器以看到效果。

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

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

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;

    /* kalman end */

    Serial.print(agx);Serial.print(",");
    Serial.print(agy);Serial.print(",");
    Serial.print(agz);Serial.println();
}

数据

image

1
分享到:

评论1

请先

  1. 编译的时候提示loop()里的millis()没有定义怎么回事
    aduser2019-04-29 20:40:06
本站资料配套硬件销售店铺:天猫店ultirobot.tmall.com 、三冠淘宝店zhongbest.taobao.com
没有账号? 忘记密码?