LoRaWAN-Zisterne


Bei diesem Projekt ging es darum, den Füllstand einer Zisterne online anzuzeigen. Da die Zisterne auf einem Grundstück außerhalb der WLAN Versorgung ist, bot sich LoRAWAN als kostenlose Alternative zu GSM an. Leider gibt es LoRaWAN in Deutschland noch nicht flächendeckend. Wir haben aber mit C-Hack vor, zumindest unsere Gegend weitreichend zu versorgen.

Den Füllstand messe ich durch Ultraschallabstandsmessung vom Rand der Zisterne herunter auf die Wasseroberfläche.

Ich habe mich dabei für folgende Komponenten entschieden:

Hier die Links zu den verwendeten Services:

Wasserstandmessung

Ich habe aus einem Aluwinkel und einem Block Polyamid eine Halterung für den Sensor gebaut, die ich an den Rand der Zisterne gedübelt habe. Man muss natürlich aufpassen, dass dort keine Schläuche unterhalb verlaufen, die das Messergebnis verfälschen könnten.

Bild "LORAWAN_Sensor.jpg"

Bild "LORAWAN_SensorMontiert.jpg"

Bild "LORAWAN_SensorTestaufbau.jpg"

Der Sensor ähnelt sehr den Standard Ultraschallsensoren HC-SR04, wie sie für Arduino in Robotikapplikationen eingesetzt werden. Bei der wasserdichten Version ist der eigentliche Sensor mit einem 2m Kabel mit der Platine verbunden. Ich musste das Kabel auf 3m verlängern.

Bild "LORAWAN_SensorTestlauf.jpg"

Auf der Platine des Sensors sind die Pins für Power, Ground, Senden des Pulses und empfangen des Echos beschriftet.
Der Arduino-Code ist identisch zu dem für HC-SR04.

long Abstand() {
  long duration, cm;

  pinMode(pingPin,OUTPUT);     // Pins vorbereiten
  pinMode(start_signal,OUTPUT);
  digitalWrite(start_signal,HIGH);
  delayMicroseconds(20);

  digitalWrite(start_signal,LOW);  // Starte Messung mit fallender Flanke
  digitalWrite(pingPin,LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin,HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin,LOW);
  pinMode(pingPin,INPUT);

  duration = pulseIn(pingPin,HIGH);  // Messung der Verzögerung bis Echo
  cm = duration / 29 / 2 ;
  
  return cm;
}


Hier könnte man jetzt schon aufhören und den Arduino z.B. mit drei LEDs (Grün - Gelb - Rot) den Wasserstand anzeigen lassen. Ich möchte den Wasserstand aber auch mobil abfragen, ohne zur Zisterne zu fahren.

LoRaWAN und TheThingsNetwork


TheThingsNetwork vernetzt tausende LoRaWAN-Gateways weltweit und ermöglicht so, dass ein angeschlossener Sensornode im Internet sichtbar wird. Da die ganze Sache verschlüsselt abläuft bleiben die Daten privat.
Um teilzunehmen braucht man einen User-Account bei https://www.thethingsnetwork.org/
Hier gibt es weitere Erklärungen zur Einrichtung eines Sensorknotens:
http://c-hack.de/projekte/lorawan

Draguino-Shield

Ich habe mich für den Anfang für das Draguino-Shield entschieden. Insbesondere deswegen, weil der das LoRA-Modul HopeRF RFM95W verwendet, das es auch günstig einzeln zu kaufen gibt. Für weitere Projekte werde ich eine spezielle Hardware auf Basis dieses Moduls entwickeln.

Bild "LORAWAN_Elektronik.jpg"

Das Draguino-Shield führt die IO-Pins des Arduino nach oben, so dass sich der Ultraschallsensor auch anschließen lässt.

Netzteil-Hack

Ein altes Nokia Ladegerät lag noch im Keller herum. Auch, wenn auf dem Gehäuse 6.2V spezifiziert sind, liefert es ca. 8V, was prima als Rohversorgungsspannung für den Arduino geeignet ist.

Bild "LORAWAN_Netzteil1.jpg"

Bild "LORAWAN_Netzteil2.jpg"

Da das Netzteil über Dosenklemmen mit starrem NYM Drähten verbunden werden soll, habe ich die Steckerpins durch 0.75mm² NYM ersetzt.

Bild "LORAWAN_Netzteil3.jpg"

Bild "LORAWAN_ElektronikKomplettt.jpg"

In einem wasserdichten IP54 Gehäuse findet dann die ganze Elektronik Platz. Der LoRa-Empfang funktioniert noch, wenn die Kiste dicht unter der Erdoberfläche vergraben ist.

Bild "LORAWAN_Gehäuse.jpg"

Software auf dem Arduino

Basiert auf dem Beispiel der LMIC-Library habe ich meinen Code entwickelt. Da die Anzeige grafisch erfolgen sollte, habe ich die Daten im Cayenne-Format erzeugt. Hierzu braucht man die Cayenne Library und am Anfang des Codes die folgenden Includes:

