22.3.2017 IoT Raspberry Pi Linux Wetterstation

Als ich vor ein paar Wochen aufgeräumt habe, fiel mir mein etwas in die Jahre gekommener Raspberry-Pi B+ auf. Vor einem Jahr war der Raspberry mein kleines NAS mit einer USB-Festplatte, was ich aber durch ein richtiges System ausgetauscht habe. Nach einigem hin und her überlegen, was man denn alles mit einem Raspberry machen kann, kam mir die Idee eine kleine Wetterstation zu bauen.

Die Sensoren

Um erstmal an Wetterdaten zu kommen, braucht man natürlich Sensoren. Eine typische Wetterstation beinhaltet folgende Sensoren:

Zur Zeit gibt es unglaublich viele Sensoren auf dem Markt und diese bieten die unterschiedlichsten Übertragungsmöglichkeiten. Eines steht jedoch fest: Man kommuniziert mit den Sensoren über die GPIO-Pins des Raspberrys. Die Sensoren, die ich mir dann gekauft habe, kommunizieren hauptsächlich über das I2C-Bussystem. Grundsätzlich funktioniert das I2C-Bussystem nach dem Master-Slave-Prinzip: Jeder Sensor ist ein Slave im Bus und wartet nur darauf, dass seine Adresse angesprochen wird. Der Raspberry ist logischerweise der Master und ruft dann nur noch die Adresse des Sensors, von dem er Daten haben möchte, in den Bus hinein und bekommt dann eine Antwort vom angesprochenen Sensor. Der klare Vorteil von I2C, ist die Geschwindigkeit mit der eine Anfrage von Sensordaten verarbeitet werden. Eine solche Anfrage dauert durchschnittlich nur wenige Millisekunden und der Sensor ist auch sofort wieder bereit für eine neue Anfrage.

Hier sind die Sensoren, die ich bestellt hatte:

Die Sensoren habe ich dann bei 2 Elektrotechnik-Shops gekauft: EXP-TECH und Christians-Shop.

Erste Schritte mit I2C

Sind die ersten Sensoren angekommen, kann es eigentlich auch schon los gehen. Ich empfehle erstmal das ganze auf einem Breadboard auszuprobieren, bis man das ganze am Ende auf eine Lochplatine lötet. Wer sich vorher einen kleinen Plan machen möchte, kann sich einmal das Tool Fritzing angucken. Damit lassen sich die Sensoren auf einem virtuellen Breadboard zusammenklicken und man hat einen kleinen Überblick, über die Verkabelung. Das Grundprinzip ist eigentlich: GND (also Ground) an GND, VIN an 3,3V, SDA an SDA und SCL an SCL. Der I2C-Bus muss Parallel geschaltet sein und bei der Stromversorgung empfiehlt sich das ganze auch. Außerdem sollte man sich vorher die Anordnung der GPIO-Pins beim Raspberry-Pi anschauen, damit auch alle Stecker richtig gesteckt werden.

Hier habe ich jetzt nur mal ein paar Sensoren verkabelt, es soll ja anschaulich bleiben :)

Wichtig ist nur noch, dass das I2C-Bussystem auf der Daten- und Taktleitung (SDA und SCL) eine Spannung braucht. Ich habe hier jeweils 2 mal 2,5kΩ von der Spannung (3,3V) genommen, denn erst dadurch kann eine korrekte Datenübertragung gesichert werden.

Ist alles verkabelt, kann am Raspberry-Pi weitergemacht werden. Das auslesen der Sensoren klappt für mich am einfachsten mit der Programmiersprache Python. Natürlich klappt auch C oder C++, aber das wollte ich mir nicht antun. Um I2C am Raspberry-Pi benutzen zu können müssen ein paar Dinge noch erledigt werden:

  1. I2C in der raspi-config aktivieren

Dazu muss in das Terminal vom Raspi der Befehl

pi@weather:~ sudo raspi-config

eingegeben werden. Danach einfach folgende Schritte ausführen:

Nun müssen noch ein paar Konfigurationsdateien umgeschrieben werden. Dazu öffnen wir mit nano /etc/modules die erste Datei und fügen folgende Zeilen am Ende der Datei ein:

i2c-bcm2708
i2c-dev

In der Datei /etc/modprobe.d/raspi-blacklist.conf sind die blacklist-Einträge noch auszukommentieren:

#blacklist spi-bcm2708
#blacklist i2c-bcm2708

Wichtig nach dem aktivieren ist der Neustart des Raspberrys. Die Oberfläche von raspi-config kann sich nach Updates gegebenfalls leicht verändern, jedoch findet sich die Option eigentlich immer.

  1. Pakete installieren

Nun kann man die ersten Pakete installieren:

pi@weather:~ sudo apt install python-smbus i2c-tools

Sind die Pakete installiert, kann auch schon direkt einmal getestet werden, ob die Sensoren erkannt werden.

pi@weather:~ sudo i2cdetect -y 1

    0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- 23 -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: 40 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: 60 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- 77

