前回、動かすたびに同じ方位でも値が異なり、うまくいきませんでしたが、
Arduino側でキャリブレーションするようにしたところ、比較的正確に方位を取得できるようになりました。
キャリブレーションといっても以下のような簡単な方法です。
OUT1とOUT2それぞれについて最大値、最小値を測定し、最小値~最大値の範囲で正規化します。
起動後にゆっくり2回転ほどさせると、正確な方位がとれるようになりました。
I2C版のHMC6352もキャリブレーション機能があるので、キャリブレーションは必須ということなのでしょう。
また、効果があるか良く分からないのですが、値の取得前にSET/RESET端子にパルスを入れるようにしています。
ArduinoのDIGITAL2をSET/RESET端子に接続します(10KΩの抵抗でプルダウン)。
■Arduinoスケッチ
// Calibration 初期値は安全な値を適当に設定 int cal_min1 = 488; int cal_max1 = 515; int cal_min2 = 463; int cal_max2 = 489; void setup() { pinMode(2, OUTPUT); Serial.begin(9600); } void loop() { // SET/RESET PULSE digitalWrite(2, LOW); delay(10); digitalWrite(2, HIGH); delay(10); digitalWrite(2, LOW); delay(10); // 読み取り int val1 = analogRead(0); int val2 = analogRead(1); // キャリブレーション if (val1<cal_min1) cal_min1 = val1; if (val2<cal_min2) cal_min2 = val2; if (val1>cal_max1) cal_max1 = val1; if (val2>cal_max2) cal_max2 = val2; int div1 = (cal_max1 - cal_min1 + 1); int div2 = (cal_max2 - cal_min2 + 1); float fval1 = (val1 - cal_min1 - div1 / 2.0) / div1; float fval2 = (val2 - cal_min2 - div2 / 2.0) / div2; // 角度(方位)を0~255に変換 int at = (atan2(fval1, fval2) + PI ) * 255 / (2*PI); Serial.print(at, BYTE); delay(100); }
■Processingスケッチ
import processing.serial.*; Serial myPort; int val; void setup() { size(200, 200); myPort = new Serial(this, "COM9", 9600); PFont font = createFont("Arial", 12); textFont(font); } void draw() { if ( myPort.available() > 0) { val = myPort.read(); } background(0); text(str(val), 1, 10); translate(width/2, height/2); rotate(val * 2 * PI/255); triangle(-10, -40, 10, -40, 0, 40); }