加速度センサーから値を読み取るシンプルな Rust プログラム
まずは、加速度センサーから値を読み取って表示するシンプルな Rust プログラムを書いてみましょう。X、Y、Z の各軸に沿った加速度を、ミリ重力(mg)単位で表示します。読み取った値はシステムコンソールに出力します。
後続の章では、これらの値を使ったいくつかの楽しい演習を見ていきます。まずは、始めてみましょう!
テンプレートからプロジェクトを作成する
このプロジェクトでは、microbit-bsp(Embassy と組み合わせて)を使用します。テンプレートを使って新しいプロジェクトを生成するには、次のコマンドを実行します。
cargo generate --git https://github.com/ImplFerris/mb2-template.git --rev 3d07b56
-
プロジェクト名の入力を求められたら、
"accelerometer-print"のような名前を入力します。 -
async を使用するかどうかを尋ねられたら、
"true"を選択します。 -
"BSP"または"HAL"のどちらを選ぶかを尋ねられたら、"BSP"を選択します。
Cargo.toml を更新する
"[lsm303agr](https://docs.rs/lsm303agr/latest/lsm303agr/)" クレートは、このプロジェクトで新たに導入する依存関係です。これは LSM303AGR センサー向けのプラットフォーム非依存な Rust ドライバーであり、デバイスからデータを読み取るための便利な関数群を提供します。また、このドライバーに対して "async" 機能も有効にしています。
lsm303agr = { version = "1.1.0", features = ["async"] }
static_cell = { version = "2" }
また、static_cell クレートも追加します。これは、静的メモリを安全に作成およびアクセスするためのツールを提供します。これを使って、TWIM(I2C)ドライバーが必要とする固定サイズの RAM バッファを確保します。このバッファは 'static ライフタイムを持ち、RAM 上に存在している必要がありますが、static_cell はそれを安全に管理するのに役立ちます。
import を更新する
始める前に、I2C ペリフェラル、タイミング、そして LSM303AGR センサードライバーに必要な import を更新しましょう。
#![allow(unused)] fn main() { use defmt_rtt as _; use embassy_executor::Spawner; use embassy_time::{Delay, Duration, Timer}; // I2C用 use embassy_nrf::{self as hal, twim::Twim}; use hal::twim; // LSM303AGRドライバー use lsm303agr::{AccelMode, AccelOutputDataRate, Lsm303agr}; // BSPクレート use microbit_bsp::Microbit; }
ボードを初期化する
いつものように、まずテンプレートに含まれている main 関数内の既存の行をすべて削除します。次に、ボードを初期化するために以下の行を追加します。
#![allow(unused)] fn main() { let board = Microbit::default(); }
I2C 割り込み
以前、温度センサーの章で割り込みについて説明しましたので、ここまで来ればその仕組みの基本的な理解はあるはずです。I2C 通信では、TWISPI0 ペリフェラルに関連付けられた割り込みを有効にする必要があります。
TWISPI0 は nRF52833 上の共有ハードウェアペリフェラルで、設定に応じて I2C(TWI)または SPI インターフェースとして機能します。
これを行うために、embassy-nrf クレートの bind_interrupts! マクロを使用します。このマクロは "Irqs" という名前のユニット構造体を定義し、TWISPI0 割り込みを適切なハンドラーに接続します。また、このマクロは Irqs に必要な Binding トレイトも実装し、正しい割り込みが設定されていることをコンパイル時に型チェックで保証します。(ここで何を説明しているのかよくわからない場合は、bind_interrupts! マクロの展開セクションを参照してください。)
#![allow(unused)] fn main() { hal::bind_interrupts!(struct Irqs { TWISPI0 => twim::InterruptHandler<hal::peripherals::TWISPI0>; }); }