Crates.io | sds011-rs |
lib.rs | sds011-rs |
version | |
source | src |
created_at | 2024-07-15 17:35:46.429244 |
updated_at | 2024-07-15 17:35:46.429244 |
description | A driver for the SDS011 particle sensor based on embedded-io. |
homepage | |
repository | https://github.com/kenohassler/sds011-rs |
max_upload_size | |
id | 1304084 |
size | 0 |
This crate implements an embedded-io driver for the SDS011 particle sensor. Thanks to this abstraction layer, it can be used on full-fledged operating systems as well as embedded devices.
The crate ships with two small CLI binaries that utilize the library:
The example below demonstrates how to use the sensor with an ESP32, showcasing the strength of the embedded-hal abstractions.
#![no_std]
#![no_main]
use embassy_executor::Spawner;
use embassy_time::{Duration, Timer, Delay};
use esp_backtrace as _;
use esp_hal::{
clock::ClockControl,
gpio::Io,
peripherals::Peripherals,
prelude::*,
system::SystemControl,
timer::timg::TimerGroup,
uart::{config::Config, TxRxPins, Uart},
};
use esp_println::println;
use sds011::SDS011;
#[main]
async fn main(_s: Spawner) -> ! {
let peripherals = Peripherals::take();
let system = SystemControl::new(peripherals.SYSTEM);
let clocks = ClockControl::max(system.clock_control).freeze();
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
esp_hal_embassy::init(&clocks, timg0);
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
let pins = TxRxPins::new_tx_rx(io.pins.gpio17, io.pins.gpio16);
let mut uart0 = Uart::new_async_with_config(
peripherals.UART0,
Config::default().baudrate(9600),
Some(pins),
&clocks,
);
uart0
.set_rx_fifo_full_threshold(sds011::READ_BUF_SIZE as u16)
.unwrap();
let sds011 = SDS011::new(&mut uart0, sds011::Config::default());
let mut sds011 = sds011.init(&mut Delay).await.unwrap();
loop {
let dust = sds011.measure(&mut Delay).await.unwrap();
println!("{}", dust);
Timer::after(Duration::from_millis(30_000)).await;
}
}
The sensor has two operating modes:
We abstract this into the following interface:
new()
is in "Uninitialized" state.
No serial communication is performed during creation.init()
. This will return a sensor in "Polling" state.
The sensor is instructed via serial commands to switch to query mode and
goes to sleep (fan off). This operation may fail.measure()
function.
This will wake the sensor, spin the fan for a configurable duration
(which is necessary to get a correct measurement), read the sensor and
put it back to sleep. This operation may fail.make_periodic
on a sensor in "Polling" state.
This puts the sensor in charge of sleeping and waking up.
Since it will continuously produce data, make sure to call measure()
in time so the serial output buffer does not overflow.This abstraction does not yet support sending commands only to a specific sensor id (it effectively uses broadcast mode all the time). This feature seemed irrelevant, but the backend code for it is completely implemented, so this may change in a future version if there is demand. Also, putting sensors into periodic mode can have the side effect of missing package boundaries. The current version cannot recover from this; it will return an error. Close the serial port and retry, or probably better, just don't use periodic mode.
Thank you to Tim Orme, who implemented sds011lib in Python and wrote documentation that pointed me in the right direction, especially to:
License: MIT OR Apache-2.0