Ardunio mpu6050 dmp 数据通过串口实现与matlab(mac)实时绘图 学习过程 【2014-9-8】

Day2

0. Ardunio 端:

今天早上顺丰就把我定的ardunio mega送来了。一时困意全无,翻身起来就开始

第一步自然是写Ardunio 端的程序:

这并不难,尤其是ardunio的社区就有现成的代码的时候,只要认认真真读完,自己再重新写一个合意的十分轻松。

当然为了便于今后的学习,我还是把社区里的代码粘上来较为妥当,自己写的实在是乱的不堪入目

// MPU-6050 Accelerometer + Gyro
// -----------------------------
//
// By arduino.cc user "Krodal".
//
// June 2012
//      first version
// July 2013 
//      The 'int' in the union for the x,y,z
//      changed into int16_t to be compatible
//      with Arduino Due.
//
// Open Source / Public Domain
//
// Using Arduino 1.0.1
// It will not work with an older version, 
// since Wire.endTransmission() uses a parameter 
// to hold or release the I2C bus.
//
// Documentation:
// - The InvenSense documents:
//   - "MPU-6000 and MPU-6050 Product Specification",
//     PS-MPU-6000A.pdf
//   - "MPU-6000 and MPU-6050 Register Map and Descriptions",
//     RM-MPU-6000A.pdf or RS-MPU-6000A.pdf
//   - "MPU-6000/MPU-6050 9-Axis Evaluation Board User Guide"
//     AN-MPU-6000EVB.pdf
// 
// The accuracy is 16-bits.
//
// Temperature sensor from -40 to +85 degrees Celsius
//   340 per degrees, -512 at 35 degrees.
//
// At power-up, all registers are zero, except these two:
//      Register 0x6B (PWR_MGMT_2) = 0x40  (I read zero).
//      Register 0x75 (WHO_AM_I)   = 0x68.
// 

#include 


// The name of the sensor is "MPU-6050".
// For program code, I omit the '-', 
// therefor I use the name "MPU6050....".


