In diesem Gastbeitrag wird das Projekt “Raspi’s Wetterauskunft” mit dem Kleinrechner Raspberry Pi von mir vorgestellt. Dabei wird der Raspi mit zwei Sensoren für Temperatur und Luftfeuchtigkeit (außen und innen) ausgestattet. Die Werte werden in einer Datenbank für die spätere Auswertung und Visualisieurng mittels einem PHP-Skript aufgezeichnet. Der folgende Screenshot gibt einen Blick auf diese Auswertung:
Hardware und Verkabelung
DHT11 (Innentemperatur und Luftfeuchtigkeit: 0 bis 50°C)
PIN-Belegung (Ansicht von oben, Kontakte zeigen nach unten, wie auf dem Bild):
PIN 1 => ganz links (VCC)
PIN 2 => nächster von links (SIG)
PIN 3 => nächster von links (NC)
PIN 4 => ganz rechts (GND)
Raspberry Pi Verbindung (DHT11-PINs auf GPIO-PINs)
PIN 1 => 3,3V
PIN 2 => 4 (PIN zur Übermittlung der Daten; hier GPIO 4)
PIN 3 => –
PIN 4 => GND
DHT22 (Aussentemperatur und Luftfeuchtigkeit: -40 bis 125°C)
PIN-Belegung (Ansicht von oben, Kontakte zeigen nach oben, wie auf dem Bild):
PIN 1 => ganz links (GND)
PIN 2 => nächster von links (VCC)
PIN 3 => nächster von links (NC)
PIN 4 => ganz rechts (SIG)
Raspberry Pi Verbindung (DHT22-PINs auf GPIO-PINs)
PIN 1 => GND
PIN 2 => 3,3V
PIN 3 => –
PIN 4 => 17 (PIN zur Übermittlung der Daten; hier GPIO 17)
Ansteuerung der Sensoren
Die Ansteuerung und der Abruf von Temperatur und Luftfeuchtigkeit der Sensoren findet über ein einfaches Signal-Protokoll statt. Hierbei werden Signale an die Sensoren gesandt und daraufhin antworten diese mit den Sensor-Daten. Diese Signal-Daten müssen von Raspi in eine Zahl füt die Temperatur (z.B. 21,5 °C) und Luftfeuchtigkeit (z. B. 80 %) interpretiert werden. Hierfür stehen kleine Programme zur Verfügung, die hier heruntergeladen werden können:
Die Programme liegen im Quelltext vor, sodass hier Änderungen (z. B. ein abweichender Signal-PIN als oben angegeben; eine abweichende Ausgabe der Temperatur und Luftfeuchtigkeit) vorgenommen werden können. Vor der Ausführung muss der Quelltext in Maschinencode übersetzt (kompiliert) werden. Hierfür werden Entwicklungstools benötigt (z. B. Installation in Debian: sudo apt-get install build-essential) und ggf. zusätzliche Pakete wie Wiring Pi. Falls solche Abhängigkeiten nicht erfüllt sind, sollte der Übersetzungsprozess mit entsprechenden Meldungen abbrechen.
Speicherung der Daten in einer Datenbank
Für eine Auswertung historischer Temperatur- und Luftfeuchtigkeitsdaten werden diese in einer Datenbank gespeichert. Dafür müssen zusätzlich Pakete auf dem Raspi installiert werden:
- Datenbankmanagementsystem (hier Postgres DB; denkbar z. B. auch MySQL)
- Webserver mit PHP-Unterstützung (hier lighttpd; denkbar z. B. auch Apache)
- Datenbank-Bindings für PHP (hier php5-pgsql)
Nun muss eine Datenbank zur Speicherung der Werte entworfen werden. In diesem Fall werden alle Werte in einer Datenbank mit Tabellen jeweils für ein Messdatum (Temperatur innen und außen, Luftfeuchtigkeit innen und aussen) erstellt. Die folgenden SQL-Befehle erzeugen unter Postgres eine entsprechende Datenbank:
CREATE DATABASE temphumid;
CREATE TABLE temp_inside_record( temp_id serial primary key, temperature real not null, stamptime TIMESTAMP );
CREATE TABLE temp_outside_record( temp_id serial primary key, temperature real not null, stamptime TIMESTAMP );
CREATE TABLE humid_inside_record( humid_id serial primary key, humidity real not null, stamptime TIMESTAMP );
CREATE TABLE humid_outside_record( humid_id serial primary key, humidity real not null, stamptime TIMESTAMP );
Hinweis:
Im Fall von Problemen bei der Erstellung der Datenbank-Struktur hat Manuel in einem Kommentar eine mögliche Ursache und die Behebung des Problems beschrieben (siehe auch Kommentar am Ende des Beitrags):
Nach dem erstellen der Datenbank (CREATE DATABASE temphumid;) muss man diese VOR dem Erstellen der Tabellen erst einmal auswählen mittels: “\c temphumid” innerhalb der psql Konsole.
Zur Speicherung von Temperatur- und Luftfeuchtigkeitsdaten in der oben erstellten Datenbank wird folgendes Bash-Skript genutzt:
#/bin/bash dht11="Fehler" dht22="Fehler" path="PATH_TO_SENSOR_EXECUTABLES" while [ "$dht11" = "Fehler" ] do dht11=`$path/DHT11` done while [ "$dht22" = "Fehler" ] do dht22=`$path/DHT22` done humidAussen="`echo $dht22 | awk -F':' '{print $1}'`" tempAussen="`echo $dht22 | awk -F':' '{print $2}'`" humidInnen="`echo $dht11 | awk -F':' '{print $1}'`" tempInnen="`echo $dht11 | awk -F':' '{print $2}'`" set -e set -u # Set these environmental variables to override them, # but they have safe defaults. export PGHOST=${PGHOST-localhost} export PGPORT=${PGPORT-5432} export PGDATABASE=${PGDATABASE-temphumid} export PGUSER=${PGUSER-#####################} export PGPASSWORD=${PGPASSWORD-####################} # Update temperature and humidity RUN_PSQL="psql -X --set ON_ERROR_STOP=on " ${RUN_PSQL} <<SQL INSERT INTO humid_inside_record (humidity, stamptime) VALUES ($humidInnen,to_timestamp(`date +%s`)); INSERT INTO humid_outside_record (humidity, stamptime) VALUES ($humidAussen,to_timestamp(`date +%s`)); INSERT INTO temp_inside_record (temperature, stamptime) VALUES ($tempInnen,to_timestamp(`date +%s`)); INSERT INTO temp_outside_record (temperature, stamptime) VALUES ($tempAussen,to_timestamp(`date +%s`)); SQL
Das Skript kann auch hier heruntergeladen werden: updateTempHumidDB.tar.gz
Hinweis:
Falls Daten nicht in die Datenbank geschrieben werden hat Manuel in einem Kommentar eine mögliche Ursache und die Behebung des Problems beschrieben (siehe auch Kommentar am Ende des Beitrags):
Zum erfolgreichen Schreiben und Senden der Daten fehlt als vorletzte Zeile innerhalb des Bashscripts (also vor der Zeile “SQL”) noch ein “commit;”. Dieses ist nötig, da du bei der Parametrisierung ja auch “autocommit=off” gesetzt hast.
Danach erhält man auf der Console nicht nur die Insert-Bestätigung, sondern auch das Commit:
INSERT 0 1
INSERT 0 1
INSERT 0 1
INSERT 0 1
COMMIT
Die DB-Konfiguration sowie der Pfad zu den DHT-Programmen muss in dem Skript angepasst werden. Danach lassen sich durch den Aufruf des Skripts die Sensordaten in die Datenbank schreiben.
Damit die Sensordaten in regelmäßigen Abständen in die Datenbank geschrieben werden, wird folgender Cron-Eintrag erstellt (hier: jede halbe Stunde):
0,30 * * * * root /PFAD_ZUM_SKRIPT/updateTempHumidDB.sh
Aufgrund der notwendigen Privilegien zur Ansteuerung der GPIO-PINs bei der Ermittlung der Sensordaten muss das Programm unter dem Administratorkonto root gestartet werden.
Visualisierung
Zur Auswertung und Visualisierung der gespeicherten Messwerte in der Datenbank wird das JavaScript-Framework NVD3.js eingesetzt. Dieses basiert auf D3.js und ermöglicht schöne Effekte bei der Darstellung der Daten. Die Homepages der Frameworks zeigen einige Beispiele zu den Möglichkeiten der Tools.
Als erstes müssen diese JavaScript-Frameworks von den Homepages heruntergeladen werden:
- https://raw.githubusercontent.com/novus/nvd3/master/build/nv.d3.min.js (Produktiv-Version von NVD3.js)
- https://github.com/mbostock/d3/releases/download/v3.4.11/d3.zip (Produktiv-Version von D3.js)
Die heruntergeladenen Dateien müssen ggf. extrahiert und in dem Unterverzeichnis “js” des Webverzeichnisses gespeichert werden (relativ zu dem PHP-Skript). Auf diese Dateien wird im HTML-Code des Auswertungs-PHP-Skriptes verwiesen.
Anschließend wird das PHP-Skript weather.php in dem Webverzeichnis gespeichert. In dem Skript muss die Datenbank-Konfiguration noch angepasst werden, dann kann das Skript über den Browser von dem Webserver des Raspberry Pi abgerufen werden.
Bedienung und Kompatibilität
Im oberen Bereich der Anzeige wird der letzte Datenbankeintrag angezeigt und somit werden die letzten Messwerte ausgegeben. Über ein Formular mit einer HTML5-Datumsauwahl (nicht unterstützt von Firefox, jedoch Chrome) kann ein Zeitraum zur Visualisierung vorgegeben werden. Bei dem ersten Aufruf ist der vergangene Tag als Zeitraum gewählt.
Anpassungen und Weiterentwicklung
Ausgehend von diesem Projekt lässt sich die Darstellung der Daten leicht über die JavaScript-Framework-Funktionen anpassen und ändern. So stehen die Daten den JavaScript-Frameworks nun in einem unterstützten Format zur Verfügung. Die Homepages der Bibliotheken bieten eine gute Übersicht über mögliche Darstellungsformen mit direkten Code-Beispielen zur Übernahme in das eigene Skript.
Über Feedback würde ich mich freuen, insbesondere über neue Darstellungsformen, die dann in diesen Blog-Beitrag einfließen.
Sehr geehrter Herr Klein.
Danke für Ihre Anleitung. Ich habe versucht das ganze bei mir zu implementieren bin aber dann an der grafischen Darstellung gescheitert.
Vlt. könnten Sie mir weiterhelfen:
ich habe die Daten in der Datenbank, und kann auch die den letzten aktuellen Wert darstellen.
Die Seite schaut auch so aus wie auf dem Screenshot.
Wenn ich allerdings den Grafen aufrufen will. ändert sich nichts. (Firefox, Internet Explorer und Chrome zeigen das gleiche Verhalten)
Ich habe dann die Daten auf einen Windows Rechner übertragen, da ich dachte mit den Rechten irgendeinen Fehler zu haben. -> Gleiches Ergebnis.
Der js Ordner ist im selben Ordner wie das .php script.
Wo kann ich weitersuchen?
Danke und mfg
Marcus
Hallo Marcus,
mein Beitrag ist ein Gastbeitrag, deshalb sei bitte nicht verwundert, dass ich antworte und nicht Stephan :)
Mir fallen zwei Problem-Quellen ein:
1) Datenbank-Anbindung bzw. Darstellung
Da das JavaScript zur graphischen Aufarbeitung lediglich auf Daten innerhalb der HTML-Seite zurückgreift, ist es denkbar, dass der Fehler schon bei der Abfrage und Einbettung der Daten aus der Datenbank auftritt. Hierzu empfehle ich den Quellcode der HTML-Seite und insbesondere den Abschnitt des JavaScript-Codes zu prüfen. Hier sollte ein Array hinterlegt sein, der Deine Temperatur-Daten enthält. Das weitere Testen kannst Du in diesem Fall am besten durch direkte PHP-Aufrufe Deines Skripts auf der Kommandozeile und Gegenprüfen der Ausgabe bzw. des JavaScript-Arrays durchführen.
2) JavaScript-Fehler
Eine zweite Fehlerquelle kann aus meiner Sicht die JavaScript-Einbindung bzw. Interpretation sein. Dafür empfehle ich den JavaScript-Debugger Deines Browsers einzuschalten und auf Fehler-Hinweise zu achten. Empfehlen würde ich hier den Chrome als Browser (da weitestgehend kompatibel mit der JS-Bibliothek und effiziente JS-Engine). Dafür musst Du die Entwicklertools aktivieren und auf die JavaScript-Console achten. Lass Dich nicht erschrecken von den vielen Optionen in der Entwickler-Ansicht, sondern orientiere Dich insbesondere an der “Console” und den dort auftretenden Fehlermeldungen.
Das Betriebssystem schließe ich als Fehlerquelle aus, da es sich um eine Web-Anwendung handelt, die ausschließlich im Browser läuft.
Ich hoffe, dass die Hinweise Dir eine Hilfe sind. Am Ende geht es ja nicht nur um das Ergebnis, sondern auch um den Weg ;)
In diesem Sinne viele Grüße und viel Erfolg!
Jan
Danke für deinen Tipp!
Jetzt habe ich den Fehler gefunden:
Im PHP script wird auf eine css Datei verwiesen, die natürlich erst anzulegen ist. Und als zweiten Fehler habe ich die ” .transitionDuration(500) ” auskommentieren müssen. Da sie den Fehler xxx is not a function generierte. Warum das so ist weiß ich noch nicht – aber mal weiterschauen.
Danach hat es geklappt.
Die Linien werden dargestellt, nun sind noch Formatieraufgaben etc zu erledigen.
Noch einmal ein herzliches Dankeschön
Marcus
Ich bin absoluter Neuling und habe mit mir den Raspberry Pi 2 Model B SBC [Made in the U.K.] gekauft.
1. Ich möchte gerne ein zwei Keller Räume Temperatur und Luftfeuchtigkeit messen.
Bei einem bestimmten Wert der Luftfeuchtigkeit soll über email alamiert werden so das man reagieren kann.
Wenn man diese Werte dann noch über http://192.168.xxx.xxx auslesen kann mit einem verkauf der letzten Woche wäre klasse.
So wie ich das gelesen habe ist das mit dem Raspberry Pi möglich.
Es gibt verschiedene Anleitungen im Internet mit unterschiedlichen Sensoren.
Da ich mich aber in der Programmiersache gar nicht auskenne traue ich mich nicht ran.
Hallo Matthias,
Deine Idee ist grundsätzlich durchführbar und wie Du bereits geschrieben hast gibt es hierfür auch Anleitungen im Internet. Anhand meiner Anleitung wirst Du lediglich die Temperatur- und Luftfeuchtigkeits-Werte aufzeichnen und darstellen können. Eine Alarmierung ist nicht Ziel meines kleinen Projekts.
Prinzipiell lässt sich meine Lösung jedoch einfach erweitern, indem die gespeicherten Temperatur- und Luftfeuchtigkeits-Werte in der Datenbank automatisiert ausgewertet werden. Auf eine Überschreitung/Unterschreitung eines Wert kann beispielsweise eine Email versand werden. Dies könnte in einem kleinen Bash-Skript realisiert werden, welches über einen cronjob in regelmäßigem Intervall aufgerufen wird.
Zur Zeit ist das für mich nicht in Planung, würde mich aber freuen wenn Du Deine Lösung hier verlinken würdest.
Viele Grüße
Jan
Hallo zusammen und ganz herzlichen Dank, für die tolle Anleitung.
Alles soweit so gut, jedoch erhalte ich seitens psql die folgenden Fehlermeldung:
“ERROR: relation “humid_inside_record” does not exist
LINE 1: INSERT INTO humid_inside_record (humidity, stamptime) VALUES…”
Ich habe schon stundenlang herumprobiert und bin drauf und dran, nun auf MySQL zu wechseln. ;)
Weiß jemand vielleicht eine Lösung bzw. hat es bei euch einfach so geklappt?
Die Tabellen und die Datenbank existieren, jenes habe ich über die psql Console direkt abgefragt.
Auch habe ich vorsichtshalber nachträglich die Berechtigungen angepasst, was vermutlich gar nicht nötig war.
Ich würde mich wirklich sehr über deine/eure Hilfe freuen.
Beste Grüße, Manuel
Hallo Jan,
okay, ich habe es nun. Es fehlen noch zwei kleine, aber sehr entscheidende, Punkte in deiner sonst sehr guten Anleitung:
1) Nach dem erstellen der Datenbank (CREATE DATABASE temphumid;) muss man diese VOR dem Erstellen der Tabellen erst einmal auswählen mittels: “\c temphumid” innerhalb der psql Konsole.
–> Das löst das von mir beschriebene Problem mit der nicht vorhandenen Relation.
2) Zum erfolgreichen Schreiben und Senden der Daten fehlt als vorletzte Zeile innerhalb des Bashscripts (also vor der Zeile “SQL”) noch ein “commit;”. Dieses ist nötig, da du bei der Parametrisierung ja auch “autocommit=off” gesetzt hast.
Danach erhält man auf der Console nicht nur die Insert-Bestätigung, sondern auch das Commit:
INSERT 0 1
INSERT 0 1
INSERT 0 1
INSERT 0 1
COMMIT
Das als kleine Ergänzung. Hat ein wenig gedauert, da ich absolut keinerlei Ahnung von Postgres habe/hatte. ;-)
Dennoch nochmals vielen lieben Dank für die Anleitung; ich mache mich nun an die Sache mit der Visualisierung.
Frohe Ostern, Manuel
Hallo Manuel,
es freut mich, dass Du das Problem lösen konntest! Leider habe ich die Wettererfassung nicht mehr im Betrieb, sodass ich Deinen Korrekturen gedanklich folgen, jedoch diese nicht mehr erproben kann. Daher verweise ich auf Dein Kommentar an den entsprechenden Stellen im Text.
Weiterhin viel Erfolg!
Frohe Ostern auch Dir und viele Grüße
Jan
Hallo,
ich habe die PHP-Datei auf mySQL angepasst. Das funktioniert auch so weit.
Jedoch bekomme ich immer bei folgendem Punkt
// Convert SQL fetched Data to d3.js-compatible data
function getTempHumidData() {
var tempInside = [], tempOutside = [], humidInside = [], humidOutside = []
<?php
for($i=0; $i < count($tempInside); $i++)
{
echo "tempInside.push({x: ($tempInsideDate[$i] * 1000), y: $tempInside[$i]});\n";
}
for($i=0; $i < count($tempOutside); $i++)
{
echo "tempOutside.push({x: ($tempOutsideDate[$i] * 1000), y: $tempOutside[$i]});\n";
}
for($i=0; $i < count($humidInside); $i++)
{
echo "humidInside.push({x: ($humidInsideDate[$i] * 1000), y: $humidInside[$i]});\n";
}
for($i=0; $i
die Fehlermeldung “SyntaxError: missing ) in parenthetical” angezeigt.
Dieser Fehler bedeutet wohl, dass eine Klammer fehlt. Jedoch bin ich nicht der große JavaScript-Experte um den Fehler selber zu lokalisieren. Hast du eine Idee woran das liegen könnte?
Für eine kleine Rückmeldung wäre ich dankbar.
Hallo Jürgen,
es scheint, dass die letzte Zeile unvollständig oder überflüssig ist:
> for($i=0; $i
Ansonsten erkenne ich spontan keine Fehler. Weiterhin viel Erfolg bei der Fehlersuche! Vielleicht könntest Du mir Deine Änderungen zusenden, dann würde ich sie als alternative MySQL-Version hier zum Download anbieten oder auf Deine Seite verlinken.
Viele Grüße
Jan
Hallo,
habe das Projekt hier auch mal versucht auf meinem Pi zu realisieren, aber leider bekomme ich beim ausführen der “updateTempHumidDB.sh” folgenden Fehler:
updateTempHumidDB.sh: line 5: $’\r’: command not found
updateTempHumidDB.sh: line 40: warning: here-document at line 35 delimited by ‘)d-of-file (wanted `SQL
updateTempHumidDB.sh: line 41: syntax error: unexpected end of file
Vielleicht hat ja jemand ein Tip für mich.
Gruß
Thomas
Hallo zusammen,
ich versuche ebenfalls das “Projekt” umzusetzen.
Habe soweit alles hinbekommen, dass ich mein DHT22 in eine mysqldb schreiben lassen.
Leider finde ich die “nv.d3.css” hier nicht auf der Seite – hab mir diese nun von https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.6/nv.d3.css heruntergeladen….
Nun bekomme ich jedoch im weather.php den Fehler “[ERROR]”.
Es muss sicherlich an der Zeile des mysql query liegen….
“= ‘” . $sqlFromDate . “‘ and stamptime ”
Kann mir vielleicht jemand weiter helfen – hat jemand einen Tipp?
Vielen Dank!
Dennis
Was kommt bei Path to Sensor executeables. Soll das wirklich der Pfad zu dem Sensor sein also /devices/….
Hallo Lukas,
damit ist der Pfad zu dem Verzeichnis gemeint, in den Du die “DHT11 und DHT22 Ansteuerungsprogramme” gespeichert hast. Diese Dateien kannst Du als Quellcode unter dem folgenden Link herunterladen, wie bereits in Kapitel “Ansteuerung der Sensoren” beschrieben und verlinkt:
https://klein-gedruckt.de/wp-content/uploads/2014/08/dht_sources.tar.gz
Die Datei musst Du auspacken und den Quellcode des jeweiligen Sensors ggf. anpassen (z. B. PIN-Belegung) und kompilieren (z. B. mittels “make” und einem Compiler wie “gcc”). Die kompilierte und ausführbare Datei musst Du nun in einem Verzeichnis Deiner Wahl speichern. Dieses Verzeichnis musst Du im Skript in der Variable “path” hinterlegen, z. B.:
path=”/home/pi/dht-sensor-executables-directory”
Ich hoffe das hilft und viel Spaß beim Basteln!
Abend,
das Projekt ist ja schon etwas älter, habe es jedoch vor 2 Jahren ohne Probleme nachgebaut.
Nun möchte ich meinen (zu feuchten) Keller überwachen, bekomme aber die DHT22 nicht zum laufen. Wo kann man hier den verwendeten GPIO einsetzen? Die Variable _pin zu verändern führt nur zu Fehlern?
Danke!
Hallo Gerrit,
leider habe ich das Projekt schon lange nicht mehr im Betrieb und kann Dir daher auch nur theoretische Hinweise geben. Ich denke, dass Du bereits an der richtigen Stelle im Quellcode warst. Die Variable _pin enthält die GPIO PIN. Allerdings habe ich in Erinnerung, dass nicht alle GPIO PINs vom Raspberry Pi für diese Zwecke nutzbar sind sowie gibt es zwei unterschiedliche Nummerierungen der PINs (siehe auch http://wiringpi.com/pins/). Vielleicht hilft Dir das weiter bei der Fehlersuche.
Viel Spaß beim Experimentieren!
Hi,
kurzes Update von mir: Habs sein lassen, zwischenzeitlich ist Openhabian das Mittel der Wahl (für mich zumindest). Zumal ich hier bei erreichen eines Schwellenwertes direkt z.B. eine Steckdose schalten kann. Im Keller ggf. nicht verkehrt.
Grüße