大きさ
地球の磁場はどれくらい強いのでしょうか? magnetic_field() メソッドのドキュメントによると、取得している x y z の値の単位はナノテスラです。つまり、磁場の大きさをナノテスラで求めるために計算しなければならないのは、x y z の値が表す 3 次元ベクトルの大きさだけです。学校で習ったのを覚えているかもしれませんが、これは単に次のように求められます:
#![allow(unused)]
fn main() {
use libm::sqrtf;
let magnitude = sqrtf(x * x + y * y + z * z);
}
Rust の core には sqrtf() のような浮動小数点数学関数がないため、no_std
プログラムではどこかから実装を入手する必要があります。そのために libm クレートを使います。
これらをすべてプログラム (examples/magnitude.rs) にまとめると、次のようになります:
#![deny(unsafe_code)]
#![no_main]
#![no_std]
use cortex_m_rt::entry;
use embedded_hal::delay::DelayNs;
use panic_rtt_target as _;
use rtt_target::{rprintln, rtt_init_print};
use libm::sqrtf;
use microbit::{
hal::{twim, Timer},
pac::twim0::frequency::FREQUENCY_A,
};
use lsm303agr::{Lsm303agr, MagMode, MagOutputDataRate};
#[entry]
fn main() -> ! {
rtt_init_print!();
let board = microbit::Board::take().unwrap();
let i2c = { twim::Twim::new(board.TWIM0, board.i2c_internal.into(), FREQUENCY_A::K100) };
let mut timer0 = Timer::new(board.TIMER0);
let mut sensor = Lsm303agr::new_with_i2c(i2c);
sensor.init().unwrap();
sensor
.set_mag_mode_and_odr(
&mut timer0,
MagMode::HighResolution,
MagOutputDataRate::Hz10,
)
.unwrap();
let mut sensor = sensor.into_mag_continuous().ok().unwrap();
loop {
while !sensor.mag_status().unwrap().xyz_new_data() {
timer0.delay_ms(1u32);
}
let (x, y, z) = sensor.magnetic_field().unwrap().xyz_nt();
let (x, y, z) = (x as f32, y as f32, z as f32);
let magnitude = sqrtf(x * x + y * y + z * z);
rprintln!("{} mG", magnitude / 100.0);
}
}
これを cargo run --example magnitude で実行してください。
このプログラムは、磁場の大きさ(強さ)をナノテスラ (nT) と
ミリガウス (mG、1 mG = 100 nT) で報告します。地球の磁場の大きさは
250 mG から 650 mG の範囲にあります(大きさは地理的な位置によって変化します)ので、理想的にはその範囲にだいたい収まる値が見えるはずです。センサーがまだキャリブレーションされていないため、値はかなりずれている可能性があります。キャリブレーションについては appendix 3 を参照してください。キャリブレーションすると、私はおよそ 340 mG の大きさを確認しています。
いくつか質問があります:
-
ボードを動かさない状態では、どのような値が見えますか? 常に同じ値が見えますか?
-
ボードを回転させると、大きさは変化しますか? 変化するべきでしょうか?