📟 pmme-device: PM2.5 is now being read and written to an ArcMutex
This commit is contained in:
parent
8e6fc96e4d
commit
d87215bebd
@ -22,9 +22,31 @@ use ssd1306::{I2CDisplayInterface, Ssd1306, size::*, rotation::*};
|
||||
use ssd1306::mode::DisplayConfig;
|
||||
|
||||
use std::thread;
|
||||
use log::info;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use log::{info, warn};
|
||||
|
||||
fn oled_task(i2c: I2cDriver) -> Result<()> {
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct Pms7003Data {
|
||||
// PM concentrations (CF=1, standard particle) in μg/m³
|
||||
pub pm1_0_cf1: u16,
|
||||
pub pm2_5_cf1: u16,
|
||||
pub pm10_cf1: u16,
|
||||
|
||||
// PM concentrations (atmospheric environment) in μg/m³
|
||||
pub pm1_0_atm: u16,
|
||||
pub pm2_5_atm: u16,
|
||||
pub pm10_atm: u16,
|
||||
|
||||
// Particle counts (particles per 0.1L air)
|
||||
pub particles_0_3um: u16,
|
||||
pub particles_0_5um: u16,
|
||||
pub particles_1_0um: u16,
|
||||
pub particles_2_5um: u16,
|
||||
pub particles_5_0um: u16,
|
||||
pub particles_10um: u16,
|
||||
}
|
||||
|
||||
fn oled_task(pm_data: Arc<Mutex<Pms7003Data>>, i2c: I2cDriver) -> Result<()> {
|
||||
info!("Staring OLED Task");
|
||||
|
||||
let interface = I2CDisplayInterface::new(i2c);
|
||||
@ -39,11 +61,12 @@ fn oled_task(i2c: I2cDriver) -> Result<()> {
|
||||
im.draw(&mut display).unwrap();
|
||||
display.flush().map_err(|e| anyhow!("Could not flush display! {:?}", e))?;
|
||||
|
||||
FreeRtos::delay_ms(3000);
|
||||
FreeRtos::delay_ms(2000);
|
||||
loop {
|
||||
let current_pm_data = pm_data.lock().unwrap().clone();
|
||||
display.clear(BinaryColor::Off).map_err(|e| anyhow!("Could not clear display! {:?}", e))?;
|
||||
Text::new(
|
||||
"PM 2.5: 4",
|
||||
&format!("PM 2.5: {}", current_pm_data.pm2_5_atm),
|
||||
Point::new(20, 40),
|
||||
MonoTextStyle::new(&FONT_10X20, BinaryColor::On),
|
||||
).draw(&mut display).map_err(|e| anyhow!("Could not draw text! {:?}", e))?;
|
||||
@ -52,6 +75,32 @@ fn oled_task(i2c: I2cDriver) -> Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
// u16::from_be_bytes is too verbose
|
||||
fn get_u16(buf: &[u8]) -> u16 { ((buf[0] as u16) << 8) | buf[1] as u16 }
|
||||
|
||||
fn read_pm_data(buf: &[u8; 32]) -> Option<Pms7003Data> {
|
||||
let checksum: u16 = buf.iter().take(29).copied().map(u16::from).sum();
|
||||
let csum_target = get_u16(&buf[30..32]);
|
||||
if checksum != csum_target {
|
||||
warn!("Checksum from PMS7003 READ does not match, skipping read");
|
||||
return None
|
||||
}
|
||||
Some(Pms7003Data {
|
||||
pm1_0_cf1: get_u16(&buf[ 4..6 ]),
|
||||
pm2_5_cf1: get_u16(&buf[ 6..8 ]),
|
||||
pm10_cf1: get_u16(&buf[ 8..10]),
|
||||
pm1_0_atm: get_u16(&buf[10..12]),
|
||||
pm2_5_atm: get_u16(&buf[12..14]),
|
||||
pm10_atm: get_u16(&buf[14..16]),
|
||||
particles_0_3um: get_u16(&buf[16..18]),
|
||||
particles_0_5um: get_u16(&buf[18..20]),
|
||||
particles_1_0um: get_u16(&buf[20..22]),
|
||||
particles_2_5um: get_u16(&buf[22..24]),
|
||||
particles_5_0um: get_u16(&buf[24..26]),
|
||||
particles_10um: get_u16(&buf[26..28]),
|
||||
})
|
||||
}
|
||||
|
||||
fn send_pms7003_command(uart: &UartDriver, cmd: u8, datah: u8, datal: u8) -> Result<()> {
|
||||
let mut command = [0x42u8, 0x4D, cmd, datah, datal, 0, 0];
|
||||
|
||||
@ -66,23 +115,23 @@ fn send_pms7003_command(uart: &UartDriver, cmd: u8, datah: u8, datal: u8) -> Res
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn pm_sensor_task(uart: &UartDriver) -> Result<()> {
|
||||
fn pm_sensor_task(pm_data: Arc<Mutex<Pms7003Data>>, uart: &UartDriver) -> Result<()> {
|
||||
info!("Staring UART PM Sensor Task");
|
||||
|
||||
send_pms7003_command(uart, 0xE1, 0x00, 0x00)?;
|
||||
|
||||
let mut buf = [0_u8; 32];
|
||||
loop {
|
||||
send_pms7003_command(uart, 0xE2, 0x00, 0x00)?;
|
||||
|
||||
let mut buf = [0_u8; 32];
|
||||
let len = uart.read(&mut buf, BLOCK)?;
|
||||
if len > 0 {
|
||||
info!("Read some bytes! {}", len);
|
||||
for i in 0..len {
|
||||
info!("0x{:02x}", buf[i]);
|
||||
if let Some(data) = read_pm_data(&buf) {
|
||||
let mut pm_data = pm_data.lock().unwrap();
|
||||
*pm_data = data;
|
||||
}
|
||||
} else {
|
||||
info!("No bytes read");
|
||||
// info!("No bytes read");
|
||||
}
|
||||
uart.clear_rx()?;
|
||||
FreeRtos::delay_ms(5000);
|
||||
@ -120,14 +169,19 @@ fn main() -> Result<()> {
|
||||
&config,
|
||||
)?;
|
||||
|
||||
let pm_data = Arc::new(Mutex::new(Pms7003Data::default()));
|
||||
|
||||
let pm_data1 = Arc::clone(&pm_data);
|
||||
let pm_data2 = Arc::clone(&pm_data);
|
||||
|
||||
let handles = vec! [
|
||||
thread::spawn(move || {
|
||||
if let Err(e) = oled_task(i2c) {
|
||||
if let Err(e) = oled_task(pm_data1, i2c) {
|
||||
log::error!("OLED Task Error: {:?}", e);
|
||||
}
|
||||
}),
|
||||
thread::spawn(move || {
|
||||
if let Err(e) = pm_sensor_task(&uart) {
|
||||
if let Err(e) = pm_sensor_task(pm_data2, &uart) {
|
||||
log::error!("PM Sensor Task Error: {:?}", e);
|
||||
}
|
||||
}),
|
||||
|
Loading…
x
Reference in New Issue
Block a user