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.