Beliebige Sensoren via LoRa über Entfernugen von > 1 km anbinden

Begonnen von Persuasiv, 28 Juli 2019, 22:07:27

Vorheriges Thema - Nächstes Thema

Persuasiv

Hallo,

mein Gelände ist weitläufig. Deswegen muss ich Sensordaten über ~100 m verschicken. Eine Glasfaseranbindung der Nebengebäude existiert nicht. Dazu bietet sich LoRa an. Damit können Entfernungen von > 1 km legal überbrückt werden. Mit einer kurzen Drahtantenne sind 100 m inkl. zwei Häuserwänden oder 20 m und drei ca. 30 cm dicke Betondecken realistisch. Laut meiner Simulation gehen unter optimalen Bedingungen auch 35 km @433 MHz.

Grundsätzlich sieht die Idee bei der Umsetzung so aus: Erfassung der Messwerte → Kodieren der Messwerte via Keyvalueprotokoll → Verschicken der Werte → Empfangen der Werte → Übergabe der Messwerte an FHEM → Darstellung der Messwerte

Für den Empfänger nutze ich den leicht abgewandelten Code von Adafruit für den Feather 32u4 LoRa:
#include <SPI.h>
#include <RH_RF95.h>

#define RFM95_CS 8
#define RFM95_RST 4
#define RFM95_INT 7
#define LED 13
#define RF95_FREQ 868.0
RH_RF95 rf95(RFM95_CS, RFM95_INT);

void setup()
{
  pinMode(LED, OUTPUT);     
  pinMode(RFM95_RST, OUTPUT);
  digitalWrite(RFM95_RST, HIGH);
  Serial.begin(9600);
  delay(100);
  digitalWrite(RFM95_RST, LOW);
  delay(10);
  digitalWrite(RFM95_RST, HIGH);
  delay(10);

  while (!rf95.init())
  {
Serial.println("Initialisierung fehlgeschlagen!");
while (1);
  }
  Serial.println("Initialisierung erfolgreich abgeschlossen!");

  if (!rf95.setFrequency(RF95_FREQ))
  {
Serial.println("setFrequency failed");
while (1);
  }
  Serial.print("Set Freq to: "); Serial.println(RF95_FREQ);
  rf95.setTxPower(10, false);
}

void loop()
{
  if (rf95.available())
  {
uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];
uint8_t len = sizeof(buf);

if (rf95.recv(buf, &len))
{
  digitalWrite(LED, LOW);
  Serial.print("OK VALUES ");
  Serial.print((char*)buf);
  Serial.print(",R=");
  Serial.println(rf95.lastRssi(), DEC);
  Serial.println();
}
  }
}


Die Erfassung, die Aufbereitung und der Versand erfolgen dann so (hier wird ein RCWL-0516 ausgewertet):

#include <Adafruit_Sensor.h>
#define LOG_PERIOD 300000

#include <SPI.h>
#include <RH_RF95.h>
#include <Wire.h>                                                                     

#define RFM95_CS 8                                                                   
#define RFM95_RST 4
#define RFM95_INT 7
#define VBATPIN A9
#define RF95_FREQ 868.0                                                             


RH_RF95 rf95(RFM95_CS, RFM95_INT);                                                   


String type = "BW";                                                               
uint8_t SenderID = 1;   
String message = "";                                                                 
unsigned long previousMillis;                         

const int pinradar = 0;                                       

int feindkontakte = 0;
int bewegung = 0;

String Stringkonvertierung0(float Wert) {
  char charBuff[10];
  dtostrf(Wert,2, 0, charBuff);
  return charBuff;
}

