3軸地磁気センサー(HMC5883L)の使い方 [Arduino]
XYZの3軸による「デジタルコンパス」モジュールの使い方です。
今回のスケッチでは簡易的な8方位「北、東、南、西、北東、東南、南西、北西」をシリアルモニターへ表示します。
使用部品・材料
総額で約1,170円です。(Arduino本体の値段を除く)
部品/材料 | 値段 | 備考 |
---|---|---|
ブレッドボード | ¥270 | 秋月電子の通販コード(P-00315) |
HMC5883L使用 デジタルコンパスモジュール 3軸地磁気センサ DIP化キット | ¥600 | 秋月電子の通販コード(K-09705) |
I2Cバス用双方向電圧レベル変換モジュール(FXMA2102) | ¥200 | 秋月電子の通販コード(M-05825) |
方位磁石(コンパス) | ¥100 | 100円ショップ |
私は100円ショップの「方位磁石」でキャリブレーション(位置調整)をしましたので、高価な方位磁石がある方はそちらに合わせると良いと思います。
配線図
HMC5883Lの裏面にある「JP1」はハンダを盛って結線します。結線する事でSCL/SDAが2.2kΩでプルアップされます。
次は公式の「使い方説明書」より引用(AE_HMC5883L_DEMO.zip)
上記はHMC5883Lモジュールの基板(表)に表示されているシンボルの拡大図です。ここに表示されている「X軸の矢印方向が方位」となります。
スケッチ(プログラム)
シリアルモニターに「方位」及び「3軸座標/角度データ」を表示します。
#include <Wire.h> // デバイスアドレス(スレーブ) uint8_t DEVICE_ADDRESS = 0x1E; // キャリブレーション用(調整用) // ※「地域」及び「コンパスの性能」によって異なるので適宜、変更して下さい。 float N = 325; // 北(North) float E = 139; // 東(East) float S = 192; // 南(South) float W = 252; // 西(West) float ambiguous = 15; // 誤差±15度 // 角度の範囲を0-360度にする float range360(float value){ if(value >= 360){ return value - 360; } if(value < 0) { return 360 + value; } return value; } void setup() { Serial.begin(9600); // マスタとしてI2Cバスに接続する Wire.begin(); // Mode Register(測定モード) Wire.beginTransmission(DEVICE_ADDRESS); // Mode Registerのアドレス Wire.write(0x02); // 測定モードを連続測定モードにする // 00 連続測定モード // 01 単位測定モード(デフォルト) // ※1度だけ測定後、アイドルモードとなる // 10,11 アイドルモード Wire.write(0x00); Wire.endTransmission(); } void loop() { // XYZレジスタ用のテーブル(6byte) uint8_t RegTbl[6]; // 6byteのデータを取得する for (int i=0; i< 6; i++){ // 各XZYの先頭アドレスに移動する Wire.beginTransmission(DEVICE_ADDRESS); Wire.write(0x03 + i); Wire.endTransmission(); // デバイスへ1byteのレジスタデータを要求する Wire.requestFrom(DEVICE_ADDRESS, 1); while (Wire.available() == 0 ){} RegTbl[i] = Wire.read(); } // データを各XYZの値に変換する int16_t x = (((int16_t)RegTbl[0]) << 8) | RegTbl[1]; int16_t z = (((int16_t)RegTbl[2]) << 8) | RegTbl[3]; int16_t y = (((int16_t)RegTbl[4]) << 8) | RegTbl[5]; // X,Y軸の位置からラジアンを算出する float rad = atan2(y,x); // XYZの3軸のうち、X軸方向の角度 // ※X軸方向の詳細は記事を参照ください。 float degree = rad * 180 / M_PI; if(degree <0){ degree = 360 + degree; } // 誤差(±15度) float hi = range360(degree + ambiguous); float lo = range360(degree - ambiguous); // 北東南西 Serial.print("方位:"); bool orientation= false; if(N >= lo && N <= hi){ Serial.print("北 "); orientation = true; }else if(E >= lo && E <= hi){ Serial.print("東 "); orientation = true; }else if(S >= lo && S <= hi){ Serial.print("南 "); orientation = true; }else if(W >= lo && W <= hi){ Serial.print("西 "); orientation = true; } // 北東/東南/南西/北西 if(!orientation){ if(N <= degree || E >= degree){ Serial.print("北東"); }else if(E <= degree && S >= degree){ Serial.print("東南"); }else if(S <= degree && W >= degree){ Serial.print("南西"); }else if(W <= degree && N >= degree){ Serial.print("北西"); } } Serial.print(" (以下、調整前データ → "); Serial.print("X:"); Serial.print(x); Serial.print(" Y:"); Serial.print(y); Serial.print(" Z:"); Serial.print(x); Serial.print(" 方位角:"); Serial.print(degree); Serial.println(")"); delay(1000); }
地磁気センサーなので本来(*1)は「方位磁石」と同じ地磁気での北(磁北)を差しています。磁北は地図上の北(真北)とは異なります。この差を磁気偏差(Magnetic declination)と呼ぶようです。
この磁北は真北より西側(国内では約5から10度)に向いています。磁北線は国土地理院地図の[機能][設定][磁北線]で確認する事が可能です。(ズーム11以上の場合)
※1 このHMC5883Lの各値はキャリブレーション(調整)が必要です。
最後に
今回のスケッチでは地域によって異なる「磁北」は考慮せずに「±15度の誤差」を使用して簡易的なデジタルコンパスとしています。
高精度な方位が必要な場合は適宜、コードを変更して下さいませ。
掲示板
ArduinoやRaspberry Piなどの電子工作の掲示板を作成しました。質問やわからない事は電子工作 (Arduino・ラズパイ等)でユーザー同士で情報を共有して下さい。