Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

第1案

LED コンパスを、完璧ではなくても、もっとも単純な方法で実装するにはどうすればよいでしょうか?

まずは、磁場の X 成分と Y 成分だけを気にすれば十分です。というのも、コンパスを見るときは常に水平に持つため、コンパスは XY 平面内にあるからです。

X 成分と Y 成分の符号だけを見れば、磁場がどの象限に属しているかを判定できます。ここで当然問題になるのは、4 つの象限がそれぞれどの方角(北、北東など)を表すのか、ということです。これを確かめるには、micro:bit を回転させて、別の方向に向けるたびに象限がどのように変化するかを観察すればよいだけです。

少し試してみると、たとえば micro:bit を北東の方向に向けたとき、X 成分と Y 成分はどちらも常に正になることがわかります。この情報をもとにすれば、ほかの象限がどの方角を表すのかも判断できるはずです。

象限と方角の対応関係がわかったら、以下のテンプレートを完成できるはずです。

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

use cortex_m_rt::entry;
use panic_rtt_target as _;
use rtt_target::{rprintln, rtt_init_print};

mod calibration;
use crate::calibration::calc_calibration;
use crate::calibration::calibrated_measurement;

mod led;
use led::Direction;

use microbit::{display::blocking::Display, hal::Timer};

#[cfg(feature = "v1")]
use microbit::{hal::twi, pac::twi0::frequency::FREQUENCY_A};

#[cfg(feature = "v2")]
use microbit::{hal::twim, pac::twim0::frequency::FREQUENCY_A};

use lsm303agr::{AccelOutputDataRate, Lsm303agr, MagOutputDataRate};

#[entry]
fn main() -> ! {
    rtt_init_print!();
    let board = microbit::Board::take().unwrap();

    #[cfg(feature = "v1")]
    let i2c = { twi::Twi::new(board.TWI0, board.i2c.into(), FREQUENCY_A::K100) };

    #[cfg(feature = "v2")]
    let i2c = { twim::Twim::new(board.TWIM0, board.i2c_internal.into(), FREQUENCY_A::K100) };

    let mut timer = Timer::new(board.TIMER0);
    let mut display = Display::new(board.display_pins);

    let mut sensor = Lsm303agr::new_with_i2c(i2c);
    sensor.init().unwrap();
    sensor.set_mag_odr(MagOutputDataRate::Hz10).unwrap();
    sensor.set_accel_odr(AccelOutputDataRate::Hz10).unwrap();
    let mut sensor = sensor.into_mag_continuous().ok().unwrap();

    let calibration = calc_calibration(&mut sensor, &mut display, &mut timer);
    rprintln!("Calibration: {:?}", calibration);
    rprintln!("Calibration done, entering busy loop");
    loop {
        while !sensor.mag_status().unwrap().xyz_new_data {}
        let mut data = sensor.mag_data().unwrap();
        data = calibrated_measurement(data, &calibration);

        let dir = match (data.x > 0, data.y > 0) {
            // 象限 ???
            (true, true) => Direction::NorthEast,
            // 象限 ???
            (false, true) => panic!("TODO"),
            // 象限 ???
            (false, false) => panic!("TODO"),
            // 象限 ???
            (true, false) => panic!("TODO"),
        };

        // led モジュールを使って方角を LED の矢印に変換し
        // それを第 5 章の LED 表示関数を使って
        // 矢印として表示する
    }
}