Luchtkwaliteit (CO2-gehalte) bewaken met open-source IoT

Voldoende ventilatie is een belangrijke maatregel om het leefklimaat binnenshuis op peil te kunnen houden. Slechte ventilatie leidt immers tot verminderde luchtkwaliteit. En dat kan weer leiden tot gezondsheidsklachten zoals vermoeidheid en hoofdpijn en tot een verhoogd risico op virusbesmetting via aerosolen. Vandaar dat de overheid ons, in haar strijd tegen covid-19 besmetting, dringend adviseert om drukke publieke ruimtes zoals huiskamers, klaslokalen, kantoren, etc goed te ventileren.

CO2 meter

Het kooldioxide (CO2) gehalte van de binnenlucht blijkt een belangrijke indicator voor onvoldoende ventilatie. Mensen ademen immers zuurstof (O2) in, zetten die door verbranding om in kooldioxide (CO2) en ademen dat vervolgens weer uit. Bij slechte ventilatie zal het kooldioxide-gehalte binnenshuis dus toenemen. Buitenlucht bevat typisch 400ppm CO2. Een binnenklimaat met 400-800ppm wordt beschouwd als gezond, 800-1200ppm als matig en een CO2-gehalte boven de 1200ppm beschouwen we als ongezond. In dat geval is ventilatie absoluut noodzakelijk.

Daarom ook dat CO2-meters zoals hiernaast aangegeven in Belgische cafe’s en restaurants wettelijk verplicht zijn. Doel is om de kans op covid-19 besmetting in de publieke ruimte te beperken. Dergelijke apparaten zijn prima betaalbaar (< €150) en te koop via het internet.

Maar het is natuurlijk veel leuker om zoiets zelf te bouwen.

Systeem introductie

In dit artikel laat ik zien hoe je goedkoop een CO2-sensor kunt bouwen en die via een eveneens goedkoop open-source IoT systeem op afstand kunt monitoren. Dwz, ik geef alleen de ingredienten die ik zelf gebruikt heb. Iedere situatie is immers anders, bijv. mbt type en aantal sensoren en mbt de manier waarop je dat vervolgens wilt visualiseren. De daadwerkelijke implementatie laat ik daarom graag over aan je eigen inzichten en creativiteit :-).

Onderstaand blokschema geeft ruwweg aan hoe mijn basissysteem opgebouwd is. Eventueel is het systeem eenvoudig uit te breiden voor meerdere CO2-sensoren; een voor elke kamer, lokaal of kantoor.

IoT systeemoverzicht

De belangrijkste hardware componenten zijn: een CO2-sensor (MH-Z19B/C), een programmeerbare WiFi-module (ESP32) en een cloud-server (Raspberry Pi = RPi). De belangrijkste software componenten zijn: Arduino SDK uitgebreid met ESP32 ondersteuning, Ubuntu voor de RPi, Mosquitto MQTT broker, Node-red IoT-programmeer-omgeving, InfluxDB database voor de meetdata, en Grafana voor datavisualisatie. Allen zijn open-source en dus gratis.

De dataflow is simpel:

  • De ESP32 bestuurt de CO2 sensor, leest de meetwaarde, en stuurt die mbv de MQTT-client-publisher via WiFi naar de MQTT-broker op de RPi.
  • de Mosquitto MQTT broker fungeert als doorgeefluik. Het ontvangt meetwaarden van de sensor (MQTT-publisher) en stuurt ze door naar iedereen die ze wil ontvangen (MQTT-subscribers).
  • Node-red ontvangt middels de MQTT-client-subscriber de meetwaarde van de MQTT-broker en stuurt die door naar de influxDB database voor opslag. Het fungeert daarmee vooral als doorgeefluik tussen de MQTT-broker en de influxDB database. Daarnaast gebruik ik Node-red om wat ‘dummy’-meetwaarden te genereren voor testdoeleinden.
  • InfluxDB is de database waarin alle meetwaarden worden opgeslagen. Om te voorkomen dat de database overloopt hebben de meetwaardes een vooraf ingestelde retentieperiode.
  • Grafana leest de CO2 meetwaardes uit de influxDB database en geeft ze weer als grafieken en/of als meter op een eenvoudig zelf te ontwerpen web-pagina.

De sensor module

Arduino SDK met ESP32 ondersteuning

Voor het meten van het CO2 niveau koos ik de uiterst betaalbare Winsen MH-Z19C. Die werkt op 3V3, heeft een meetbereik van 400-2000ppm, een nauwkeurigheid van +/-50ppm +5% en is eenvoudig aan te sluiten via de UART (digitaal) of PWM (analoog) interfaces van een microcontroller. Het stroomverbruik is wat aan de hoge kant (80mA) dus batterijvoeding is niet echt een optie. Wel jammer, want de ESP32 BLE/WiFi connectivity module is wel uiterst zuinig. In ons geval communiceert de sensor met de ESP32 via UART2 op 9600baud, UART0 van de ESP32 is immers al in gebruik als programmeer interface.

Voor het programmeren van de ESP32 koos ik voor de Arduino software ontwikkelomgeving, uitgebreid met de ESP32 plug-in. Software bibliotheek voor WiFi is standaard inbegrepen. Een veelgebruikte open source MQTT pubsubclient voor Arduino is te vinden op github, evenals een Arduino bibliotheek voor de MH-Z19 sensor. Hiermee is eenvoudig een Arduino sketch te bouwen die met CO2 meetwaardes verzamelt en via WiFi opstuurt naar de MQTT broker.

