73 lines
2.2 KiB
Rust
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);
|
|
}
|
|
}
|