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

Pinout V1

Zum Vergrössern klicken

Hardware

Mein Prototyp der Schaltung ist auf eine Lochrasterplatine gelötet und mit Kupferlackdraht auf der Unterseite verdrahtet:

Heltec-Demo

  • 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.

Schaltplan der Erweiterungen

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:

Steckbrett

Platformio

https://platformio.org

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 oder pio 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 mit Strg-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.

    Fair Use Policy

  • 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".