Skip to content

Monitoring air quality (CO2, temperature, humidity and TVOC) with a Raspberry Pi, an MH-Z19 and an VMA342 sensor.

Notifications You must be signed in to change notification settings

StijnGoossens/rpi-airquality

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Air quality monitoring with Raspberry Pi

In this project, we'll monitor several parameters of indoor air quality with a Raspberry Pi and the following sensors:

  • MH-Z19 -> CO2
  • VMA342, consisting of:
    • BME280 -> temperature + humidity + air pressure
    • CCS811 -> volatile organic compounds (TVOC) [Work in progress]


A Streamlit dashboard will allow you to monitor the current air quality as well as the evolution over time:

Requirements

  • Raspberry Pi*, including:
    • MicroSD card
    • Micro USB power cable and adapter
    • Protective case
    • WiFi dongle (for RPi's older than model 3)
  • VMA342 sensor
  • MH-Z19 sensor**
  • Small breadboard
  • Jumper cables (male-female)
  • Ethernet cable for the initial setup

*I used a Raspberry Pi model 2B for this project. Other models likely work as well, but weren't tested.

**The MH-Z19 sensor comes in multiple versions. I used the MH-Z19B. The mh-z19 python library seems to support at least the MH-Z19 and MH-Z19B. If your sensor doesn't come with output pins (like mine), you'll have to solder some stacking headers yourself.

General Raspberry Pi setup

Install OS and activate SSH

  1. Install Raspberry Pi Imager.
  2. Insert micro SD card and install the Raspberry Pi OS using Raspberry Pi Imager.
  3. Add “SSH” File to the SD Card Root (touch /Volumes/boot/ssh).
  4. Insert the SD card, connect your computer and Pi with an ethernet cable and boot the Pi by plugging in the power cord.
  5. Connect with the Pi via SSH: ssh pi@raspberrypi.local, default password = raspberry.

Connect the RPi to WiFi

The following steps will allow you to SSH into your Raspberry Pi over Wifi instead of over ethernet.

  1. On the Pi, edit the wpa_supplicant.conf file by adding your Wifi networks ssid and password as shown below:

sudo nano /etc/wpa_supplicant/wpa_supplicant.conf

Add the following content:

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=be                                           

network={
    ssid="my-ssid"
    psk="my-password"
}
  1. sudo reboot
  2. Check the WiFi connection: ifconfig wlan0 An IP address should be visible if the connection was successful.

Wiring the hardware

Connect the Raspberry Pi and MH-Z19 as follows:

RPi MH-Z19
5V Vin
GND GND
TXD Rx
RXD Tx

Note how the TXD and RXD are cross connected between the RPi and MH-Z19.

Connect the Raspberry Pi and VMA342 as follows:

RPi VMA342
3V3 3.3V
GND GND
SDA SDA
SCL SCL
GND WAKE

Project specific setup

Clone this repository in the Documents folder: cd Documents git clone https://github.com/StijnGoossens/rpi-airquality.git

Subsequently, install the packages below in order to interact with the sensors.

MH-Z19 (CO2)

  • Enable Serial via sudo raspi-config (source)

  • Install the mh-z19 package with sudo pip install mh-z19

VMA342

General

  • pip install wheel (not sure whether really required)
  • Install RPi.GPIO with export CFLAGS=-fcommon and pip3 install RPi.GPIO (source)
  • Enable I2C via sudo raspi-config (source)
  • Optionally adding the I2C module to the kernel: sudo nano /etc/modules and add i2c-dev to the end of the file.
  • Reduce the baudrate in order to make the sensor compatible with Raspberry Pi: sudo nano /boot/config.txt and add dtparam=i2c_arm_baudrate=10000 (source).

Tip: i2cdetect -y 1 shows the current I2C connections.

BME280 (temperature + humidity + air pressure)

  • sudo pip install RPi.bme280

Example to try out the CCS811 library:

import smbus2
import bme280

port = 1
address = 0x77
bus = smbus2.SMBus(port)

calibration_params = bme280.load_calibration_params(bus, address)

# the sample method will take a single reading and return a
# compensated_reading object
data = bme280.sample(bus, address, calibration_params)

# the compensated_reading class has the following attributes
print(data.id)
print(data.timestamp)
print(data.temperature)
print(data.pressure)
print(data.humidity)

# there is a handy string representation too
print(data)

CCS811 (TVOC + eCO2)

⚠️ STILL WIP. A BUG OCCURS WHEN READING OUT THE TVOC (and eCO2) VALUES

datasheet

  • pip3 install adafruit-circuitpython-ccs811

Example to try out the CCS811 library:

import board
import adafruit_ccs811

i2c = board.I2C()  # uses board.SCL and board.SDA
ccs811 = adafruit_ccs811.CCS811(i2c, 0x5b)

# Wait for the sensor to be ready
while not ccs811.data_ready:
    pass

while True:
    print("CO2: {} PPM, TVOC: {} PPB".format(ccs811.eco2, ccs811.tvoc))
    time.sleep(0.5)

Note that 0x5b is the I2C address of the CCS811 on the VMA342 board (default is 0x5a).

Streamlit

Optional

For some reason a tornado.iostream.StreamClosedError: Stream is closed error might occur after a running the Streamlit dashboard for a while. This can be resolved by increasing making the following changes to the Streamlit configuration:

  • Change the MESSAGE_SIZE_LIMIT parameter in site-packages\streamlit\server\server_util.py from 50 * 1e6 to 600 * 1e6.
  • Change the websocket_ping_timeout parameter in site-packages\streamlit\server\Server.py from 60 to 200.

Automatically run the scripts on startup

  • chmod 664 ~/Documents/rpi-airquality/src/monitor.pypi
  • Run crontab -e and append the following command to the bottom of the file:
@reboot (/bin/sleep 30; sudo python3 /home/pi/Documents/rpi-airquality/src/monitor.py > /home/pi/cronjoblog-monitor 2>&1)
@reboot (/bin/sleep 30; export PATH=$PATH:/home/pi/.local/bin; streamlit run /home/pi/Documents/rpi-airquality/src/dashboard.py > /home/pi/cronjoblog-dashboard 2>&1)
*/5 * * * * /bin/ping -c 2 www.google.com > /home/pi/cronjoblog-ping.txt 2>&1

This will start the monitoring script and Streamlit dashboard on startup. Logs will be printed to the specified files in the /home/pi/ folder. The third command will ping every five minutes in order to prevent the Raspberry Pi from losing internet connection ((source)[https://forums.raspberrypi.com/viewtopic.php?t=274966]).

Note that in order to streamlit to work from the cron job, the second statement adds the streamlit path to $PATH. This streamlit path can be found by running which streamlit. Which returns something like /home/pi/.local/bin/streamlit. Addapt the above line accordingly. The reason is that in cron, PATH is restricted to /bin:/usr/bin (source).

Extra: to make sure that the cron jobs have run, you can use the following command: grep CRON /var/log/syslog

Turn of the LED's of the Raspberry Pi (optional)

Raspberry Pi 3

  • Run crontab -e and append the following command to the bottom of the file (source):
@reboot (/bin/sleep 30; sudo sh -c 'echo 0 > /sys/class/leds/led0/brightness')
@reboot (/bin/sleep 30; sudo sh -c 'echo 0 > /sys/class/leds/led1/brightness')

Raspberry Pi 4

  • sudo nano /boot/config.txt
  • Add the following lines below the [Pi4] settings (source):
# Disable the PWR LED
dtparam=pwr_led_trigger=none
dtparam=pwr_led_activelow=off
# Disable the Activity LED
dtparam=act_led_trigger=none
dtparam=act_led_activelow=off
# Disable ethernet port LEDs
dtparam=eth_led0=4
dtparam=eth_led1=4
  • The lights will turn off once the Raspberry Pi has been restarted.

View dashboard

The Streamlit dashboard can be viewed from any device connected to the local network. Find out the IP address of the dashboard by viewing the log files of the dashboard script (nano /home/pi/cronjoblog-dashboard). In there, you should see some output like below. The network URL is what you need. http://raspberrypi.local:8501/ might also work.

You can now view your Streamlit app in your browser.
Network URL: http://192.168.0.247:8501
External URL: http://81.82.78.41:8501

About

Monitoring air quality (CO2, temperature, humidity and TVOC) with a Raspberry Pi, an MH-Z19 and an VMA342 sensor.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages