📟 pmme-device: Use embedded_graphics + ssd1306 crates to display logo on the OLED

This commit is contained in:
Joseph Ferano 2025-06-10 18:04:23 +07:00
parent cc163589fc
commit 9e3ae56aa1
4 changed files with 88 additions and 9 deletions

View File

@ -3,7 +3,8 @@ target = "xtensa-esp32-espidf"
[target.xtensa-esp32-espidf] [target.xtensa-esp32-espidf]
linker = "ldproxy" linker = "ldproxy"
runner = "espflash flash --monitor" # runner = "espflash flash --monitor --speed 921600 # or even 1500000"
runner = "espflash flash --monitor --baud 921600"
rustflags = [ "--cfg", "espidf_time64"] rustflags = [ "--cfg", "espidf_time64"]
[unstable] [unstable]

View File

@ -1,5 +1,5 @@
[package] [package]
name = "rust-version" name = "pmme-device"
version = "0.1.0" version = "0.1.0"
authors = ["Joseph Ferano <joseph@ferano.io>"] authors = ["Joseph Ferano <joseph@ferano.io>"]
edition = "2021" edition = "2021"
@ -7,7 +7,7 @@ resolver = "2"
rust-version = "1.77" rust-version = "1.77"
[[bin]] [[bin]]
name = "rust-version" name = "pmme-device"
harness = false # do not use the built in cargo test harness -> resolve rust-analyzer errors harness = false # do not use the built in cargo test harness -> resolve rust-analyzer errors
[profile.release] [profile.release]
@ -20,11 +20,15 @@ opt-level = "z"
[features] [features]
default = [] default = []
experimental = ["esp-idf-svc/experimental"] # experimental = ["esp-idf-svc/experimental"]
[dependencies] [dependencies]
log = "0.4" log = "0.4"
esp-idf-svc = { version = "0.51", features = ["critical-section", "embassy-time-driver", "embassy-sync"] } esp-idf-svc = { version = "0.51", features = ["critical-section", "embassy-time-driver", "embassy-sync"] }
anyhow = "1.0.98"
embedded-graphics = "0.8.1"
ssd1306 = "0.10.0"
# esp-idf-hal = { version = "0.45.2", features = ["std"] }
[build-dependencies] [build-dependencies]
embuild = "0.33" embuild = "0.33"

Binary file not shown.

View File

@ -1,13 +1,87 @@
fn main() { use anyhow::{bail, Result, Context, anyhow};
use esp_idf_svc::hal::delay::FreeRtos;
use esp_idf_svc::hal::i2c::{I2cConfig, I2cDriver};
use esp_idf_svc::hal::peripherals::Peripherals;
use esp_idf_svc::hal::delay::BLOCK;
use esp_idf_svc::hal::prelude::FromValueType;
use embedded_graphics::{
mono_font::{
ascii::{FONT_10X20, FONT_5X8, FONT_6X12, FONT_9X15},
MonoTextStyle, MonoTextStyleBuilder,
},
image::{Image, ImageRaw},
pixelcolor::BinaryColor,
prelude::*,
text::Text,
};
use ssd1306::{I2CDisplayInterface, Ssd1306, size::*, rotation::*};
use ssd1306::mode::DisplayConfig;
use std::thread;
use log::info;
const SSD1306_ADDRESS: u8 = 0x3c;
fn oled_task(mut i2c: I2cDriver) -> Result<()> {
info!("Staring OLED Task");
let interface = I2CDisplayInterface::new(i2c);
let mut display = Ssd1306::new(interface, DisplaySize128x64, DisplayRotation::Rotate0)
.into_buffered_graphics_mode();
display.init().unwrap();
let raw: ImageRaw<BinaryColor> = ImageRaw::new(include_bytes!("../rust.raw"), 64);
let im = Image::new(&raw, Point::new(32, 0));
im.draw(&mut display).unwrap();
display.flush().map_err(|e| anyhow!("Could not flush display! {:?}", e))?;
FreeRtos::delay_ms(3000);
loop {
display.clear(BinaryColor::Off).map_err(|e| anyhow!("Could not clear display! {:?}", e))?;
Text::new(
"PM 2.5: 4",
Point::new(20, 40),
MonoTextStyle::new(&FONT_10X20, BinaryColor::On),
).draw(&mut display).map_err(|e| anyhow!("Could not draw text! {:?}", e))?;
display.flush().map_err(|e| anyhow!("Could not flush display! {:?}", e))?;
FreeRtos::delay_ms(500);
}
}
fn main() -> Result<()> {
// It is necessary to call this function once. Otherwise some patches to the runtime // It is necessary to call this function once. Otherwise some patches to the runtime
// implemented by esp-idf-sys might not link properly. See https://github.com/esp-rs/esp-idf-template/issues/71 // implemented by esp-idf-sys might not link properly. See https://github.com/esp-rs/esp-idf-template/issues/71
esp_idf_svc::sys::link_patches(); esp_idf_svc::sys::link_patches();
// Bind the log crate to the ESP Logging facilities // Initialize NVS
// esp_idf_hal::nvs::EspDefaultNvsPartition::take()
// .context("Could not take NVS partition")?;
esp_idf_svc::log::EspLogger::initialize_default(); esp_idf_svc::log::EspLogger::initialize_default();
loop { let peripherals = Peripherals::take()?;
log::info!("Hello, world!"); let i2c = peripherals.i2c0;
std::thread::sleep(std::time::Duration::from_secs(1)); let sda = peripherals.pins.gpio21;
let scl = peripherals.pins.gpio22;
let config = I2cConfig::new().baudrate(100.kHz().into());
let i2c = I2cDriver::new(i2c, sda, scl, &config)?;
let handles = vec! [
thread::spawn(move || {
if let Err(e) = oled_task(i2c) {
log::error!("OLED Task Error: {:?}", e);
}
}),
// thread::spawn(move || {
// }),
];
for h in handles {
h.join().unwrap();
} }
Ok(())
} }