LoRa Endgerät mit Heltec WiFi LoRa 32 V1
Die Board Version V1 habe ich beim Workshop 2023 auf dem Linux Infotag verwendet.
Von den im vorherigen Abschnitten genannten Möglichkeiten, einen LoRa Knoten zu realisieren, habe ich mich für die Heltec Variante entschieden, der Preis liegt in etwa zwischen 10 und 20 Euro pro Stück.
LoRa Gerät mit Heltec WiFi LoRa 32 V1
Hardware
Mein Prototyp der Schaltung ist auf eine Lochrasterplatine gelötet und mit Kupferlackdraht auf der Unterseite verdrahtet:
-
Der schwarze Taster ist active low und mit GPI36 verbunden. Vom Taster geht ein 10 kOhm Pullup Widerstand nach VCC (3.3V).
-
Die Anode der rote LED ist über einen 390 Ohm Widerstand mit GPIO17 verbunden, ist also active high. Die Kathode ist natürlich mit Masse verbunden. Auf dem Bild ist das die LED über der schwarzen Taste, sie sieht leider gelb aus, ist aber tatsächlich rot.
-
Ein Trimmpoti ist mit ADC Eingang GPI37 verbunden (ADC1 Channel 1 mit 12-Bit Auflösung). Das Trimmpoti hat 50 kOhm, je 3k9 nach Masse und Plus, da der lineare Messbereich des ADC Eingangs nur im Bereich ca. 0.2V bis 3.1 Volt ist. Damit liegt der gemessene 12-Bit Wert auf Linksanschlag bei 160, auf Rechtsanschlag bei 3920.
Im Workshop würde man die Schaltung auf ein Steckbrett stecken. Statt des Heltec Boards ist hier ein "TTGO LORA 868 MHz SX1276 ESP32" Board zu sehen. Es hat die gleichen Anschlüsse wie das Heltec Board:
Platformio
Platformio ist ein in Python geschriebenes Framework das viele
Mikrocontroller-Programmierumgebungen und Plattformen vereint. Wir verwenden
Platformio zur Programmierung der Heltec-Demo. Die Plattform ist "ESP32", die
Programmierumgebung ist "Arduino". Man kann alles von der Kommandozeile
steuern, die Arduino IDE wird nicht benötigt. Allerdings braucht man einen
Programmiereditor, mit dem man die Datei src/main.cpp
Änderungen machen
kann. Es eignen sich die üblichen kleinen Editoren wie pico
, nano
und
micro
. Wer Vi kennt, verwendet natürlich vim
.
-
Platformio installieren mit
python3 -c "$(curl -fsSL https://raw.githubusercontent.com/platformio/platformio/master/scripts/get-platformio.py)"
Danach gibt es im Homeverzeichnis den Ordner
~/.platformio
. Er ist ca. 40 MByte gross.Info: https://docs.platformio.org/en/latest/core/installation/methods/installer-script.html
-
Virtuelle Umgebung starten mit
. ~/.platformio/penv/bin/activate
Zum Deaktivieren einfach
deactivate
eingeben.Version abfragen:
pio --version PlatformIO Core, version 6.1.6
-
Projekt initialisieren
In
ttn_workshop/heltec
ausführen:pio project init --board heltec_wifi_lora_32
In diesem Schritt wird auch bereits die MCCI LoRaWAN LMIC Bibliothek installiert.
-
Serielle Schnittstelle für gewöhnlichen User freigeben.
Damit Platformio auf die serielle Schnittstelle kommt noch das Kommando
sudo adduser $USER dialout
oder
sudo usermod -a -G dialout $USER
eingeben. Dann ausloggen und wieder einloggen. Bei Mint-Linux musste ich neu booten, damit der
adduser
Wirkung zeigte. -
Kompilieren des Codes mit
pio run
oderpio run -v
.Achtung: Vorher muss der Code angepasst werden. Siehe unten.
-
Upload mit
pio run -v -t upload
.Das Heltec Board muss über ein USB Kabel an den PC angeschlossen sein. Das Device der seriellen Schnittstelle wird automatisch gesucht, kann aber schief gehen. Explizite Angabe des Ports mit z.B.
--upload-port /dev/ttyUSB3
. -
Konsolenausgabe
Nach dem Programmieren kann man einen Terminal-Emulator an der gleichen seriellen Schnittstelle anschliessen. Damit sieht man dann die Ausgaben, die mit
Serial.println()
in den Code gestreut sind.picocom -b 115200 /dev/ttyUSB0
Man beendet
picocom
mitStrg-A-X
.Picocom muss eventuell noch installiert werden:
sudo apt install picocom
Der Code
-
Der Quelltext ist in einer einzigen Datei enthalten:
heltec/src/main.cpp
. Er stammt von einem Beispielprogramm, das in der LMIC Bibliothek enthalten ist, und das ich leicht modifiziert habe:https://github.com/mcci-catena/arduino-lmic/blob/master/examples/ttn-otaa/ttn-otaa.ino
Die Anwendung auf dem Heltec LoRa Board ist ein sehr einfacher LoRaWAN Knoten. Es ist ein "Class A" LoRaWAN Knoten der jede Minute den Zustand eines Tasters und eines Drehpotis als Uplink sendet. Man kann über den Downlink die rote LED ein- oder ausschalten.
WARNUNG: Das Senden jede Minute ist für ein LoRaWAN Gerät schon zu häufig. Im normalen Betrieb senden LoRaWAN Knoten alle 20 bis 30 Minuten, viele noch deutlich seltener. Bitte die "Fair Access Policy" anschauen. Die Minute habe ich nur zum schnelleren Test gewählt. Das gilt auch für den Downlink. Die Regel ist max. 10 Downlinks am Tag.
-
Muss bei eigenem Code angepasst werden (OTAA):
- APPEUI (8 Byte, kann Null bleiben. Auch JoinEUI genannt.)
- DEVEUI (8 Byte, wird in der TTN Konsole generiert)
- APPKEY (16 Byte, wird in der TTN Konsole generiert)
Wie man diese Werte bekommt, findet man im nächsten Abschnitt "TTN Konfigurieren".
Wichtig: Die DEVEUI muss im Quelltext tatsächlich anders herum (little endian) eingegeben werden als in der TTN Konsole sichtbar.
Diese Konfiguration betrifft die LMIC Bibliothek, deshalb kann man auch in dessen Doku schauen: https://github.com/mcci-catena/arduino-lmic#configuration
-
Uplink Payload
Der Code definiert eine Payload mit 5 Byte in einem Array das
mydata
heisst:static uint8_t mydata[5] = { 0, 0, 0, 0, 0 };
Von den 5 Byte Payload werden wir im Beispiel nur 2 Byte nutzen. Das erste Byte (Offset 0) kodiert das Betätigen des schwarzen Tasters (0 = Taste offen, 1 = Taste wurde gedrückt). Das zweite Byte kodiert mit 7 Bit die Position des blauen Drehwiderstandes. Oben wurde schon gesagt, dass der Poti-Wert mit 12 Bit gemessen wird. Um auf die 7 Bit zu kommen, muss der Wert um 5 Bit nach rechts geschoben werden. Das erledigt die Zeile
mydata[1] = potValue >> 5; // Convert ADC value to 7-Bit
So sieht die Payload dann aus:
+----+----+----+----+----+ | 0 | 1 | 2 | 3 | 4 | +----+----+----+----+----+ | | | Poti Taste
Die Werte für die Bytes an dritter, vierter und fünfter Stelle sind immer Null.
-
Downlink Payload
Die Payload beim Downlink besteht nur aus einem Byte. Wenn das Byte den Wert 0 hat, wird die rote LED ausgeschaltet. Bei dem Wert 1 wird die rote LED eingeschaltet (genau genommen ist lediglich das niederwertigste Bit entscheidend!). Siehe den folgenden Quelltext:
digitalWrite(LED_RED_PIN, LMIC.frame[LMIC.dataBeg] & 1);
Das ist erst mal die "rohe" Payload in Bytes. Später kann man noch Payload Formatierer einbauen, welche die Umwandlung in besser lesbare JSON Objekte vornehmen. Siehe den Abschnitt "Payload Formatierung".