今回はobnizで加速度センサ,ジャイロセンサ,磁気センサを全て内蔵したMPU9250を使ってみたので忘備録とobnizの宣伝を兼ねて記事書いてみた.
obnizとは
今回は通信するのに以下に挙げるobnizというマイコンボードを用いました.
obnizっていうマイコンボードは
- htmlとjava scriptでプログラムを書けるので,ブラウザで操作コンソールなどを自分で作れる
- ブロックプログラムを作れるプラットフォームを完備,しかもブロックプログラムで書いたプログラムをhtmlにコンバート出来る!!(ここ重要)
- ESP-WROOM-32搭載なので,Wifi経由で書き込みでき,どこからでも調整可能!
- モータードライバ無しでモーター駆動可能,OLED搭載でデバックしやすい,どのIOピンでも大体の機能をアサイン可能
など,初めてマイコンを触る人やWeb系の人がIoTを手軽に始められる便利なツールです.詳しい説明はAmazonの説明欄分かりやすいから見て.
obniz - 現実をソフトウェア化する
イメージ的にはこんな感じ.
Atmelマイコンを使いやすくしたArduino ⇔ ESP-WROOM-32を使いやすくしたobniz
個人的にはブロックプログラムが優秀なのでArduinoより使いやすいし,htmlコンバートしてからの詳細編集によってより発展的で複雑な内容にも移行しやすいと思ってます.
(あとESPコマンドめんどいのをobnizで楽に書けるってのも利点かも)
MPU9250とは
特徴
適当にstrawberry linuxからデータシートを取ってくる.このページが全てまとまってて分かりやすい.感謝.
https://strawberry-linux.com/support/12250/1703893
加速度センサ,ジャイロセンサのMPU6500と,磁気センサAK8963を内蔵した徹底的に角度,傾きを測るモジュールです.本体は実装チップだけど,モジュールが色んな形で売ってるのでそれ買うのが楽でいいと思います.
通信もアドレスなどを自分で調べて書かないといけない,設定もレジスタを読んでデータを書き込まないといけない,などとまあまあ難しいので説明をちょっと細かめに書いていきたいと思います.
ハードの設定
今回の通信はI2Cでやりました(楽なんで).
I2Cって何?って人はこのサイトが分かりやすい.
高速通信したい人とかはSPI使えばいいんじゃないですかね.暇だったら今度使って載せます.
ただ,高速SPI(10MHz~25MHz以上)は,ノイズの関係できちんとした実装基板以外ではやめといた方が良いとかいう噂を聞いたことがあるので気を付けて.
I2Cは簡単.SCLとSDAというピンをMPU9250,obnizそれぞれの同じ名前のところに繋ぐだけ(Arduinoも同じ).
obnizはどのIOピンにもI2Cを設定出来るので以下の様に書けばどのピンでもI2Cが出来ます.(今回は2ピン:SDA,3ピン:SCL)
var i2c = obniz.getFreeI2C(); //get I2C address
i2c.start({ mode: "master", sda: 2, scl: 3, clock: 100000, pull: "3v" }); //I2C start
MPU9250は5Vトレラントではないため,通信のピンは3Vでプルアップしておきます.
またobnizから電源供給する場合は,5Vを出力してレギュレータで3.3Vに落として使いましょう.obnizの仕様です(威圧).
(追記:接続図せっかくあったのに上げ忘れました.大変申し訳ない)
アドレスへの通信
ジャイロなどのデータは,かなーり低レイヤーのデータ処理を行わないとなので適当に解説.
bit, byte, hexの話は説明する気ないので,もしこの後の話分からないようならこれとか読んでね.
MPU9250のチップの中にはレジスタマップという下の様な表が広がっています.
アドレスは中の住所を表しています.
また,MPU9250にはobnizとI2C通信するために0x68というアドレスが振られてます.これはほかにもI2C機器を接続していた時に見分ける為です.
これによって上の図で言うと
0x68(MPU9250)にアクセス→0x6B(電源設定)にアクセス→設定を書きこみ/データを読み取り
という流れでセットしたい部分にアクセスできます.
書き込み方は0x80だと7bit目のみ1になるので,例えば今言った電源設定ではリセットがかかります.ちなみに0x00を書き込むとMPU9250が起動します.
このようにして0と1を書き込んで自分の使いたい機能をON/OFFします.
obnizでは以下のように書いて今言った事を実現します.
i2c.write(0x68, [0x6B, 0x00]); //activate MPU9250
他にもレジスタには機能があるのでもっと知りたい人はどうぞ.
加速度を読む
それでは基本編.
まずは加速度を読んでいきましょう.
MPU6500の加速度のアドレスにアクセス(0x68→0x3B)して14バイトのデータを読みます.こうすることで0x3Bのアドレス以降にある
0~5 byte:加速度x,y,z軸
6,7 byte:チップ温度
8~13byte:ジャイロx,y,z軸
のデータが一気に読めて楽です.
2バイトのデータは読むときは1バイトずつ読むので,その後1つに連結する処理が必要です.そこでビットシフトやOR演算子という手段を使います.分からない人は詳しい話をチェック.
実際のプログラムは下みたいな感じで,これを全ての2バイトデータに適用すればいいだけです.
var A_raw = new Int16Array(3); //accel x, y, z raw data
Ax_raw[0] = (data[0] << 8) | data[1];
出したデータは
16bit(2byte) = -32,768~32,767
なのでこれを加速度のレンジ-16G~16Gに直します.
Accel[i] = A_raw[i] * 16 / 32768; //divide 16bit(±32768) & multiply ±16G
プログラム
Obnizはオンラインエディタがあるので,そこに以下のコードをコピー.
もしVS codeで書きたい人は以下をチェック.
VS Codeで簡単にJava Script, HTMLの統合開発環境を作ってみた(obnizに応用してみた)
実行すると画面に加速度の値が出ます.
重力加速度があるので,該当の軸を下に向ければ1Gになるのが確認できるはずです.
次回は加速度以外の値(磁気,ジャイロ等)の設定したり,値を安定させるためにフィルタ処理したりします.
ではまた.
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://obniz.io/js/jquery-3.2.1.min.js"></script>
<script src="https://unpkg.com/obniz@2.0.2/obniz.js"></script>
</head>
<body>
<div id="obniz-debug"></div>
<script>
//define
var A_raw = new Int16Array(3); //accel x, y, z raw data
var Accel = new Array(3); //accel x, y, z vaule
var obniz = new Obniz("ID"); //obniz ID here
//if obniz connect
obniz.onconnect = async function () {
//setup
obniz.io0.output(false); //IO0 use as GND
obniz.io1.output(true); //IO1 use as VCC
await obniz.wait(20); //wait for oscillation stabilize & power supply (not necessary)
var i2c = obniz.getFreeI2C(); //get I2C address
i2c.start({ mode: "master", sda: 2, scl: 3, clock: 100000, pull: "3v" }); //I2C start
i2c.write(0x68, [0x6B, 0x00]); //activate MPU9250
i2c.write(0x68, [0x1C, 0x18]); //accel range set (0x00:2g, 0x08:4g, 0x10:8g, 0x18:16g)
//loop
obniz.repeat(async function () { //repeat every 100msec (Callback)
i2c.write(0x68, [0x3B]); //access MPU6050 data
var data = await i2c.readWait(0x68, 14);//read 14byte
//Accel value calc
for (var i = 0; i < 3; i++) {
A_raw[i] = (data[2 * i] << 8) | data[2 * i + 1];
Accel[i] = A_raw[i] * 16 / 32768; //divide 16bit(±32768) & multiply ±16G
}
//print to browzer
document.write("Accel =", Accel[0].toFixed(2).fontcolor("red"), ' ', Accel[1].toFixed(2).fontcolor("blue"), ' ', Accel[2].toFixed(2).fontcolor("fuchsia"), "<br>");
window.scroll(0, $(document).height()); //auto scroll (x,y)
}, 100);
};
</script>
</body>
</html>