David GherghitaIoan Herisanu
Published © GPL3+

Air Quality Monitor using Raspberry Pi 4, SPS30 and Azure

Connect a particulate matter sensor to a Raspberry Pi and obtain easy-to-read graphs based on the read data using Microsoft Azure.

IntermediateProtip5 hours51,046
Air Quality Monitor using Raspberry Pi 4, SPS30 and Azure

Things used in this project

Hardware components

Sensirion SPS30
Raspberry Pi 4 Model B
Raspberry Pi 4 Model B
Breadboard (generic)
Breadboard (generic)
Jumper wires (generic)
Jumper wires (generic)

Software apps and online services

Rust Programming Language
Microsoft Azure
Microsoft Azure
Yocto Project
Yocto Project


Read more



Photo of the circuit on a breadboard.



Rust program called by the Python script to print data from the sensor to the screen.
use linux_embedded_hal::{Delay, I2cdev};
use sps30_i2c::Sps30;

fn main() {
    let dev = I2cdev::new("/dev/i2c-1").unwrap();
    let delay = Delay;
    let mut sensor = Sps30::new_sps30(dev, delay);

    let result = sensor.read_measured_values().unwrap();

    println!("{}", result.mass_pm1_0);
    println!("{}", result.mass_pm2_5);
    println!("{}", result.mass_pm4_0);
    println!("{}", result.mass_pm10);

    println!("{}", result.number_pm0_5);
    println!("{}", result.number_pm1_0);
    println!("{}", result.number_pm2_5);
    println!("{}", result.number_pm4_0);
    println!("{}", result.number_pm10);

    println!("{}", result.typical_size);


Python script to get data from the Rust program and send it to the Azure cloud.

import os
import asyncio
from azure.iot.device.aio import IoTHubDeviceClient
from azure.iot.device import Message
import time
import subprocess

async def main():
	# Connect device to IoT Hub
	conn_str = "TODO"
	device_client = IoTHubDeviceClient.create_from_connection_string(conn_str)
	await device_client.connect()

	while True:
		# Read data from sensor
		cmd = ['sensor-read/target/release/sensor-read']
		process = subprocess.Popen(cmd, stdout=subprocess.PIPE)

		results = []
		for line in process.stdout:

		# Send message
		msg = Message('{\
			"mass_pm1.0": %f,\
			"mass_pm2.5": %f,\
			"mass_pm4.0": %f,\
			"mass_pm10": %f,\
			"number_pm0.5": %f,\
			"number_pm1.0": %f,\
			"number_pm2.5": %f,\
			"number_pm4.0": %f,\
			"number_pm10": %f,\
			"typical_size": %f,\
		}' % tuple(results))
		await device_client.send_message(msg)


if __name__ == "__main__":

Yocto layer

Yocto layer for configuring the distro.


David Gherghita

David Gherghita

2 projects • 1 follower
Ioan Herisanu

Ioan Herisanu

1 project • 1 follower