73 lines
2.2 KiB
Rust

use crate::Pms7003Data;
use anyhow::Result;
use log::{info, warn};
use std::sync::{Arc, Mutex};
use esp_idf_svc::hal::{
delay::{FreeRtos, BLOCK},
uart::UartDriver,
};
// 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];
let checksum: u16 = command.iter().take(5).copied().map(u16::from).sum();
command[5] = ((checksum >> 8) & 0xFF) as u8;
command[6] = (checksum & 0xFF) as u8;
uart.write(&command)?;
Ok(())
}
pub fn sensors_task(pm_data: Arc<Mutex<Pms7003Data>>, uart: &UartDriver) -> Result<()> {
info!("Staring UART PM Sensor Task");
send_pms7003_command(uart, 0xE1, 0x00, 0x00)?;
loop {
send_pms7003_command(uart, 0xE2, 0x00, 0x00)?;
let mut buf = [0_u8; 32];
let len = uart.read(&mut buf, BLOCK)?;
if len > 0 {
if let Some(data) = read_pm_data(&buf) {
let mut pm_data = pm_data.lock().unwrap();
*pm_data = data;
}
} else {
// info!("No bytes read");
}
uart.clear_rx()?;
FreeRtos::delay_ms(5000);
}
}