動作環境
ESP-WROOM-02
MPU-9250 https://strawberry-linux.com/catalog/items?code=12250
ライブラリ https://github.com/jrowberg/i2cdevlib/
MPU-9250で加速度の校正ができたようだ。方法に関する資料はなく、結果を見ながらの推測。
手順は以下の通り。
`1. Arduino\libraries\MPU9150\MPU9150.hのレジスタの値を変更する
(これはレジスタマップを参照した)
MPU9150.h
/*
#define MPU9150_RA_XA_OFFS_H 0x06 //[15:0] XA_OFFS
#define MPU9150_RA_XA_OFFS_L_TC 0x07
#define MPU9150_RA_YA_OFFS_H 0x08 //[15:0] YA_OFFS
#define MPU9150_RA_YA_OFFS_L_TC 0x09
#define MPU9150_RA_ZA_OFFS_H 0x0A //[15:0] ZA_OFFS
#define MPU9150_RA_ZA_OFFS_L_TC 0x0B
*/
#define MPU9150_RA_XA_OFFS_H 0x77 //[15:0] XA_OFFS
#define MPU9150_RA_XA_OFFS_L_TC 0x78
#define MPU9150_RA_YA_OFFS_H 0x7A //[15:0] YA_OFFS
#define MPU9150_RA_YA_OFFS_L_TC 0x7B
#define MPU9150_RA_ZA_OFFS_H 0x7D //[15:0] ZA_OFFS
#define MPU9150_RA_ZA_OFFS_L_TC 0x7E
`2. getXAccelOffset()などで元の値を取得する
(例: XOFFSET:-5170, YOFFSET:5390. ZOFFSET:8424)
Serial.println(accelgyro.getXAccelOffset());
Serial.println(accelgyro.getYAccelOffset());
Serial.println(accelgyro.getZAccelOffset());
`3. 元の値に2の倍数を足し引きする
測定値と正負反対の値を8で割った値に近い2の倍数とする。
(奇数を足し引きすると全く異なる値になる)
accelgyro.setXAccelOffset(-5170 - 8); // divide by 8, but should be even not odd number
accelgyro.setYAccelOffset(5390 - 38); // divide by 8, but should be even not odd number
accelgyro.setZAccelOffset(8424 + 16); // divide by 8, but should be even not odd number
code v0.2
esp8266_160703_calibMPU9250.ino
/*
* v0.2 2016 Jul. 05
* - add calibration example
* v0.1 2016 Jul. 03
* - remove Calibration()
* - use Interrupt
* - import for MPU-9250
* - based on the code at
* http://www.i2cdevlib.com/forums/topic/96-arduino-sketch-to-automatically-calculate-mpu6050-offsets/
*/
#include "I2Cdev.h"
#include "MPU9150_9Axis_MotionApps41.h"
#include "Wire.h"
#include <ESP8266WiFi.h>
MPU9150 accelgyro;
#define INTERRUPT_PIN 14 // ESP8266
int buffersize = 1000; //Amount of readings used to average, make it higher to get more precision but sketch will be slower (default:1000)
int16_t ax, ay, az,gx, gy, gz;
int mean_ax, mean_ay, mean_az;
int mean_gx, mean_gy, mean_gz;
int state=0;
int ax_offset, ay_offset, az_offset;
int gx_offset, gy_offset, gz_offset;
uint16_t packetSize;
uint16_t fifoCount;
void meansensors();
void showData();
volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high
void dmpDataReady() {
mpuInterrupt = true;
}
void setup() {
WiFi.disconnect();
Wire.begin();
Wire.setClock(400000L); // 400kHz
Serial.begin(115200);
accelgyro.initialize();
pinMode(INTERRUPT_PIN, INPUT);
while (Serial.available() && Serial.read()); // empty buffer
while (!Serial.available()){
Serial.println(F("Send any character to start sketch.\n"));
delay(1500);
}
while (Serial.available() && Serial.read()); // empty buffer again
packetSize = accelgyro.dmpGetFIFOPacketSize();
Serial.println("\nYour MPU-9250 should be placed in horizontal position, with package letters facing up. \nDon't touch it until you see a finish message.\n");
delay(3000);
// // verify connection
// Serial.println(accelgyro.testConnection() ? "MPU9250 connection successful" : "MPU9250 connection failed");
// delay(1000);
}
void loop() {
if (state==0){
Serial.println("\nReading sensors for first time...");
meansensors();
state++;
delay(1000);
}
if (state==1) {
Serial.println("\nMeasuring...");
showData();
state++;
delay(1000);
}
if (state==2) {
meansensors();
Serial.print("\nSensor readings with zero offsets:\t");
Serial.print(mean_ax);
Serial.print("\t");
Serial.print(mean_ay);
Serial.print("\t");
Serial.print(mean_az);
Serial.print("\t");
Serial.print(mean_gx);
Serial.print("\t");
Serial.print(mean_gy);
Serial.print("\t");
Serial.println(mean_gz);
Serial.println("\nData is printed as: acelX acelY acelZ giroX giroY giroZ");
Serial.println("Check that your sensor readings are close to 0 0 16384 0 0 0");
state++;
}
}
/////////////////////////////////// FUNCTIONS ////////////////////////////////////
void meansensors(){
long i=0;
int buff_ax=0;
int buff_ay=0;
int buff_az=0;
int buff_gx=0;
int buff_gy=0;
int buff_gz=0;
while (i < (buffersize + 101) ){
fifoCount = accelgyro.getFIFOCount();
if (!mpuInterrupt && fifoCount < packetSize) {
continue;
}
mpuInterrupt = false;
accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
if ( (i > 100) && i <= (buffersize + 100) ){ // First 100 discarded
buff_ax = buff_ax + ax;
buff_ay = buff_ay + ay;
buff_az = buff_az + az;
buff_gx = buff_gx + gx;
buff_gy = buff_gy + gy;
buff_gz = buff_gz + gz;
}
if ( i == (buffersize + 100) ) {
mean_ax = buff_ax / buffersize;
mean_ay = buff_ay / buffersize;
mean_az = buff_az / buffersize;
mean_gx = buff_gx / buffersize;
mean_gy = buff_gy / buffersize;
mean_gz = buff_gz / buffersize;
}
i++;
}
}
void showData()
{
Serial.println(accelgyro.getXAccelOffset());
Serial.println(accelgyro.getYAccelOffset());
Serial.println(accelgyro.getZAccelOffset());
// accelgyro.setXAccelOffset(0);
// accelgyro.setYAccelOffset(0);
// accelgyro.setZAccelOffset(0);
// accelgyro.setXGyroOffset(0);
// accelgyro.setYGyroOffset(0);
// accelgyro.setZGyroOffset(0);
for(int loop = 0; loop < 10; loop++) {
meansensors();
Serial.print(" ,mean_ax:");
Serial.print(mean_ax);
Serial.print(" ,mean_ay:");
Serial.print(mean_ay);
Serial.print(" ,mean_az:");
Serial.print(mean_az);
//
Serial.print(" ,mean_gx:");
Serial.print(mean_gx);
Serial.print(" ,mean_gy:");
Serial.print(mean_gy);
Serial.print(" ,mean_gz:");
Serial.print(mean_gz);
//
Serial.println();
}
accelgyro.setXAccelOffset(-5170 - 8); // divide by 8, but should be even not odd number
accelgyro.setYAccelOffset(5390 - 38); // divide by 8, but should be even not odd number
accelgyro.setZAccelOffset(8424 + 16); // divide by 8, but should be even not odd number
accelgyro.setXGyroOffset( 80 / 4); // divide by 4
accelgyro.setYGyroOffset( 8 / 4); // divide by 4
accelgyro.setZGyroOffset( 286 / 4); // divide by 4
for(int loop = 0; loop < 10; loop++) {
meansensors();
Serial.print(" ,mean_ax:");
Serial.print(mean_ax);
Serial.print(" ,mean_ay:");
Serial.print(mean_ay);
Serial.print(" ,mean_az:");
Serial.print(mean_az);
//
Serial.print(" ,mean_gx:");
Serial.print(mean_gx);
Serial.print(" ,mean_gy:");
Serial.print(mean_gy);
Serial.print(" ,mean_gz:");
Serial.print(mean_gz);
//
Serial.println();
}
}
結果
Send any character to start sketch.
Send any character to start sketch.
Your MPU-9250 should be placed in horizontal position, with package letters facing up.
Don't touch it until you see a finish message.
Reading sensors for first time...
Measuring...
-5170
5390
8424
,mean_ax:63 ,mean_ay:304 ,mean_az:16262 ,mean_gx:-78 ,mean_gy:-10 ,mean_gz:-287
,mean_ax:63 ,mean_ay:306 ,mean_az:16261 ,mean_gx:-78 ,mean_gy:-10 ,mean_gz:-285
,mean_ax:60 ,mean_ay:307 ,mean_az:16264 ,mean_gx:-77 ,mean_gy:-8 ,mean_gz:-285
,mean_ax:60 ,mean_ay:308 ,mean_az:16264 ,mean_gx:-78 ,mean_gy:-8 ,mean_gz:-286
,mean_ax:62 ,mean_ay:309 ,mean_az:16267 ,mean_gx:-78 ,mean_gy:-9 ,mean_gz:-285
,mean_ax:65 ,mean_ay:309 ,mean_az:16263 ,mean_gx:-77 ,mean_gy:-8 ,mean_gz:-286
,mean_ax:66 ,mean_ay:309 ,mean_az:16255 ,mean_gx:-77 ,mean_gy:-7 ,mean_gz:-286
,mean_ax:64 ,mean_ay:309 ,mean_az:16258 ,mean_gx:-79 ,mean_gy:-8 ,mean_gz:-285
,mean_ax:65 ,mean_ay:304 ,mean_az:16260 ,mean_gx:-79 ,mean_gy:-9 ,mean_gz:-285
,mean_ax:55 ,mean_ay:305 ,mean_az:16256 ,mean_gx:-78 ,mean_gy:-8 ,mean_gz:-285
,mean_ax:-3 ,mean_ay:7 ,mean_az:16388 ,mean_gx:2 ,mean_gy:0 ,mean_gz:-2
,mean_ax:-4 ,mean_ay:1 ,mean_az:16388 ,mean_gx:1 ,mean_gy:0 ,mean_gz:-1
,mean_ax:0 ,mean_ay:3 ,mean_az:16388 ,mean_gx:1 ,mean_gy:0 ,mean_gz:-2
,mean_ax:0 ,mean_ay:7 ,mean_az:16390 ,mean_gx:1 ,mean_gy:0 ,mean_gz:-2
,mean_ax:0 ,mean_ay:4 ,mean_az:16387 ,mean_gx:1 ,mean_gy:-2 ,mean_gz:-1
,mean_ax:0 ,mean_ay:6 ,mean_az:16389 ,mean_gx:2 ,mean_gy:-1 ,mean_gz:-1
,mean_ax:-1 ,mean_ay:5 ,mean_az:16388 ,mean_gx:0 ,mean_gy:0 ,mean_gz:-1
,mean_ax:0 ,mean_ay:1 ,mean_az:16390 ,mean_gx:1 ,mean_gy:0 ,mean_gz:-1
,mean_ax:0 ,mean_ay:5 ,mean_az:16383 ,mean_gx:0 ,mean_gy:0 ,mean_gz:0
,mean_ax:-3 ,mean_ay:1 ,mean_az:16391 ,mean_gx:0 ,mean_gy:-2 ,mean_gz:-2
Sensor readings with zero offsets: 0 9 16387 2 -2 -2
Data is printed as: acelX acelY acelZ giroX giroY giroZ
Check that your sensor readings are close to 0 0 16384 0 0 0
補足
-
加速度の補正値を8で割ったり、ジャイロの補正値を4で割る理由は不明だが、MPU-6050の補正でも8や4で割っていた。
-
補正値を奇数にすると値がおかしくなる
- レジスタマップのp.44, XA_OFFS_Lの説明にBIT[7:1]とあり、LSB([0]のこと)については設定しないようになっている。奇数の場合(LSB=1)おかしな測定値が出力されるのと関係があるのかもしれない
-
azは16384に近ければ補正できている。他の値は0に近いこと。
-
一番最初に加速度のオフセットを0にしてしまうと、元の値とまったく異なる値になり、32768や-32768の測定値になってしまう。元の値からの補正にすること。