void setup()
  {
    pinMode(13, OUTPUT);
    Serial.begin(115200);
    Serial1.begin(115200);
    pinMode(pinradar, INPUT);     
    pinMode(RFM95_RST, OUTPUT);
    digitalWrite(RFM95_RST, HIGH); 
                                                                                   
    delay(100);
                                                                                     
    digitalWrite(RFM95_RST, LOW);                                                     
    delay(10);
    digitalWrite(RFM95_RST, HIGH);
    delay(10);
 
    while (!rf95.init())
{
  Serial.println("Initialisierung fehlgeschlagen!");
  while (1);
}
                                                                                 
    if (!rf95.setFrequency(RF95_FREQ))
{
  Serial.println("Frequenzeinstellung fehlgeschlagen!");
  while (1);
}

    rf95.setTxPower(5, false);                                                           
  }


void loop()
  {
   
    if(digitalRead(pinradar)==LOW)
      {
        digitalWrite(13, LOW);         
      }
   
   
    if(digitalRead(pinradar)==HIGH)
      {
        feindkontakte++;
        bewegung = 1;
        digitalWrite(13, HIGH);
        delay(1000);
      }

 
  unsigned long currentMillis = millis();
 
  if(currentMillis - previousMillis > LOG_PERIOD)
    {
        previousMillis = currentMillis;   
       
        message = type+" "+String(SenderID)+" A="+Stringkonvertierung0(bewegung)+",F="+Stringkonvertierung0(feindkontakte);
       
        int messageSize = message.length()+1;
        char radiopacket[messageSize];
        message.toCharArray(radiopacket, messageSize);
           
        rf95.send((uint8_t *)radiopacket, messageSize);
        rf95.waitPacketSent();

        feindkontakte = 0;
        bewegung = 0;
    }
   
}


Die Übergabe der Messwerte erfolgt so:
defmod Empfaenger JeeLink /dev/serial/by-id/usb-Adafruit_Feather_32u4-if00@9600

In Fhem wird direkt ein Nodespezifischer FileLog angelegt. Diesen kann man dann nutzen, um z. B. Plots anfertigen zu können. Die Sensoren werden bei mir zumeist mit vier 18650er Akkus betrieben. Daraus ergibt sich eine Akkulaufzeit von ca. einem Jahr.

Verwendete Hardware:
https://www.adafruit.com/product/3078

Müsste auch gehen (ungetestet):
https://www.ebay.de/itm/2-x-LoRa32u4-II-Development-Board-IOT-LiPo-Atmega328-SX1276-HPD13-868mhz-Antenna/163801909356?hash=item26235ac86c:m:mF6GRPJv6lUBfrKhk6s2aPQ


blueberry63

Es gibt schon einen Thread zu LoRa:

https://forum.fhem.de/index.php/topic,63856.0.html

Ich habe mich noch nicht mit dem Thema beschäftigt, aber vielleicht solltet ihr euch zusammen tun.

FHEM auf BBB mit Wheezy: 1x CUL_HM_HM_SCI_3_FM, 1x INSTAR CAM3010, 1x HM-LC-SW1-PL2, 1x HM-LC-Bl1PBU-FM, 1x HM-Sen-MDIR-O, Viessmann Heizung, Gaszähler via GPIO, Klingel via HM-LC-Bl1PBU-FM an FBox, Mailcheck, AVR, XBMC, NanoCUL 433+668 an Raspi per Ethernet, Funksteckdosen (Pollin, IT), Automower

Persuasiv

