Raspberry Pi zero w zur Raumluft und Luftqualitätsüberwachung

Aus Laub-Home Wiki
Raspberry Pi zero w als Raumklimastation

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.

mit RGB LED

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

Anschluss der Sensoren

Raspberry Pi GPIO Pin Belegung

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:

Verkabelung I2C Hub
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
  • 000 .. 050 gut
  • 051 .. 100 durchschnittlich
  • 101 .. 150 nicht so gut
  • 151 .. 200 schlecht
  • 201 .. 300 schlimm
  • 301 .. 500 sehr schlecht
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:

versteckter BME680 Sensor
TSL2561 nicht ganz versteckt.

Das Endergebnis sieht dann so aus....

Optional: RGB LED als Warnleuchte

Warn LED

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:

Anschluss RGB LED
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