In dem Beispiel hier sind alle Sensoren angeschlossen, die über I2C kommunizieren. Sollten hier nicht alle Sensoren auftauchen, sollte nochmal die Leitung überprüft werden (nicht SDA und SCL vertauschen!). Ein Problem kann auch sein, dass der Raspberry nicht genügend Strom bekommt. Ich benutze für die Stromversorgung ein AmazonBasics USB-Netzteil mit einem Output von 2,1A.

Auslesen der I2C-Sensoren

Die meisten I2C-Sensoren werden von Adafruit produziert und können über die Adafruit-Bibliotheken angesprochen werden. Ich habe die Python-Skripte von Adafruit so angepasst, dass sie nur noch einen Wert ausgeben und dieser dann in eine MySQL-Datenbank übertragen wird. Meine Dateien finden sich in meinem GitHub-Repository unter weather-station/sensors.

DHT-22

Jetzt habe ich die ganze Zeit über den tollen I2C-Bus geredet und eigentlich haben wir auch genügend Sensoren, die alles abdecken. Ich hatte den DHT22 nur eigentlich zuerst gekauft und ein anderer Sensor hat sich als besserer Luftfeuchtigkeitssensor (SI7021) herausgestellt 1. Die Temperaturmessungen vom DHT22 finde ich aber immer noch am besten und deshalb habe ich diesen einfach behalten. Die Ansteuerung über die GPIOs funktioniert anders als bei den anderen Sensoren, da dieser Sensor kein I2C unterstützt sondern digital ausgelesen wird. Im oberen Fritzing-Bild kann dennoch die Schaltung für den DHT22-Sensor herausgelesen werden. Wichtig ist der 10kΩ Pull-Up-Widerstand, der vor die Datenleitung geschaltet wird, denn erst durch diesen können vernünftige Werte vom Sensor gelesen werden.

Speichern in der Datenbank

Jede Python-Skript-Datei endet bei mir mit diesem Befehl:

subprocess.call([dbscript, TABLE, VALUE ])

Dadurch wird der vom Sensor abgelesene Wert in die Datenbank übertragen. Das DB-Skript macht nichts anderes, als ein INSERT INTO-Statement auszuführen.

#!/usr/bin/python
import MySQLdb
import sys

def main():
    argv = sys.argv
    table = argv[1]
    value = argv[2]
    db = MySQLdb.connect(
        host="your-db-server",
        user="weatheruser",
        passwd="s3(ret",
        db="weather")
    cur = db.cursor()
    try:
        cur.execute("INSERT INTO " + table + " (value, time) VALUES (" + value + ", NOW());")
        db.commit()
    except:
        db.rollback()

    db.close()

Der Datenbank-Server kann theoretisch direkt auf dem Raspberry-Pi laufen und somit die Daten dauerhaft speichern. Jede weitere Analyse der Daten, wie zum Beispiel: “Wie war die Durchschnittstemperatur im März 2017” können direkt über SQL-Statement abgefragt werden. Die Sensor-Skripte werden bei mir über ein Shell-Skript aufgerufen, welches alle 5 Minuten durch einen Cron-Job ausgeführt wird.

Wind und Regen

Jetzt wird es kniffelig: Der Regen und Windsensor von SparkFun ist zwar im Vergleich zu den anderen Sensoren etwas teuer, aber man muss sich die Sensoren nicht irgendwie selber zusammenschustern. Warum dann kniffelig, wenn man doch schon 80€ für die 3 Dinger da bezahlen muss? Leider sind die Sensoren hier anders gemacht, als die schon von mir verbauten. Der Regenmesser besteht aus einer kleinen Wippe, die bei ca. 0.27mm umkippt. Dabei wird ein Stromkreis unterbrochen. Ein ähnliches Prinzip gibt es beim Anemometer, das an einer bestimmten Stelle der Umdrehung den Stromkreis unterbricht. Diese zwei Sensoren könnten über einen GPIO des Raspberry-Pis beobachtet werden und die zugehörigen Berechnungen machen, wäre da nicht die Windfahne. Die Windrichtung wird bei diesem Sensor über mehrere Widerstände bestimmt, die den Stromkreis unterschiedlich beeinflussen. Man muss also die Spannung messen und dann mit der Wertetabelle des Datenblatts vergleichen. Ich habe mich für einen Arduino Uno entschieden, der die gesamten Daten von Regen- und Windmessern aufnimmt und der Raspberry-Pi diese Daten nur noch ausliest.

Der fertige Code findet sich dann unter weather-station/arduino. Die Daten, die dort herauspurzeln sind nicht im metrischen System. Die Windgeschwindigkeit wird in miles per hour gemessen und die Regenmenge ist in inches. Die hier gewonnenen Daten können natürlich wieder in eine Datenbank gepackt werden und dann in ein gewünschtes Format überführt werden.

Andere Umsetzungen:


Update 25.01.2018


Update 16.04.2017

Meine Wetterstation ist jetzt online und unter zwei verschiedenen Varianten erreichbar:

Nach oben