Raspberry Pi zero w zur Raumluft und Luftqualitätsüberwachung
Ich möchte hier zeigen wie man aus einem Raspberry Pi zero w, einem BME680 und TSL2561 Sensor eine kleine Raumklima Station für das Smart Home bauen kann. Hierzu möchte ich auf technischer Seite die Werte der beiden Sensoren auslesen und via MQTT an einen MQTT Broker schicken. Diesen binden wir dann in openHAB ein. Das Ganze wird mittels Homie MQTT Convention publiziert und kann so sehr einfach in die gängigen SmartHome Systeme eingebunden werden. Als "Gehäuse" für das Setup nutze ich eine Kunstoffpflanze und einen Kunstoff Übertopf (von IKEA), der Pi wird im Übertopf versteckt und die Sensoren kommen nach oben und werden in der Kunstoffpflanze so gut es geht ebenfalls versteckt.
Optional kann noch eine RGB LED als Warnleuchte für zu hohen CO2 Gehalt und zu hoher Luftfeuchtigkeit eingesetzt werden.
Kunstoffplanze und Übertopf konnte ich bei IKEA für 5 € kaufen. Der Pi zero liegt bei etwa 13€, eine 32 GB SD Karte bei etwa 8€ und USB Stromadapter bei etwa 3€. Beide Sensoren liegen bei etwa 20€. Also liegt man bei knapp 50€.
Der Stromverbrauch liegt zwischen 0,5 Watt im idle und im max bei 0,8 Watt. Was im Max einem Tagesverbrauch von 0,019 kWh entspricht. Im Jahr also 6,935 kWh also ca. 2€ Stromkosten / Jahr.
Verwendete Hardware / Material
- Raspberry Pi zero wh (beim wh ist der Header bereits drauf gelötet)
- Micro-USB Poweradapter
- Micro SD Card
- BME680 Sensor
- TSL2561 Sensor
- Kunstoffpflanze (IKEA Fejka, künstlich, Thymian)
- Kunstoff Übertopf (IKEA Nypon)
- Optional:
Anschluss der Sensoren
Als erstes schließen wir alles ordnungsgemäß an den Raspberry Pi zero w an. Um mehrere I2C Sensoren anschließen zu können nutzen wir einen I2C Hub und Grove to Femal Pin Kabel. Diese habe ich damit es schöner aussieht noch vorab in einen Schrumpfschlauch gepackt. Diesen kann man mit einem Gasfeuerzeug erwärmen, sollte man keinen geeigneten Heißluftföhn haben. Verkabelt wird dann wie folgt:
Kabel | I2C Hub Jumper | I2C Hub | to | Pin |
---|---|---|---|---|
Grove to Femal Pin Kabel 1 | J1 | G | Raspberry Pi GPIO Pin | Ground (Pin 9) |
V | 3.3 V (Pin 1) | |||
SDA | GPIO2 / SDA (Pin 3) | |||
SCL | GPIO3 / SCL (Pin 5) | |||
Grove to Femal Pin Kabel 2 | J2 | G | BME680 | GND |
V | VCC | |||
SDA | SDA | |||
SCL | SCL | |||
Grove to Femal Pin Kabel 3 | J3 | G | TSL2561 | GND |
V | VCC | |||
SDA | SDA | |||
SCL | SCL |
Fertig verkabelt, inklusive Micro USB Stromversorgung sieht das Ganze dann so aus:
Falls ihr keinen I2C Hub verwenden möchtet, könnt ihr auch die Variante nutzen, einen zweiten I2C Bus auf dem Raspberry Pi zu aktivieren.
Ansonsten geht es nun weiter mit der Installation.
Installation Raspberry Pi OS
Als erstes Installieren wir das Raspberry Pi OS Lite auf der SD Karte. Wir benötigen hierbei die folgenden Features:
- SSH beim Booten Aktivieren
- WLAN Verbindung beim Booten herstellen
Wie das geht, könnt ihr hier nachlesen.
Ziel ist es ein grundinstalliertes Raspberry Pi OS Lite auf der SD Karte zu haben, von der wir dann auch gleich booten können und über WLAN und SSH einen Fernzugriff auf den Pi hinbekommen.
Wenn ihr euch erfolgreich auf dem Raspberry Pi einloggen konntet, können wir diesen konfigurieren. Hierzu nutzen wir das Script rpi_autoconf.sh welches wir einfach in das Homeverzeichnis des pi
users laden und editieren:
cd && wget https://raw.githubusercontent.com/alaub81/rpi_autoconf/main/rpi_autoconf.sh
chmod 700 rpi_autoconf.sh
nano rpi_autoconf.sh
Wir konfigurieren hier das folgende:
## Pi's setup configuration
# Pi User new Password
PIPASSWORD="YOURPASS1234"
# Root User new Password
ROOTPASSWORD="YOURPASS1234"
# Raspberry Pi's hostname
PIHOSTNAME="YOURRASPI"
# the wifi Country
WIFICOUNTRY="DE"
# your Raspberry Pi's timezone
TIMEZONE="Europe/Berlin"
## True or False
# Disable Swap File (be carefull with that!)
SWAPDISABLE="True"
# Deinstallation of the avahi Daemon
AVAHIUNINSTALL="True"
# Deactivate USB Hub to save power (not working on Pi zero)
USBDISABLE="True"
# Disable Bluetooth to save power
BTDISABLE="True"
# Disable HDMI to save power
HDMIDISABLE="True"
# Disable Soundcard
SOUNDDISABLE="True"
# Minimizie Syslog Messages a little bit
SYSLOGBLOCK="True"
# /tmp as tmpfs mounting
TMPTMPFS="True"
# tmpfs Size (recommended: 16M for pi zero / 64M for Pi 4)
TMPFSSIZE="16M"
## Interface Configuration
## 0 Enable / 1 Disable
# i2c bus
I2CBUS="0"
# spi bus
SPIBUS="1"
# one wire bus
ONEWIRE="1"
# Raspberry Pi's camera module
CAMERA="1"
Wichtig ist, das ihr den I2CBUS
auf 0
setzt. Den Rest könnt ihr gerne variieren. Ich habe mein Setup hier auf Energiesparen ausgelegt und benötige den Rest nicht. Ändert auch bitte in der ersten Sektion die Passwörter und den PIHOSTNAME
ab.
nun können wir das Setup Script starten:
./rpi_autoconf.sh
nach dem automatischem Neustart verbindet ihr euch via ssh mit dem neuen Hostname und dem root
User auf euren Raspberry Pi:
ssh root@yourpisnewhostname
nun ist der Raspberry Pi grundinstalliert und wir können den Sensor installieren.
Sensorwerte an MQTT Broker senden
Nun kommen wir zur Installation des Sensors oder besser der Scripte die wir brauchen um die Sensordaten an unseren MQTT Broker homie konform und via TLS Verschlüsselung zu schicken. Dafür installieren wir zuerst ein paar Abhängigkeiten auf dem Raspberry Pi:
apt update && apt install -y git python3-pip python3-paho-mqtt python3-systemd i2c-tools
bsec_bme680-homie Scripts
Nun brauchen wir die Scripte aus dem folgenden Git Repository bsec_bme680-homie
. Ladet euch diese bitte am besten nach /opt
herunter:
cd /opt/
git clone https://github.com/alaub81/bsec_bme680-homie.git
Großen Dank hier an Alex H von dem ich die C Application genommen habe und Dank an rstoermer für den Python JSON Ansatz, den ich dankend für meine Zwecke benutzt habe.
Als nächste laden wir uns die BSEC Library herunter und kompilieren diese ...
Bosch BSEC Library
Um den BME680 Sensor mit allen Features nutzen zu können bietet Bosch die sogenannte BSEC (Bosch Sensortec Environmental Cluster) Library an. Diese ist leider closed Source und kann nur von der Bosch Webseite heruntergeladen werden. Deshalb ist der erste Schritt das ihr euch die Library herunterladet. Dafür müsst ihr euch registrieren, dann bekommt ihr den Download Link per Mail zugeschickt:
Legt die heruntergeladene Library (Zip Archiv) bitte in /opt/bsec_bme680-homie/src
ab und entpackt das Zip Paket direkt in diesem Ordner:
cd /opt/bsec_bme680-homie/src/
wget https://LINK.IN/EMAIL
unzip bsec_1-4-8-0_generic_release_updated_v3.zip
nun wechseln wir wieder in /opt/bsec_bme680-homie
und konfigurieren das Makefile:
cd /opt/bsec_bme680-homie
nano make.config
/opt/bsec_bme680-homie/make.config
# Use right Version of downloaded bsec Library
BSEC_DIR='./src/BSEC_1.4.8.0_Generic_Release_updated_v3'
# which Version
VERSION='normal_version'
# which architecture you like to use
# Other architectures can be found in BSEC_DIR/algo/${VERSION}/bin/.
# that one runs under raspberry pi zero
ARCH="${VERSION}/bin/RaspberryPi/PiThree_ArmV6"
# which config you like to use
# Other configs are:
# generic_18v_300s_28d
# generic_18v_300s_4d
# generic_18v_3s_28d
# generic_18v_3s_4d
# generic_33v_300s_28d
# generic_33v_300s_4d
# generic_33v_3s_28d
# generic_33v_3s_4d
CONFIG='generic_33v_3s_4d'
# where is the config dir?
CONFIG_DIR='.'
wenn ihr einen Pi Zero verwendet, könnt ihr alles so lassen wie es ist. prüft ggf. ob es eine neuere Version der Library gibt und ändert dann den Pfad ganz oben ab.
Fast ihr noch einen Temperatur Offset einrichten wollt, könnt ihr dies im bsec_bme680.c
file direkt machen. Bei mir passt der Offset soweit. Die Zeile findet ihr ziemlich am Anfang des Scripts.
#define temp_offset (0.5f)
nachdem nun alles eingerichtet ist, kompilieren wir uns unser bsec_bme680
:
cd /opt/bsec_bme680-homie
./make.sh
Wenn dieser Kompilierungsvorgang ohne Fehler abgeschlossen ist, können wir einen ersten Test wagen und schauen ob der Sensor uns Daten liefert:
chmod +x bsec_bme680
./bsec_bme680
Ihr solltet nun folgendes als Ausgabe sehen:
bsec_iaq.state empty {"IAQ_Accuracy": "0","IAQ":"25.00","Temperature": "19.01","Humidity": "54.96","Pressure": "988.73","Gas": "14918","Status": "0","Static_IAQ": "25.00","eCO2": "500.000000000000000","bVOCe": "0.4999999403953552246093750"} {"IAQ_Accuracy": "0","IAQ":"25.00","Temperature": "18.95","Humidity": "55.09","Pressure": "988.73","Gas": "17290","Status": "0","Static_IAQ": "25.00","eCO2": "500.000000000000000","bVOCe": "0.4999999403953552246093750"} {"IAQ_Accuracy": "0","IAQ":"25.00","Temperature": "19.00","Humidity": "54.78","Pressure": "988.69","Gas": "19586","Status": "0","Static_IAQ": "25.00","eCO2": "500.000000000000000","bVOCe": "0.4999999403953552246093750"}
mit STRG+C könnt ihr das Programm abbrechen. Nachdem wir nun wissen das die BSEC Library tut was sie soll, können wir einen ersten Test mittels Python Script wagen:
chmod +x bsec_bme680.py
./bsec_bme680.py
Die Ausgabe sollte hier dann nach ca. 20 Sekunden so aussehen:
bsec_iaq.state empty Temperature: 19.09 Humidity: 53.57 Pressure: 988.64 Gas: 27568.0 IAQ: 25.0 IAQ_Accuracy: 0.0 Static_IAQ: 25.0 eCO2: 500.0 bVOCe: 0.4999999403953552 Status: 0.0
Auch hier kommt ihr mit STRG+C aus dem laufenden Programm.
bsec_bme-homie.py - Homie MQTT Script
Nachdem wir nun wissen das alles Läuft, können wir die Daten an den MQTT Broker senden. Dies machen wir über das Script bsec_bme680-homie.py
. Bitte dieses Script mit dem Editor eurer Wahl öffnen und im oberen Bereich die Variablen so anpassen, das Sie zu eurem MQTT Broker passen:
bsec_bme680-homie.py
# set the variables
# MQTT Broker Connection
broker = "FQDN / IP ADDRESS"
port = 8883
mqttclientid = "clientid-bsecbme680-homie"
clientid = "clientid-bsecbme680"
clientname = "Clientname BSEC BME680 Sensor"
nodes="bme680"
username = "mosquitto"
password = "password"
insecure = True
qos = 1
retain_message = True
# Retry to connect to mqtt broker
mqttretry = 5
# how many values should be collected before publishing the median
medianvalues = 10
# True/False led warning (only True if you have an RGB Led connected)
ledwarning = False
# set red,green and blue pins
redPin = 22
greenPin = 27
bluePin = 17
# At which value CO2 alarm will be fired (x in ppm)
eco2alarm = 1000
# At which value humidity alarm will be fired (x in %)
humidityalarm = 70
Nachdem ihr alles angepasst habt, könnt ihr einen ersten Versuch wagen und schauen ob nach ca. 20-30 Sekunden die ersten Daten in den MQTT Topics ankommen:
chmod +x bsec_bme680-homie.py
./bsec_bme680-homie.py
auch hier kann das Script mit STRG+C abgebrochen werden.
tls2561-homie.py - Homie MQTT Script
Nun kommen wir zum Hellligkeitssensor. hierfür verwenden wir das Script tls2561-homie.py
für das wir als erstes die Adafruit Library nachinstallierten:
pip3 install --user adafruit-circuitpython-tsl2561
Dann laden wir uns das Script nach /usr/local/sbin
herunter:
cd /usr/local/sbin
wget https://github.com/alaub81/rpi_sensor_scripts/raw/main/tsl2561-homie.py
chmod +x tsl2561-homie.py
Und passen nun die Variablen im oberen Bereich an:
tls2561-homie.py
# set the variables
broker = "FQDN / IP ADDRESS"
port = 8883
mqttclientid = "clientid-tsl2561-homie"
clientid = "clientid-tsl2561"
clientname = "Clientname TSL2561 Sensor"
nodes="tsl2561"
username = "mosquitto"
password = "password"
insecure = True
qos = 1
retain_message = True
# Retry to connect to mqtt broker
mqttretry = 5
# how often should be a publish to MQTT (in Seconds)
publishtime=15
Nun kann man einen ersten Start des Skriptes wagen und schauen ob die Werte im MQTT Broker ankommen.
tsl2561-homie.py
Mit STRG+C kommt man aus dem laufenden Script heraus.
systemd Service aktivieren
Um das Ganze nun dauerhaft zum Laufen zu bringen, installieren wir ein Systemd Service File welches das Python Script startet und dieses auch ggf. bei einem Fehler neustartet.
cp /opt/bsec_bme680-homie/bsec_bme680-homie.service /etc/systemd/system/
cd /etc/systemd/system/
wget https://github.com/alaub81/rpi_sensor_scripts/raw/main/tsl2561-homie.service
systemctl daemon-reload
systemctl start bsec_bme680-homie.service
systemctl enable bsec_bme680-homie.service
systemctl start tsl2561-homie.service
systemctl enable tsl2561-homie.service
Den Status des Service könnt ihr so abrufen:
# für den BME680 Sensor
systemctl status bsec_bme680-homie.service
# für den Helligkeitssensor
systemctl status tsl2561-homie.service
Die Ausgabe sollte dann in etwa so aussehen:
● bsec_bme680-homie.service - BSEC BME680 MQTT Homie Service Loaded: loaded (/etc/systemd/system/bsec_bme680-homie.service; enabled; vendor preset: enabled) Active: active (running) since Thu 2021-02-11 18:42:55 CET; 16s ago Main PID: 1545 (python3) Tasks: 3 (limit: 877) CGroup: /system.slice/bsec_bme680-homie.service ├─1545 /usr/bin/python3 /opt/bsec_bme680-homie/bsec_bme680-homie.py └─1549 ./bsec_bme680 Feb 11 18:42:53 laub-iot01 systemd[1]: Starting BSEC BME680 MQTT Homie Service... Feb 11 18:42:55 laub-iot01 systemd[1]: Started BSEC BME680 MQTT Homie Service. Feb 11 18:42:55 laub-iot01 python3[1545]: MQTT Connection established, Returned code= 0 Feb 11 18:42:55 laub-iot01 python3[1545]: bsec_iaq.state empty ########################## ● tsl2561-homie.service - TSL2561 MQTT Homie Service Loaded: loaded (/etc/systemd/system/tsl2561-homie.service; enabled; vendor preset: enabled) Active: active (running) since Fri 2021-02-19 09:30:16 CET; 8s ago Main PID: 13306 (python3) Tasks: 2 (limit: 877) CGroup: /system.slice/tsl2561-homie.service └─13306 /usr/bin/python3 /usr/local/sbin/tsl2561-homie.py Feb 19 09:30:15 laub-iot01 systemd[1]: Starting TSL2561 MQTT Homie Service... Feb 19 09:30:16 laub-iot01 systemd[1]: Started TSL2561 MQTT Homie Service. Feb 19 09:30:16 laub-iot01 python3[13306]: MQTT Connection established, Returned code= 0
Nun sollten die folgenden Topics in eurem MQTT Broker zusehen sein. Ich nutze hier immer den MQTT Explorer:
Übersicht der Sensorwerte
Sensor | MQTT Topic | Wert | Einheit | Beschreibung |
---|---|---|---|---|
BME680 | homie/clientid/bme680/iaqaccuracy | IAQ_Accuracy | 1-3 (Integer) | Indoor Air Quality Genauigkeit (beginnt bei 0 nach dem Start, geht nach ein paar Minuten auf 1 und erreicht 3, wenn der Sensor kalibriert ist) |
homie/clientid/bme680/iaq | IAQ | 0-500
(float) |
Indoor Air Quality Index
| |
homie/clientid/bme680/staticiaq | Static_IAQ | Float | Statische IAQ (Schätzung der unskalierten Raumluftqualität)
"Der Hauptunterschied zwischen IAQ und statischem IAQ (sIAQ) hängt vom Skalierungsfaktor ab, der auf der Grundlage der jüngsten Sensorhistorie berechnet wird. Der sIAQ-Ausgang wurde für stationäre Anwendungen (z.B. feste Innengeräte) optimiert, während der IAQ-Ausgang ideal für mobile Anwendungen (z.B. Handgepäckgeräte) ist." (Quelle: Bosch Forum) | |
homie/clientid/bme680/temperature | Temperature | °C | Temperatur | |
homie/clientid/bme680/pressure | Pressure | hPa | absoluter Luftdruck | |
homie/clientid/bme680/gas | Gas | ohm | Rohdaten vom Gassensor als Widerstandswert in Ohm | |
homie/clientid/bme680/humidity | Humidity | % | Luftfeuchtigkeit | |
homie/clientid/bme680/humidityalarm | boolean | True / False | Luftfeuchtigkeuts Alarm. Grenzwert kann im Skript definiert werden. Standardwert ist 70 % | |
homie/clientid/bme680/sensorstate | Status | Integer | Rückgabewert der BSEC-Bibliothek | |
homie/clientid/bme680/eco2 | eCO2 | ppm | CO2-Äquivalent (Schätzung des CO2-Äquivalents in ppm in der Umwelt)
"Schätzt eine CO2-äquivalente (CO2eq) Konzentration [ppm] in der Umwelt. Es wird auch auf der Grundlage der sIAQ-Ausgabe berechnet und aus VOC-Messungen und Korrelationen aus Feldstudien abgeleitet." (Quelle: Bosch Forum) | |
homie/clientid/bme680/eco2alarm | boolean | True / False | CO2 Alarm. Grenzwert kann im Skript definiert werden. Standardwert ist 1000 ppm | |
homie/clientid/bme680/bvoce | bVOCe | ppm | Atem-VOC-Äquivalentleistung (schätzt die Gesamt-VOC-Konzentration in ppm in der Umwelt)
"Die Atem-VOC-Äquivalentleistung (bVOCeq) schätzt die Gesamt-VOC-Konzentration [ppm] in der Umwelt. Es wird auf der Grundlage der sIAQ-Ausgabe berechnet und aus Labortests abgeleitet." (Quelle: Bosch Forum) | |
BH1750 | homie/clientid/bh1750/illuminance | Illuminance | lux | Beleuchtungsstärke |
Good to know:
Da bVOCeq und CO2eq auf dem sIAQ-Ausgang basieren, wird erwartet, dass sie in stationären Anwendungen, bei denen die Hauptquelle für VOCs in der Umwelt aus menschlicher Aktivität (z.B. in einem Schlafzimmer) stammt, optimal funktionieren.
Zusammenbau der Raumklima-Station
Ich habe als erstes in den Kunstoff Übertopf ein Loch gebohrt, damit ich das USB Ladekabel durch dieses hindurch in den Topf zum Raspberry Pi bekomme. Hierfür habe ich mit einem Akkuschrauber und einem 8er Metallbohrer zuerst ein Loch unten in den Topf gebohrt, gerade so hoch damit es direkt über dem Topfboden herauskommt.
Als nächstes habe ich mit dem Bohrer ein zweites Loch direkt neben dem ersten gebohrt und die beiden mit einander verbunden. Dabei habe ich den Bohrer als eine Art Säge verwendet um das Loch in der Breite zu vergrößern. Anschließend habe ich mit einem scharfen Messer noch etwas nachgearbeitet. Das Material ist sehr weich und lässt sich einfach bearbeiten.
Nun kann man das USB-Stromkabel einfach in den Topf führen und dann darin den Raspberry Pi anschließen. Wir legen den Pi wie auch den I2C Hub unten auf den Boden und lassen die bereits verkabelten Sensoren von innen am Rand aus dem Topf hängen.
Dann stellen wir einfach die Kunstpflanze in den Topf und verstecken die Sensoren sauber im Grün. Der Helligkeitssensor sollte jedoch nicht ganz versteckt werden, denn wir wollen ja die Raumhelligkeit messen. Das Ganze kann dann so aussehen:
Das Endergebnis sieht dann so aus....
Optional: RGB LED als Warnleuchte
Möchtet ihr nicht nur die Warnings als MQTT Werte, sondern auch eine "leuchtende" Kunstpflanze, so könnt ihr zusätzlich eine RGB LED an den Raspberry Pi anschließen:
Diese habe ich an die folgenden Pins angeschlossen, da ich GND bereits für die anderen Sensoren verwendet habe:
Raspberry Pi GPIO Pin | RGB LED Pin |
---|---|
6 (Ground) | GND |
11 (GPIO 17) | B |
13 (GPIO 27) | G |
15 (GPIO 22) | R |
Dann einfach die LED unten in der Pflanze verstecken und im Skript bsec_bme680-homie.py
die LED Anzeige aktivieren:
# True/False led warning (only True if you have an RGB Led connected)
ledwarning = True
Dann den Service noch Neustarten, fertig:
systemctl restart bsec_bme680-homie.service
Optional: Tuning
Man kann die Power LED des Raspberry Pi zero deaktivieren, falls diese stört. Dafür editieren wir die /boot/config.txt
und hängen die folgenden Zeilen an das Ende.
/boot/config.txt
# Disable the ACT LED on the Pi Zero. dtparam=act_led_trigger=none dtparam=act_led_activelow=on
zum Aktivieren einfach den Pi Neustarten. Wenn alles läuft kann man dann noch das gesamte Dateisystem readonly schalten, das sorgt dafür das die SD Karte länger lebt und vor allem, das bei einem Stromausfall kein korruptes Dateisystem übrig bleibt.
raspi-config nonint enable_overlayfs
raspi-config nonint enable_bootro
reboot
Einbinden in openHAB
Nun wollen wir natürlich das Ganze noch in unser Smart Home bringen. Dafür legen wir als erstes in openHAB Things und Items an. Wie das geht, findet ihr hier:
Ich nutze die Werte dann in einer Sitemap, in HABPanel und auch in Grafana. Wenn ihr mehr zu openHAB erfahren wollt schaut doch einfach hier rein:
Quellen
- https://learn.adafruit.com/adafruit-bme680-humidity-temperature-barometic-pressure-voc-gas/bsec-air-quality-library
- https://www.bluedot.space/tutorials/air-quality-measurement-with-the-bme680/
- https://www.bosch-sensortec.com/software-tools/software/bsec/
- https://github.com/rstoermer/bsec_bme680_python
- https://github.com/alexh-name/bsec_bme680_linux
- https://community.home-assistant.io/t/bme680-using-the-official-bosch-sensortec-bsec-library/54103