Arduinoで電子工作入門(6軸ジャイロMPU6050から加速度・角速度を取得する)
Вставка
- Опубліковано 12 вер 2024
- 入門者向けで有名なマイコンボード、Arduinoの使い方を説明します!
今回は6軸ジャイロMPU6050について説明します
(MPU6050は以前にも一度紹介しているんですが、当時より色々理解が
深まったのでアップデートしてみました。)
IMU(ジャイロセンサー)は角度・角速度を取得することができ、ロボットやドローンなど幅広い用途で使われています
MPU6050は上記に加え、自身の内部で姿勢計算を行うDMPという
プロセッサを備えた多機能なIMUで、多くのドローンのフライトコントローラーでも
採用されています。
一方で、多機能なために情報量も多く、初期の段階では色々使いこなすのが
難しい面もあります。
この動画では、一次情報である加速度・角速度をArduinoで取得するための
方法について解説します。
猛烈にわかりやすい...!何の値が取れるのか混乱した上に、補正用の温度センサまで付いているとあり、お手上げ状態でした。ArduinoではなくPICで挑戦していますが、これで一歩進めそうです。
とても助かりました。感謝です
とても分かりやすかったです。ありがとうございました!!
一つ質問なのですが、情報取得にarduinoのa4a5ピンを使っていると思うのですが、それはプログラムのどの部分で宣言しているのですか?
最近触ってなくて記憶が怪しいですが・・・・
元々、ArduinoはI2C通信するときはA4、A5ピンを使う仕様になっていて、wire.hはI2C通信するためのライブラリになっている。
つまり、冒頭の「include」で呼んでいる「wire.h」内で定義されていることになってるはずです。
@@diymechatrodiychallenge1434 なるほど、〈Wire.h〉内だからぱっと見じゃ分からないんですね...
丁寧に答えていただきありがとうございます!
こんにちは、質問があります。動画のコードをそのまま写し、そして最後に積分して角度を得るためのコードを書きました。試験的にx軸周りの角速度、角度だけをシリアルに送ります。しかし、90度傾けても30ほどしか値が出ません。このコードはどこが間違いでしょうか?
Tsはサンプリング周期で、単純にang_xに短冊の面積を足し続けるコードになっています。
#include
#define GYRO_RATE 131.1 //deg/s converter
volatile uint8_t data[14]; //to accomodate data
const float Ts=0.01; // [s]
volatile unsigned long Time;
volatile float rx=0; //gyro x data
volatile float ang_x=0;
//uint8_t is like int
//reg_setter
void i2cWriteReg(uint8_t ad, uint8_t reg, volatile uint8_t data ){
Wire.beginTransmission(ad); //starts transmission
Wire.write(reg); //select reg
Wire.write(data); //write data
Wire.endTransmission(); //ends transmission
}
void setup() {
Serial.begin(9600); //Starts serial
Wire.begin(); //Starts I2C
i2cWriteReg(0x68,0x6b,0x00); //Turn on a sensor
i2cWriteReg(0x68,0x1b,0x00); //-250 < deg/s
ざっと見た感じなんですが。
10ミリ秒おき、つまり一秒間に100回角速度の積分とシリアル出力を
実行するという処理ですね。
角速度の積分を一秒で100回はマイコンの性能的に多分大丈夫だと思うんですが、
一秒間にシリアル100回って間に合いますかね?
間に合ってないとしたら、処理が一秒間に100回実行できていない可能性があると思います。
その点(一秒間に何回ループが回っているか)をチェックしてみたらどうでしょう?
@@diymechatrodiychallenge1434 ご返信ありがとうございます。勉強不足なのですが、どうやらwhileループのことについて自分は何か誤認しているようです。
まず、
while(1){ if( (millis() - time) >= Ts * 1000 ) break;
}
の処理を言語化するとどうなりますでしょうか?(誰かのコードを勝手にお借りしましたので自分でも言語化できません、情けない。)
僕は単に、「Ts秒経つまでは、何もせずに待つ」だと思っていました。しかしよく考えてみれば不可解な点があります。
・まず millis() -timeについてです。最初に timeを定義した瞬間から計測が始まり、1ms,2ms,3ms…と数えられていきます。そしてmillisはそのあとに1ms,2ms..と始まっていきますよね?となると、差は負になりませんか?リファレンスを何度も見ましたが、「プログラム開始時からの時間を測る」としか書いていませんでした。
僕は、単にループが一巡するごとの時間をサンプリング周期として積分したいだけなのですが、どうにもその周期がmillis-timeで出せているのかわかりません。
どうか、教えてください。
何度も失礼します。一度基礎に立ち返って、主さんのプログラムをそのまま実行してみたのですが、rx, ry, rzが常に-1.5あたりを取ります。これは普通のことなのでしょうか
これはオフセットと呼ばれるもので、センサーのゼロ点がずれているので静止していても角速度があるかのようになってしまう現象です。
ジャイロセンサーでは一般的にある程度発生するものです。
オフセットの大きさは個体差があります。1.5度というのはちょっと大きい気がしますが、ありえない数字とか故障とまでは言えないと思います。
対処としては、静止させて、発生する数値を把握して、それを常に引くという処理を加えてください。
僕は単に、「Ts秒経つまでは、何もせずに待つ」だと思っていました。
↑その認識であっています。
millis()-timeは、「プログラム開始時 - 最後にtimeを記録した時点」です。timeの更新はループの先頭でやっているので、「ループが開始してから何ミリ秒経過したか」を意味します。前回のループの終了時点と今回のループの開始の間の時間間隔はほとんど差がないので「前のループが終わってから何ミリ秒経過したか」と言い換えてもあまり変わらないと思います。
ただし、あくまで一回の処理に必要な時間がTs秒に収まっている場合に成立する話です。
最初の返信で書いたように、一回の処理がTs秒より長くかかっているために待つ状態になっていない可能性が高いです。