Das Raspberry PI Projekt
Die Idee des Projekts
entstand schon vor langer Zeit. Seit 2008 wird die WS2500/WS2000 Wetterstation
nicht mehr produziert. 2010 erfolgte dann auch bei ELV der Abverkauf der für
Garantiefälle gelagerten Ersatzteile, so dass sich jeder Stationsbesitzer noch
einmal mit Sensoren und Empfängern, Displays und allem eindecken konnte. Bisher
hatte ich Glück und meine Sensoren, insbesondere der Regen- und Windsensor
erwiesen sich als besonders zäh. Aber der Temperatursensor in 2m Höhe hatte
sich schon sehr bald verabschiedet. Der Ersatzsensor lief auf Batterie und ein
falsches Einsetzen neuer Batterien bescherte ihm 2011 den Hitzetod. Erst ein
halbes Jahr später gab es dann endlich Ersatz von einem Hobbybastler und die
Station konnte wieder korrekte Daten liefern. Im Herbst 2013 fing ich dann an,
mich mit Bascom und den programmierbaren
Schaltkreisen von Atmel zu beschäftigen. Schnell kam
der Wunsch auf, mir endlich eigene Sensoren bauen zu können, was dann im Frühjahr
2014 auch klappte. Parallel dazu wurde ein Empfänger, basierend auf einem Aurel
4mm5 RX (433.92MHz) entwickelt, welcher die Stationssensoren empfangen und
dekodieren kann. Im Juli 2014 erfuhr ich vom Raspberry
Pi und wurde neugierig. Er war der ideale Kandidat um eine
Echtzeitdatenerfassung zu realisieren und die Daten auch in Echtzeit ins
Internet zu stellen.
Hier sind der Raspberry Pi,
sowie die kleine Empfängerschaltung zu sehen. Auf der Rückseite der
Empfängerplatine befindet sich die Empangsplatine
„Aurel 4mm5 RX“ an deren Antennenanschluss und GND ein Antennenkabel angelötet
ist. An der anderen Seite des Antennenkabels befindet sich eine Dipolantenne.
Beide Dipole bestehen aus einem 4mm Messing-Vollmaterialstab und sind je 32,6cm
lang. Dadurch wird der Empfang nochmals deutlich gesteigert.
Der Empfänger:
Hierbei handelt es um einen
Atmega16, welcher über seine Interruptpins die Daten
des Aurel 4mm5 RX auswertet. Int0 ist auf steigende Flanke eingestellt, Int1
auf fallende. Löst Int0 aus, so wird ein Timer gestartet, welcher eine Variable
hoch zählt. Löst nun Int1 aus, so wird der Timer gestoppt und die Variable
ausgewertet. Entspricht die gemessene Zeit der Bedingung für eine log. 1
(+Fehlertoleranz), so wird das erste Bit einer Datenvariable auf log. 1
gesetzt. Entspricht sie der Bedingung einer log. 0, so wird das Variablenbit auf log. 0 gesetzt. Entspricht die gemessene
Zeit selbst mit Fehlertoleranz keiner von beiden Bedingungen, so wird einfach
nichts gemacht.
Wie genau das
Datenübertragungsprotokoll der Funksensoren aussieht, ist hier nachzulesen.
Als Präambel (Startzeichen,
das jetzt ein Datentelegramm vom Sensor kommt) werden 7-10
mal log. 0 gefolgt von einer logischen 1 gesendet. Es muss also mind. 7 mal der Zustand 0 gefolgt von log. 1 empfangen werden. Auf
die Art wird ein Bit nach dem anderen der Datenvariable gesetzt. Da die Funksensoren
im 4 Bit Modus senden, ist die erste Datenvariable
nach 4 Bits bereits fertig. Nach einem Trennbit, welches immer log. 1 ist,
folgen dann die Bits für die zweite Datenvariable. Im Programm gibt es daher
auch für den log. 0 Zustand eine Zählvariable. Ist diese größer gleich 7 UND
das letzte empfangene Bit ist log. 1, dann beginnt gerade ein Sensortelegramm.
Danach folgt als erstes der
Sensortyp, wovon es 6 gibt. 0= Temperatursensor (Nur WS2000), 1= Temperatur und
Feuchtesensor, 2=Regensensor, 3=Windsensor,
4=Innensensor mit Temperatur, Feuchte und Luftdruck (Nur WS2000),
5=Helligkeitssensor (nur WS2500). Gefolgt von der Sensoradresse. Bei den
Temperatursensoren kann diese mittels Steckbrücken eingestellt werden, während
sie bei Regen, Wind, Helligkeit und dem Innensensor fest verlötet sind und auf
7 stehen. Nach diesen beiden ersten „Bytes“ (Anführungszeichen-Zeichen daher,
da ja nur 4, statt wie üblich 8 Bit) kommen nun die eigentlichen Daten. Nach
jedem „Byte“, also jedes 5. Bit, ist eine log. 1 als Trennzeichen.
Diese Daten fasst der Atmega16 zu Zahlenwerten zusammen, verarbeitet sie
und gibt sie letztlich alle 5 Minuten über seine UART Schnittstelle aus,
welches dann wie folgt aussieht:
02.08.2014;01:15;20.1;79.4;259;14.2;135;1014;0#
Datum;Zeit;Temperatur2m;Feuchte2m;Zählerstand
Regensensor;Windgeschwindigkeit;Windrichtung;Luftdruck;Helligkeit#
Das Semikolon stellt hierbei
das Datenrennzeichen dar und ist damit kompatibel zu dem CSV Standart, welcher
bei MS Excel Anwendung findet.
Der Raspberry:
Es wurde das Modell B mit
512MB RAM bestellt und als er dann da war, erst einmal großes grübeln wie denn
die Daten vom UART Ausgang des verwendeten Atmega16 den Weg in den Raspberry finden sollten. Denn hier war nun eine
Pegelanpassung von 5V auf 3,3V notwendig. Auch wenn es so nicht im Datenblatt
steht, aber der Atmega16 (keine L-Version) läuft auch mit 3,3V sehr gut und
stabil, wodurch die Pegelanpassung dann entfallen kann. Programmiert wird unter
Lazarus, welches auch auf dem Raspberry läuft und
dort Programme kompilieren kann. Jedoch hatte ich große Probleme Schnittstellenkomponenten
zu installieren, mit denen ein direkter Empfang der Wetterdaten am UART möglich
gewesen wäre. Also blieb mir nichts anderes übrig, als die Wetterdaten per *.sh Script in eine Datei schreiben zu lassen und diese Datei
vom Programm auf Änderungen zu überprüfen. Wenn in der Datei eine neue Zeile
geschrieben wurde, so werden die Daten vom Programm übernommen und ausgewertet.
Dieser Weg führte schnell zum Ziel und mittels der Lazarus eigenen Diagramm Komponenten, können nun farbenfrohe und übersichtliche
Diagramme in Echtzeit generiert werden. Das Programm bekam dann noch weitere
Routinen um die aktuellen Wetterdaten in eine *.htm Datei zu gießen, so dass
diese dann zusammen mit den als *.jpg gespeicherten
Diagrammen per crontab im 5 Minuten Intervall ins
Internet geladen werden können.
Die Funktion „stty“ schreibt, per *.sh Script
gestartet, alle über die UART Schnittstelle beim Raspberry
eintreffenden Datenpakete zusammen mit Datum und Zeit in eine Textdatei. Denn
Der Atmega16 gibt keine Datums und Zeitdaten aus, daher werden diese durch den Raspberry hinzugefügt. Im Laufe eines Tages ergibt sich
eine reichlich gefüllte Datei.
Hier mal ein kleiner
Ausschnitt aus einer solchen Datei:
02.08.2014;00:01;19.5;79.2;259;10.3;120;1014;0#
02.08.2014;00:06;19.7;78.9;259;5.8;115;1014;0#
02.08.2014;00:11;19.7;78.9;259;5.6;115;1014;0#
02.08.2014;00:16;19.7;78.9;259;8.5;120;1014;0#
02.08.2014;00:21;19.8;78.9;259;8.9;125;1014;0#
02.08.2014;00:26;20.0;78.9;259;14.2;125;1014;0#
02.08.2014;00:31;20.0;78.9;259;15.6;125;1014;0#
02.08.2014;00:36;20.1;79.0;259;11.3;125;1014;0#
02.08.2014;00:41;20.1;79.1;259;11.6;125;1014;0#
02.08.2014;00:46;20.1;79.1;259;9.6;130;1014;0#
02.08.2014;00:51;20.1;79.1;259;11.4;125;1014;0#
02.08.2014;00:56;20.1;79.0;259;8.2;125;1014;0#
02.08.2014;01:00;20.1;79.0;259;8.2;125;1014;0#
02.08.2014;01:05;20.1;79.3;259;10.1;125;1014;0#
02.08.2014;01:10;20.1;79.3;259;11.3;130;1014;0#
02.08.2014;01:15;20.1;79.4;259;14.2;135;1014;0#
02.08.2014;01:20;20.1;79.4;259;11.3;120;1014;0#
02.08.2014;01:25;20.1;79.4;259;11.2;15;1014;0#
02.08.2014;01:30;20.0;79.7;259;9.2;30;1014;0#
02.08.2014;01:35;20.0;79.7;259;9.2;30;1014;0#
02.08.2014;01:40;20.0;79.3;259;7.3;115;1014;0#
02.08.2014;01:45;19.9;79.4;259;6.9;100;1014;0#
02.08.2014;01:50;19.9;79.4;259;9.0;95;1014;0#
02.08.2014;01:55;19.9;79.4;259;6.2;105;1014;0#
02.08.2014;02:00;19.7;80.4;259;11.5;95;1014;0#
02.08.2014;02:05;19.7;81.0;259;9.7;100;1014;0#
Diese wird im 5 Minutentakt
vom Programm neu geladen und schaut ob eine weitere Zeile hinzugekommen ist.
Ist dies der Fall, so wird die letzte Zeile Zeichen für Zeichen abgearbeitet.
Die Daten werden solange in ein und die selbe Variable
geschrieben, bis das aktuelle Zeichen ein Semikolon ist. Ist dem so, so wird
die nächste Variable angefangen. Auf diese Weise werden die Daten ausgelesen
und können nun von Textzeichen in Zahlenwerte umgewandelt und in die Diagramme
eingetragen werden.
Noch einmal großes Grübeln
verursachte die Umsetzung der Taupunktberechnung. Diese Formeln kamen nun zum
Einsatz:
SDD(T) = 6.1078 * 10^((a*T)/(b+T))
DD(r,T)
= r/100 * SDD(T)
r(T,TD) = 100 * SDD(TD) /
SDD(T)
TD(r,T)
= b*v/(a-v) mit v(r,T) =
log10(DD(r,T)/6.1078)
AF(r,TK)
= 10^5 * mw/R* * DD(r,T)/TK;
AF(TD,TK) = 10^5 * mw/R* * SDD(TD)/TK
Bezeichnungen:
r = relative Luftfeuchte
T = Temperatur in °C
TK = Temperatur in Kelvin (TK
= T + 273.15)
TD = Taupunkttemperatur in °C
DD = Dampfdruck in hPa
SDD = Sättigungsdampfdruck in
hPa
Parameter:
a = 7.5, b = 237.3 für T
>= 0
a = 7.6, b = 240.7 für T <
0 über Wasser (Taupunkt)
a = 9.5, b = 265.5 für T <
0 über Eis (Frostpunkt)
Quelle: http://www.wetterochs.de/wetter/feuchte.html
Wie man sieht, sind noch 2
Einheiten zu berechnen, bevor man damit den Taupunkt berechnen kann. Zunächst
gilt es SDD(t) zu berechnen, da dies in der Formel für DD(r,T) vor kommt. DD(r,T) wird wiederum für die Berechnung von v(r,T) benötigt, welches wiederum in der Formel für den
Taupunkt verwendet wird. Am einfachsten ist es, diesen Parametern je eine
eigene Variable zu spendieren und sie am besten auch so zu benennen wie sie in
der Formel verwendet werden.
tmp=(a*T)/(b+T)
--- tmp ist hier als kleiner Zwischenspeicher zu
verstehen
SDD=6.1078 * 10^tmp
DD= (r/100) * SDD
V=log10(DD/6.1078)
TD=(b*v)/(a-v)
Ich hatte wirklich lange
probieren müssen, bis ich mit dieser Routine genau auf die Werte kam, welche
auch online Taupunktrechner und die eigene Wetterstation lieferten. Als es dann
aber soweit war, wurde diese Routine noch flugs ins Echtzeitprogramm
eingebunden und es stand nun auch der Taupunkt zur Verfügung.
Letztlich sieht nun das auf
dem Raspberry laufende Programm folgender Maßen aus:
Hier unter Windows7 geladen
um einen Screenshot machen zu können. Oben rechts
sind die geladenen Tagesdaten in einer Textfeldkomponente zu sehen, darunter
die automatisch generierte Homepage-Webseite. Diese wird in einer
Textfeldkomponente erzeugt und als HTM-Seite gespeichert. Parallel dazu werden
die Grafiken der 3 Diagramme als JPG Datei gespeichert. Im 3 Minuten Takt wird
per Cronjob ein Uploadscript ausgeführt, welches die
Webseite, sowie die 3 Diagrammgrafiken auf die Homepage hoch laden.
Die Echtzeitdatenerfassung
allein ist ja alles gut und schön. Da es aber ein wenig sinnlos ist, wenn die
Daten des aktuellen Tages nach 23:59 Uhr verloren gehen, wurde noch eine
weitere Routine eingebaut, welche permanent im Sekundentakt die aktuelle Zeit
prüft. Ist es 23:58:30 Uhr, dann werden die Datensätze des aktuellen Tages in
eine Textdatei mit dem aktuellen Datum als Dateiname (Datum.txt) exportiert und
die Datei, in welche das *.sh Script die Daten vom
Empfänger ablegt, geleert. Da der Inhalt der Diagramme unter Lazarus leider
nicht zu löschen geht, beendet sich das Programm nach dem Ablegen der Datum.txt
selbst und wird mittels cronjob um 00:15 Uhr wieder
gestartet. In der Zwischenzeit schnappt sich um 23:59 Uhr ein weiteres, selbst
geschriebenes Lazarus-Programm die erstellte Datum.txt, liest diese ein und
erstellt daraus die Monats-HTM-Datei, zusammen mit
den in der Monatsdatei verlinkten Tagesdiagrammen. Monatsdatei und
Tagesdiagramme werden dann mittels cronjob um 00:10 Uhr
per FTP-Upload ins Internet gestellt, so dass man die Daten des Vortages in der
Monatsdatei als Grafiklink vorfindet. Die Daten in der Monatsdatei welche nicht
als Minimum oder Maximum ausgwiesen sind, stellen
Tagesdurchschnittswerte dar. Da das Monatsprogramm so und so den gesamten Tagesdatensatz
lädt um diesen noch einmal in die Diagramme zu zeichnen, wird die Gelegenheit
genutzt um alle Werte aufzusummieren und letztlich durch die Anzahl der Werte
zu teilen. Es ergeben sich daher die Tagesdurchschnittswerte dieser Werte.