Raspberry Pi (Zero W) mit RFM95W als Funk-Sensor-Daten-Empfänger

Zu meinem ersten Funk-Aussensensor wollte ich jetzt noch einen kleinen, einfachen Empfänger auf Basis eines Rasperry Pi Zero W haben um nicht gleich einen großen Raspberry Pi damit zu  belegen wenn ich nur einen Empfänger für die Sensordaten haben möchte und keine Übertragung über das TTN gehen soll.

Man kann das Modul natürlich auch auf andere Rasperry Pi Versionen aufsetzen.

Also habe ich eine kleine Platine entworfen auf der sich ein RFM95W Modul, eine LED inkl. Vorwiderstand, eine Antennenbuchse sowie eine Buchsenleiste befindet.

Aussehen tut die Platine so…
RFM95W-RPI-SCG-PCB Raspberry Pi (Zero W) mit RFM95W als Funk-Sensor-Daten-EmpfängerSie ist quasi die kleine Schwester der Version mit integriertem 1-Wire Adapter. Mein erster Sensor sendet alle 2 Minuten eine Nachricht die wie folgt aufgebaut ist:

*SENSORID|TEMPERATUR|ADC-WERT HELLIGKEIT#

Diese Nachricht wird dann vom Raspberry Pi Zero W empfangen und in einer Datei unter /tmp abgelegt. Ein Python Script schaut laufend ob sich eine bestimmte Datei im Ordner /tmp befindet und liest diese ggf. aus und sendet die Daten per UDP an meinen Loxone Miniserver.

Fertig aufgebaut schaut es dann so aus…
RFM95W-RPI-SCG-Fertig-solo Raspberry Pi (Zero W) mit RFM95W als Funk-Sensor-Daten-Empfänger

…und aufgesetzt auf einen Raspberry Pi Zero W  dann so…
RFM95W-RPI-SCG-Fertig Raspberry Pi (Zero W) mit RFM95W als Funk-Sensor-Daten-EmpfängerDiese Kombination kann auch super genutzt werden um ein sehr günstiges LoRa™ Gateway für z.B. The Things Network aufzubauen.

Folgende Kontakte des Raspberry Pi Pinheader werden benutzt…
RFM95W-SCG-Anschlussbelegung-RPi Raspberry Pi (Zero W) mit RFM95W als Funk-Sensor-Daten-EmpfängerQuelle: http://www.element14.com

Wichtiger Hinweis !!!

Funkmodule, wie das hier eingesetzte RFM95W NIE ohne angeschlossene Antenne betreiben, die nicht abgeführte Leistung kann die Module zerstören.

Hier noch ein paar Worte zur eingesetzten Software. Auf dem Raspberry Pi Zero W läuft ein Raspbian Lite, dieses habe ich so konfiguriert das es zum größten Teil Read only funktioniert um die SD Karte zu schonen.

Eine tolle Anleitung dazu findet man unter https://kofler.info/raspbian-lite-fuer-den-read-only-betrieb/.

Um das RFM95W Modul anzusprechen muss in der raspi-config unter Interfaces das SPI Interface aktiviert werden, dann kommt bei mir eine angepasste Software zum Einsatz dessen Sourcen man unter https://github.com/dragino/rpi-lora-tranceiver finden kann.

Von dieser Software nutze ich den Teil unter /dragino_lora_app, ich habe die main.c wie folgt angepasst:

/*******************************************************************************
*
* Configure these values!
*
*******************************************************************************/

// SX1272 - Raspberry connections
int ssPin = 10;
int dio0 = 7;
int RST = 0;

// LED for signaling
int LED = 3;

// Set spreading factor (SF7 - SF12)
sf_t sf = SF10;

// Set center frequency
uint32_t freq = 868100000; // in Mhz! (868.1)

byte hello[32] = "*#";

Weiterhin habe ich dann die eigentlichen Empfangsroutinen abgeändert, diese sehen jetzt so aus…

boolean receive(char *payload) {
    // clear rxDone
    digitalWrite(LED, HIGH);
    writeReg(REG_IRQ_FLAGS, 0x40);

    int irqflags = readReg(REG_IRQ_FLAGS);

    //  payload crc: 0x20
    if((irqflags & 0x20) == 0x20)
    {
        printf("CRC error\n");
        writeReg(REG_IRQ_FLAGS, 0x20);
        digitalWrite(LED, LOW);
        return false;
    } else {

        byte currentAddr = readReg(REG_FIFO_RX_CURRENT_ADDR);
        byte receivedCount = readReg(REG_RX_NB_BYTES);
        receivedbytes = receivedCount;

        writeReg(REG_FIFO_ADDR_PTR, currentAddr);

        for(int i = 0; i < receivedCount; i++)
        {
            payload[i] = (char)readReg(REG_FIFO);
        }
    }
    return true;
}