De cloud server

Een eenvoudige RPi is al voldoende om een leuke cloud server te kunnen bouwen. Ikzelf gebruik hiervoor een Raspberry Pi model 2B (v1.1 met 1 GB RAM) en met een standaard Ubuntu installatie en dat draait prima. Met een RPi model 3 of 4 draait het natuurlijk allemaal wel een beetje sneller :-). Monitor, keyboard en muis zijn handig tijdens de Ubuntu installatie en configuratie maar daarna zijn ze niet echt meer nodig. Werken met remote desktop via een VNC viewer is een prima alternatief.

De database vormt het hart van elke cloud server. Ik koos voor influxDB, met name omdat het geoptimaliseerd is voor “meetdata met een tijdlijn”, zo krijgt elke meetwaarde automatisch een time-stamp waarop data geselecteerd/gefilterd kan worden. Dat maakt het vullen, post-processen en visualiseren van de meetdata een stuk eenvoudiger en sneller dan met relationale databases zoals mySQL en bongoDB.

MQTT concept

Standaard komt InfluxDB met Telegraf om berichten naar de database te versturen en van de database te ontvangen. Maar ik kies voor MQTT icm Node-red. Geen speciale reden, gewoon omdat het kan :-).

MQTT staat voor “Message Queuing Telemetry Transport” en is een veelgebruikt protocol voor het versturen van IoT berichten. Een MQTT-broker is een soort van doorgeefluik waarmee zenders en ontvangers van IoT berichten losgekoppeld kunnen worden zodat ze elkaar, onafhankelijk van het moment, berichten kunnen versturen en ontvangen. Een MQTT-client-publisher verstuurt (published) zijn IoT berichten naar de MQTT-broker op het moment dat het hem uitkomt. MQTT-berichten bestaan uit 2 delen; het “topic” en de “content”. Het “topic” is de naam waaronder de meetwaarde naar de MQTT-broker gepublished is, bijvoorbeeld “MHZ19/CO2waarde” of “MHZ19/temperatuur“. De MQTT-broker houdt dit bericht vast totdat een MQTT-client-subscriber in staat is om het te bericht te ontvangen. Daarvoor moet een MQTT-client zich eerst op een topic abonneren (subscriben). Daarna worden berichten met dat topic automatisch doorgestuurd naar de subscriber zodra die (weer) verbinding gemaakt heeft met de MQTT-broker. Meerdere MQTT-client-subscribers kunnen geabonneerd zijn op hetzelfde MQTT-topic.

Node-red

In ons geval zal de MQTT-client op de ESP32 de sensormeetdata rechtstreeks publishen naar de MQTT-broker op de RPi.

Voor het ophalen van de meetdata van de broker en het doorsturen ervan naar de influxDB database is een MQTT-client (subscriber) nodig. Daarvoor gebruik ik Node-red.

Node-red is een grafische programmeer omgeving met standaard bouwblokken die met lijntje verbonden kunnen worden om zo een dataflow te realiseren. Onder de motorkap is node-red gebaseerd op NodeJS en is het mogelijk om de functionaliteit van de standaard bouwblokken uit te breiden (bijv. voor het post-processen van de meetdata) met JavaScript als programmeertaal. Voor het grafisch ‘programmeren’ maakt node-red gebruik van een web-interface die te bereiken is via ‘localhost:1880’.

In het figuur is te zien dat mijn node-red zich geabonneerd heeft op verschillende MQTT topics (localhost/fddata/xyz…), dat die meetdata eerst omgezet wordt van een text-string naar een floating point getal, en dat die meetwaarde tenslotte weggeschreven wordt naar de databbase (influxdb/xyz…). Daarnaast worden diezelfde meetwaardes ook gepubliceerd op de eigen node-red GUI die te bereiken is via ‘localhost:1880/ui’.

Datavisualisatie

Tenslotte is het leuk als alle ontvangen meetdata ook gevisualiseerd kan worden. Ik gebruik daarvoor Grafana, dat schijnt (van horen zeggen) toch net weer iets leuker te zijn dat chronograf dat standaard in het pakket zit bij InfluxDB. Het koppelen van Grafana en InfluxDB is een fluitje van een cent, gewoon de juiste database preset kiezen uit een menu, credentials instellen en klaar is kees. Daarna kun je via een grafische interface (localhost:3000) je dashboard gaan opbouwen door panels toe te voegen. Met een panel visualiseer je de meetdata door eerst een of meerdere datastromen uit de InfluxDB te selecteren, vervolgens het type grafiek te selecteren uit een zeer uigebreide bibliotheek en tenslotte deze grafiek aan te passen aan de eigen behoefte (titels, assen, kleuren, metrische eenheid, etc). En omdat grafana een responsive webinterface biedt ziet de website er niet alleen prima uit op een laptop scherm, maar ook op je smartphone :-).

Grafana UI

Varianten

Alle gebruikte software is open source en is beschikbaar op verschillende platformen. Zo gebruikte ik voor de cloud een Raspberri Pi, maar even zo goed is dit alles werkend te krijgen:

Maar voor hen die zelf wat minder technisch willen ‘prutsen’ en een wat meer plug&play oplossing ambieren kan ik Home Assistant icm met ESP home aanbevelen. Wellicht schrijf ik daar nog eens een nieuwe blog over.