We spend most of our lives indoors — but how often do we actually think about the air we’re breathing? CO₂ buildup, VOCs from furniture, humidity swings, and invisible pollutants all quietly affect focus, sleep, and long-term health. With a Raspberry Pi, a few cheap sensors, and a touch of machine learning, you can build a Smart Air Quality Monitor that tracks your environment 24/7 and pings your phone the moment something’s off.

Perfect for health-conscious makers, home office dwellers, and small businesses who want a healthier workspace.

What You’ll Need

Grab the following:

  • Raspberry Pi 4 (2GB or more) — 4GB is comfortable overkill
  • MicroSD card (32GB+) with Raspberry Pi OS (64-bit)
  • BME280 sensor — temperature, humidity, pressure (I²C)
  • MQ-135 sensor — general air quality / VOCs / CO₂ proxy
  • SGP30 or CCS811 sensor (optional) — more accurate eCO₂ and TVOC readings
  • PMS5003 sensor (optional) — PM2.5 and PM10 particulate matter
  • MCP3008 ADC chip — needed to read the analog MQ-135
  • Breadboard + jumper wires
  • Official Raspberry Pi power supply
  • Small case with ventilation holes (airflow matters!)
  • Wi-Fi connection

Step 1: Prepare the Raspberry Pi

Flash Raspberry Pi OS (64-bit), boot up, connect to Wi-Fi, and update:

bash
sudo apt update && sudo apt full-upgrade -y
sudo apt install python3-pip python3-smbus i2c-tools -y
pip3 install adafruit-circuitpython-bme280 adafruit-circuitpython-mcp3xxx flask pandas scikit-learn requests

Enable I²C and SPI via sudo raspi-config → Interface Options, then reboot.

Confirm your sensors are detected:

bash
i2cdetect -y 1

Step 2: Wire Up the Sensors

BME280 (I²C):

  • VCC → 3.3V
  • GND → GND
  • SDA → GPIO 2
  • SCL → GPIO 3

MQ-135 via MCP3008 (SPI):

  • MQ-135 AOUT → MCP3008 CH0
  • MCP3008 → 3.3V, GND, CLK (GPIO 11), MISO (GPIO 9), MOSI (GPIO 10), CS (GPIO 8)

PMS5003 (optional): connects via USB-to-serial or directly to the Pi’s UART pins.

Keep sensors away from direct heat sources like the Pi’s CPU — heat skews temperature and humidity readings badly.

Step 3: Write the Sensor Reading Script

Create monitor.py to poll your sensors every minute and log data to a CSV + SQLite database:

python
import time, sqlite3, board, busio
from adafruit_bme280 import basic as bme280
import digitalio, adafruit_mcp3xxx.mcp3008 as MCP
from adafruit_mcp3xxx.analog_in import AnalogIn

i2c = busio.I2C(board.SCL, board.SDA)
bme = bme280.Adafruit_BME280_I2C(i2c, address=0x76)

spi = busio.SPI(clock=board.SCK, MISO=board.MISO, MOSI=board.MOSI)
cs = digitalio.DigitalInOut(board.D8)
mcp = MCP.MCP3008(spi, cs)
mq135 = AnalogIn(mcp, MCP.P0)

db = sqlite3.connect("air.db")
db.execute("""CREATE TABLE IF NOT EXISTS readings
              (ts TEXT, temp REAL, humidity REAL, pressure REAL, voc REAL)""")

while True:
    t = bme.temperature
    h = bme.humidity
    p = bme.pressure
    v = mq135.value
    db.execute("INSERT INTO readings VALUES (?,?,?,?,?)",
               (time.strftime("%Y-%m-%d %H:%M:%S"), t, h, p, v))
    db.commit()
    print(f"{t:.1f}°C  {h:.0f}%  {p:.0f}hPa  VOC:{v}")
    time.sleep(60)

Step 4: Add AI-Powered Anomaly Detection

Instead of dumb fixed thresholds, let a simple ML model learn your normal baseline and alert you when things drift.

Use Isolation Forest from scikit-learn — lightweight and perfect for spotting weird air quality patterns:

python
from sklearn.ensemble import IsolationForest
import pandas as pd

df = pd.read_sql("SELECT temp, humidity, voc FROM readings", sqlite3.connect("air.db"))
model = IsolationForest(contamination=0.05).fit(df)

def is_anomaly(temp, hum, voc):
    return model.predict([[temp, hum, voc]])[0] == -1

Retrain it weekly on your latest data so it adapts to seasons and daily rhythms.

Step 5: Send Smart Alerts to Your Phone

Hook it up to Telegram for instant notifications:

python
import requests
def alert(msg):
    requests.post("https://api.telegram.org/bot<TOKEN>/sendMessage",
                  data={"chat_id": "<CHAT_ID>", "text": f"⚠️ Air Alert: {msg}"})

Trigger an alert whenever is_anomaly() returns True, or when values cross health-based limits (e.g., humidity <30% or >60%, VOC spikes, CO₂ > 1000 ppm).

Step 6: Build a Live Dashboard

A quick Flask + Chart.js dashboard lets you visualize trends from any device:

python
from flask import Flask, render_template_string
import sqlite3

app = Flask(__name__)

@app.route("/")
def home():
    db = sqlite3.connect("air.db")
    rows = db.execute("SELECT ts, temp, humidity, voc FROM readings ORDER BY ts DESC LIMIT 100").fetchall()
    return render_template_string("""
    <h1>🌿 Air Quality Monitor</h1>
    <table border=1 cellpadding=5>
    <tr><th>Time</th><th>Temp</th><th>Humidity</th><th>VOC</th></tr>
    {% for r in rows %}<tr><td>{{r[0]}}</td><td>{{r[1]}}</td><td>{{r[2]}}</td><td>{{r[3]}}</td></tr>{% endfor %}
    </table>
    """, rows=rows)

app.run(host="0.0.0.0", port=5000)

Open http://<your-pi-ip>:5000 on any device to see live readings. For fancier graphs, pipe data into Grafana + InfluxDB — a popular combo for IoT dashboards.

Step 7: Auto-Start on Boot

Wrap both scripts in systemd services so the Pi starts monitoring automatically after power cuts. Set it, forget it, breathe easier.

Tips for Accurate Readings

  • Let the MQ-135 “burn in” for 24–48 hours before trusting its numbers
  • Place the monitor at head height, away from windows and vents
  • Avoid direct sunlight — it cooks sensors and skews temperature
  • Ventilate the case — stagnant air = useless readings
  • Calibrate periodically by comparing against a known reference meter

Wrapping Up

You’ve just built a private, intelligent air quality monitor that doesn’t just log numbers — it actually learns what your home normally feels like and warns you when something changes. Expand it with outdoor sensors, room-by-room units, or automate your air purifier to switch on when VOCs spike.

Because the first step to breathing better… is knowing what you’re breathing. 🌬️💚


Loved this project? Follow @raspitips on Instagram for more Raspberry Pi builds, tips, and tutorials.

Leave A Comment

Related Posts