Bisher hat niemand eine alternative Lösung gepostet :( Aktuell verzweifel ich an meinem Seismograf. FHEM kommt mit der Datenmenge (1,3 Mrd. Messwerte pro Jahr) nicht klar ...

Tobias

super interessant,
du verwendest den Feather sowohl als Sender als auch Empfänger ?
Theoretisch wäre es egal ob man 868 oder 433MHZ verwendet? (natürlich bei Sender und Empfänger identisch)
Wäre eine Batterienutzung auch möglich wenn das Modul permanent aktiviert ist um auf Befehle zu reagieren?
Maintainer: Text2Speech, TrashCal, MediaList

Meine Projekte: https://github.com/tobiasfaust
* PumpControl v2: allround Bewässerungssteuerung mit ESP und FHEM
* Ein Modbus RS485 zu MQTT Gateway für SolarWechselrichter

Persuasiv

Ich verwende die Feather als Sender und als Empfänger. Die Frequenz spielt schon eine Rolle.


433 MHz868 MHz
Antennenlänge~16,5 cm~8,2 cm
BandISM-Band Region 1SRD-Band Europa
Anzahl Störsenderhochklein
Reichweitehöherhoch

@869,4 MHz sind sogar Sendeleistungen von 500 mW erlaubt. Eine Batterienutzung ist bei permanentem Empfang unmöglich, wenn man einen Feather verwendet. D. h. das hier gezeigte Beispiel eignet sich nur für autonome Sensoren. Man darf auch nicht den Fehler begehen und den deutlich leistungsstärkeren Feather M0 verwenden zu wollen. Es besteht ein Bug in der Sleepydog-Library. Dieser wird auch nicht mehr gefixt. Ich habe den Fehler vor über zwei Jahren gemeldet: https://github.com/adafruit/Adafruit_SleepyDog/issues/13

Shojo

Zitat von: Persuasiv am 08 August 2019, 21:40:26
FHEM kommt mit der Datenmenge (1,3 Mrd. Messwerte pro Jahr) nicht klar ...

Sowas würde ich auch in eine InfluxDB oder der gleichen speichern.
Und mit Grafana auswerten.

Hier mal paar Links:
FHEM auf: Shuttle PC (x64) (Docker)
Bridge: SignalESP 433mHz, ConBee (deCONZ in Docker)
Rest: ESP8266, SONOFF, Sonos, Echo Dot, Xiaomi Vacuum (root), ESP RGBWW Wifi Led Controller, Node-RED, LEDMatrix, Pixel It

Tobias

danke für die Info, was meinst du mit autonome sensoren? Ich habe in deinem Sketch keine explizite (De-)Aktivierung des Sendemoduls wenn der MessageString gesendet werden soll gesehen.
Mein UseCase ist, 1-3mal pro Tag wird eine Message an den LoRaWan BatterieClient gesendet und dieser soll sofort drauf reagieren. Ist aus deiner Sicht eine Batterienutzung möglich?
Maintainer: Text2Speech, TrashCal, MediaList

Meine Projekte: https://github.com/tobiasfaust
* PumpControl v2: allround Bewässerungssteuerung mit ESP und FHEM
* Ein Modbus RS485 zu MQTT Gateway für SolarWechselrichter

Persuasiv

#7
Autonome Sensoren erfassen alle x Minuten einen Messwert und schicken diesen zum Server. Dabei wird nicht überprüft, ob der Server die Nachricht erhalten hat. Letzteres macht keinen Sinn, weil Störsender meist zu lange aktiv sind. Dadurch würde die Akkulaufzeit zu stark leiden. Anbei kann man die stark schwankende Signalqualität nachvollziehen. Der Sender + Empfänger wurden dabei zu keinem Zeitpunkt bewegt.

Der obige Node läuft die ganze Zeit am Server und eignet sich nicht für den Akkubetrieb. Dazu muss man die SleepyDog-Library einbinden:

#include "Adafruit_SleepyDog.h"

und den Feather 5 Minuten in den DeepSleep schicken:


  int n = 37;                                                                           //Watchdog sleep max 8 sek je Zyklus
  int i = 1;

  while (i <= n)
    {
      i = i + 1;
      Watchdog.sleep(8000);
    }
  Watchdog.disable();

// mache beliebiges ....

  Watchdog.enable();


ZitatMein UseCase ist, 1-3mal pro Tag wird eine Message an den LoRaWan BatterieClient gesendet und dieser soll sofort drauf reagieren. Ist aus deiner Sicht eine Batterienutzung möglich?

Mit dem Feather auf keinen Fall. Im DeepSleep zieht er ~300 µA. Wenn das Radio aktiv ist, dann sind es ~13 mA. Meine Sensoren brauchen inkl. der Datenübertragung (alle 5 Minuten) im Schnitt ca. 2 mA.