今回作るのは、電子コンパスの第二案です。最初の電子コンパスは、9軸加速度・ジャイロ・磁気センサMPU9250に内蔵された磁気センサAK8963で地磁気ベクタを計測、サーボモータを駆動して常に北方位を指し示すコンパスでした(下図)。
この装置(以下、マーク1と呼びます)の最大の難点は、「サーボモータの可動範囲が180°しかない」と、言う事です。このため、北の方角がサーボモータの可動範囲内に無かった場合には、北方位を指し示すことが出来ず、装置を180°回転させる必要がありました。
磁気センサとしてはマーク1と同じく、MPU9250(下図)内のAK8963を使います。
マーク1の時に作ったプログラム(e_compas.ino)に追加するので、回路図のMPU9250接続シートはそのまま流用できます(以下図、再掲)。
I/O電圧5VのUNOを使いますので、MPU9250(3.3V定格)との接続にはL/Sが必要です(上回路図の通り)。
マーク1の時に解説済みですが、MPU9250の外部I2Cバス側(ECL,EDA)を使い、直接内部のAK8963へアクセスします。マーク1で回路図を作った時(Rev.1)には、プライマリI2Cバス側(SCL,SDA)を接続せずに浮かせてあったのですが、悪さしないようにプルアップしておきました(Rev.2)。
※ここで使用した双方向L/Sは、オープンドレイン+プルアップタイプなので、接続しておくとプルアップしたのと同じことになります。
AK8963の制御方法については、マーク1の記事(「#9-10 電子コンパスの作成」)を参照してください。
冒頭で述べた通り、サーボモータでは可動範囲が180°しかなかったため、可動範囲の反対側に北方位がある場合、北の方角を指し示すことができませんでした。物理的に物が動く電子コンパスはそれなりに面白かったのですが、アプリケーションとしては大きな欠点でした。
今回は円形配置RGB LED(下図)を使って、360°どの方角に北があっても、方位を表示可能な電子コンパスにしたいと思います。
フルカラーのRGB LED(WS2812B)が円形に24個配置されたモジュールです。円形に配置されているので、ぐるっと360°、360°/24個=15°毎に方位を示すことが可能です。以下の定数でモジュールのピクセル数を指定することができます。
const int rgb_MAX_PIX=24;
rgb_MAX_PIXが4の倍数だった場合には、東西南北の4方位を表示することができるので、以下の色で各方位を表示することにします。
北(青) | |||
西(黄) | 🗾 |
東(緑) | |
南(赤) |
ピクセル数が4の倍数ではないモジュールを使った場合には、北だけを表示します。
WS2812Bの制御方法については「#11-2 円形配置RGB LED(WS2812B)を使う」を参照してください。
円形配置RGB LEDを表示に使った、マーク2を設計して行きます。
まずは、部品の物理的配置から検討します。
磁気センサAK8963で計測した地磁気ベクタを円形配置RGB LEDの座標系にマッピングする必要があるので、予め円形配置RGB LEDに以下図の様な座標系を設定しておきます。
円形配置RGB LEDの円をU-V平面に置き、円の中心を原点に設定しました。後で地磁気ベクタとu軸とのなす角度を計算して、光らせるべきピクセル位置を求めるため、中心からピクセル#0へ向かう直線をu軸、LEDの配置(発光)面がw軸正方向となるように座標軸UVW系を設定します。残るv軸は、v=w×u(×はベクタ積)で定義します。
ちゃんとした筐体を作るつもりはないので(1^^;)、円形配置RGB LEDとMPU9250をブレッドボードに直挿しして使います(下図)。
座標軸の黒丸は紙面に対して垂直に奥側へ延びる矢印、白丸は逆に手前側に延びる矢印を表しています。
MPU9250のシルクに表示された座標軸は、加速度センサとジャイロセンサを使う時の座標軸です。磁気センサAK8963は、同一パッケージ内に封入された別チップのため、座標軸が異なっています。そこへ更に、円形配置RGB LEDのUVW系が登場するので、大騒ぎです。対応は以下の通りとなります。
シルクのx:y:z軸 ⇔ AK8963のy:x:−z軸 ⇔ 円形配置RGB LEDのw:v:−u軸
プログラムでは、AK8963から読みだした地磁気ベクタ(x,y,z)から、円形配置RGB LEDの表示座標(u,v,w)への変換が必要になります。関係性は以下の通りとなります。
円形配置RGB LEDのu:v:w軸 ⇔ AK8963のz:x:y軸
コードとしては以下の様になります(一部抜粋)。
meas_ak8963 (hx,hy,hz);
// affine transform
hu=hz;
hv=hx;
hw=hy;
上図とは異なる配置にする場合には、上コードの変換式を変更する必要があります。
マーク1の時と同様にして、地磁気ベクタとu軸(下図ではx軸に相当)とのなす角度θを−180°≦θ≦180°の範囲で求めます(下図左側)。
※上図は「#9-10 電子コンパスの作成」からの流用です。右半分のサーボの図は無視してくださいm(1__)m。
上図のy軸が円形配置RGB LEDに設定したUVW系のv軸に相当しますので、UVW系の定義図に当てはめるとθ>0°方向は反時計回りとなり、ピクセル番号が減少する反対周りとなります。また、−180°〜+180°よりも、0°〜360°で算出された方が使い易いので、以下の様に角度を補正して、光らせるピクセルを決定します。
// set compass
th=-th;
while (th<0)
th += 360;
while (th>=360)
th -= 360;
// North, blue
idx=rgb_SIZ_PIX*(rgb_MAX_PIX*th/360);
pbuf[idx + 0]=0;
pbuf[idx + 1]=0;
pbuf[idx + 2]=rgb_MAX_LUM;
ここで、変数thがθに相当する変数名です。上の処理によって、thはピクセル#0から時計回りに0°〜360°の範囲で北方位を示します。
ネットリスト(接続表)でも良いくらいなのですが、一応、回路図を示しておきます(↓)。
※マーク1(サーボモータ版)回路図に於けるシート2の置き換えで、シート2Bとしてあります。
RGB LEDチップWS2812Bの定格電源電圧はVdd=3.5〜5.3[V]なので、微妙に、3.3Vでは駆動できない仕様です。まあ、UNOを使うので5VをつないでおけばOKです。DUE等で使おうとすると面倒だな……、と、思っただけです。
プログラムはマーク1で作成したe_compas.inoを改造して使おうと思います。
円形配置RGB LED(WS2812B)の制御には8ビットタイマ(TC2)を使っています。Servoライブラリも、何らかのタイマを使って制御されているはずで、はたしてWS2812BとServoライブラリは共存できるのだろうか?と、Servoライブラリのソースを確認してみたのですが、複雑すぎて良く解りません(1^−^;)。多分見た感じ、UNOだと16ビットタイマ(TC1)が使われているみたい??なので、恐らく共存可能だな……、と……(自信無し)。
ただ、e_compas.ino自体のコードで、北方位がサーボモータの可動範囲から外れた時のエラー表示がdelay()関数を使ったLED表示になっているため、この間、処理がブロックされてしまうことが判りました。このため、共存させず#ifdefで場合分けすることにしました(↓)。
#ifdef USE_RGB_LED_RING
:
: マーク2(円形配置RGB LED版)の処理
:
#else // USE_RGB_LED_RING
:
: マーク1(サーボモータ版)の処理
:
#endif // USE_RGB_LED_RING
従って、マーク1(サーボモータ版)とマーク2(円形配置RGB LED版)は、排他的に、どちらかを選択してコンパイルすることが出来ます。
以下に、完成したプログラムをリンクしておきます。
完成版プログラム:e_compas.ino
いつもの様にオリジナルを差し替えてあるので、どこからダウンロードしても最新のコードとなります。
ダウンロードした状態だと、先頭付近の「#define USE_RGB_LED_RING」をコメントしてあります。その状態だとマーク1(サーボモータ版)の制御となっています。マーク2(円形配置RGB LED版)の制御に使用する場合は、先頭付近の「#define USE_RGB_LED_RING」を有効化してください。
前節の回路(シート1およびシート2B)をブレッドボードなどに構築してUNOと接続したら、プログラム(e_compas.ino)の「#define USE_RGB_LED_RING」を有効にしてコンパイル&書き込んでください。この状態でもう、電子コンパス(マーク2)として機能しています。
デバッグ用機能以外はシリアルモニタを必要としないので、モバイルバッテリ(例えば以下図)などを使って、UNOごと持ち歩くことが出来ます。
以下、実験中の様子です。
今回のプログラムでは、円形配置RGB LEDに設定したUVW系のw軸正方向が鉛直上方向に向いていることを前提としていますので、ひっくり返すと東西が逆転してしまいます。正しい向きで使ってください。
実験中の様子を動画で確認していただけます(↓)。
近くに強い磁場を発生する機器があると、間違った方位を表示することがあります。適切な環境で実験してみてください。
サーボモータを使って機械的に方位を示す電子コンパスも面白かったけど、機械的な可動機構を作り込むのは結構大変でした。その点、機械的な動きのない円形配置RGB LEDを使ったマーク2は、実現が容易であった上に表示不能範囲もなく、良いこと尽くし。ガックシ……m(1__)m。