Arduinoで実験 (デジタルコンパス)

2013/05/07


◆ ディジタルコンパスモジュール HMC6352

I2C で制御し角度を出力することのできる方位センサ ディジタルコンパスモジュール HMC6352 を入手したので、さっそく使ってみる。

いろいろと方位センサのモジュールが発売されていますが、このモジュールは直接角度の数値を得ることができます。 一般にセンサ類はアナログ出力で入力値を変換する計算が必要になります。 直接角度の数値を得ることができるのでマイコンで面倒な計算をする必要はありません。 特に Arduino は、 double 型が 4 バイトなので小数点以下 4位位で誤差が出るので、なおさらです。

ピンは、三角の印が付いている四角いランドが 1 番ピンとなります。

I2C アドレスは 0x42 ですが、 Arduino では上位 7 ビットを使用するので右シフトする。、
 0x42 >> 1  =  0x21

1 GND    グランド
2 SDA    SDA (Arduino A4)
3 SCL    SCL (Arduino A5)
4 Vdd    電源 ( 2.7V ~ 5V )
5 CB1    アナログ出力
6 NC     未使用
7 CA1    アナログ出力
8 ~MCLR  リセット端子

以下は HMC6352 のコマンド

コマンド 機能 ディレイ
w 0x77 Write to EEPROM 70us
r 0x72 Read from EEPROM 70us
G 0x47 Write to RAM Register 70us
g 0x67 Read from RAM Register 70us
S 0x53 Enter Sleep Mode 10us
W 0x57 Exit Sleep Mode 100us
O 0x4F Update Bridge Offsets 6000us
C 0x43 Enter User Calibration Mode 10us
E 0x45 Exit User Calibration Mode 14000us
L 0x4C Save Op Mode to EEPROM 125us
A 0x41 Get Data. Compensate and Calculate New Heading 6000us

HMC6352 内の EEPROM

アドレス 機能 初期値
0x00 I2C Slave Address 0x42
0x01 Magnetometer X Offset MSB factory test value
0x02 Magnetometer X Offset LSB factory test value
0x03 Magnetometer Y Offset MSB factory test value
0x04 Magnetometer Y Offset LSB factory test value
0x05 Time Delay (0 - 255 ms) 0x01
0x06 Number of Summed measurements (1 - 16) 0x04
0x07 Software Version Number 0x01
0x08 Operation Mode Byte 0x50

レジスタの内容は以下の通りです。

Operation Mode Byte (0x74)
  bit7 - bit6 - bit 5 - bit4 - bit3 - bit2 - bit1 - bit0
    0    MR1    MR0       P      0      0     M1     M0


bit6,bit5 (Continuous Mode Measurement Rate)

  0 ,  0    1 Hz measurement Rate
  0 ,  1    5 Hz measurement Rate
  1 ,  0   10 Hz measurement Rate
  1 ,  1   20 Hz measurement Rate


bit4 (Periodic Set / Reset)

  0  =  off
  1  =  on


bit1,bit0 (Operational Mode Value)

  0 ,  0   Standby Mode
  0 ,  1   Query Mode
  1 ,  0   Continuous Mode
  1 ,  1   Not Allowed

Output Mode Byte (0x4E)
  bit7 - bit6 - bit 5 - bit4 - bit3 - bit2 - bit1 - bit0
    0      0      0       0      0     M2     M1     M0

bit2,bit1,bit0 (Output Mode Value)
  0, 0, 0  Heading Mode
  0, 0, 1  Raw Magnetometer X Mode
  0, 1, 0  Raw Magnetometer Y Mode
  0, 1, 1  Magnetometer X Mode
  1, 0, 0  Magnetometer Y Mode

Standby Mode は、コマンド 'A' を送信し一つの測定値を受信します。 再度測定する際にもコマンドを発行します。

Query Mode は、コマンド 'A' 送信後にデータを読み取るとデータ読み取り毎に自動で次の計測を開始します。

Continuous Mode は一定周期で計測を行い測定値を出力します。 周期の設定はレジスタ 0x74 の bit6 と bit5 を変更します。

EEPROM  関連のコマンド W と r はコマンド発行後 1 バイトのアドレスを送ります。 書込みなら続けて 1バイトを送信。 読込みなら 1バイトの読込みとなります。

レジスタ関連のコマンド G と g はコマンド発行後 1バイトの RAM アドレスを送ります。 書込みなら続けて 1バイトを送信。 読込みなら 1バイトの読込みとなります。

A コマンド発行後は、 2バイトのデータが返ってきます。 最初の 1バイトは MSB、次の 1バイトは LSB となります。

その他のコマンドは、コマンドの発行のみでデータはありません。

 

//
// 110-01 デジタルコンパス実験スケッチ
//

#include <Wire.h>

#define I2C_addr 0x21 // デジタルコンパスのアドレス 0x42 >> 1

void setup() {
  Wire.begin();
  Serial.begin(9600);

// モード設定
  Wire.beginTransmission(I2C_addr);
  Wire.write('G');   // コマンド発行
  Wire.write(0x74);  // RAM アドレス指定
  Wire.write(0x72);  // 20 Hz
                    // Periodic Reset
                    // Continuous Mode
  Wire.endTransmission();
  delay(1);
} 

void loop() {
  unsigned int deg_dat;   // 角度データ用変数
  deg_dat = getDeg();
  Serial.println((double)deg_dat / 10);
} 

// 角度データの取得用関数
unsigned int getDeg(void) {
  unsigned int ret = 0;
  Wire.requestFrom(I2C_addr, 2);
  while(Wire.available() < 2);
  ret = Wire.read();  // MSB
  ret = ret << 8;
  ret += Wire.read(); // LSB
  delay(50);
  return (ret);  
}

近くにスピーカーがあったので、180度位回転させても値がおかしかった。 結構いろんな影響を受けるようだ。

グルグル回したら一時おかしくなり、測定しなかった。 デリケートなセンサです。


◆ アナログ出力

CA1 と CA2 でアナログ出力ができるとある。 Continuous Mode でピンを接続して読んでみたが出力されていなかった。 Heading Mode では出力されないのかもしれない。

Magnetometer Mode を試してみればよいのだが更生処理が面倒なので試していない。 試して見たら以下に追記しておく。