// Register names according to the datasheet.
// According to the InvenSense document 
// "MPU-6000 and MPU-6050 Register Map 
// and Descriptions Revision 3.2", there are no registers
// at 0x02 ... 0x18, but according other information 
// the registers in that unknown area are for gain 
// and offsets.
// 
#define MPU6050_AUX_VDDIO          0x01   // R/W
#define MPU6050_SMPLRT_DIV         0x19   // R/W
#define MPU6050_CONFIG             0x1A   // R/W
#define MPU6050_GYRO_CONFIG        0x1B   // R/W
#define MPU6050_ACCEL_CONFIG       0x1C   // R/W
#define MPU6050_FF_THR             0x1D   // R/W
#define MPU6050_FF_DUR             0x1E   // R/W
#define MPU6050_MOT_THR            0x1F   // R/W
#define MPU6050_MOT_DUR            0x20   // R/W
#define MPU6050_ZRMOT_THR          0x21   // R/W
#define MPU6050_ZRMOT_DUR          0x22   // R/W
#define MPU6050_FIFO_EN            0x23   // R/W
#define MPU6050_I2C_MST_CTRL       0x24   // R/W
#define MPU6050_I2C_SLV0_ADDR      0x25   // R/W
#define MPU6050_I2C_SLV0_REG       0x26   // R/W
#define MPU6050_I2C_SLV0_CTRL      0x27   // R/W
#define MPU6050_I2C_SLV1_ADDR      0x28   // R/W
#define MPU6050_I2C_SLV1_REG       0x29   // R/W
#define MPU6050_I2C_SLV1_CTRL      0x2A   // R/W
#define MPU6050_I2C_SLV2_ADDR      0x2B   // R/W
#define MPU6050_I2C_SLV2_REG       0x2C   // R/W
#define MPU6050_I2C_SLV2_CTRL      0x2D   // R/W
#define MPU6050_I2C_SLV3_ADDR      0x2E   // R/W
#define MPU6050_I2C_SLV3_REG       0x2F   // R/W
#define MPU6050_I2C_SLV3_CTRL      0x30   // R/W
#define MPU6050_I2C_SLV4_ADDR      0x31   // R/W
#define MPU6050_I2C_SLV4_REG       0x32   // R/W
#define MPU6050_I2C_SLV4_DO        0x33   // R/W
#define MPU6050_I2C_SLV4_CTRL      0x34   // R/W
#define MPU6050_I2C_SLV4_DI        0x35   // R  
#define MPU6050_I2C_MST_STATUS     0x36   // R
#define MPU6050_INT_PIN_CFG        0x37   // R/W
#define MPU6050_INT_ENABLE         0x38   // R/W
#define MPU6050_INT_STATUS         0x3A   // R  
#define MPU6050_ACCEL_XOUT_H       0x3B   // R  
#define MPU6050_ACCEL_XOUT_L       0x3C   // R  
#define MPU6050_ACCEL_YOUT_H       0x3D   // R  
#define MPU6050_ACCEL_YOUT_L       0x3E   // R  
#define MPU6050_ACCEL_ZOUT_H       0x3F   // R  
#define MPU6050_ACCEL_ZOUT_L       0x40   // R  
#define MPU6050_TEMP_OUT_H         0x41   // R  
#define MPU6050_TEMP_OUT_L         0x42   // R  
#define MPU6050_GYRO_XOUT_H        0x43   // R  
#define MPU6050_GYRO_XOUT_L        0x44   // R  
#define MPU6050_GYRO_YOUT_H        0x45   // R  
#define MPU6050_GYRO_YOUT_L        0x46   // R  
#define MPU6050_GYRO_ZOUT_H        0x47   // R  
#define MPU6050_GYRO_ZOUT_L        0x48   // R  
#define MPU6050_EXT_SENS_DATA_00   0x49   // R  
#define MPU6050_EXT_SENS_DATA_01   0x4A   // R  
#define MPU6050_EXT_SENS_DATA_02   0x4B   // R  
#define MPU6050_EXT_SENS_DATA_03   0x4C   // R  
#define MPU6050_EXT_SENS_DATA_04   0x4D   // R  
#define MPU6050_EXT_SENS_DATA_05   0x4E   // R  
#define MPU6050_EXT_SENS_DATA_06   0x4F   // R  
#define MPU6050_EXT_SENS_DATA_07   0x50   // R  
#define MPU6050_EXT_SENS_DATA_08   0x51   // R  
#define MPU6050_EXT_SENS_DATA_09   0x52   // R  
#define MPU6050_EXT_SENS_DATA_10   0x53   // R  
#define MPU6050_EXT_SENS_DATA_11   0x54   // R  
#define MPU6050_EXT_SENS_DATA_12   0x55   // R  
#define MPU6050_EXT_SENS_DATA_13   0x56   // R  
#define MPU6050_EXT_SENS_DATA_14   0x57   // R  
#define MPU6050_EXT_SENS_DATA_15   0x58   // R  
#define MPU6050_EXT_SENS_DATA_16   0x59   // R  
#define MPU6050_EXT_SENS_DATA_17   0x5A   // R  
#define MPU6050_EXT_SENS_DATA_18   0x5B   // R  
#define MPU6050_EXT_SENS_DATA_19   0x5C   // R  
#define MPU6050_EXT_SENS_DATA_20   0x5D   // R  
#define MPU6050_EXT_SENS_DATA_21   0x5E   // R  
#define MPU6050_EXT_SENS_DATA_22   0x5F   // R  
#define MPU6050_EXT_SENS_DATA_23   0x60   // R  
#define MPU6050_MOT_DETECT_STATUS  0x61   // R  
#define MPU6050_I2C_SLV0_DO        0x63   // R/W
#define MPU6050_I2C_SLV1_DO        0x64   // R/W
#define MPU6050_I2C_SLV2_DO        0x65   // R/W
#define MPU6050_I2C_SLV3_DO        0x66   // R/W
#define MPU6050_I2C_MST_DELAY_CTRL 0x67   // R/W
#define MPU6050_SIGNAL_PATH_RESET  0x68   // R/W
#define MPU6050_MOT_DETECT_CTRL    0x69   // R/W
#define MPU6050_USER_CTRL          0x6A   // R/W
#define MPU6050_PWR_MGMT_1         0x6B   // R/W
#define MPU6050_PWR_MGMT_2         0x6C   // R/W
#define MPU6050_FIFO_COUNTH        0x72   // R/W
#define MPU6050_FIFO_COUNTL        0x73   // R/W
#define MPU6050_FIFO_R_W           0x74   // R/W
#define MPU6050_WHO_AM_I           0x75   // R


// Defines for the bits, to be able to change 
// between bit number and binary definition.
// By using the bit number, programming the sensor 
// is like programming the AVR microcontroller.
// But instead of using "(1<

上面的代码绝大部分都是宏定义,建议不愿意用官方库的同学,复制粘贴下来作为头文件使用。

上一篇我推荐了一个 串口调试 的app,经测试非常不好用

这里可以直接用ardunio的serial monitor

Ardunio mpu6050 dmp 数据通过串口实现与matlab(mac)实时绘图 学习过程 【2014-9-8】_第1张图片  <--- Ardunio          

Ardunio mpu6050 dmp 数据通过串口实现与matlab(mac)实时绘图 学习过程 【2014-9-8】_第2张图片  <--- 首先在Tools栏里面选择串口

Ardunio mpu6050 dmp 数据通过串口实现与matlab(mac)实时绘图 学习过程 【2014-9-8】_第3张图片  <--- 然后点击这个按钮就弹出Serial Monitor窗口了

