LoRaWan (Long Range Wide Area Network) nutzt eine von Semtech entwickelte proprietäre Funktechnik und sie ermöglicht es, kostenfrei im lizenzfreien SDR/ISM 868 MHz Band Datenpakete via Funk zu übertragen. Mit dieser Technik im Sub-GHz-Bereich mit wesentlich geringerer Freiraumdämpfung, werden teilweise beeindruckende Reichweiten von bis zu mehreren Kilometern erzielt (abhängig von der Antenne bzw. Antennengewinn). Dieser Artikel gibt einen Einblick in die Technik von LoRaWan und zeigt anhand eines Beispiels einer Node to Node Kommunikation, wie die Hard- und Software hierbei aufgebaut ist.
LoRa als Übertragungstechnik bietet sich im IoT Umfeld geradezu an, wenn keine zeitkritischen Daten oder nur kleinere Pakete übermittelt werden. Wird LoRa WAN verwendet, wird die Kommunikation mit 128 Bit AES verschlüsselt.
Datenpakete können hier mit Geschwindigkeiten von 292 Bytes/sec bis knapp 50 KBit/s extrem energiesparend über weite Strecken versendet werden. Im privaten Feldtest erfolgreich bis max. 13.5 km bei Sichtkontakt mit Spezialantennen getestet.
Dieser Abschnitt zeigt den Aufbau einer Node to Node Kommunikation, hier bezieht ein LoRa Controller Werte von einem Sensor ( Luftdruck, Luftfeuchte und Temperatur). Datenpakete werden periodisch via Funk zur Weiterverarbeitung an einen LoRa Receiver gepusht.
Sie finden nachfolgend eine Zusammenfassung über die angesprochenen Inhalte der weiteren Abschnitte dieses Artikels:
Bei der Inbetriebnahme (auch bei Tests) unbedingt vorher die Antenne 868 Mhz konnektieren, das Funkmodul könnte ohne Antenne durch Überlastung beschädigt werden.
Es wird das LoRa Board Heltec V2 mit ESP32 CPU verwendet.
Dieser Abschnitt zeigt die technischen Spezifikationen in einer tabellarischen Darstellung.
Komponenten | Eigenschaften |
---|---|
ESP32 Controller |
|
WiFi |
|
Bluetooth |
|
LoRa Chip |
|
Anschlüsse |
|
Weitere Eigenschaften |
|
Abmessungen | 50.2 x 25.5 x 9.74 mm |
Stromverbrauch gemessen |
|
Vorderseite |
|
Rückseite |
|
Diese Abschnitt zeigt den Gehäuseaufbau der beiden Geräte LoRa Receiver und Transceiver.
Das Gehäuse für den LoRa Receiver besteht aus zwei Teilen, die STL Dateien für den 3D Druck finden Sie am Ende des Artikels.
Später kann das Board mit der mitgelieferten Antenne direkt mit dem U.FL / IPEX Antennenanschluss auf der PCB verbunden werden.
Der LoRa Transceiver besteht aus folgenden Komponenten:
Für das Gehäuse für LoRa Transceiver gibt es ebenso STL Dateien, Sie finden diese ebenso am Ende des Artikels.
Später kann das Board mit der mitgelieferten Antenne direkt mit dem U.FL / IPEX Antennenanschluss auf der PCB verbunden werden. Bei Nutzung der vorhandenen Schraublöcher, sehr kurze Schrauben verwenden. Um generell den barometrischen Sensor für erste Tests ohne Aufbau anzuschließen, kann dieser wie folgt mit dem Board verbunden/verlötet werden (siehe fliegender Aufbau):
Hinweis: Für spätere Verwendung des Boards im Custom Case, ist es ratsam die Kabel vom BME nicht wie hier auf der Rückseite, sondern direkt auf der Vorderseite anzulöten. Beachten Sie dazu das Bild wie das Kabel im Gehäuse verbaut wurde weiter unten.
Das folgende Schema zeigt die korrekte Kontaktierung der Platine. Tipp: Ein kleiner Tropfen Heißkleber fixiert die Zuleitungen am BM280.
ESP LoRa32 <----> BME 280 Sensor Kontaktierungen: PIN 15 <-------> SCL PIN 4 <-------> SDA GND <-------> GND 3.3V+ <-------> VIN
Stecken sie den barometrischen Sensor BME 280 vorsichtig in die Aussparung bzw. Öffnung. Das Antennenkabel ist (ohne Knicke) um die runden Aussparungen zu legen. Bemessen Sie die Zuleitung gerade so lang, dass die Antenne optimal verstaut werden kann.
Der vorherige Abschnitt zeigte die Konfiguration der Hardware (LoRa Receiver und Transceiver), nun zeigen wir Ihnen wie Sie die erforderlichen Softwarekomponenten installieren und einrichten.
Um die Kompatibilität zu anderen Systemen zu erhöhen, um es schlicht "so einfach wie möglich" zu halten, wurde hier auf die Kompilierung in der Linux Shell verzichtet. Das Mittel der Wahl ist die Arduino IDE die für Linux sowie Windows kostenfrei erhältlich ist.[1]
Die weitere Vorgehensweise bezieht sich hier im Artikel dabei auf die Einrichtung unter Ubuntu Linux.
Da das DevBoard der IDE noch unbekannt ist, müssen die Informationen hierzu über einen Link zugänglich gemacht werden. Der nachfolgende Link wird unter "Additonal Board Manager URLs" eingetragen werden (siehe unten)
Um alle zusätzlichen Eigenschaften zu verwenden, sind weitere Libraries erforderlich:
Ziehen sie die Bibliotheken für das Oled Display über den Menüpunkt Sketch Include Library → Manage Library nach.
Suchen Sie nach folgender aktueller Library: Adafruit bme 280
Hier ist zu beachten das das ursprüngliche PinMapping mit dem Board nicht übereinstimmt. Konfigurieren Sie dazu eine Datei um, diese liegt im Arduino Verzeichnis. Der Speicherort der Datei kann sich je nach Installationsart oder Version bzgl. der Grundinstallation unterscheiden:
In der Datei nach folgenden Einträgen suchen:
static const uint8_t SDA = 21; static const uint8_t SCL = 22;
Die SDA und SCL Pinbelegung ändern auf:
static const uint8_t SDA = 4; static const uint8_t SCL = 15;
Nach dieser Änderung kann der BME 280 einwandfrei vom ESP32 angesprochen werden.
Im Library Manager nach LoRa suchen und die LoRa Library von Sandeep Mistry hinzufügen, diese ist in Verbindung mit den Semtech ICs empfehlenswert. Es sind nun alle notwendigen Softwarebibliotheken für den Betrieb eingerichtet.
Nachdem alle Bibliotheken vorhanden sind, wird das Programm (siehe unten) direkt in den Speicher des ESP32 geflashed. Wir verbinden hierzu den fertig aufgebauten LoRa Receiver via MicroUSB/USB Kabel mit dem Rechner. Wählen hierzu den passenden Port aus, meist ist es unter Linux /dev/ttyUSB0.
Der nachfolgende Programmcode richtet den Receiver mit SPI / LoRa / OLED SSD1306 Display komplett ein.
Hierzu wird unter der Arduino IDE ein neuer Sketch mit folgendem Inhalt (siehe unten) angelegt:
#include <LoRa.h> #include <U8x8lib.h> #include <U8g2lib.h> #include <SPI.h> #define ss 18 #define rst 14 #define dio0 26 //WatchDog #include <esp_task_wdt.h> //WatchDog Timer #define WDT_TIMEOUT 150 // Um Grafiken umzuwandeln sollte diese monochrome gewandelt // u. die passende Größe hier 128x64 Pixel haben // sowie als xbm exportiert werden. // Anzeigen der Pixelgrafik static unsigned char TK_OLED_SOURCE_bits[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xaa, 0xba, 0xfa, 0x57, 0x57, 0x55, 0xfd, 0xfa, 0x7f, 0xf5, 0x7f, 0xf5, 0xff, 0x85, 0xfe, 0x07, 0x00, 0x30, 0xf8, 0x07, 0x03, 0x00, 0x70, 0xe0, 0x3f, 0xf0, 0x3f, 0xf0, 0xff, 0x00, 0xf8, 0x07, 0x00, 0x30, 0xf8, 0x07, 0x03, 0x00, 0x70, 0xe0, 0x3f, 0xf0, 0x3f, 0xf0, 0x7f, 0x00, 0xf8, 0x07, 0x00, 0x30, 0xf8, 0x07, 0x03, 0x00, 0x70, 0xc0, 0x3f, 0xf0, 0x1f, 0xf0, 0x3f, 0x00, 0xf8, 0x0f, 0x00, 0x30, 0xf8, 0x07, 0x03, 0x00, 0x70, 0xc0, 0x3f, 0xf0, 0x1f, 0xe0, 0x1f, 0x00, 0xf8, 0xff, 0xc1, 0x3f, 0xf8, 0x07, 0x07, 0x00, 0x78, 0xc0, 0x1f, 0xf0, 0x1f, 0xe0, 0x1f, 0xf8, 0xfe, 0xff, 0xc1, 0x3f, 0xf8, 0x07, 0xff, 0xff, 0x3f, 0x80, 0x1f, 0xe0, 0x0f, 0xc0, 0x1f, 0xfc, 0xff, 0xff, 0xc1, 0x3f, 0xf8, 0x07, 0xff, 0xff, 0x7f, 0x80, 0x0f, 0xe0, 0x0f, 0xc0, 0x1f, 0xf8, 0xff, 0xff, 0xc1, 0x3f, 0xf8, 0x07, 0xff, 0xff, 0x3f, 0x00, 0x0f, 0xe0, 0x0f, 0x80, 0x1f, 0xf8, 0xff, 0xff, 0xc1, 0x3f, 0xf8, 0x07, 0xff, 0xff, 0x7f, 0x00, 0x07, 0xe0, 0x0f, 0x82, 0x1f, 0xe0, 0xff, 0xff, 0xc1, 0x3f, 0x00, 0x00, 0xff, 0xff, 0x3f, 0x00, 0x06, 0xe0, 0x07, 0x83, 0x3f, 0x80, 0xff, 0xff, 0xc1, 0x3f, 0x00, 0x00, 0xff, 0xff, 0x7f, 0x08, 0x86, 0xe0, 0x07, 0x83, 0x3f, 0x00, 0xfe, 0xff, 0xc1, 0x3f, 0x00, 0x00, 0xff, 0xff, 0x3f, 0x08, 0x82, 0xe0, 0x83, 0x07, 0xff, 0x00, 0xfc, 0xff, 0xc1, 0x3f, 0x00, 0x00, 0xff, 0xff, 0x7f, 0x10, 0x82, 0xe0, 0x83, 0x07, 0xff, 0x01, 0xf8, 0xff, 0xc1, 0x3f, 0xd8, 0x06, 0xff, 0xff, 0x3f, 0x18, 0xc0, 0xe0, 0x03, 0x00, 0xff, 0x0f, 0xf8, 0xff, 0xc1, 0x3f, 0xf8, 0x07, 0xff, 0xff, 0x7f, 0x18, 0xc0, 0xe0, 0x01, 0x00, 0xfe, 0x1f, 0xf0, 0xff, 0xc1, 0x3f, 0xf8, 0x07, 0xff, 0xff, 0x3f, 0x30, 0xe0, 0xe0, 0x01, 0x00, 0xfc, 0x3f, 0xf0, 0xff, 0xc1, 0x3f, 0xf8, 0x07, 0xff, 0xff, 0x7f, 0x30, 0xe0, 0xe0, 0x01, 0x00, 0xfc, 0x3f, 0xf0, 0xff, 0xc1, 0x3f, 0xf8, 0x07, 0xaf, 0xaa, 0x3a, 0x78, 0xf0, 0xe0, 0xc0, 0x0f, 0xbc, 0x3f, 0xf0, 0xff, 0xc1, 0x3f, 0xf8, 0x07, 0x03, 0x00, 0x70, 0x78, 0xf0, 0xe0, 0xe0, 0x1f, 0x0c, 0x1e, 0xf0, 0xff, 0xc1, 0x3f, 0xf8, 0x07, 0x03, 0x00, 0x30, 0xf0, 0xfd, 0x60, 0xe0, 0x1f, 0x0c, 0x00, 0xf8, 0xff, 0xc1, 0x3f, 0xf8, 0x07, 0x03, 0x00, 0x30, 0xf8, 0xff, 0x60, 0xf0, 0x3f, 0x08, 0x00, 0xfc, 0xff, 0xc1, 0x3f, 0xf8, 0x07, 0x03, 0x00, 0x30, 0xf8, 0xff, 0x60, 0xf0, 0x3f, 0x08, 0x00, 0xfc, 0xff, 0xc1, 0x3f, 0xf8, 0x07, 0x07, 0x00, 0x38, 0xf8, 0xff, 0x60, 0xf0, 0x3f, 0x30, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0xc1, 0x1f, 0x1c, 0x00, 0xff, 0x00, 0x80, 0x83, 0xff, 0xf0, 0xe1, 0x3f, 0x18, 0xf8, 0xff, 0xff, 0xc3, 0x1f, 0x1c, 0x00, 0xfc, 0x01, 0x80, 0x07, 0xff, 0xe0, 0xc1, 0x7f, 0x58, 0xfa, 0xff, 0xff, 0xc1, 0x0f, 0x1e, 0x00, 0xf8, 0x00, 0x80, 0x03, 0xff, 0xe0, 0x81, 0x3f, 0x58, 0xf2, 0xff, 0xff, 0xc1, 0x07, 0x1e, 0x00, 0xf0, 0x00, 0x80, 0x03, 0xfe, 0xe0, 0x81, 0x3f, 0x18, 0xf8, 0xff, 0xff, 0xc1, 0x03, 0x1f, 0x28, 0xf0, 0x40, 0xd5, 0x03, 0xfe, 0xe0, 0x01, 0x3f, 0x38, 0xfc, 0xff, 0xff, 0xc1, 0x83, 0x1f, 0x7c, 0xf0, 0xe0, 0xff, 0x03, 0xfc, 0xe0, 0x01, 0x3e, 0xf8, 0xff, 0xff, 0xff, 0xc1, 0x81, 0x1f, 0x78, 0xe0, 0xe0, 0xff, 0x03, 0xf8, 0xe0, 0x01, 0x3e, 0xf8, 0xff, 0xff, 0xff, 0xc1, 0xc0, 0x1f, 0x7c, 0xe0, 0xe0, 0xff, 0x03, 0xf0, 0xe0, 0x01, 0x3c, 0xf8, 0xff, 0xff, 0xff, 0x41, 0xe0, 0x1f, 0x78, 0xf0, 0xe0, 0xff, 0x03, 0xf0, 0xe0, 0x01, 0x3c, 0xf8, 0xff, 0xff, 0xff, 0x01, 0xf0, 0x1f, 0x7c, 0xf0, 0xc0, 0xff, 0x03, 0xe0, 0xe0, 0x01, 0x30, 0xf8, 0xff, 0xff, 0xff, 0x01, 0xf8, 0x1f, 0x1c, 0xf0, 0x00, 0xe0, 0x83, 0xe0, 0xe0, 0x01, 0x30, 0xf8, 0xff, 0xff, 0xff, 0x01, 0xf0, 0x1f, 0x00, 0xf8, 0x00, 0xc0, 0x83, 0xc0, 0xe0, 0x41, 0x30, 0xf8, 0xff, 0xff, 0xff, 0x01, 0xe0, 0x1f, 0x00, 0xf8, 0x00, 0xe0, 0x83, 0x81, 0xe0, 0x41, 0x20, 0xf8, 0xff, 0xff, 0xff, 0x01, 0xe0, 0x1f, 0x00, 0xfe, 0x00, 0xe0, 0x83, 0x83, 0xe0, 0xc1, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x81, 0xc0, 0x1f, 0x00, 0xfe, 0xe0, 0xff, 0x83, 0x03, 0xe0, 0xc1, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x81, 0xc0, 0x1f, 0x0c, 0xfc, 0xe0, 0xff, 0x83, 0x07, 0xe0, 0xc1, 0x01, 0xf8, 0xff, 0xff, 0xff, 0xc1, 0x81, 0x1f, 0x08, 0xfc, 0xe0, 0xff, 0x83, 0x0f, 0xe0, 0xc1, 0x03, 0xf8, 0xff, 0xff, 0xff, 0xc1, 0x83, 0x1f, 0x1c, 0xf8, 0xe0, 0xff, 0x83, 0x0f, 0xe0, 0xc1, 0x07, 0xf8, 0xff, 0xff, 0xff, 0xc1, 0x03, 0x1f, 0x18, 0xf8, 0xe0, 0xff, 0x83, 0x1f, 0xe0, 0xc1, 0x07, 0xf8, 0xff, 0xff, 0xff, 0xc1, 0x07, 0x1e, 0x3c, 0xf0, 0xc0, 0xff, 0x83, 0x3f, 0xe0, 0xc1, 0x0f, 0xf8, 0xff, 0xff, 0xff, 0xc1, 0x07, 0x1e, 0x78, 0xf0, 0x00, 0x80, 0x83, 0x3f, 0xe0, 0xc1, 0x1f, 0xf8, 0xff, 0xff, 0xff, 0xc1, 0x0f, 0x1c, 0x7c, 0xe0, 0x00, 0x80, 0x83, 0x7f, 0xe0, 0xc1, 0x1f, 0xf8, 0xff, 0xff, 0xff, 0xc1, 0x1f, 0x1c, 0xf8, 0xc0, 0x00, 0x80, 0x83, 0xff, 0xe0, 0xc1, 0x3f, 0xf8, 0xff, 0xff, 0xff, 0xc1, 0x1f, 0x18, 0xfc, 0xc1, 0x00, 0x80, 0x83, 0xff, 0xe1, 0xc1, 0x3f, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; int counter = 1; String rxquality; String lorastring; // Konfiguration des OledDisplays U8X8_SSD1306_128X64_NONAME_SW_I2C u8x8(15, 4, 16); U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ 15, /* data=*/ 4, /* reset=*/ 16); void setup() { Serial.begin(115200); // Watchdog Konfiguration Serial.println("Configuring WatchDogTimer.."); esp_task_wdt_init(WDT_TIMEOUT, true); // panic auf den ESP32, dann wird ein Neustart ausgelöst esp_task_wdt_add(NULL); // Thread zu WDT Watch addieren Serial.println(""); Serial.println("LoRa Receiver Starting..."); Serial.println("-------------------------"); u8g2.begin(); u8g2.clearBuffer(); // internen Display Speicher löschen u8g2.drawXBM(0,0, 128, 64, TK_OLED_SOURCE_bits); u8g2.sendBuffer(); // alles jetzt auf das Display senden delay(3000); u8x8.begin(); u8x8.setFont(u8x8_font_chroma48medium8_r); u8x8.clearDisplay(); Serial.println("LoRa Radio konfiguriert"); SPI.begin(5, 19, 27, 18); LoRa.setPins(ss, rst, dio0); u8x8.setCursor(0, 2); u8x8.print(""); u8x8.setCursor(0, 4); u8x8.print(" > Waiting Pckt <"); if (!LoRa.begin(868E6)) { Serial.println("LoRa nicht gestartet!"); u8x8.clearDisplay(); u8x8.setCursor(0, 1); u8x8.print("LoRa nicht gestartet!.. "); while (1); delay(1000); } } void loop() { // Test // Serial.println("Void loop"); int paketlaenge = LoRa.parsePacket(); if (paketlaenge) { Serial.println("Paket empfangen"); u8x8.clearDisplay(); u8x8.setCursor(0, 2); u8x8.print(" LoRa IoT"); u8x8.setCursor(0, 4); u8x8.print(" > Received <"); u8x8.setCursor(0, 5); u8x8.print(" > PACKET <"); delay(1000); lora_paket(); display_status(); esp_task_wdt_reset(); // Serial.println(" << WDT Reset >> "); } } void lora_paket() { boolean trig = 1; while (LoRa.available()) { if (trig == 1) { lorastring = ""; trig = 0; } lorastring+= (char)LoRa.read(); } trig = 1; } void display_status() { String feld1 = split_string( lorastring, '/', 0); String feld2 = split_string( lorastring, '/', 1); String feld3 = split_string( lorastring, '/', 2); u8x8.clearDisplay(); u8x8.setCursor(0, 1); u8x8.print("Celsius: "); u8x8.print(feld1); u8x8.print("C"); u8x8.print(" "); u8x8.setCursor(0, 2); u8x8.print("Feuchte: "); u8x8.print(feld2); u8x8.print("%"); u8x8.setCursor(0, 3); u8x8.print("mBar : "); u8x8.print(feld3); u8x8.setCursor(0, 5); u8x8.print("--- IoT LoRa ---"); Serial.print(feld1); Serial.print(feld2); Serial.print(feld3); u8x8.setCursor(0, 6); u8x8.print("RX-Pakete: "); u8x8.print(counter); counter = counter + 1; rxquality = LoRa.packetRssi(); Serial.print(rxquality); u8x8.setCursor(0, 7); u8x8.print("Quality: "); u8x8.print(rxquality); u8x8.print(" dBm"); delay(5000); } // Hier wird der Sting gesplittet und separiert String split_string(String data, char separator, int index) { int found = 0; int strIndex[] = { 0, -1 }; int maxIndex = data.length(); for (int i = 0; i <= maxIndex && found <= index; i++) { if (data.charAt(i) == separator || i == maxIndex) { found++; strIndex[0] = strIndex[1] + 1; strIndex[1] = (i == maxIndex) ? i + 1 : i; } } return found > index ? data.substring(strIndex[0], strIndex[1]) : ""; }
Nachdem der Programmcode kompiliert in den FlashSpeicher geschrieben wurde, wird der ESP32 autmatisch neu gestartet. Das Thomas-Krenn Logo sollte kurz zu sehen sein. Es erscheint eine Meldung im Display dass Pakete erwartet werden, der Receiver ist somit einsatzbereit.
Hinweis: Falls es zu Problemen beim Flashen unter Linux kommt, finden Sie Hilfestellung weiter unten im Absatz Troubleshooting.
Nachdem alle Bibliotheken vorhanden sind, wird das Programm (siehe unten) auf den ESP geflasht. Wir verbinden hierzu den fertig aufgebauten LoRa Transceiver via Micro USB/USB mit dem Rechner. Wählen Sie den passenden Port aus, unter Linux-basierten Betriebssystemen meist /dev/ttyUSB1.
Hinweis: wenn der Receiver abgesteckt wurde, ist das Gerät meist unter /dev/ttyUSB0 erreichbar.
Funktionsweise LoRa Transceiver:
Programmcode
#include <SPI.h> #include <LoRa.h> #include <U8x8lib.h> #include <U8g2lib.h> //Libraries for BME280 #include <Adafruit_Sensor.h> #include <Adafruit_BME280.h> //BME280 definition festlegen #define SDA 4 #define SCL 15 TwoWire I2Cone = TwoWire(1); Adafruit_BME280 bme; //Paketzähler ID setzen int readingID = 0; int counter = 0; String LoRaMessage = ""; float temperature = 0; float humidity = 0; float pressure = 0; #define ss 18 #define rst 14 #define dio0 26 //ISM Band festlegen (hier in Europa 868MHZ) #define BAND 866E6 // Display passend konfigurieren U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ 15, /* data=*/ 4, /* reset=*/ 16); U8X8_SSD1306_128X64_NONAME_SW_I2C u8x8(15, 4, 16); // Um Grafiken umzuwandeln sollte diese in S/W sein die passende Größe hier 128x64 Pixel haben // und als xbm exportiert werden. static unsigned char TK_OLED_SOURCE_bits[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xaa, 0xba, 0xfa, 0x57, 0x57, 0x55, 0xfd, 0xfa, 0x7f, 0xf5, 0x7f, 0xf5, 0xff, 0x85, 0xfe, 0x07, 0x00, 0x30, 0xf8, 0x07, 0x03, 0x00, 0x70, 0xe0, 0x3f, 0xf0, 0x3f, 0xf0, 0xff, 0x00, 0xf8, 0x07, 0x00, 0x30, 0xf8, 0x07, 0x03, 0x00, 0x70, 0xe0, 0x3f, 0xf0, 0x3f, 0xf0, 0x7f, 0x00, 0xf8, 0x07, 0x00, 0x30, 0xf8, 0x07, 0x03, 0x00, 0x70, 0xc0, 0x3f, 0xf0, 0x1f, 0xf0, 0x3f, 0x00, 0xf8, 0x0f, 0x00, 0x30, 0xf8, 0x07, 0x03, 0x00, 0x70, 0xc0, 0x3f, 0xf0, 0x1f, 0xe0, 0x1f, 0x00, 0xf8, 0xff, 0xc1, 0x3f, 0xf8, 0x07, 0x07, 0x00, 0x78, 0xc0, 0x1f, 0xf0, 0x1f, 0xe0, 0x1f, 0xf8, 0xfe, 0xff, 0xc1, 0x3f, 0xf8, 0x07, 0xff, 0xff, 0x3f, 0x80, 0x1f, 0xe0, 0x0f, 0xc0, 0x1f, 0xfc, 0xff, 0xff, 0xc1, 0x3f, 0xf8, 0x07, 0xff, 0xff, 0x7f, 0x80, 0x0f, 0xe0, 0x0f, 0xc0, 0x1f, 0xf8, 0xff, 0xff, 0xc1, 0x3f, 0xf8, 0x07, 0xff, 0xff, 0x3f, 0x00, 0x0f, 0xe0, 0x0f, 0x80, 0x1f, 0xf8, 0xff, 0xff, 0xc1, 0x3f, 0xf8, 0x07, 0xff, 0xff, 0x7f, 0x00, 0x07, 0xe0, 0x0f, 0x82, 0x1f, 0xe0, 0xff, 0xff, 0xc1, 0x3f, 0x00, 0x00, 0xff, 0xff, 0x3f, 0x00, 0x06, 0xe0, 0x07, 0x83, 0x3f, 0x80, 0xff, 0xff, 0xc1, 0x3f, 0x00, 0x00, 0xff, 0xff, 0x7f, 0x08, 0x86, 0xe0, 0x07, 0x83, 0x3f, 0x00, 0xfe, 0xff, 0xc1, 0x3f, 0x00, 0x00, 0xff, 0xff, 0x3f, 0x08, 0x82, 0xe0, 0x83, 0x07, 0xff, 0x00, 0xfc, 0xff, 0xc1, 0x3f, 0x00, 0x00, 0xff, 0xff, 0x7f, 0x10, 0x82, 0xe0, 0x83, 0x07, 0xff, 0x01, 0xf8, 0xff, 0xc1, 0x3f, 0xd8, 0x06, 0xff, 0xff, 0x3f, 0x18, 0xc0, 0xe0, 0x03, 0x00, 0xff, 0x0f, 0xf8, 0xff, 0xc1, 0x3f, 0xf8, 0x07, 0xff, 0xff, 0x7f, 0x18, 0xc0, 0xe0, 0x01, 0x00, 0xfe, 0x1f, 0xf0, 0xff, 0xc1, 0x3f, 0xf8, 0x07, 0xff, 0xff, 0x3f, 0x30, 0xe0, 0xe0, 0x01, 0x00, 0xfc, 0x3f, 0xf0, 0xff, 0xc1, 0x3f, 0xf8, 0x07, 0xff, 0xff, 0x7f, 0x30, 0xe0, 0xe0, 0x01, 0x00, 0xfc, 0x3f, 0xf0, 0xff, 0xc1, 0x3f, 0xf8, 0x07, 0xaf, 0xaa, 0x3a, 0x78, 0xf0, 0xe0, 0xc0, 0x0f, 0xbc, 0x3f, 0xf0, 0xff, 0xc1, 0x3f, 0xf8, 0x07, 0x03, 0x00, 0x70, 0x78, 0xf0, 0xe0, 0xe0, 0x1f, 0x0c, 0x1e, 0xf0, 0xff, 0xc1, 0x3f, 0xf8, 0x07, 0x03, 0x00, 0x30, 0xf0, 0xfd, 0x60, 0xe0, 0x1f, 0x0c, 0x00, 0xf8, 0xff, 0xc1, 0x3f, 0xf8, 0x07, 0x03, 0x00, 0x30, 0xf8, 0xff, 0x60, 0xf0, 0x3f, 0x08, 0x00, 0xfc, 0xff, 0xc1, 0x3f, 0xf8, 0x07, 0x03, 0x00, 0x30, 0xf8, 0xff, 0x60, 0xf0, 0x3f, 0x08, 0x00, 0xfc, 0xff, 0xc1, 0x3f, 0xf8, 0x07, 0x07, 0x00, 0x38, 0xf8, 0xff, 0x60, 0xf0, 0x3f, 0x30, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0xc1, 0x1f, 0x1c, 0x00, 0xff, 0x00, 0x80, 0x83, 0xff, 0xf0, 0xe1, 0x3f, 0x18, 0xf8, 0xff, 0xff, 0xc3, 0x1f, 0x1c, 0x00, 0xfc, 0x01, 0x80, 0x07, 0xff, 0xe0, 0xc1, 0x7f, 0x58, 0xfa, 0xff, 0xff, 0xc1, 0x0f, 0x1e, 0x00, 0xf8, 0x00, 0x80, 0x03, 0xff, 0xe0, 0x81, 0x3f, 0x58, 0xf2, 0xff, 0xff, 0xc1, 0x07, 0x1e, 0x00, 0xf0, 0x00, 0x80, 0x03, 0xfe, 0xe0, 0x81, 0x3f, 0x18, 0xf8, 0xff, 0xff, 0xc1, 0x03, 0x1f, 0x28, 0xf0, 0x40, 0xd5, 0x03, 0xfe, 0xe0, 0x01, 0x3f, 0x38, 0xfc, 0xff, 0xff, 0xc1, 0x83, 0x1f, 0x7c, 0xf0, 0xe0, 0xff, 0x03, 0xfc, 0xe0, 0x01, 0x3e, 0xf8, 0xff, 0xff, 0xff, 0xc1, 0x81, 0x1f, 0x78, 0xe0, 0xe0, 0xff, 0x03, 0xf8, 0xe0, 0x01, 0x3e, 0xf8, 0xff, 0xff, 0xff, 0xc1, 0xc0, 0x1f, 0x7c, 0xe0, 0xe0, 0xff, 0x03, 0xf0, 0xe0, 0x01, 0x3c, 0xf8, 0xff, 0xff, 0xff, 0x41, 0xe0, 0x1f, 0x78, 0xf0, 0xe0, 0xff, 0x03, 0xf0, 0xe0, 0x01, 0x3c, 0xf8, 0xff, 0xff, 0xff, 0x01, 0xf0, 0x1f, 0x7c, 0xf0, 0xc0, 0xff, 0x03, 0xe0, 0xe0, 0x01, 0x30, 0xf8, 0xff, 0xff, 0xff, 0x01, 0xf8, 0x1f, 0x1c, 0xf0, 0x00, 0xe0, 0x83, 0xe0, 0xe0, 0x01, 0x30, 0xf8, 0xff, 0xff, 0xff, 0x01, 0xf0, 0x1f, 0x00, 0xf8, 0x00, 0xc0, 0x83, 0xc0, 0xe0, 0x41, 0x30, 0xf8, 0xff, 0xff, 0xff, 0x01, 0xe0, 0x1f, 0x00, 0xf8, 0x00, 0xe0, 0x83, 0x81, 0xe0, 0x41, 0x20, 0xf8, 0xff, 0xff, 0xff, 0x01, 0xe0, 0x1f, 0x00, 0xfe, 0x00, 0xe0, 0x83, 0x83, 0xe0, 0xc1, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x81, 0xc0, 0x1f, 0x00, 0xfe, 0xe0, 0xff, 0x83, 0x03, 0xe0, 0xc1, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x81, 0xc0, 0x1f, 0x0c, 0xfc, 0xe0, 0xff, 0x83, 0x07, 0xe0, 0xc1, 0x01, 0xf8, 0xff, 0xff, 0xff, 0xc1, 0x81, 0x1f, 0x08, 0xfc, 0xe0, 0xff, 0x83, 0x0f, 0xe0, 0xc1, 0x03, 0xf8, 0xff, 0xff, 0xff, 0xc1, 0x83, 0x1f, 0x1c, 0xf8, 0xe0, 0xff, 0x83, 0x0f, 0xe0, 0xc1, 0x07, 0xf8, 0xff, 0xff, 0xff, 0xc1, 0x03, 0x1f, 0x18, 0xf8, 0xe0, 0xff, 0x83, 0x1f, 0xe0, 0xc1, 0x07, 0xf8, 0xff, 0xff, 0xff, 0xc1, 0x07, 0x1e, 0x3c, 0xf0, 0xc0, 0xff, 0x83, 0x3f, 0xe0, 0xc1, 0x0f, 0xf8, 0xff, 0xff, 0xff, 0xc1, 0x07, 0x1e, 0x78, 0xf0, 0x00, 0x80, 0x83, 0x3f, 0xe0, 0xc1, 0x1f, 0xf8, 0xff, 0xff, 0xff, 0xc1, 0x0f, 0x1c, 0x7c, 0xe0, 0x00, 0x80, 0x83, 0x7f, 0xe0, 0xc1, 0x1f, 0xf8, 0xff, 0xff, 0xff, 0xc1, 0x1f, 0x1c, 0xf8, 0xc0, 0x00, 0x80, 0x83, 0xff, 0xe0, 0xc1, 0x3f, 0xf8, 0xff, 0xff, 0xff, 0xc1, 0x1f, 0x18, 0xfc, 0xc1, 0x00, 0x80, 0x83, 0xff, 0xe1, 0xc1, 0x3f, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; #define uS_TO_S_FACTOR 1000000 // Umberechnungsfaktor Mikro Sekunden auf Sekunden #define TIME_TO_SLEEP 120 // Dauer des Tiefschlafzustands in Sekunden RTC_DATA_ATTR int bootCount = 0; void setup() { u8g2.begin(); Serial.begin(115200); //while (!Serial); Serial.println(""); Serial.println("----------------------------"); Serial.println(" LoRa Sender with BME 280 "); Serial.println("----------------------------"); Serial.println(""); Serial.println("Booting..."); u8g2.clearBuffer(); // Internen Display Speicher komplett löschen u8g2.drawXBM(0,0, 128, 64, TK_OLED_SOURCE_bits); u8g2.sendBuffer(); // Inhalt des Speichers direkt auf das Display pushen delay(2000); // Statusmeldung // Auslesen des TempSensors / Versand des LoRa Paketes. // Nach Versand wird sofort in Deep Sleep Modus gewechselt // hier ist nur noch der RTC in Betrieb // Core / Wifi / Lora usw. wird alles in dem Zeitraum von 120 sek abgeschaltet u8x8.begin(); u8x8.setFont(u8x8_font_chroma48medium8_r); u8x8.drawString(0, 2, " Readout BME280" ); delay (2000); u8x8.clear(); u8x8.drawString(0, 2, " Send Data "); u8x8.drawString(0, 3, " & "); u8x8.drawString(0, 4, " Deep Sleep "); u8x8.drawString(0, 6, "..for 120 sec"); delay (3000) ; u8x8.clear(); SPI.begin(5, 19, 27, 18); LoRa.setPins(ss, rst, dio0); if (!LoRa.begin(868E6)) { Serial.println("Start of LoRa failed!"); while (1); } } void loop() { startBME(); temperature = bme.readTemperature(); humidity = bme.readHumidity(); pressure = bme.readPressure() / 100.0F; Serial.print("Sending LoRa Packet: "); Serial.print("Sending Complete Data: "); LoRaMessage = String(temperature) + "/" + String(humidity) + "/" + String(pressure); Serial.println(LoRaMessage); // send packet LoRa.beginPacket(); LoRa.print(LoRaMessage); LoRa.endPacket(); counter++; Serial.print("LoRa Message send...."); Serial.print("Entering Now --> DeepSleep Mode"); Serial.print(" for 120 sec.."); esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR); esp_deep_sleep_start(); } void startBME(){ delay(1000); I2Cone.begin(SDA, SCL, 100000); bool status1 = bme.begin(0x76, &I2Cone); if (!status1) { Serial.println("Kein BME280 Sensor gefunden!"); while (1); } delay(3000); }
In den vorherigen Abschnitten wurden die beiden Geräte vorbereitet und sie sind nun einsatzbereit. Dieser Abschnitt zeigt wie sie beide LoRa Geräte nun in Betrieb nehmen.
Der LoRa Sender kann via USB betrieben werden. Nach erfolgreichem Flash-Vorgang ist hier kurz das Thomas-Krenn Logo zu sehen.
Nachdem der Receiver über USB angeschlossen wurde, kann der Empfänger jetzt verwendet werden.
Erklärungen zu den Rohdaten
Ausgabe auf Serieller Schnittstelle: 24.0143.64986.42-56 Datenpaket aufgeschlüsselt: 24.01 Temperatur in °C 43.64 Luftfeuchtigkeit in % 986.42 Luftdruck in mBar -56 Signalqualität in dBm
Sie können 3D Cases mit allen Gehäusebauteilen im STL Format zum Slicen beziehungsweise Ausdrucken bei Thomas-Krenn herunterladen: LoRa_Cases.zip
Dieser Abschnitt gibt Ihnen eine Sammlung bzw. Use Cases zur Hand, wie LoRa Sensoren eingesetzt werden könnten, um hier kleine Datenpakete periodisch an eine Sammelstelle zu übertragen.
Der Artikel LoRaWAN Troubleshooting FAQ liefert eine Sammlung an Lösungen, falls Probleme bei der Installation und Konfiguration auftreten.
Die Eckdaten der Testumgebung:
Autor: Wilfried Seifert Wilfried Seifert, tätig in der Abteilung Systems Engineering bei Thomas-Krenn, ist in seinem Arbeitsbereich für die System-/Prototypenentwicklung sowie Softwaredeployment / Rollout zuständig. LPIC 3 zertifiziert, beschäftigt sich u.a. mit Aufbau / Programmierung Embedded Systemen.
|