キャリブレーション

ボードを回転すると、磁力計に対する地球磁場の方向は変わりますが、大きさは変わりません! それでも、磁力計は、ボードが回転すると磁場の大きさが変化することを示しています。

それはなぜでしょうか?結局のところ、磁力計が正しい答えを返すためには、キャリブレーションが必要なのです。

キャリブレーションには、多くの数学(行列)が必要であるため、ここでは取り上げません。もし興味があるのであれば、 アプリケーションノートにその計算方法が記述されています。 代わりに、このセクションでやることは、どの程度正しい答えからずれているか、を視覚化することです。

次の実験を試してみましょう。別方向にボードをゆっくり回転している間、磁力計から読んだ値を記録しましょう。 読んだ値をタブ区切り(TSV; Tab Separated Values)に変換するため、iprintlnマクロを使います。

#![deny(unsafe_code)]
#![no_main]
#![no_std]

#[allow(unused_imports)]
use aux15::{entry, iprint, iprintln, prelude::*, I16x3};

#[entry]
fn main() -> ! {
    let (_leds, mut lsm303dlhc, mut delay, mut itm) = aux15::init();

    loop {
        let I16x3 { x, y, z } = lsm303dlhc.mag().unwrap();

        iprintln!(&mut itm.stim[0], "{}\t{}\t{}", x, y, z);

        delay.delay_ms(100_u8);
    }
}

コンソールに次のような出力が得られるはずです。

$ # itmdumpコンソール
-76     213     -54
-76     213     -54
-76     213     -54
-76     213     -54
-73     213     -55

次のコマンドを使って、ファイルにパイプできます。

$ # 注意!他に実行中の`itmdump`インスタンスを全て終了します
$ itmdump -F -f itm.txt > emf.txt

数秒間、データをログ出力している間、ボードを様々な方向に回転します。

その後、TSVファイルをスプレッドシートプログラムに取り込み(もしくは、下記のPythonスクリプトを使い)、 最初の2つの列を散布図としてプロットします。

#!/usr/bin/python

import csv
import math
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
import sys

# プロット形式を適用します
sns.set()

x = []
y = []

with open(sys.argv[1], 'r') as f:
    rows = csv.reader(f, delimiter='\t')

    for row in rows:
        # データが欠けている行は捨てます
        if len(row) != 3 or not row[0] or not row[1]:
            continue

        x.append(int(row[0]))
        y.append(int(row[1]))

r = math.ceil(max(max(np.abs(x)), max(np.abs(y))) / 100) * 100

plt.plot(x, y, '.')
plt.xlim(-r, r)
plt.ylim(-r, r)
plt.gca().set_aspect(1)
plt.tight_layout()

plt.savefig('emf.svg')
plt.close

ボードを水平な平面上で回転した場合、磁場のZ要素は、比較的同じ値を取り続けたはずです。 このプロットは、原点を中心とした円形(楕円形でない)でなければなりません。 上図のプロットのように、ボードをランダムな方向に回転した場合、多数の点からなる原点を中心とした円が得られるはずです。 円形からの偏差は、磁力計をキャリブレーションする必要があることを示しています。

覚えておいてほしいこと:センサから読んだ値を単純に信用しないで下さい。適切な値が出力されていることを確認して下さい。 適切な出力でなければ、キャリブレーションして下さい。