in der receivepacket() Routine erzeuge ich dann die Datei wie folgt…

            printf("Packet RSSI: %d, ", readReg(0x1A)-rssicorr);
            printf("RSSI: %d, ", readReg(0x1B)-rssicorr);
            printf("SNR: %li, ", SNR);
            printf("Length: %i", (int)receivedbytes);
            printf("\n");
            printf("Payload: %s\n", message);

            // Dateizeiger erstellen
            FILE *fp;

            // Datei oeffnen
            fp = fopen("/tmp/rfm95w_sensor_data.txt", "w");

            if(fp == NULL) {
                printf("Datei konnte NICHT geoeffnet werden.\n");
            }else {
                time_t rawtime;
                time (rawtime);
                localtime (rawtime);  
                fputs(ctimerawtime), fp);

                for(int i=0; i < (int)receivedbytes; i++) {
                        fputc(message[i], fp);
                }

                // Datei schliessen
                fclose(fp);

Abschließend schalte ich in der gleichen Routine vor der abschließenden geschweiften Klammer noch die LED wieder aus.

digitalWrite(LED, LOW);

Danach werden die Sourcen noch mit einem sudo make übersetzt und dannach kann das Programm mit sudo ./dragino_lora_app rec gestartet werden.

Die Ausgabe sieht dann bei mir wie folgt aus…

SX1276 detected, starting.
Listening at SF10 on 868.100000 Mhz.
——————

Wurde ein Datenpaket empfangen sieht es dann z.B. so aus…

SX1276 detected, starting.
Listening at SF10 on 868.100000 Mhz.
——————
Packet RSSI: -71, RSSI: -98, SNR: 9, Length: 28
Payload: *28ffd1d46b180174|16.56|274#

Als eindeutige Sensor ID nutze ich die 64Bit ID des eingesetzen DS18B20 😉

Es wird dann unter /tmp eine Datei mit dem Namen rfm95w_sensor_data.txt erzeugt die von folgendem Python Script ausgelesen wird, und die enthaltenen Daten  werden dann per UDP an meinen Loxone Miniserver gesendet.

#!/usr/bin/env python

import time
import socket
import os
  
# hier die IP Adresse des eigenen Miniservers eintragen
UDP_IP = "LOXONE MINISERVER IP"
# hier die Port Nummer des UDP Eingangs eintragen
UDP_PORT = LOXONE MINISERVER UDP PORT
FILENAME = "/tmp/rfm95w_sensor_data.txt"
LASTMESSAGETEMP = ""
LASTMESSAGELIGHT = ""
 
while True:

 try:
  if os.path.exists(FILENAME):
   if os.system("file -b " + FILENAME + " | grep text &amp;gt; /dev/null") == 0: 
    tempfile = open(FILENAME)
    data_temp = tempfile.read()
    tempfile.close()

    os.remove(FILENAME)

    if len(data_temp) > 19:
      data_array = data_temp.split("*")
    
      if len(data_array) > 1:
        data_array = data_array[1].split("|")
        sensorid = data_array[0]
        temperature = data_array[1]
     
        MESSAGETEMP = str(sensorid)+":Temp=" + str(temperature)

        if MESSAGETEMP != LASTMESSAGETEMP:
          sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
          sock.sendto(MESSAGETEMP, (UDP_IP, UDP_PORT))

          LASTMESSAGETEMP = MESSAGETEMP 

          print MESSAGETEMP

        if len(data_array) > 2:
          data_array = data_array[2].split("#")
          
          if len(data_array) > 0:
            light =  data_array[0]

            MESSAGELIGHT = str(sensorid) + ":Light=" + str(light) 

            if MESSAGELIGHT != LASTMESSAGELIGHT:
              sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
              sock.sendto(MESSAGELIGHT, (UDP_IP, UDP_PORT))

              LASTMESSAGELIGHT = MESSAGELIGHT 

              print MESSAGELIGHT 
 except:
  pass

 time.sleep(1)

Da ich bisher noch nicht viel mit Python gearbeitet habe sei mir der Programmierstil verziehen, da es aber seit nunmehr einer Woche funktioniert bin ich damit zufrieden 🙂

