ドライバを使う
第5章ですでに説明したとおり、embedded-hal は、ハードウェアとやり取りできるプラットフォームに依存しないコードを書くために使える抽象化を提供します。実際、LED ルーレット の章とこの章のここまででハードウェアとやり取りするために使ってきたすべてのメソッドは、embedded-hal で定義されたトレイトのものでした。ここで初めて、embedded-hal が提供するトレイトを実際に使います。
embedded Rust がサポートするすべてのプラットフォーム向けに、私たちの LSM303AGR 用ドライバを実装するのは無意味です(そして、今後登場するかもしれない新しいものについても同様です)。これを避けるために、embedded-hal のトレイトを実装したジェネリック型を受け取るドライバを書くことで、プラットフォームに依存しないバージョンのドライバを提供できます。幸いなことに、これはすでに lsm303agr クレートで行われています。そのため、実際の加速度計と磁力計の値の読み取りは、基本的にはプラグアンドプレイになります(加えて、少しドキュメントを読むだけです)。実際、crates.io のページには、Raspberry Pi を使って加速度計データを読み取るために必要なことがすべてすでに書かれています。あとはそれを私たちのチップ向けに合わせるだけです。
リンク先のページにある Raspberry Pi Linux のサンプルコードを見てください。
すでに 前のページ で embedded_hal::blocking::i2c トレイトを実装するオブジェクトのインスタンスを作成する方法はわかっているので、サンプルコードを適応させるのは簡単です(examples/show-accel.rs):
#![deny(unsafe_code)]
#![no_main]
#![no_std]
use cortex_m_rt::entry;
use panic_rtt_target as _;
use rtt_target::{rprintln, rtt_init_print};
use microbit::{
hal::{twim, Timer},
pac::twim0::frequency::FREQUENCY_A,
};
use lsm303agr::{AccelMode, AccelOutputDataRate, Lsm303agr};
#[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);
// Code from documentation
let mut sensor = Lsm303agr::new_with_i2c(i2c);
sensor.init().unwrap();
sensor
.set_accel_mode_and_odr(
&mut timer0,
AccelMode::HighResolution,
AccelOutputDataRate::Hz50,
)
.unwrap();
loop {
if sensor.accel_status().unwrap().xyz_new_data() {
let (x, y, z) = sensor.acceleration().unwrap().xyz_mg();
// RTT instead of normal print
rprintln!("Acceleration: x {} y {} z {}", x, y, z);
}
}
}
前のスニペットと同じように、次のようにして試せるはずです。
$ cargo embed --example show-accel
さらに、micro:bit を少し(物理的に)動かすと、表示されている加速度の値が変化するのがわかるはずです。