Microbit と Rust で光に反応する LED 回路を作る
それでは始めましょう。前のいくつかのセクションで理論は十分に扱いました。ここからはコードを書いていきます。ADC 値の閾値を定義します。それを上回った場合(部屋が暗くなるとそうなるはずです)、LED マトリクスに ⚡ の絵文字を表示します。
テンプレートからプロジェクトを作成する
このプロジェクトでは、microbit-bsp(Embassy を使用)を使います。テンプレートを使って新しいプロジェクトを生成するには、次のコマンドを実行します。
cargo generate --git https://github.com/ImplFerris/mb2-template.git --rev 3d07b56
-
プロジェクト名の入力を求められたら、"led-dracula" のような名前を入力します。
-
async を使うかどうか尋ねられたら、"true" を選択します。
-
"BSP" と "HAL" のどちらを使うか選ぶよう求められたら、"BSP" を選択します。
ディスプレイを初期化する
まず、micro:bit のディスプレイを初期化します。次に、5x5 の ⚡ 絵文字パターンを定義し、ディスプレイの明るさを最大に設定します。
#![allow(unused)] fn main() { let board = Microbit::default(); let mut display = board.display; #[rustfmt::skip] const FLASH: [u8; 5] = [ 0b00010, 0b00100, 0b01110, 0b00100, 0b01000, ]; display.set_brightness(Brightness::MAX); }
ADC を設定する
再び bind_interrupts! マクロを使って、SAADC 割り込みを対応するハンドラーに接続します。
#![allow(unused)] fn main() { bind_interrupts!(struct Irqs { SAADC => saadc::InterruptHandler; }); }
それでは ADC を設定しましょう。シングルエンドモードで構成します。これは、1 本のピンの電圧をグラウンド基準で測定するという意味です。この場合は micro:bit の P0 ピンを使っており、これは nRF52833 チップ上の GPIO ピン P0.02 に対応しています。
#![allow(unused)] fn main() { let channel_config = ChannelConfig::single_ended(board.p0); let config = saadc::Config::default(); let mut adc = Saadc::new(board.saadc, Irqs, config, [channel_config]); }
サンプルを読み取る
次に ADC 値を読み取ります。これをループ内で行い、結果を閾値と比較します。sample 関数は、設定したチャネル数と同じ要素数を持つ可変バッファを必要とします。今回は 1 つのチャネルしか使わないため、要素数 1 の配列を渡します。ADC は変換を実行し、その結果を配列の最初の(そして唯一の)要素に格納します。
#![allow(unused)] fn main() { let mut buf = [0; 1]; adc.sample(&mut buf).await; }
絵文字を表示する
ADC 値が取得できれば、LED ディスプレイの制御は簡単です。値がある閾値(この場合は 3500)より大きければ、絵文字を表示します。そうでなければ、ディスプレイをクリアします。セットアップに応じて感度を高くしたり低くしたりできるよう、閾値は調整できます。
#![allow(unused)] fn main() { const THRESHOLD: i16 = 3500; }
#![allow(unused)] fn main() { if buf[0] > THRESHOLD { display.apply(display::fonts::frame_5x5(&FLASH)); display.render(); } else { display.clear(); } ```rust }
最終コード
#![no_std] #![no_main] use embassy_executor::Spawner; use embassy_nrf::{ bind_interrupts, saadc::{self, ChannelConfig, Saadc}, }; use microbit_bsp::{ Microbit, display::{self, Brightness}, }; use {defmt_rtt as _, panic_probe as _}; bind_interrupts!(struct Irqs { SAADC => saadc::InterruptHandler; }); const THRESHOLD: i16 = 3500; #[embassy_executor::main] async fn main(_spawner: Spawner) -> ! { let board = Microbit::default(); let mut display = board.display; let config = saadc::Config::default(); let channel_config = ChannelConfig::single_ended(board.p0); let mut adc = Saadc::new(board.saadc, Irqs, config, [channel_config]); #[rustfmt::skip] const FLASH: [u8; 5] = [ 0b00010, 0b00100, 0b01110, 0b00100, 0b01000, ]; display.set_brightness(Brightness::MAX); loop { let mut buf = [0; 1]; adc.sample(&mut buf).await; if buf[0] > THRESHOLD { display.apply(display::fonts::frame_5x5(&FLASH)); display.render(); } else { display.clear(); } } }
既存のプロジェクトをクローンする
私が作成したプロジェクトをクローン(または参照)して、ldr-dracula フォルダに移動することもできます。
git clone https://github.com/ImplFerris/microbit-projects
cd microbit-projects/bsp-embassy/ldr-dracula
書き込み
あとはコードを micro:bit に書き込み、実際に動かしてみるだけです。
プロジェクトフォルダから次のコマンドを実行します。
#![allow(unused)] fn main() { cargo run }
次に、部屋の明かりを消したり、LDR をより暗い場所に移動したり、あるいは単に手で覆ってみてください。十分に暗くなると、LED マトリクスに ⚡ の絵文字が表示されるはずです。期待どおりに反応しない場合は、環境により合うように閾値を調整できます。