試行 1
LED コンパスを実装するいちばん単純な方法は何でしょうか。たとえ完全ではないとしても。
まずは、磁場の X 成分と Y 成分だけを気にすれば十分です。というのも、コンパスを見るときは 常に水平に持つので、コンパスは XY 平面内にあるからです。
たとえば、次のような場合にはどの LED を点灯させるでしょうか。EMF は Earth’s Magnetic Field の略で、緑の矢印は EMF の向きを示しています(北を指しています)。
Southeast LED、ですよね?
その状況では、磁場の X 成分と Y 成分の 符号 はどうなっているでしょうか。どちらも 正です。
X 成分と Y 成分の符号だけを見れば、磁場がどの象限に属するかを 判断できます。
先ほどの例では、磁場は第1象限にあり(x と y は正でした)、SouthEast LED を点灯させるのが
妥当でした。同様に、磁場が別の象限にあるなら、別の LED を点灯させることができます。
そのロジックを試してみましょう。スターターコードは次のとおりです。
#![deny(unsafe_code)]
#![no_main]
#![no_std]
#[allow(unused_imports)]
use aux15::{entry, iprint, iprintln, prelude::*, switch_hal::OutputSwitch, Direction, I16x3};
#[entry]
fn main() -> ! {
let (leds, mut lsm303dlhc, mut delay, _itm) = aux15::init();
let mut leds = leds.into_array();
loop {
let I16x3 { x, y, .. } = lsm303dlhc.mag().unwrap();
// X 成分と Y 成分の符号を見て、磁場がどの
// 象限にあるかを判断する
let dir = match (x > 0, y > 0) {
// 象限 ???
(true, true) => Direction::Southeast,
// 象限 ???
(false, true) => panic!("TODO"),
// 象限 ???
(false, false) => panic!("TODO"),
// 象限 ???
(true, false) => panic!("TODO"),
};
leds.iter_mut().for_each(|led| led.off().unwrap());
leds[dir as usize].on().unwrap();
delay.delay_ms(1_000_u16);
}
}
led モジュールには、方位にちなんだ 8 つのバリアントを持つ Direction 列挙型があります:
North, East, Southwest などです。これらの各バリアントは、コンパスにある 8 個の LED
のうち 1 つを表します。Leds の値は Direction enum を使ってインデックス指定でき、その
結果として、その Direction を向く LED が得られます。