MPU-6000(6050)为全球首例整合性6轴运动处理组件,相较于多组件方案,免除了组合陀螺仪与加速器时之轴间差的问题,减少了大量的包装空间。MPU-6000(6050)整合了3轴陀螺仪、3轴加速器,并含可藉由第二个I2C端口连接其他厂牌之加速器、磁力传感器、或其他传感器的数位运动处理(DMP: Digital Motion Processor)硬件加速引擎,由主要I2C端口以单一数据流的形式,向应用端输出完整的9轴融合演算技术。
InvenSense的运动处理资料库,可处理运动感测的复杂数据,降低了运动处理运算对操作系统的负荷,并为应用开发提供架构化的API。
MPU-6000(6050)的角速度全格感测范围为±250、±500、±1000与±2000°/sec (dps),可准确追緃快速与慢速动作,并且,用户可程式控制的加速器全格感测范围为±2g、±4g±8g与±16g。产品传输可透过最高至400kHz的IC或最高达20MHz的SPI(MPU-6050没有SPI)。
以上摘自百度百科
芯片本身体积较小,规格为4*4*0.9mm,与Arduino板子连接,使用I2C端口。我使用的是Arduino senser 扩展板, 上面自带有SCL和SDA接口。如果没有扩展板的,可以将A4接SDA,A5接SCL。详见arduino学习笔记37 – Arduino Uno + MPU6050首例整合性6轴演示实验。
连接好电路就可以烧代码进去了
3 | // I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files |
4 | // for both classes must be in the include path of your project |
8 | // class default I2C address is 0x68 |
9 | // specific I2C addresses may be passed as a parameter here |
10 | // AD0 low = 0x68 (default for InvenSense evaluation board) |
18 | bool blinkState = false; |
21 | // join I2C bus (I2Cdev library doesn't do this automatically) |
24 | // initialize serial communication |
25 | // (38400 chosen because it works as well at 8MHz as it does at 16MHz, but |
26 | // it's really up to you depending on your project) |
30 | Serial.println("Initializing I2C devices..."); |
31 | accelgyro.initialize(); |
34 | Serial.println("Testing device connections..."); |
35 | Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed"); |
37 | // configure Arduino LED for |
38 | pinMode(LED_PIN, OUTPUT); |
42 | // read raw accel/gyro measurements from device |
43 | accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz); |
45 | // these methods (and a few others) are also available |
46 | //accelgyro.getAcceleration(&ax, &ay, &az); |
47 | //accelgyro.getRotation(&gx, &gy, &gz); |
49 | // display tab-separated accel/gyro x/y/z values |
50 | Serial.print("a/g:\t"); |
51 | Serial.print(ax/16384.0); Serial.print("\t"); |
52 | Serial.print(ay/16384.0); Serial.print("\t"); |
53 | Serial.print(az/16384.0); Serial.print("\t"); |
54 | Serial.print(gx/131.0); Serial.print("\t"); |
55 | Serial.print(gy/131.0); Serial.print("\t"); |
56 | Serial.println(gz/131.0); |
58 | // blink LED to indicate activity |
59 | blinkState = !blinkState; |
60 | digitalWrite(LED_PIN, blinkState); |
上面ax,ay,az 除以一个浮点数16384并且gx,gy,gz除以了131. 在MPU寄存器中每个分量加速度和角速度都是用16bits来储存,也就是存储范围可以达0~65535。上面提到MPU提供了几个不同的精度标准:MPU-6000(6050)的角速度全格感测范围为±250、±500、±1000与±2000°/sec (dps),可准确追緃快速与慢速动作,并且,用户可程式控制的加速器全格感测范围为±2g、±4g、±8g与±16g。并且默认情况下,MPU的initialize 函数是这样的:
1 | void MPU6050::initialize() |
3 | setClockSource(MPU6050_CLOCK_PLL_XGYRO); |
4 | setFullScaleGyroRange(MPU6050_GYRO_FS_250); |
5 | setFullScaleAccelRange(MPU6050_ACCEL_FS_2); |
6 | setSleepEnabled(false); // thanks to Jack Elston for pointing this one out! |
所以可见加速度默认的range是±2g,角速度默认的range是±250°/sec (dps)。那么用16位来覆盖这样的range,就用65536分别除以4和500,就得到上述的两个数字了。
这样就得到了传感器的输出结果
1 | a/g: 0.01 0.01 1.06 4.77 -0.62 -6.92 |
2 | a/g: 0.02 0.00 1.07 5.05 -0.50 -6.66 |
3 | a/g: 0.01 0.01 1.07 5.04 -0.46 -6.53 |
4 | a/g: 0.01 0.01 1.07 4.81 -0.55 -6.39 |
5 | a/g: 0.01 0.01 1.07 4.96 -0.53 -6.37 |
6 | a/g: 0.01 0.01 1.07 4.93 -0.65 -6.21 |
7 | a/g: 0.01 0.00 1.06 4.94 -0.66 -6.18 |
8 | a/g: 0.01 0.01 1.06 4.91 -0.55 -6.13 |
9 | a/g: 0.01 0.01 1.07 4.89 -0.52 -6.16 |
10 | a/g: 0.02 0.01 1.07 5.11 -0.56 -6.16 |
11 | a/g: 0.02 0.01 1.06 4.99 -0.66 -6.09 |
12 | a/g: 0.01 0.02 1.07 4.99 -0.60 -6.08 |
13 | a/g: 0.01 0.01 1.06 4.76 -0.55 -6.12 |
14 | a/g: 0.01 0.00 1.07 5.12 -0.63 -6.14 |
15 | a/g: 0.01 0.00 1.07 4.93 -0.44 -6.44 |
16 | a/g: 0.01 0.01 1.07 4.93 -0.37 -6.39 |
17 | a/g: 0.02 0.01 1.06 4.85 -0.60 -6.40 |
18 | a/g: 0.02 0.01 1.07 4.73 -0.44 -6.61 |
19 | a/g: 0.02 0.01 1.07 5.08 -0.63 -6.42 |
20 | a/g: 0.01 0.01 1.07 4.69 -0.49 -6.65 |
21 | a/g: 0.02 0.01 1.05 5.01 -0.66 -6.67 |
22 | a/g: 0.01 0.01 1.07 5.04 -0.57 -6.76 |
23 | a/g: 0.02 0.01 1.07 4.71 -0.66 -6.69 |
24 | a/g: 0.02 0.01 1.07 4.94 -0.54 -6.81 |
25 | a/g: 0.01 0.01 1.07 5.08 -0.63 -6.71 |
26 | a/g: 0.01 0.01 1.06 4.92 -0.63 -6.69 |
27 | a/g: 0.01 0.00 1.06 4.87 -0.66 -6.69 |
28 | a/g: 0.01 0.01 1.07 4.80 -0.60 -6.49 |
这个状态是水平放置的结果,前三列代码代表加速度,后三列表示角速度,分别都是x,y,z的顺序。加速度好理解前两个接近于0,后一列接近于1代表1g。z轴受到地面一个mg大小的反作用力,所以有一个大小为g的加速度。至于后面三个不等零的数字,我之前一直想不通,直到后来采集了大量数据放到matlab观测得到,无聊传感器以任何角度静止摆放,这个几个数字基本不动,所以基本确定下来这个几个数字是偏移量,只要用一个常数将他校准就可以了。
这个图是我通过matlab画出的观测到的数据,总共有三千多组数据,其中三个短的线是加速度,分别为以三种不同角度摆放的加速度测量结果,又粗又大的是角速度偏移量,另一个细线是噪音,在这里将次忽略。画这个图的目的就是为了说明一个问题:无论传感器怎么摆放,在静止状态下的输出数据都是一个固定的点(会有波动),我们将此大量数据取平均,再在计算的时候将其减去,就可以达到矫正的效果了。
以上是x,y,z 轴矫正后的误差分布图,都控制在了1以内。代码插入时,就在刚读取出角速度时候矫正就行:
1 | accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz); |
以上是我测得的偏移量,不过对于每一个不同的传感器的偏移量应该都不一样,但是矫正的方法是一至的。
另外,目前对于加速度的教程的必要性还不明确,有待进一步探讨。
|