Ardunio mpu6050 dmp 数据通过串口实现与matlab(mac)实时绘图 学习过程 【2014-9-8】_第4张图片  <--- 使用Ardunio社区程序后的输出

想必大家也想到了,这里的输出有很多注解,必定会对后面的matlab采集数据造成困难。不过这就是学习过程,佛挡杀佛,神挡杀神。

思路:

0. 对字符串进行筛选,截取,获得double型的数据

1. 将数据放入 data 数组中

2. 实时更新图像

要点:

0. 将字符串str从第a个字符截取到第b个字符的方法:

 str = str(a:b)


1. 将元素e放入A数组的方法:

A = [A, e]


2. 在一个窗口画多个图像的方法:

help subplot // 参数m为列数, n为行数, p为第几个图像 具体可以使用 

3. 在一个图像内画多个函数的方法:

hold all           //可理解为暂时不更新图像
plot(x1,y1,s)      //参数s,为线条描述,详细可help slop查阅
plot(x2,y2,s)
hold off           //可理解为跟新图像

程序:

callback.m  //下载地址在下面
%%callback.m 文件
function callback(s, ~)
    global count1;
    global count2;
    global count3;
    global accelX;
    global gyroX;
    global tempX;
    global accelY1;
    global accelY2;
    global accelY3;
    global gyroY1;
    global gyroY2;
    global gyroY3;
    global tempY;

    out = fscanf(s);
    out = deblank(out);
    
    if (strfind(char(out),'accel:') > 0)
        temp = out(7:end);
        data = regexp(temp,',','split');
        data1 = str2num(char(data(1)));
        data2 = str2num(char(data(2)));
        data3 = str2num(char(data(3)));
        accelX = [accelX,count1];
        accelY1 = [accelY1,data1];
        accelY2 = [accelY2,data2];
        accelY3 = [accelY3,data3];
        count1 = count1 + 1;
        subplot(2,2,1)
        hold all
        plot(accelX, accelY1, 'b');
        plot(accelX, accelY2, 'g');
        plot(accelX, accelY3, 'r');
        hold off
        break;
    elseif (strfind(char(out),'gyro:') > 0)
        temp = out(6:end);
        data = regexp(temp,',','split');
        data1 = str2num(char(data(1)));
        data2 = str2num(char(data(2)));
        data3 = str2num(char(data(3)));
        gyroX = [gyroX,count2];
        gyroY1 = [gyroY1,data1];
        gyroY2 = [gyroY2,data2];
        gyroY3 = [gyroY3,data3];
        count2 = count2 + 1;
        subplot(2,2,2)
        hold all
        plot(gyroX, gyroY1, 'b');
        plot(gyroX, gyroY2, 'g');
        plot(gyroX, gyroY3, 'r');
        hold off
        break;
    elseif (strfind(char(out),'temp:') > 0)
        temp = out(6:end);
        data = str2num(char(temp));
        tempX = [tempX,count3];
        tempY = [gyroY1,data];
        count3 = count3 + 1;
        subplot(2,2,3:4)
        plot(tempX, tempY, 'b');
        break;
    end
    
    %%x = x + 1;
    %%subplot(2,2,1);
    %%plot()
    %%axis([x x+500 -1000 1000]);
end

live.m //下载地址在下面

%%live.m
function live
    
global count1;
global count2;
global count3;
global accelX;
global gyroX;
global tempX;
global accelY1;
global accelY2;
global accelY3;
global gyroY1;
global gyroY2;
global gyroY3;
global tempY;

count1 = 1;
count2 = 1;
count3 = 1;
accelX = [];
gyroX = [];
tempX  =[];
accelY1 = [];
accelY2 = [];
accelY3 = [];
gyroY1 = [];
gyroY2 = [];
gyroY3 = [];
tempY = [];

%ONTIME Summary of this function goes here
%   Detailed explanation goes here

s=serial('/dev/tty.usbmodem1411');
set(s,'BaudRate', 9600,'DataBits',8,'StopBits',1,'Parity','none','FlowControl','none');
s.BytesAvailableFcnMode = 'terminator';
s.BytesAvailableFcn = {@callback};
fopen(s);


pause;
fclose(s);
delete(s);
clear s;
close all;
clear all;
end

callback.m 中的函数是会掉函数,当串口中有数据时边会自动调用


然后就是这样啦!

Ardunio mpu6050 dmp 数据通过串口实现与matlab(mac)实时绘图 学习过程 【2014-9-8】_第5张图片


目标:

0. 读取dmp中的数据,进行绘图

1. 继续使用row data,对数据进行卡尔曼滤波,进行绘图

2. 比较效果


送自己一句话:Ever since the world has been characterized by a rancorous bitterness.

你可能感兴趣的:(学习)