センサーデータを表示する
このセクションでは、センサーデータを ePaper ディスプレイに表示します。ディスプレイには、大きめのフォントでタイトル「Air Quality」を表示し、その下に数値、その値、単位を小さめのフォントで表示します。
この機能を 12_scd_30_alert.rs から実装していきます。
配線
✅ ブレッドボードの + ワイヤーを開発ボードの VDD に、- ワイヤーを GND に再接続します。
✅ その他のすべてのケーブルを、開発ボード上のそれぞれ対応するピンに接続します。
✅ ePaper Display は十分な電流を得るために、専用の電源が必要です。もう一方の VDD と GND に接続します。

SPIM をインスタンス化する
これは前章の繰り返しです。 自分で試して、どれだけ学んだか確認してみましょう!方法を覚えていない場合は、前の章に戻ってください。
✅ コードを実行して、すべてビルドできることを確認します。ディスプレイには新しいものは何も表示されないはずです。
静的テキストを表示する
✅ 新しいモジュール display_helper を追加します。
✅ display_helper/mod.rs 内で、次のリソースをスコープに取り込みます。
#![allow(unused)]
fn main() {
use epd_waveshare::{
epd4in2::*,
};
use embedded_graphics::{
egtext,
fonts::{Font12x16, Font24x32, Text},
geometry::Point,
pixelcolor::BinaryColor,
prelude::*,
style::TextStyle,
text_style,
};
}
最初のステップは、タイトルや表示される測定値の名前など、静的なままのテキストを書くことです。この関数は、ディスプレイ型である Display4in2 を可変引数として受け取り、それを返します。
組み込みフォントを使った基本的なテキストは、基本図形と似た方法で追加されます。ディスプレイ上に配置するには、次のものが必要です。
- 文字列
- テキストが始まる位置の左上座標
この場合、シンプルなビットマップフォントの 6 種類のサイズと、スタイルとして色をオンまたはオフにする選択肢があります。タイトル用のフォントは、残りのテキスト用のフォントより大きくします。
✅ 次の関数をモジュールに追加します。
#![allow(unused)]
fn main() {
pub fn draw_text (mut display: Display4in2 ) -> Display4in2 {
Text::new("Air Quality", Point::new(20, 30))
.into_styled(TextStyle::new(Font24x32, BinaryColor::On))
.draw(&mut display).unwrap();
Text::new("Carbon Dioxide:", Point::new(20, 90))
.into_styled(TextStyle::new(Font12x16, BinaryColor::On))
.draw(&mut display).unwrap();
Text::new("Temperature:", Point::new(20, 130))
.into_styled(TextStyle::new(Font12x16, BinaryColor::On))
.draw(&mut display).unwrap();
Text::new("Humidity:", Point::new(20, 170))
.into_styled(TextStyle::new(Font12x16, BinaryColor::On))
.draw(&mut display).unwrap();
display
}
}
✅ メインファイルに移動します。
✅ 測定用の loop の中に、ディスプレイのインスタンスを追加し、その後に fn draw_text の呼び出しを追加します。
#![allow(unused)]
fn main() {
let display = Display4in2::default();
let display = display::draw_text(display);
}
✅ ディスプレイがバッファに書き込まれた内容を実際に表示するようにするため、フレームを更新して表示する次の行を追加します。
#![allow(unused)]
fn main() {
epd4in2.update_frame(&mut spi, &display.buffer()).unwrap();
epd4in2.display_frame(&mut spi).expect("display frame new graphics");
}
✅ プログラムを実行します。タイトルに続いて 3 行のテキストが表示されるはずです。
動的テキストを表示する
静的テキストは比較的単純ですが、プログラムの実行中に変化すると想定される値をフォーマット文字列を使って表示するのは、[no_std] 環境では動的メモリ割り当てがないため、少し複雑です。フォーマット文字列を使用するために、固定サイズの配列と文字列を提供する arrayvec クレートを使います。
✅ cargo.toml の [dependencies] セクションに次の行を追加します。
#![allow(unused)]
fn main() {
arrayvec = {version = "0.5.2", default-features = false }
}
✅ display_helper/mod.rs 内で、次のリソースをスコープに取り込みます。
#![allow(unused)]
fn main() {
use arrayvec::ArrayString;
use core::fmt::Write;
}
✅ 次の関数をモジュールに追加します。
#![allow(unused)]
fn main() {
pub fn draw_numbers (value: f32, unit: &str, position: (i32, i32), mut display: Display4in2 ) -> Display4in2 {
// 内容
display
}
}
pub fn draw_numbers は、測定値の値、その単位、測定値を表示する位置の top_left 座標、および display を引数として受け取ります。ディスプレイが返されます。
次のステップは、書き込みバッファ buf として固定サイズの ArrayString を作成することです。このバッファは、フォーマットされた動的データを保存するために必要です。表示したい文字数以上の文字を格納できる必要があります。
✅ 書き込みバッファを作成し、write! マクロを使って、小数点以下 2 桁までの値と単位を含むフォーマット文字列を、書き込みバッファ buf に書き込みます。
#![allow(unused)]
fn main() {
let mut buf = ArrayString::<[_; 12]>::new();
write!(&mut buf, "{:.2} {}", value, unit).expect("Failed to write to buffer");
}
次に、egtext! マクロを使って、テキストを display バッファに書き込みます。
✅ 次の行を pub fn draw_numbers に追加します。
#![allow(unused)]
fn main() {
egtext!(
text = &buf,
top_left = position,
style = text_style!(
font = Font12x16,
text_color = BinaryColor::On,
)
)
.draw(&mut display).unwrap();
}
✅ メインプログラムファイルに移動します。
✅ fn main() の直前に、次の定数を定義します。
#![allow(unused)]
fn main() {
const CO2_POSITION: (i32, i32) = (220, 90);
const CO2_UNIT: &str = "ppm";
const TEMP_POSITION: (i32, i32) = (220, 130);
const TEMP_UNIT: &str = "°C";
const HUMIDITY_POSITION: (i32, i32) = (220, 170);
const HUMIDITY_UNIT: &str = "%";
}
これらの定数は、数値を表示する位置とその単位を設定します。
✅ fn main 内の測定用の loop の中で、センサーから値を読み取った後に、各測定値について fn draw_numbers を呼び出します。
#![allow(unused)]
fn main() {
let display = display_helper::draw_numbers(co2, CO2_UNIT, CO2_POSITION, display);
let display = display_helper::draw_numbers(temp, TEMP_UNIT, TEMP_POSITION, display);
let display = display_helper::draw_numbers(humidity, HUMIDITY_UNIT, HUMIDITY_POSITION, display);
}
✅ プログラムを実行します。ePaper には、静的テキストの横にタイトル、数値、単位が表示されるはずです。

ディスプレイは非常に頻繁に、とても派手に更新されます。これを減らすために、ループの最後の遅延を変更します。ePaper ディスプレイは各更新に約 4 秒必要なので、それより頻繁に測定しても意味がありません。
✅ 遅延を 2000 ms から 30000ms に変更します。
#![allow(unused)]
fn main() {
timer.delay_ms(30000_u32);
led_1.set_high().unwrap();
timer.delay_ms(30000_u32);
led_1.set_low().unwrap();
}
✅ プログラムを実行します。同じ出力が表示されるはずですが、画面は 1 分ごとにのみ更新されます。
ディスプレイは更新時にまだ点滅しますが、この点やその他のより見た目に関する問題は、1 月に提供されるこのプロジェクトの最後の更新で対処されます。