ドライバーを使う
すでに第 5 章で説明したように、embedded-hal はハードウェアとやり取りできるプラットフォーム非依存のコードを書くために使える抽象化を提供します。実際、第 7 章でハードウェアとやり取りするために使ったメソッド、そしてここまでの第 8 章で使ってきたメソッドは、すべて embedded-hal で定義されたトレイトに由来するものでした。ここで初めて、embedded-hal が提供するトレイトを実際に活用します。
embedded Rust がサポートするすべてのプラットフォーム(そして今後新たに登場するかもしれないもの)ごとに、LSM303AGR 用のドライバーを実装するのは無意味です。これを避けるために、embedded-hal のトレイトを実装したジェネリック型を受け取るドライバーを書くことで、プラットフォームに依存しないバージョンのドライバーを提供できます。幸い、これについてはすでに lsm303agr クレートで実現されています。そのため、加速度計と磁力計の実際の値を読み取る作業は、基本的にプラグアンドプレイ(と少しのドキュメント確認)で済みます。実際、crates.io のページには、Raspberry Pi を使って加速度計データを読み取るために必要なことがすでにすべて載っています。あとはそれを私たちのチップ向けに合わせるだけです。
use linux_embedded_hal::I2cdev;
use lsm303agr::{AccelOutputDataRate, Lsm303agr};
fn main() {
let dev = I2cdev::new("/dev/i2c-1").unwrap();
let mut sensor = Lsm303agr::new_with_i2c(dev);
sensor.init().unwrap();
sensor.set_accel_odr(AccelOutputDataRate::Hz50).unwrap();
loop {
if sensor.accel_status().unwrap().xyz_new_data {
let data = sensor.accel_data().unwrap();
println!("Acceleration: x {} y {} z {}", data.x, data.y, data.z);
}
}
}
前のページで embedded_hal::blocking::i2c トレイトを実装したオブジェクトのインスタンスを作る方法はすでに分かっているので、これはとても簡単です。
#![deny(unsafe_code)]
#![no_main]
#![no_std]
use cortex_m_rt::entry;
use rtt_target::{rtt_init_print, rprintln};
use panic_rtt_target as _;
#[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,
};
#[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 sensor = Lsm303agr::new_with_i2c(i2c);
sensor.init().unwrap();
sensor.set_accel_odr(AccelOutputDataRate::Hz50).unwrap();
loop {
if sensor.accel_status().unwrap().xyz_new_data {
let data = sensor.accel_data().unwrap();
// 通常の print の代わりに RTT
rprintln!("Acceleration: x {} y {} z {}", data.x, data.y, data.z);
}
}
}
前のスニペットと同じように、これは次のようにそのまま試せるはずです。
# micro:bit v2 の場合
$ cargo embed --features v2 --target thumbv7em-none-eabihf
# micro:bit v1 の場合
$ cargo embed --features v1 --target thumbv6m-none-eabi
さらに、micro:bit を少し(物理的に)動かしてみると、表示される加速度の数値が変化するのが分かるはずです。