868 MHz Wetterdatenempfänger mit RX868 und Raspberry Pi

Martin Kompf

Das Empfangsmodul RX868-SH passt mit in das Gehäuse eines Raspberry Pi B+.

Der selbstgebaute drahtlose Sensor für die Wetterstation verwendet das Sendemodul TX868. Als Gegenstück dazu bietet ELV den Empfänger RX868-SH an. Ihn kann man direkt an einen Raspberry Pi anschließen und die Wetterdaten per Software dekodieren und damit den USB-WDE1 ersetzen.

Empfängermodul RX868-SH

Beim RX868-SH handelt es sich um einen sehr empfindlichen Superhet-Empfänger für 868,35 MHz. Er verfügt über die nötige Großsignalfestigkeit und Trennschärfe, um in einer von WLAN und LTE verseuchten Umgebung zu bestehen. Das Modul verfügt über vier Anschlüsse: Masse, Betriebsspannung von 2,3 bis 5,5 V, Datenausgang DATA und Steuereingang EN zum An- und Abschalten des Moduls. Damit kann man es direkt an die GPIO-Leiste des Raspberry Pi anschließen. Dabei muss die Spannungsversorgung mit 3,3 V erfolgen, da die Eingänge des Raspberry Pi nur einen Maximalpegel von 3,3 V erlauben!

Für meinen Aufbau habe ich diese Anschlusszuordnung gewählt:

Raspberry Pi GPIO ------ RX868 
Pin WiringPi-Signal      Signal
13  GPIO2 --------------- DATA 
15  GPIO3 --------------- EN
17   3V3 ---------------- +UB 
 9   GND ---------------- GND

Software

Nachdem man den RX868 mittels eines HIGH Pegels am EN Anschluss aktiviert hat, liefert sein Datenausgang DATA ein digitales Signal, wobei ein HIGH Pegel des Vorhandensein eines aktiven Signals auf 868,35 MHz anzeigt.

Das verwendete Übertragungsprotokoll kodiert ein Bit in einem Symbol von 1220 µs Länge. Die Kodierung von logisch 1 und 0 wird über das Puls-Pausen Verhältnis vorgenommen: 366 µs Puls (HIGH) und 854 µs Pause (LOW) kodieren eine 1, 854 µs Puls und 366 µs Pause eine 0. Um eine eindeutige Dekodierung vornehmen zu können, muss das Abtastintervall daher kleiner als 366 µs sein. Das entspricht einer Abtastrate von größer 2,7 kHz. Die spannende Frage ist, ob ein Raspberry Pi Model B+ eine derartig hohe Abtastrate in Software realisieren und gleichzeitig die Daten dekodieren kann und zu welcher CPU Auslastung dies führt.

Am Anfang steht die Auswahl einer geeigneten Programmiersprache und Methode zum Zugriff auf die GPIO. Es gibt dafür eine Vielzahl von Möglichkeiten. Eine Bewertung einiger Methoden aus Performancesicht liefert der Artikel Benchmarking Raspberry Pi GPIO Speed - allerdings untersucht er nur die relativ simple Ausgabe eines Rechtecksignals. Trotzdem zeigt die Analyse eindrucksvoll, dass für zeitkritische Aufgaben nur eine Implementierung in C/C++ infrage kommt. Die softwaretechnisch bequemste Variante ist dann aus meiner Sicht der Einsatz der Wiring Pi Library.

Aufnahme läuft!

WiringPi ist nicht im Repository von Raspbian Wheezy enthalten. Man muss es daher zunächst von der Webseite herunterladen und installieren. Die Programmierung gegen WiringPi ist relativ einfach und verständlich. Wer schon einmal einen Arduino Sketch programmiert hat, findet sich hier sofort zurecht.

Der Sourcecode eines vollständigen C++ Programms zum Dekodieren des vom RX868 gelieferten Datenstroms ist im Github Repository TempHygroRX868 verfügbar. Klonen, compilieren und Ausführen des Programms erfolgen in gewohnter Weise mittels

