データシート
https://www.invensense.com/wp-content/uploads/2015/02/MPU-6000-Datasheet1.pdf
レジスタマップ
https://www.invensense.com/wp-content/uploads/2015/02/MPU-6000-Register-Map1.pdf
購入元
https://www.amazon.co.jp/gp/product/B010RYGIRM
回路としては
vccは5v、SDA,SCLにI2Cをつなぐ(A4->SDA,A5->SCL)。使われているMPU6050はSPIとして使う機能はないため、I2C only注意!
たぶん、5vでSDA,SCL動かして大丈夫だと思う。(センサー側でプルアップされているため)
XDA,XCLは外部のセンサーをつなぐことで内部のFIFOメモリを使ったりできる感じだと思う。(使わないので私はずっとOPENにしてる。)
AD0はI2Cでのアドレスをセットできる。
0->0x68,1 -> 0x69 となる。
データの通信の仕方としては、レジスタマップに加速度、角速度などが随時保存されるため、I2Cで取得していく形になると思う。
注意点:最初に レジスタアドレス0x6B の Bit6 の SLEEP を LOW にしないと動作しない。(デフォルトで0x6B-> 0x40 のため、最初はSLEEPがついている。)
Arudino での I2C のプログラム方法
まず、Wire.begin();でWireを使えるようにする。
書き込む場合ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
Wire.beginTransmission(デバイスのアドレス->0x68,0x69);
↓
Wire.write(書き込みたいレジスタのアドレス);
↓
Wire.write(書き込みたいデータ);
↓
Wire.endTransmission();
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
読み込む場合ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
Wire.beginTransmission(デバイスのアドレス->0x68,0x69);
↓
Wire.write(読みたいレジスタのアドレス);
↓
Wire.endTransmission();
↓
Wire.requestFrom(デバイスのアドレス, 1); //1byte読みたい
↓
変数=Wire.read();
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
例
void writem(byte add, byte data) {
Wire.beginTransmission(0x68);
Wire.write(add);
Wire.write(data);
Wire.endTransmission();
}
byte readm(byte add) {
byte k;
Wire.beginTransmission(0x68);
Wire.write(add);
Wire.endTransmission();
Wire.requestFrom(0x68, 1);
while (Wire.available()) {
k = Wire.read();
}
return k;
}
レジスタマップについて
LSBとは求まる数値の1bitの変位による、対象物の変位つまり、感度を表すために使う
131LSB/(°/s )とは
1°/s = 131bit
つまり、得られたデータが262(0x106)ならば 2°/s の角加速度ということ
出力結果のレジスタマップ
となる。
実際の制作
http://tocknlab.hatenablog.com/entry/2017/03/11/182703
この方の説明がわかりやすく、よいプログラム。
今後
実際やってみると、I2cの速度は
の通り1byte読むのに約450usかかってしまうため、ArduinoでFIFOを使うことはできないだろう。カルマンフィルター、相補フィルターを理解し、raspberry Pi でやってみたいと思う。また、倒立ロボを作ってみたい。
#include <Wire.h>
#define MPU6050_ADDR 0x68 // MPU-6050 device address
#define MPU6050_SMPLRT_DIV 0x19 // MPU-6050 register address
#define MPU6050_CONFIG 0x1a
#define MPU6050_GYRO_CONFIG 0x1b
#define MPU6050_ACCEL_CONFIG 0x1c
#define MPU6050_WHO_AM_I 0x75
#define MPU6050_PWR_MGMT_1 0x6b
#define switch1 5 //5pinで安定時の角度を指定する
#define moter1 3
#define moter2 4
#define led 13
double offsetX = 0, offsetY = 0, offsetZ = 0;
double gyro_angle_x = 0, gyro_angle_y = 0, gyro_angle_z = 0;
float angleX, angleY, angleZ;
float interval, preInterval;
float acc_x, acc_y, acc_z, acc_angle_x, acc_angle_y;
float gx, gy, gz, dpsX, dpsY, dpsZ;
float anglexp = 0;
int key = 0;
void culcRotation();
//I2c書き込み
void writeMPU6050(byte reg, byte data) {
Wire.beginTransmission(MPU6050_ADDR);
Wire.write(reg);
Wire.write(data);
Wire.endTransmission();
}
//i2C読み込み
byte readMPU6050(byte reg) {
Wire.beginTransmission(MPU6050_ADDR);
Wire.write(reg);
Wire.endTransmission(true);
Wire.requestFrom(MPU6050_ADDR, 1/*length*/);
byte data = Wire.read();
return data;
}
void setup() {
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, INPUT_PULLUP);
pinMode(13, OUTPUT);
digitalWrite(moter1 ,LOW);
digitalWrite(moter2,LOW);
Wire.begin(0x68);
Wire.beginTransmission(MPU6050_ADDR);
Wire.write(0x6B); // PWR_MGMT_1 register
Wire.write(0); // set to zero (wakes up the MPU-6050)
Wire.endTransmission(true);
Serial.begin(9600);
delay(100);
//正常に接続されているかの確認
if (readMPU6050(MPU6050_WHO_AM_I) != 0x68) {
Serial.println("\nWHO_AM_I error.");
while (true) ;
}
//設定を書き込む
writeMPU6050(MPU6050_SMPLRT_DIV, 0x00); // sample rate: 8kHz/(7+1) = 1kHz
writeMPU6050(MPU6050_CONFIG, 0x00); // disable DLPF, gyro output rate = 8kHz
writeMPU6050(MPU6050_GYRO_CONFIG, 0x08); // gyro range: ±500dps
writeMPU6050(MPU6050_ACCEL_CONFIG, 0x00); // accel range: ±2g
writeMPU6050(MPU6050_PWR_MGMT_1, 0x01); // disable sleep mode, PLL with X gyro
//キャリブレーション
Serial.print("Calculate Calibration");
for (int i = 0; i < 3000; i++) {
int16_t raw_acc_x, raw_acc_y, raw_acc_z, raw_t, raw_gyro_x, raw_gyro_y, raw_gyro_z ;
Wire.beginTransmission(MPU6050_ADDR);
Wire.write(0x3B);
Wire.endTransmission(false);
Wire.requestFrom(MPU6050_ADDR, 14, true);
raw_acc_x = Wire.read() << 8 | Wire.read();
raw_acc_y = Wire.read() << 8 | Wire.read();
raw_acc_z = Wire.read() << 8 | Wire.read();
raw_t = Wire.read() << 8 | Wire.read();
raw_gyro_x = Wire.read() << 8 | Wire.read();
raw_gyro_y = Wire.read() << 8 | Wire.read();
raw_gyro_z = Wire.read() << 8 | Wire.read();
dpsX = ((float)raw_gyro_x) / 65.5;
dpsY = ((float)raw_gyro_y) / 65.5;
dpsZ = ((float)raw_gyro_z) / 65.5;
offsetX += dpsX;
offsetY += dpsY;
offsetZ += dpsZ;
if (i % 1000 == 0) {
Serial.print(".");
}
}
Serial.println();
offsetX /= 3000;
offsetY /= 3000;
offsetZ /= 3000;
digitalWrite(led, HIGH);
}
void loop() {
calcRotation();
if (key == 0) {
if (digitalRead(switch1) == 0) {
anglexp = angleX;
Serial.print("point");
Serial.println(anglexp);
key = 1;
}
}
if(key==1){
Serial.println(angleX);
if((angleX-anglexp)>=0){
digitalWrite(moter2,LOW);
digitalWrite(moter1,HIGH);
}else{
digitalWrite(moter1,LOW);
digitalWrite(moter2,HIGH);
}
}
}
//加速度、ジャイロから角度を計算
void calcRotation() {
int16_t raw_acc_x, raw_acc_y, raw_acc_z, raw_t, raw_gyro_x, raw_gyro_y, raw_gyro_z ;
//レジスタアドレス0x3Bから、計14バイト分のデータを出力するようMPU6050へ指示
Wire.beginTransmission(MPU6050_ADDR);
Wire.write(0x3B);
Wire.endTransmission();
Wire.requestFrom(MPU6050_ADDR, 4);
//出力されたデータを読み込み、ビットシフト演算
raw_acc_x = Wire.read() << 8 | Wire.read();
raw_acc_y = Wire.read() << 8 | Wire.read();
Wire.beginTransmission(MPU6050_ADDR);
Wire.write(0x3B);
Wire.endTransmission();
Wire.requestFrom(MPU6050_ADDR, 4);
raw_acc_z = Wire.read() << 8 | Wire.read();
raw_t = Wire.read() << 8 | Wire.read();
Wire.beginTransmission(MPU6050_ADDR);
Wire.write(0x3B);
Wire.endTransmission();
Wire.requestFrom(MPU6050_ADDR, 4);
raw_gyro_x = Wire.read() << 8 | Wire.read();
raw_gyro_y = Wire.read() << 8 | Wire.read();
Wire.beginTransmission(MPU6050_ADDR);
Wire.write(0x3B);
Wire.endTransmission();
Wire.requestFrom(MPU6050_ADDR, 2);
raw_gyro_z = Wire.read() << 8 | Wire.read();
//単位Gへ変換
acc_x = ((float)raw_acc_x) / 16384.0;
acc_y = ((float)raw_acc_y) / 16384.0;
acc_z = ((float)raw_acc_z) / 16384.0;
//加速度センサーから角度を算出
acc_angle_y = atan2(acc_x, acc_z + abs(acc_y)) * 360 / -2.0 / PI;
acc_angle_x = atan2(acc_y, acc_z + abs(acc_x)) * 360 / 2.0 / PI;
dpsX = ((float)raw_gyro_x) / 65.5; // LSB sensitivity: 65.5 LSB/dps @ ±500dps
dpsY = ((float)raw_gyro_y) / 65.5;
dpsZ = ((float)raw_gyro_z) / 65.5;
//前回計算した時から今までの経過時間を算出
interval = millis() - preInterval;
preInterval = millis();
//数値積分
gyro_angle_x += (dpsX - offsetX) * (interval * 0.001);
gyro_angle_y += (dpsY - offsetY) * (interval * 0.001);
gyro_angle_z += (dpsZ - offsetZ) * (interval * 0.001);
//相補フィルター
angleX = (0.996 * gyro_angle_x) + (0.004 * acc_angle_x);
angleY = (0.996 * gyro_angle_y) + (0.004 * acc_angle_y);
angleZ = gyro_angle_z;
gyro_angle_x = angleX;
gyro_angle_y = angleY;
gyro_angle_z = angleZ;
}
というかんじで、先に紹介したブログのプログラムをほぼ利用してやってみたが、時々フリーズしたかのように
void calcRotation() {
int16_t raw_acc_x, raw_acc_y, raw_acc_z, raw_t, raw_gyro_x, raw_gyro_y, raw_gyro_z ;
//レジスタアドレス0x3Bから、計14バイト分のデータを出力するようMPU6050へ指示
Wire.beginTransmission(MPU6050_ADDR);
Wire.write(0x3B);
Wire.endTransmission();
Wire.requestFrom(MPU6050_ADDR, 4);
ここのどこかで、whileループでもしているかのように戻ってこなくなった。
8/12 追記
I2Cはモータのノイズに弱いため(オープンドレインでHIGHのため)。SCLがHIGHの間にSDAが変化しているからかもしれない。
NACK(Not Acknow bit)が出ている。
L3G4200はSPIで信号に強うそうなためこちらについて研究していきたいと思う。
//11/19追記
IvanSenserはDMPについての情報を公開していない(レジスタアドレス0x39DMP_INT_STATUSなど)ため、DMPを使うためには、解析してくれている、下記のライブラリを理解するかだと思う。しかし、ライブラリを使った方が、速い気がする。
https://www.i2cdevlib.com/devices/mpu6050#source
ライブラリ内のMPU6050_DMP6.ino
では10msごとに、加速度データを送っていた(ロジックアナライザで読んだのみ)
https://www.invensense.com/wp-content/uploads/2015/02/MPU-6000-Datasheet1.pdf
レジスタマップ
https://www.invensense.com/wp-content/uploads/2015/02/MPU-6000-Register-Map1.pdf
購入元
https://www.amazon.co.jp/gp/product/B010RYGIRM
回路としては
vccは5v、SDA,SCLにI2Cをつなぐ(A4->SDA,A5->SCL)。使われているMPU6050はSPIとして使う機能はないため、I2C only注意!
たぶん、5vでSDA,SCL動かして大丈夫だと思う。(センサー側でプルアップされているため)
XDA,XCLは外部のセンサーをつなぐことで内部のFIFOメモリを使ったりできる感じだと思う。(使わないので私はずっとOPENにしてる。)
AD0はI2Cでのアドレスをセットできる。
0->0x68,1 -> 0x69 となる。
データの通信の仕方としては、レジスタマップに加速度、角速度などが随時保存されるため、I2Cで取得していく形になると思う。
注意点:最初に レジスタアドレス0x6B の Bit6 の SLEEP を LOW にしないと動作しない。(デフォルトで0x6B-> 0x40 のため、最初はSLEEPがついている。)
Arudino での I2C のプログラム方法
まず、Wire.begin();でWireを使えるようにする。
書き込む場合ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
Wire.beginTransmission(デバイスのアドレス->0x68,0x69);
↓
Wire.write(書き込みたいレジスタのアドレス);
↓
Wire.write(書き込みたいデータ);
↓
Wire.endTransmission();
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
読み込む場合ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
Wire.beginTransmission(デバイスのアドレス->0x68,0x69);
↓
Wire.write(読みたいレジスタのアドレス);
↓
Wire.endTransmission();
↓
Wire.requestFrom(デバイスのアドレス, 1); //1byte読みたい
↓
変数=Wire.read();
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
例
void writem(byte add, byte data) {
Wire.beginTransmission(0x68);
Wire.write(add);
Wire.write(data);
Wire.endTransmission();
}
byte readm(byte add) {
byte k;
Wire.beginTransmission(0x68);
Wire.write(add);
Wire.endTransmission();
Wire.requestFrom(0x68, 1);
while (Wire.available()) {
k = Wire.read();
}
return k;
}
レジスタマップについて
A | B | C | D | |
---|---|---|---|---|
1
| Register Address | 内容 | 具体的内容 | 注意点 |
2
| 0x19 | サンプリング周波数を決める | 8khz / (このレジスタで設定した数値) | ローパスフィルタなどの機能を付与すると8khz ではなくなる。 |
3
| 0x1B | ジャイロセンサの読み取る数値の最大値を決める | Bit3,4で設定(bit0,1,2,3,4)とbit0もある | ↓ 範囲、感度 |
4
| 0x1B | 0 | ±250°/s ,131LSB/(°/s ) | |
5
| 0x1B | 1 | ±500°/s ,65.5LSB/(°/s ) | |
6
| 0x1B | 2 | ±1000°/s ,32.8LSB/(°/s ) | |
7
| 0x1B | 3 | ±2000°/s ,16.4LSB/(°/s ) |
LSBとは求まる数値の1bitの変位による、対象物の変位つまり、感度を表すために使う
131LSB/(°/s )とは
1°/s = 131bit
つまり、得られたデータが262(0x106)ならば 2°/s の角加速度ということ
A | B | C | D | |
---|---|---|---|---|
1
| Register Address | 内容 | 具体的内容 | |
2
| 0x1c | selfcheckと 加速度センサーの範囲感度 | ±2g | 16384LSB/g |
3
| 範囲と感度はBIT4,3で制御する。 | ±4g | 8192LSB/g | |
4
| 上から0,1,2,3となる | ±8g | 4096LSB/g | |
5
| ±16g | 2048LSB/g |
出力結果のレジスタマップ
となる。
実際の制作
http://tocknlab.hatenablog.com/entry/2017/03/11/182703
この方の説明がわかりやすく、よいプログラム。
今後
実際やってみると、I2cの速度は
の通り1byte読むのに約450usかかってしまうため、ArduinoでFIFOを使うことはできないだろう。カルマンフィルター、相補フィルターを理解し、raspberry Pi でやってみたいと思う。また、倒立ロボを作ってみたい。
2018 3/29 追記 ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
ステッピングモーターを使い、倒立振子製作成功しました。
 ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
#include <Wire.h>
#define MPU6050_ADDR 0x68 // MPU-6050 device address
#define MPU6050_SMPLRT_DIV 0x19 // MPU-6050 register address
#define MPU6050_CONFIG 0x1a
#define MPU6050_GYRO_CONFIG 0x1b
#define MPU6050_ACCEL_CONFIG 0x1c
#define MPU6050_WHO_AM_I 0x75
#define MPU6050_PWR_MGMT_1 0x6b
#define switch1 5 //5pinで安定時の角度を指定する
#define moter1 3
#define moter2 4
#define led 13
double offsetX = 0, offsetY = 0, offsetZ = 0;
double gyro_angle_x = 0, gyro_angle_y = 0, gyro_angle_z = 0;
float angleX, angleY, angleZ;
float interval, preInterval;
float acc_x, acc_y, acc_z, acc_angle_x, acc_angle_y;
float gx, gy, gz, dpsX, dpsY, dpsZ;
float anglexp = 0;
int key = 0;
void culcRotation();
//I2c書き込み
void writeMPU6050(byte reg, byte data) {
Wire.beginTransmission(MPU6050_ADDR);
Wire.write(reg);
Wire.write(data);
Wire.endTransmission();
}
//i2C読み込み
byte readMPU6050(byte reg) {
Wire.beginTransmission(MPU6050_ADDR);
Wire.write(reg);
Wire.endTransmission(true);
Wire.requestFrom(MPU6050_ADDR, 1/*length*/);
byte data = Wire.read();
return data;
}
void setup() {
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, INPUT_PULLUP);
pinMode(13, OUTPUT);
digitalWrite(moter1 ,LOW);
digitalWrite(moter2,LOW);
Wire.begin(0x68);
Wire.beginTransmission(MPU6050_ADDR);
Wire.write(0x6B); // PWR_MGMT_1 register
Wire.write(0); // set to zero (wakes up the MPU-6050)
Wire.endTransmission(true);
Serial.begin(9600);
delay(100);
//正常に接続されているかの確認
if (readMPU6050(MPU6050_WHO_AM_I) != 0x68) {
Serial.println("\nWHO_AM_I error.");
while (true) ;
}
//設定を書き込む
writeMPU6050(MPU6050_SMPLRT_DIV, 0x00); // sample rate: 8kHz/(7+1) = 1kHz
writeMPU6050(MPU6050_CONFIG, 0x00); // disable DLPF, gyro output rate = 8kHz
writeMPU6050(MPU6050_GYRO_CONFIG, 0x08); // gyro range: ±500dps
writeMPU6050(MPU6050_ACCEL_CONFIG, 0x00); // accel range: ±2g
writeMPU6050(MPU6050_PWR_MGMT_1, 0x01); // disable sleep mode, PLL with X gyro
//キャリブレーション
Serial.print("Calculate Calibration");
for (int i = 0; i < 3000; i++) {
int16_t raw_acc_x, raw_acc_y, raw_acc_z, raw_t, raw_gyro_x, raw_gyro_y, raw_gyro_z ;
Wire.beginTransmission(MPU6050_ADDR);
Wire.write(0x3B);
Wire.endTransmission(false);
Wire.requestFrom(MPU6050_ADDR, 14, true);
raw_acc_x = Wire.read() << 8 | Wire.read();
raw_acc_y = Wire.read() << 8 | Wire.read();
raw_acc_z = Wire.read() << 8 | Wire.read();
raw_t = Wire.read() << 8 | Wire.read();
raw_gyro_x = Wire.read() << 8 | Wire.read();
raw_gyro_y = Wire.read() << 8 | Wire.read();
raw_gyro_z = Wire.read() << 8 | Wire.read();
dpsX = ((float)raw_gyro_x) / 65.5;
dpsY = ((float)raw_gyro_y) / 65.5;
dpsZ = ((float)raw_gyro_z) / 65.5;
offsetX += dpsX;
offsetY += dpsY;
offsetZ += dpsZ;
if (i % 1000 == 0) {
Serial.print(".");
}
}
Serial.println();
offsetX /= 3000;
offsetY /= 3000;
offsetZ /= 3000;
digitalWrite(led, HIGH);
}
void loop() {
calcRotation();
if (key == 0) {
if (digitalRead(switch1) == 0) {
anglexp = angleX;
Serial.print("point");
Serial.println(anglexp);
key = 1;
}
}
if(key==1){
Serial.println(angleX);
if((angleX-anglexp)>=0){
digitalWrite(moter2,LOW);
digitalWrite(moter1,HIGH);
}else{
digitalWrite(moter1,LOW);
digitalWrite(moter2,HIGH);
}
}
}
//加速度、ジャイロから角度を計算
void calcRotation() {
int16_t raw_acc_x, raw_acc_y, raw_acc_z, raw_t, raw_gyro_x, raw_gyro_y, raw_gyro_z ;
//レジスタアドレス0x3Bから、計14バイト分のデータを出力するようMPU6050へ指示
Wire.beginTransmission(MPU6050_ADDR);
Wire.write(0x3B);
Wire.endTransmission();
Wire.requestFrom(MPU6050_ADDR, 4);
//出力されたデータを読み込み、ビットシフト演算
raw_acc_x = Wire.read() << 8 | Wire.read();
raw_acc_y = Wire.read() << 8 | Wire.read();
Wire.beginTransmission(MPU6050_ADDR);
Wire.write(0x3B);
Wire.endTransmission();
Wire.requestFrom(MPU6050_ADDR, 4);
raw_acc_z = Wire.read() << 8 | Wire.read();
raw_t = Wire.read() << 8 | Wire.read();
Wire.beginTransmission(MPU6050_ADDR);
Wire.write(0x3B);
Wire.endTransmission();
Wire.requestFrom(MPU6050_ADDR, 4);
raw_gyro_x = Wire.read() << 8 | Wire.read();
raw_gyro_y = Wire.read() << 8 | Wire.read();
Wire.beginTransmission(MPU6050_ADDR);
Wire.write(0x3B);
Wire.endTransmission();
Wire.requestFrom(MPU6050_ADDR, 2);
raw_gyro_z = Wire.read() << 8 | Wire.read();
//単位Gへ変換
acc_x = ((float)raw_acc_x) / 16384.0;
acc_y = ((float)raw_acc_y) / 16384.0;
acc_z = ((float)raw_acc_z) / 16384.0;
//加速度センサーから角度を算出
acc_angle_y = atan2(acc_x, acc_z + abs(acc_y)) * 360 / -2.0 / PI;
acc_angle_x = atan2(acc_y, acc_z + abs(acc_x)) * 360 / 2.0 / PI;
dpsX = ((float)raw_gyro_x) / 65.5; // LSB sensitivity: 65.5 LSB/dps @ ±500dps
dpsY = ((float)raw_gyro_y) / 65.5;
dpsZ = ((float)raw_gyro_z) / 65.5;
//前回計算した時から今までの経過時間を算出
interval = millis() - preInterval;
preInterval = millis();
//数値積分
gyro_angle_x += (dpsX - offsetX) * (interval * 0.001);
gyro_angle_y += (dpsY - offsetY) * (interval * 0.001);
gyro_angle_z += (dpsZ - offsetZ) * (interval * 0.001);
//相補フィルター
angleX = (0.996 * gyro_angle_x) + (0.004 * acc_angle_x);
angleY = (0.996 * gyro_angle_y) + (0.004 * acc_angle_y);
angleZ = gyro_angle_z;
gyro_angle_x = angleX;
gyro_angle_y = angleY;
gyro_angle_z = angleZ;
}
というかんじで、先に紹介したブログのプログラムをほぼ利用してやってみたが、時々フリーズしたかのように
void calcRotation() {
int16_t raw_acc_x, raw_acc_y, raw_acc_z, raw_t, raw_gyro_x, raw_gyro_y, raw_gyro_z ;
//レジスタアドレス0x3Bから、計14バイト分のデータを出力するようMPU6050へ指示
Wire.beginTransmission(MPU6050_ADDR);
Wire.write(0x3B);
Wire.endTransmission();
Wire.requestFrom(MPU6050_ADDR, 4);
ここのどこかで、whileループでもしているかのように戻ってこなくなった。
8/12 追記
I2Cはモータのノイズに弱いため(オープンドレインでHIGHのため)。SCLがHIGHの間にSDAが変化しているからかもしれない。
NACK(Not Acknow bit)が出ている。
L3G4200はSPIで信号に強うそうなためこちらについて研究していきたいと思う。
//11/19追記
IvanSenserはDMPについての情報を公開していない(レジスタアドレス0x39DMP_INT_STATUSなど)ため、DMPを使うためには、解析してくれている、下記のライブラリを理解するかだと思う。しかし、ライブラリを使った方が、速い気がする。
https://www.i2cdevlib.com/devices/mpu6050#source
ライブラリ内のMPU6050_DMP6.ino
では10msごとに、加速度データを送っていた(ロジックアナライザで読んだのみ)
コメント
コメントを投稿