Als kleines Gimmick habe ich noch ein Script laufen welches mir die Temperatur der Raspberry Pi Zero W CPU übermittelt..

#!/usr/bin/env python
 
import time
import socket
import os
import uuid
import re
  
# hier die IP Adresse des eigenen Miniservers eintragen
UDP_IP = "LOXONE MINISERVER IP"
# hier die Port Nummer des UDP Eingangs eintragen
UDP_PORT = LOXONE MINISERVER UDP PORT
 
while True:
 
    tempFile = open("/sys/class/thermal/thermal_zone0/temp")
    cpu_temp = tempFile.read()
    tempFile.close()

    CPU_Temp = float(cpu_temp)/1000

    mac = (':'.join(re.findall('..', '%012x' % uuid.getnode())))
 
    MESSAGE = mac + "|CPU_Temp=" + str(CPU_Temp)
 
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
    sock.sendto(MESSAGE, (UDP_IP, UDP_PORT))
 
    time.sleep(60)

Die Einbindung in der Loxone Config erfolgt dann wie folgt…

Zuerst legt man sich am besten eine Seite nur für die Funk-Sensoren an, ich nennen sie bei mir RFM95W Lora Funk Sensoren.
RFM95W-Sensor-Einbindung-in-Loxone-Config-0 Raspberry Pi (Zero W) mit RFM95W als Funk-Sensor-Daten-Empfänger
Danach legt man einen virtuellen UDP Eingang an…
RFM95W-Sensor-Einbindung-in-Loxone-Config-1 Raspberry Pi (Zero W) mit RFM95W als Funk-Sensor-Daten-EmpfängerWichtig ist das der Port derjenige ist an den auch unser Python Script die Daten versendet.

Jetzt legt man einen virtuellen UDP Eingang Befehl an…
RFM95W-Sensor-Einbindung-in-Loxone-Config-2 Raspberry Pi (Zero W) mit RFM95W als Funk-Sensor-Daten-EmpfängerHierbei ist ganz wichtig das in der Zeile Befehlserkennung am Anfang die ID unseres Sensors (in meinem Fall die ID des DS18B20) steht, gefolgt von einem Doppelpunkt und danach Temp=\v .

Wie die Daten den Loxone Miniserver erreichen kann man sich im UDP Monitor ansehen…
Loxone-UDP-Monitor-RFM95W-Sensor-Daten-1 Raspberry Pi (Zero W) mit RFM95W als Funk-Sensor-Daten-EmpfängerDie ersten beiden markierten Zeilen zeigen die Daten die vom Funk-Sensor kommen, die Zeile danach sind die Daten meines zweiten Scripts welches die Temperatur der Raspberry Pi Zero W CPU überträgt.

Die Darstellung der Werte konfiguriert man jetzt noch passend für z.B. Temperaturen…
RFM95W-Sensor-Einbindung-in-Loxone-Config-3 Raspberry Pi (Zero W) mit RFM95W als Funk-Sensor-Daten-Empfänger
Jetzt zieht man den neuen virtuellen Eingang Befehl noch auf die Seite und fertig 😉

Bei der Anzeige der Helligkeit nutze ich einen Statusbaustein den ich mir wie folgt Konfiguriert habe…
RFM95W-Sensor-Einbindung-in-Loxone-Config-4 Raspberry Pi (Zero W) mit RFM95W als Funk-Sensor-Daten-Empfänger
Der Ausgang des Status Bausteins geht dann auf einen virtuellen Status baustein der zur Anzeige der Werte auf der Webseite genutzt wird, er ist so eingestellt…
RFM95W-Sensor-Einbindung-in-Loxone-Config-5 Raspberry Pi (Zero W) mit RFM95W als Funk-Sensor-Daten-Empfänger

So sieht mein Ergebnis dann aus…

RFM95W-LORA-FUNK-SENSOREN-IN-LOXONE Raspberry Pi (Zero W) mit RFM95W als Funk-Sensor-Daten-EmpfängerDie Platine sowie einen Bausatz und auch die Antenne findet man wie immer im Blog Shop.

Verlinke diesen Beitrag:

<a href="https://blog.thomasheldt.de/raspberry-pi-zero-w-mit-rfm95w-als-funk-sensor-daten-empfaenger/">Raspberry Pi (Zero W) mit RFM95W als Funk-Sensor-Daten-Empfänger</a>

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.