Crates.io | pmsx003 |
lib.rs | pmsx003 |
version | 1.0.0 |
created_at | 2025-09-18 07:57:29.168787+00 |
updated_at | 2025-09-18 07:57:29.168787+00 |
description | Rust interface for PMS X003 air quality sensors |
homepage | |
repository | https://github.com/lomagno2003/pmsx003-rs |
max_upload_size | |
id | 1844378 |
size | 23,395 |
A no_std
Rust driver for Plantower PMS X003 series air quality sensors, including PMS5003, PMS7003, and other compatible models.
no_std
compatible - Perfect for embedded systemsThis driver supports the Plantower PMS X003 series of air quality sensors:
Add this to your Cargo.toml
:
[dependencies]
pmsx003 = "1.0.0"
embedded-hal = "1.0.0"
embedded-hal-nb = "1.0.0"
nb = "1.0.0"
use pmsx003::{PmsX003Sensor, OutputFrame};
use embedded_hal_nb::serial::{Read, Write};
// Create sensor with a combined serial interface
let mut sensor = PmsX003Sensor::new(serial);
// Read air quality data
match sensor.read() {
Ok(frame) => {
println!("PM1.0: {} μg/m³", frame.pm1_0);
println!("PM2.5: {} μg/m³", frame.pm2_5);
println!("PM10: {} μg/m³", frame.pm10);
}
Err(e) => println!("Error reading sensor: {:?}", e),
}
// Create sensor with separate TX and RX interfaces
let mut sensor = PmsX003Sensor::new_tx_rx(tx, rx);
// Same usage as above
let frame = sensor.read()?;
// Put sensor in passive mode (request data manually)
sensor.passive()?;
sensor.request()?;
let frame = sensor.read()?;
// Put sensor in active mode (continuous data)
sensor.active()?;
loop {
let frame = sensor.read()?;
// Process data...
}
// Power management
sensor.sleep()?; // Put sensor to sleep
sensor.wake()?; // Wake up sensor
The OutputFrame
struct contains all sensor measurements:
pub struct OutputFrame {
pub pm1_0: u16, // PM1.0 concentration (μg/m³)
pub pm2_5: u16, // PM2.5 concentration (μg/m³)
pub pm10: u16, // PM10 concentration (μg/m³)
pub pm1_0_atm: u16, // PM1.0 atmospheric environment (μg/m³)
pub pm2_5_atm: u16, // PM2.5 atmospheric environment (μg/m³)
pub pm10_atm: u16, // PM10 atmospheric environment (μg/m³)
pub beyond_0_3: u16, // Particles > 0.3μm per 0.1L air
pub beyond_0_5: u16, // Particles > 0.5μm per 0.1L air
pub beyond_1_0: u16, // Particles > 1.0μm per 0.1L air
pub beyond_2_5: u16, // Particles > 2.5μm per 0.1L air
pub beyond_5_0: u16, // Particles > 5.0μm per 0.1L air
pub beyond_10_0: u16, // Particles > 10.0μm per 0.1L air
// ... other fields
}
The driver provides comprehensive error handling:
use pmsx003::Error;
match sensor.read() {
Ok(frame) => { /* Process data */ }
Err(Error::ChecksumError) => println!("Data corruption detected"),
Err(Error::ReadFailed) => println!("Serial read failed"),
Err(Error::SendFailed) => println!("Serial write failed"),
Err(Error::IncorrectResponse) => println!("Unexpected sensor response"),
Err(Error::NoResponse) => println!("Sensor not responding"),
}
use esp_hal::{
gpio::Io,
uart::{config::Config, Uart},
prelude::*,
};
use pmsx003::PmsX003Sensor;
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
let uart = Uart::new_with_config(
peripherals.UART1,
Config::default(),
Some(io.pins.gpio4), // TX
Some(io.pins.gpio5), // RX
&clocks,
)?;
let mut sensor = PmsX003Sensor::new(uart);
let frame = sensor.read()?;
use stm32f4xx_hal::{
pac,
prelude::*,
serial::{config::Config, Serial},
};
use pmsx003::PmsX003Sensor;
let dp = pac::Peripherals::take().unwrap();
let gpioa = dp.GPIOA.split();
let rcc = dp.RCC.constrain();
let clocks = rcc.cfgr.freeze();
let tx = gpioa.pa2.into_alternate();
let rx = gpioa.pa3.into_alternate();
let serial = Serial::new(
dp.USART2,
(tx, rx),
Config::default().baudrate(9600.bps()),
&clocks,
)?;
let mut sensor = PmsX003Sensor::new(serial);
let frame = sensor.read()?;
Connect your PMS X003 sensor to your microcontroller:
PMS X003 Pin | Function | MCU Pin |
---|---|---|
VCC | Power | 5V |
GND | Ground | GND |
TXD | Data out | RX |
RXD | Data in | TX |
SET | Sleep | GPIO (optional) |
RESET | Reset | GPIO (optional) |
Note: The sensor's TXD connects to your MCU's RX, and sensor's RXD connects to your MCU's TX.
The driver handles the PMS X003 communication protocol automatically:
If you're upgrading from an older version:
Pms7003Sensor
→ PmsX003Sensor
scroll
dependency removed (zero external deps)// Old (v0.x)
use pmsx003::Pms7003Sensor;
let sensor = Pms7003Sensor::new(serial);
// New (v1.x)
use pmsx003::PmsX003Sensor;
let sensor = PmsX003Sensor::new(serial);
Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the MIT License - see the LICENSE file for details.