Pi als weerstation
Maak met een Raspberry Pi een eigen weerstation en toon de metingen in een grafiek
Een weerstation maken is met een Pi makkelijk te doen. Als voorbeeld gaan we aan de slag met sensors voor de temperatuur, luchtvochtigheid en luchtdruk. De data daarvan willen we in een grafiek weergeven die via het netwerk toegankelijk moet zijn. Daar gebruiken we het programma RRDtool voor.
Meestal wordt voor dit soort toepassingen een mysql- of sqlitedatabase gebruikt om de data op te slaan, wat dan gecombineerd wordt met een (betaalde) online service voor het grafische weergeven en toegang via het web. Het aantal webservices dat dashboards voor allerhande gegevens aanbiedt, groeit door de IoT-hype. Je betaalt dan meestal ook nog voor een abonnement. Voorbeelden zijn plot.ly, pubnub.com, initialstate.com, iot-dashboard.org en adafruit.io. We willen echter niet afhankelijk zijn van een externe service. Daarom hebben RRDtool van Tobi Oetiker gebruikt. Dat is een database en grafische tool ineen. RRDtool was oorspronkelijk bedoeld voor het in beeld brengen van netwerksnelheden, processor- en harddisktemperaturen, cpu-belasting et cetera. Hij is ook zeer bruikbaar voor allerhande andere datastreams. Het werken met RRDtool gaat in drie stappen.
Hardware aansluiten
Het uitgangspunt is een Raspberry Pi 1 model B met geïnstalleerde Raspbian Jessie of Raspbian Jessie Lite en een netwerkverbinding. Eerst sluit je de hardware aan. De DHT22 alias AM2302 (een andere naam voor hetzelfde beestje) is een temperatuuren luchtvochtigheidssensor die erg simpel op de Raspberry Pi is aan te sluiten. Dat kan met een (mini)breadboard of rechtstreeks als je de bijbehorende 4,7kΩ-weerstand aan de pootjes vastsoldeert. Met de bibliotheek van Adafruit (zie de link onderaan dit artikel) kun je hem ter controle rechtstreeks uitlezen:
python /home/pi/Adafruit_Python_DHT/—
examples/AdafruitDHT.py 2302 4
De output daarvan is bijvoorbeeld
Temp=19.6* Humidity=50.4%
De sensor levert geen continue datastream zoals bij analoge temperatuursensors het geval is, maar steeds een losse waarde als het Python-script daar om vraagt. Het script heeft twee parameters nodig: de code voor de sensor (2302) en het GPIO-nummer (4) van de pin op de Pi (fysieke pin 7) waar de datalijn op aangesloten is. De output geeft meteen beide waarden voor temperatuur en luchtvochtigheid.
Voor deze toepassing worden de waarden gescheiden in een variabele opgeslagen, dus kopiëren we het originele script naar twee andere scripts (AdaAMtemp.py en AdaAMhumid.py). De output daarvan levert dan alleen de waarde van de temperatuur of de vochtigheid met respectievelijk print('{0:0.1f}'.format(temperature)) en print('{1:0.1f}'.format(humidity)). – met 19.6 en 50.4 als resultaat. Dat gebruik je in het uiteindelijke bash-script bij stap 2. Voor de BMP183 doe je hetzelfde, maar daar gebruik je alleen de luchtdruksensor van. Het aangepaste Python-script noem je pressure. py. Dan kun je aan de slag met de database.
Aanmaken database
De database is een zogeheten round-robin database (RRD). Daar worden de data niet voor eeuwig in opgeslagen, maar je geeft
de circulaire database van tevoren een vaste omvang. In het begin zal hij gevuld zijn met onbekende data ('NAN', not a number), maar al snel worden de oude gegevens weggegooid om plaats te maken voor de nieuwe. Het installeren is simpel:
sudo apt-get update sudo apt-get install rrdtool
Daarna staat de software in /usr/bin/rrdtool/. In totaal heb je maar drie commando's nodig: een om de database aan te maken, een om de database te vullen en een om de data in een grafiek te zetten.
Het aanmaken van de database doe je vanuit de home-directory van pi met onderstaand commando:
/usr/bin/rrdtool create pimeteo.rrd
--start N --step 300 \ DS:temp:GAUGE:600:U:U \ DS:humid:GAUGE:600:U:U \ DS:press:GAUGE:600:U:U \ RRA:AVERAGE:0.5:1:288 \
Dat commando kun je voor het gemak in een bash-script zetten (create_pimeteo_rrd. sh). Dat maak je uitvoerbaar met chmod +x en kun je dan later starten met ./create_pimeteo_rrd.sh.
Met het bovenstaande commando wordt een database aangemaakt met de naam pimeteo. Je moet altijd een startpunt (--start) voor de database opgeven, normaal gesproken het aantal seconden sinds Epoch (01-01-1970). Maar je kunt ook N (now) gebruiken voor het huidige tijdstip. Met --step geef je in seconden aan met welk maximum interval de database nieuwe data kan verwachten. In dit geval is dat om de vijf minuten. Daarna volgen achter DS (data source) de namen waaronder ze in de database terecht moeten komen, het datasource-type (hier: GAUGE, oftewel absolute data die door RRDtool niet veranderd moeten worden) en de heartbeat (de time-outtijd in seconden). Wanneer er binnen dit interval geen data worden aangeleverd, verschijnt er NAN in de database – en dus een lege plek in de grafiek. Als laatste wordt de datarange gedefinieerd (de te verwachten minimum en maximum waarden). Die zetten we voor het gemak op U (undefined).
RRA staat voor Round Robin Archive. Daarmee bepalen we hoeveel data we opslaan en voor hoelang. AVERAGE betekent dat alleen de gemiddelde waarde (als er meerdere waarden zijn) bewaard moet worden. Met 288 geef je het aantal stappen aan dat bij die berekening meegenomen moet worden. In dit geval betekent dat 288 x 300 = 86400 seconden (1 dag).
Database vullen
Om de database met data te vullen, zet je onderstaande commando's weer in een bashscript (update_pimeteo_rrd.sh).
Eerst worden drie variabelen met de huidige data gevuld: temperature=$(python /home/pi/Adafruit_— Python_DHT/examples/AdaAMtemp.py 2302 4) humidity=$(python /home/pi/Adafruit_— Python_DHT/examples/AdaAMhumid.py 2302 4) pressure=$(python
/home/pi/bmp183-master/pressure.py)
Vervolgens worden die aan de database toegevoegd:
/usr/bin/rrdtool update pimeteo.rrd -t temp:humid:press N:$temperature:—
$humidity:$pressure
Daarbij worden de drie datasources temp, humid en press gevuld met de inhoud van de drie betreffende variabelen en voorzien van het tijdstempel N (now). De switch -t is niet per se nodig, maar maakt wel duidelijker wat er gebeurt.
Grafisch weergeven
Aangezien de grafiek in een browser getoond moet kunnen worden via het lokale netwerk of internet, moet je tussendoor nog een webserver installeren:
sudo apt-get install apache2 -y
Als er genoeg data in de database zitten, kun je een grafiek maken. Met /usr/bin/ rrdtool dump pimeteo.rrd kun je zien welke gegevens er in de database staan. Het commando voor het genereren van de grafiek zet je in het derde bash-script (create_pimeteo_graph.sh). De output wordt dan een plaatje in png-formaat van 700 x 400 pixels.
Daarbij geven we ook de titel en het opschrift van de Y-as op:
/usr/bin/rrdtool graph pimeteo.png
--width 700 --height 400 \ --title="Luchtdruk, luchtvochtigheid en
temperatuur van laatste 24 uur" \ --vertical-label="Temp.(C)<->— Luchtvochtigh.(perc.)<->Luchtdruk
(hPa/16)" \ DEF:temp=/home/pi/pimeteo.rrd
:temp:AVERAGE \ DEF:humid=/home/pi/pimeteo.rrd
:humid:AVERAGE \ DEF:press=/home/pi/pimeteo.rrd
:press:AVERAGE \
Daarna wordt bepaald welke data in de grafiek getoond worden. Het feit dat je bij de grafiek geen tweede schaal kunt toevoegen, is voor de luchtdruk een probleem. De temperatuur en luchtvochtigheid passen samen mooi in een schaal van 0 tot 100, maar de luchtdruk in hectoPascal gaat daar met een factor van minstens 10 overheen. Om die lijn niet in een aparte grafiek te hoeven zetten, pas je een trucje toe:
CDEF:press2=press,16,/
Daarmee maak je virtual name (VN), press2, aan die de waarde van de DS press bevat, maar dan gedeeld door 16. Dat staat in de reverse polish notation (RPN), dus eerst de operanden en dan de operator. Vervolgens bepaal je de grafieklijnen, hun kleur (hexadecimaal) en naam: LINE1:press2#5fd00b:Luchtdruk \ LINE1:humid#0000ff:Luchtvochtigheid \ LINE1:temp#ff0000:Temperatuur \
Die staan in de volgorde waarin ze later in de grafiek verschijnen van boven naar beneden. Voor de luchtdruk gebruik je nu de gemodificeerde waarde van press2. Het getal achter LINE bepaalt de dikte van de lijn (van 1 tot 3).
De legenda met de kleurcode wordt automatisch onder de grafiek gezet. Na twee commentaarregels om een nieuwe regel te beginnen, kun je met GPRINT de belangrijkste cijfers onder de grafiek uitlichten. In dit geval laten we de laatste, de hoogste en de laagste waarde van iedere sensor van de laatste 24 uur zien. Hieronder het commandodeel voor de luchtdruk. De uitgelichte cijfers voor de temperatuur en de vochtigheid kun je naar analogie hiervan zelf programmeren; met telkens twee van de speciale commentaarregels om ze onder elkaar te zetten. Voor de luchtdruk wordt nu wel de echte press met de originele (hogere) waarden gebruikt om onder de tabel in ieder geval de belangrijkste luchtdrukcijfers in hun echte hPa-waarden te krijgen. Bij %2.1lf staat eerst een 1 en dan de letters l en f.
COMMENT:"\t\t\t\t\t\t\l" \ COMMENT:"\t\t\t\t\t\t\l" \ GPRINT:press:LAST:"Luchtdruk
Laatste\: %2.1lf" \ GPRINT:press:MAX:"Max.\: %2.1lf" \ GPRINT:press:MIN:"Min.\: %2.1lf" \
Daarna moet het plaatje nog naar de juiste directory van de webserver gekopieerd worden:
cp /home/pi/pimeteo.png /var/www/html
In die directory staat al een index-bestand van Apache. Dat kun je verwijderen en vervangen door een index.html of index.php met het plaatje van de grafiek. Bijvoorbeeld:
<!DOCTYPE html>
<html>
<body>
<h1>PiMeteo</h1> <p>Woonkamer</>
<img src="pimeteo.png"> </body>
</html>
Automatiseren met cron
De bash-scripts update_pimeteo_rrd.sh en create_pimeteo_graph.sh moeten regelmatig herhaald worden om de database te vullen en de grafiek te updaten. Dat kan heel makkelijk met twee cron-jobs. Open de editor met crontab -e en voeg deze twee regels toe:
*/5 * * * * python /home/pi/update_—
pimeteo_rrd.sh */15 * * * * python /home/pi/create_—
graph.sh
De eerste zet het updaten van de database iedere vijf minuten in gang. De tweede zorgt ervoor dat er iedere vijftien minuten een nieuwe grafiek voor de webpagina klaarstaat.
Extra's
Je kunt meer temperatuursensors toevoegen of de webpagina mooier maken en beveiligen met een login.
RRDtool heeft nog veel meer mogelijkheden en nodigt uit tot experimenteren. De officiële documentatie staat bij de link hieronder, inclusief veel voorbeelden. Ook de volledige scripts uit dit artikel staan bij de link. (jmu)