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・ラズパイ等)でユーザー同士で情報を共有して下さい。
関連記事
プチモンテ ※この記事を書いた人
![]() | |
![]() | 💻 ITスキル・経験 サーバー構築からWebアプリケーション開発。IoTをはじめとする電子工作、ロボット、人工知能やスマホ/OSアプリまで分野問わず経験。 画像処理/音声処理/アニメーション、3Dゲーム、会計ソフト、PDF作成/編集、逆アセンブラ、EXE/DLLファイルの書き換えなどのアプリを公開。詳しくは自己紹介へ |
| 🎵 音楽制作 BGMは楽器(音源)さえあれば、何でも制作可能。歌モノは主にロック、バラード、ポップスを制作。歌詞は抒情詩、抒情的な楽曲が多い。楽曲制作は🔰2023年12月中旬 ~ | |









