#embedded-hal-async #embedded-hal #async #embedded-io #sensor #devices #embedded-devices

nightly no-std sds011-rs

基于 embedded-io 的 SDS011 粒子传感器的驱动程序

6 个版本

0.3.2 2024年7月29日
0.3.1 2024年7月22日
0.2.1 2024年7月20日
0.1.0 2024年7月15日

#175硬件支持

Download history 95/week @ 2024-07-12 395/week @ 2024-07-19 179/week @ 2024-07-26 17/week @ 2024-08-02

每月595 次下载

MIT/Apache

39KB
725

sds011-rs

该Crate实现了基于 embedded-hal 的SDS011粒子传感器的驱动程序。多亏了这个抽象层,它可以在完整的操作系统以及嵌入式设备上使用。

功能

  • sync:要使用同步接口,启用此功能。默认情况下,此库公开异步API。

示例

该Crate附带两个小型CLI示例,这些示例使用库

  • cli.rs 使用同步接口(embedded-io),
  • cli_async.rs 使用异步接口(embedded-io-async)。

下面的示例演示了如何使用ESP32与传感器一起使用,展示了 embedded-hal 抽象的强大之处。

#![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;
    }
}

技术概述

该传感器有两种操作模式

  • "查询模式":传感器什么也不做,直到它被主动指令执行测量(我们称之为轮询)。
  • "主动模式":传感器以可配置的间隔持续产生数据(我们称之为周期性)。

我们将此抽象为以下接口

  • 使用 new() 创建的传感器处于 Uninitialized 状态。在创建过程中不执行串行通信。
  • 您调用 init()。这将返回一个处于 Polling 状态的传感器。传感器通过串行命令切换到查询模式并进入睡眠状态(风扇关闭)。
  • 现在可以通过 measure() 函数查询传感器。这将唤醒传感器,以可配置的时间旋转风扇(这对于获得正确的测量值是必要的),读取传感器并将其放回睡眠状态。
  • 可选(不推荐!)的情况下,可以通过在Polling状态的传感器上调用make_periodic()将传感器置于Periodic状态。这将使传感器负责睡眠和唤醒。由于它将连续产生数据,请确保及时调用measure(),以免串行输出缓冲区溢出。

限制

此抽象尚不支持仅向特定传感器ID发送命令(它实际上始终使用广播模式)。此功能似乎不相关,但其后端代码已完全实现,因此如果需求存在,未来版本可能会进行更改。此外,将传感器置于周期模式可能会产生丢失包边界的副作用。当前版本无法从中恢复;它将返回错误。请关闭串行端口并重试,或者可能更好的办法是根本不要使用周期模式。

致谢

感谢Tim Orme,他在Python中实现了sds011lib,并编写了文档,为我指明了正确的方向,特别是

关于SDS011传感器。

许可证:MIT OR Apache-2.0

依赖关系

~0.4–0.8MB
~18K SLoC