embedded_drivers/
pmsx003.rs

1//! PMSx003, High Precision Laser Dust Sensor Module PM1.0 PM2.5 PM10 sensors.
2//!
3//!
4
5use core::convert::TryInto;
6use embedded_hal::serial;
7use nb::block;
8
9const PREFIX1: u8 = 0x42;
10const PREFIX2: u8 = 0x4d;
11
12pub struct PMSx003<S> {
13    serial: S,
14}
15
16pub struct Measurements {
17    pub cf1_pm1_0: u16,
18    pub cf1_pm2_5: u16,
19    pub cf1_pm10: u16,
20    pub pm1_0: u16,
21    pub pm2_5: u16,
22    pub pm10: u16,
23    pub db0_3_um: u16,
24    pub db0_5_um: u16,
25    pub db1_0_um: u16,
26    pub db2_5_um: u16,
27    pub db5_0_um: u16,
28    pub db10_um: u16,
29}
30
31impl Measurements {
32    // When the sensor is just started, all db*-um data will be zero.
33    pub fn is_ready(&self) -> bool {
34        self.db0_3_um != 0 || self.db0_5_um != 0 || self.db1_0_um != 0
35    }
36}
37
38impl<S> PMSx003<S>
39where
40    S: serial::Read<u8> + serial::Write<u8>,
41{
42    pub fn new(serial: S) -> Self {
43        Self { serial }
44    }
45
46    pub fn read_measurements(&mut self) -> Result<Measurements, ()> {
47        // NOTE: 0x00_1c = 28, number of remaining bytes
48        const PREFIX: [u8; 4] = [PREFIX1, PREFIX2, 0x00, 0x1c];
49
50        let mut i = 0;
51        let mut buf = [0u8; 26];
52        let mut checksum: u16 = 0;
53
54        loop {
55            let c = self.must_read_byte();
56            match i {
57                0..=3 if c == PREFIX[i] => {
58                    checksum += c as u16;
59                    i += 1;
60                }
61                4..=29 => {
62                    checksum += c as u16;
63                    buf[i - 4] = c;
64                    i += 1;
65                }
66                30 if c == (checksum >> 8) as u8 => {
67                    i += 1;
68                }
69                31 if c == (checksum & 0xff) as u8 => {
70                    break;
71                }
72                _ => {
73                    i = 0;
74                    checksum = 0;
75                }
76            }
77        }
78
79        Ok(Measurements {
80            cf1_pm1_0: u16::from_be_bytes(buf[0..2].try_into().unwrap()),
81            cf1_pm2_5: u16::from_be_bytes(buf[2..4].try_into().unwrap()),
82            cf1_pm10: u16::from_be_bytes(buf[4..6].try_into().unwrap()),
83            pm1_0: u16::from_be_bytes(buf[6..8].try_into().unwrap()),
84            pm2_5: u16::from_be_bytes(buf[8..10].try_into().unwrap()),
85            pm10: u16::from_be_bytes(buf[10..12].try_into().unwrap()),
86            db0_3_um: u16::from_be_bytes(buf[12..14].try_into().unwrap()),
87            db0_5_um: u16::from_be_bytes(buf[14..16].try_into().unwrap()),
88            db1_0_um: u16::from_be_bytes(buf[16..18].try_into().unwrap()),
89            db2_5_um: u16::from_be_bytes(buf[18..20].try_into().unwrap()),
90            db5_0_um: u16::from_be_bytes(buf[20..22].try_into().unwrap()),
91            db10_um: u16::from_be_bytes(buf[22..24].try_into().unwrap()),
92        })
93    }
94
95    pub fn release(self) -> S {
96        self.serial
97    }
98
99    fn must_read_byte(&mut self) -> u8 {
100        loop {
101            if let Ok(b) = self.read_byte() {
102                return b;
103            }
104        }
105    }
106
107    fn read_byte(&mut self) -> Result<u8, ()> {
108        block!(self.serial.read()).map_err(|_| ())
109    }
110}