#include <lmic.h>
#include <hal/hal.h>
#include <SPI.h>
#include <CayenneLPP.h>


Nachdem man sich einen Login bei TheThingsNetwork (TTN) erzeugt hat, legt man dort einen neuen Sensornode an und trägt die Keys in den Code auf dem Arduino ein (TTN erzeugt diese Daten gleich in der richtigen C/C++ - Notation):

u1_t NWKSKEY
u1_t APPSKEY
static const u4_t DEVADDR


Es muss noch eine Anpassung des Codes auf das Draguino-Shield gemacht werden:

// Pin mapping
const lmic_pinmap lmic_pins = {
    .nss = 10,
    .rxtx = LMIC_UNUSED_PIN,
    .rst = 9,
    .dio = {2, 6, 7},
};


Das Senden des Füllstands passiert dann hier:

void onEvent (ev_t ev) {
   lpp.reset();
   lpp.addAnalogInput(1, percentFull);
   if (ev == EV_TXCOMPLETE) os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(TX_INTERVAL), do_send);
}


Die globale Variable "percentFull" wird alle 10 Sekunden mit einer neuen Messung aktualisiert.

Hier die komplette Arduino-Sketch (ohne spezifische Zugangsdaten):
LORAWAN_AdruinoSketch.txt

Datenempfang im TheThingsNetwork

Wenn alles richtig aufgesetzt ist, dann sollten jetzt im Minutentakt neue Daten empfangen werden. Die kann man in der Konsole des TTN angucken:

Bild "LORAWAN_TTN-daten-vom-Node.png"

Das Cayenne-Format erzeugt dabei 4 bytes. Byte 0 und 1 spezifizieren die Nummer des Sensors und das Datenformat. Byte 2 und 3 enthalten die Payload.

Anzeigen in MyDevices-Cayenne

Um die Wasserstand auf PC oder Smartphone anzuzeigen, kann man die Daten von TTN weiter versenden. Ein Möglichkeit ist der Webservice Cayenne. Hierzu installiert man in TTN die entsprechende "Integration":

Bild "LORAWAN_TTN-Integrations-Cayenne.png"

Auch hier muss man sich dann erst mal einen Login bei MyDevices klicken und dann ein neue Device/Widget anlegen:
Add New... --> Devices&Widgets --> LoRa --> The Things Network --> Dragino Technology LoRa Shield --> Dort dann die DeviceEUI angeben.

Bild "LORAWAN_TTN-Cayenne.png"

Anzeigen auf der eigenen Website

Will man nicht einen .com Dienst wie Cayenne verwenden, so kann TTN die Daten auch zu einer beliebigen Website per HTTP POST schicken.
Dazu wählt man die entsprechende Integration für HTTP:

Bild "LORAWAN_TTN-Integrations-HTTP.png"

Dort gibt man die Ziel-URL ein und einen beliebigen Namen. Das ist alles.

Bild "LORAWAN_TTN-http-integration.png"

Damit das Datenformat schön einfach wird, habe ich das direkt in TTN umgerechnet. Das macht man mit wenigen Zeilen JavaScript Code unter der Kategorie "Payload Formats". Das Beispiel ist bereits gut geeignet, um zu zeigen, was man tun muss.
Hier ist meine Routine, bei der Byte 2 und 3 zusammengefasst werden in eine Integer Zahl, die dann per POST verschickt wird:

Bild "LORAWAN_TTN-Payload-Format.png"

Dann braucht man auf dem Webserver noch ein PHP Skript, das die Daten per POST empfängt und im einfachsten Fall eine Webseite erzeugt, die das Ergebnis anzeigt.
TTN sendet die Daten als JSON record, aus dem man die Payload extrahieren muss. PHP hat dazu einen JSON-Parser:

<?php

$received = file_get_contents('php://input');
$datei = fopen("index.html",w);

$json_data = json_decode($received, $assoc = true, $depth = 10);

if($json_data==FALSE or $json_data==NULL)  
{
  fwrite($datei, "Can't parse JSON");
}

$payload = $json_data
["payload_fields"];

$fillLevel = $payload
["fillLevel"];
  
if ($fillLevel > 50) $water_color = "green";
elseif ($fillLevel > 25) $water_color = "yellow";
else $water_color = "red";


Hier habe ich noch drei Farben vergeben, die abhängig vom Wasserstand zur Darstellung benutzt werden können. Im einfachsten Fall zeigt man den Füllstand einfach als Zahl an.
Ich habe mit ein paar Zeilen CSS einen Tank anzeigt.

Bild "LORAWAN_TTN-wasserstand.png"  
  
Hier ist die komplette PHP Datei, die den Wassertank grafisch darstellt. Den Tank und den Wasserstand habe ich dabei durch zwei Frames mit runden Ecken erzeugt.
LORAWAN_PHPScript.txt