git clone https://github.com/skaringa/TempHygroRX868.git
cd TempHygroRX868
make
sudo ./rxdec

Als Abtastintervall wählte ich 200 µs. Das ist einerseits deutlich unter den geforderten 366 µs, andererseits kann die WiringPi Funktion delayMicroseconds() dieses Intervall durch Abgabe der Kontrolle zurück an den Linuxkernel realisieren. Kleinere Werte als 100 µs implementiert WiringPi dagegen mit einer internen Programmschleife, das dürfte die CPU-Last in die Höhe treiben. Bei den verwendeten 200 µs beträgt die CPU-Last dagegen nur etwa 14 % auf einem Raspberry Pi B+, was ein durchaus akzeptabler Wert ist.

Die Dekodierung der empfangenen Datenframes ist in der Klasse Decoder implementiert. Das Hauptprogramm rxdec.cpp lagert das Auslesen der GPIO mittels digitalRead() und die Dekodierung in den separaten Thread decoderThread aus, der durch die Anweisung piHiPri(50) mit einer erhöhten Priorität läuft.

Die main() Funktion wartet auf die Bereitstellung eines vollständig dekodierten Datenframes durch decoderThread und gibt die Sensordaten dann mittels printDecoderOutput auf der Konsole aus. Zum Beispiel:

time: 10/11/15 13:53:34
sensor type: Thermo/Hygro
address: 4
temperature: 16.8
humidity: 57.7

time: 10/11/15 13:54:31
sensor type: Kombi
address: 1
temperature: 11.9
humidity: 54
wind: 0.0
rain sum: 664
rain detector: 0

Möchte man die Sensordaten nicht nur ausgeben, sondern zum Beispiel in eine Round Robin Datenbank schreiben, dann muss man den Aufruf von printDecoderOutput in der main() Funktion ersetzen. Da Datenerfassung und Ausgabe in zwei verschiedenen Threads parallel ablaufen, ist dieser Programmteil auch nicht besonders zeitkritisch:

  while (keepRunning) {
    piLock(1);
    if (hasOut) { 
      hasOut = 0;
      piUnlock(1);
      // print data
      printDecoderOutput(out);
    }
    piUnlock(1);
    delay(100);
  }
Aufbau innen
Abb. 1: Montage des Empfangsmodul RX868-SH: Mittels einer abgewinkelten Buchsenleiste sitzt es direkt auf der GPIO-Steckerleiste des RasPi.

Finish

Das Empfangsmodul RX868-SH ist mittels einer abgewinkelten Buchsenleiste direkt auf den GPIO-Port des Raspberry Pi montiert (Abb. 1). Es passt mit in ein entsprechendes Gehäuse (Abb. am Artikelanfang). Die Antenne befindet sich ebenfalls innerhalb des Gehäuses, trotzdem sind die Empfangseigenschaften hervorragend. Mit Hilfe der vorgestellten Software lässt sich auf diese Art und Weise ein USB-WDE 1 komplett ersetzen. Das ist gut zu wissen, falls der Hersteller auch hier - wie bei den Sensoren - die Produktion einstellt.

Falls man auch die selbstgebauten Sensoren verwendet, dann hat man jetzt beide Enden der drahtlosen Übertragungsstrecke in der Hand. Damit wären eigene Modifikationen des Datenübertragungsprotokolls möglich! Zum Beispiel die Übertragung zusätzlicher Messwerte, wie der Batteriespannung des Sensors.

Eine Alternative zum RX868, das auf einer festen Frequenz empfängt, ist der Einsatz eines einfachen Software Defined Radios, wie ich ihn in Empfang von Wettersensordaten mit RTL-SDR beschrieben habe. Diese Lösung lastet allerdings den Raspberry Pi erheblich stärker aus (um die 90 % CPU-Last), ist dafür aber auch auf anderen Computern einsetzbar, die nur über einen USB Anschluss verfügen.