RadioHead Serial-Radio-Gateway

Da in diversen Projekten und Beschreibungen von mir immer wieder von einem Serial-Radio-Gateway (oder auch Radio-Serial-Gateway) für das RadioHead-Protokoll die Rede ist, möchte ich dieses Gateway hier kurz beschreiben.

Was ist ein Gateway?

Allgemein gesagt ist ein Gateway eine Komponente aus Hardware und/oder Software, welche zwei Systeme miteinander verbindet.

In diesem Fall stellt das Gateway die Verbindung zwischen dem 433 MHz Funk und einer seriellen Schnittstelle her. Das RadioHead-Protokoll wird dabei beibehalten. Dadurch wird es sehr einfach möglich, den RadioHead 433 MHz Funk von diversen Mikrocontrollern an einen PC oder Raspberry Pi anzubinden.

Hardware

Die Hardware ist sehr einfach. Als Basis nehmen wir einen Arduino Nano (oder einen anderen Arduino mit USB-Schnittstelle) und schließen an diesen je einen 433 MHz Funkempfänger und Funksender an. Dabei wird VCC der Module auf +5 V des Arduinos und GND der Module auf GND vom Arduino verbunden. Die Data-Leitung des Empfängers kommt an D2 und die des Senders an D4 beim Arduino.

Aufbau der Hardware auf einem Steckbrett

Fertig!

Hinweis

Ich empfehle bei den Funkmodulen zumindest für den Empfänger Module vom Typ Superheterodyne oder 3400RF zu verwenden, da diese deutlich höhere Reichweiten als die günstigeren XY-MK-5V ermöglichen.

Software

Die Software für den Arduino ist ähnlich simpel. Hier muss nur in der Arduino IDE die RadioHead Bibliothek hinzugefügt werden (wenn nicht schon gesehen) und der folgende Sketch, den ich größtenteils aus den original RadioHead Beispielen entnommen habe, auf den Arduino geladen werden:

Arduino Sketch für das Serial-Radio Gateway
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <SPI.h>
#include <RH_ASK.h>
#include <RH_Serial.h>
#include <RHReliableDatagram.h>

RH_ASK radio(2000, 2, 4);

RH_Serial serial(Serial);

void setup()
{
Serial.begin(9600);
if (!radio.init())
Serial.println("radio init failed");

radio.setPromiscuous(true);

if (!serial.init())
Serial.println("serial init failed");

serial.setPromiscuous(true);

}

uint8_t buf[RH_SERIAL_MAX_MESSAGE_LEN];

void loop()
{
if (radio.available())
{
uint8_t len = sizeof(buf);
radio.recv(buf, &len);

serial.setHeaderTo(radio.headerTo());
serial.setHeaderFrom(radio.headerFrom());
serial.setHeaderId(radio.headerId());
serial.setHeaderFlags(radio.headerFlags(), 0xFF);
serial.send(buf, len);
}

if (serial.available())
{
uint8_t len = sizeof(buf);
serial.recv(buf, &len);

// Optional: Nachrichten nach Adresse filtern
// Kommentar vor den folgenden Zeilen entfernen, um nur Nachrichten an Adressen 0xC0 oder höher weiterzuleiten.
// if(serial.headerTo() < 0xC0){
// return;
// }

radio.setHeaderTo(serial.headerTo());
radio.setHeaderFrom(serial.headerFrom());
radio.setHeaderId(serial.headerId());
radio.setHeaderFlags(serial.headerFlags(), 0xFF);
radio.send(buf, len);
}
}

Damit ist dann das Serial-Radio-Gateway auch schon fertig und einsatzbereit. 🙂

Funktionsweise

Der als Gateway fungierende Arduino empfängt sowohl über den 433 MHz Funk, als auch über die serielle Schnittstelle die RadioHead Datenpakete für beliebige Adressen (Promiscuous-Mode) und sendet diese anschließend wieder über die jeweils andere Schnittstelle. Dabei werden die Headerdaten und der Inhalt der Datenpakete eins zu eins übernommen.

Somit wird jede über den Funk empfangene Nachricht an die serielle Schnittstelle und jede über seriell empfange Nachricht per Funk weitergeleitet.

Verarbeitung der Daten am PC / Raspberry Pi

Die vom Gateway an den PC oder Raspberry Pi weitergeleiteten Daten können hier nicht direkt in einem Terminal oder seriellen Monitor angezeigt werden, da es sich quasi um Binärdaten des RadioHead-Protokolls handelt. Versuche die Daten beispielsweise im seriellen Monitor der Arduino IDE anzuzeigen resultieren nur in wirren Zeichen. Das ist Ok so!

Zur weiteren Verarbeitung der Daten muss die Software das RadioHead-Protokoll, genauer gesagt RH_Serial, verstehen können.

Hierzu habe ich für Node.js das Modul radiohead-serial erstellt, welches das RadioHead-Protokoll mit RH_Serial in Node.js umsetzt. Auf diesem Modul basierend habe ich zudem für ioBroker den Adapter ioBroker.radiohead erstellt, wodurch RadioHead relativ einfach in diese Heimautomatisierung eingebunden werden kann.

Für Anwendungen in C/C++ können direkt die RadioHead Quellen genutzt werden, um RH_Serial zu integrieren.