LoPy4 mit Pytrack in Betrieb nehmen

Kategorien: internet of things

Nach den ersten erfolgreichen Experimenten mit Arduino wird nun ausprobiert, wie gut sich ein mit Python programmierbarer Node ins The Thing Network einbinden lässt. Von Pycom gibt es ein auf dem ESP32 basierendes LoRa-Modul mit MicroPython vorinstalliert.

Hardware

Die Pycom-Module haben keinen USB-Anschluss. Für meine Experimente mit dem LoPy4, habe ich deshalb einen Pytrack-Board mitbestellt. Damit kann ich über den USB-Port eine EVAS (Eingabe-Verarbeitung-Ausgabe-Schleife, Übersetzung von REPL read evaluate print loop) erreichen. Laut Hersteller hat es die folgenden Eigenschaften:

  • Super-genaues GNSS Glonass GPS / Super accurate GNSS Glonass GPS
  • 3-Achsen 12-Bit Accelerometer / 3 axis 12-bit accelerometer
  • USB Port mit seriellem Zugang / USB port with serial access
  • LiPo-Batterie-Ladeeinrichtung / LiPo battery charger
  • MicroSD-Karten-Kompatibilität / MicroSD card compatibility
  • Ultra-niedrige Leistung im Betrieb (ca. 1 µA im Tiefschlaf) / Ultra low power operation (~1uA in deep sleep)

Die Übersetzung der Eigenschaften ist von mir. Ich finde die Formulierung der Eigenschaften etwas blumig, aber die Eigenschaften des Boards sind sehr interessant für mich. Ich sollte damit einen TTNMapper-Knoten in Python basteln können. Die Dokumentation von Pycom für das LoPy4-Modul und das Pytracker-Experimentier-Board sieht auch ordentlich aus. Los geht’s!

Erstes Testprogramm - LoRaWAN-Anbindung

In der Pycom-Dokumentation gibt es eine Anleitung für eine LoRaWAN-Anbindung mit ABP. Da ich bis jetzt hauptsächlich mit der Authentikationsmethode Authentication by Personalisation (ABP) mit meinen ESP32-Modulen unter Arduino herumgespielt habe, passt das doch gut. Also richte ich ein neues Gerät pycom-lopy4 (der Name ist eigentlich Wurst, solange er sich an die Vorgaben hält) im The Things Network (TTN) ein. Damit habe ich die Gerätenummer, den Netzwerk-Sitzungsschlüssel und den Anwendungs-Sitzungsschlüssel. Die Werte kopiere ich direkt in die Beispieldatei aus der Anleitung:

from network import LoRa
import socket
import ubinascii
import struct

# Initialise LoRa in LORAWAN mode.
# Please pick the region that matches where you are using the device:
# Asia = LoRa.AS923
# Australia = LoRa.AU915
# Europe = LoRa.EU868
# United States = LoRa.US915
lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868)

# create an ABP authentication params

# In den folgenden drei Zeilen habe ich die Werte für mein Gerät
# pycom-lopy4 aus TTN kopiert.
dev_addr = struct.unpack(">l", ubinascii.unhexlify('00000005'))[0]
nwk_swkey = ubinascii.unhexlify('2B7E151628AED2A6ABF7158809CF4F3C')
app_swkey = ubinascii.unhexlify('2B7E151628AED2A6ABF7158809CF4F3C')

# join a network using ABP (Activation By Personalization)
lora.join(activation=LoRa.ABP, auth=(dev_addr, nwk_swkey, app_swkey))

# create a LoRa socket
s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)

# set the LoRaWAN data rate
s.setsockopt(socket.SOL_LORA, socket.SO_DR, 5)

# make the socket blocking
# (waits for the data to be sent and for the 2 receive windows to expire)
s.setblocking(True)

# send some data
s.send(bytes([0x01, 0x02, 0x03]))

# make the socket non-blocking
# (because if there's no data received it will block forever...)
s.setblocking(False)

# get any data received (if any...)
data = s.recv(64)
print(data)

Als main.py speichern - OK, aber wie bekomme ich die Datei auf das Gerät?

Im Abschnitt Getting Started - Software - Pymakr behauptet Pycom ein Plugin für zwei beliebte Editoren entwickelt zu haben. Allerdings fehlt zurzeit zumindest bei mir im Firefox alles nach dem Doppelpunkt. Welche Editoren könnten das sein? Zum Glück gibt es im Rest der Dokumentation ein Kapitel zum Pymakr. Es ist ein Plugin für Atom oder Visual Studio Code. Also schnell Atom starten und das Plugin installieren. Erledigt. Aber wie bekomme ich die Datei auf das Gerät. Ich habe jetzt zwar ein Menu Pymakr unter Packages, aber “Toggle Pycom Console” scheint nichts zu tun. Mein Verdacht ist, dass PlatformIO sich nicht mit Pymakr verträgt. Eine kurze Internet-Recherche bestätigt das. Vielleicht hat sich etwas in Pymakr oder in Atom geändert oder ich kann Atom nicht richtig bedienen (was auf jeden Fall zutrifft). Jedenfalls komme ich auch mit diesem Treffer nicht weiter. Die weiteren Treffer erwecken kein besonderes Vertrauen in Pymakr. Die Fragen sind etwa ein Jahr alt und ich stolpere heute noch darüber - meh. Da investiere ich keine weitere Zeit mehr…

Da das LoPy4 auch nur ein gut verkleidetes ESP32-Devboard mit einem LoRa-Sigfox-Modul ist, sollte man auch anders an MicroPython kommen. Da gab es doch ampy, rshell und mpfshell. Die habe ich alle drei vor langer Zeit bei meinen MicroPython auf ESP8266 ausprobiert. Doof, dass ich keinen Artikel dazu geschrieben habe, aber ich glaube, rshell hat mir damals am besten gefallen. Da ich Python 3 mit pip auf meinen Rechner habe, wird es mit pip install --user rshell flugs (laut Duden veraltend für schnell – ich bin also veraltend – so ein schönes Wort ‘flugs’) installiert.

Nach dem Start von rshell -p /dev/ttyACM0 sieht mein Prompt etwas anders aus, aber ich kann mit cp main.py /flash/ die Datei auf den LoPy4 kopieren. Die rshell bietet auch das Kommando repl mit dem man sich in der EVAS (siehe oben) von MicroPython befindet. Das wird hier zwar nicht gebraucht, ist aber schon praktisch.

Nach einem Reset des LoPy4 kommt die Nachricht [0x01, 0x02, 0x03] im TTN an.

Erfolg!

Gehäuse für Pytrack, LoPy4 und LiPo-Batterie

Es gibt ein Gehäuse von Pycom, das aber zurzeit nicht lieferbar ist. Bei den anderen ist mir nicht klar, ob sie auch für das Pytrack passen. Egal, ich hatte sowieso vergessen eins mit zu bestellen, ausserdem habe ich einen 3D-Drucker.

Eine Internet-Recherche führt mich zu zwei Gehäusen zum Ausdrucken. Auf Thingyverse habe ich Pycom GPy + Pytrack & Battery Carrying Case gefunden. GPy oder LoPy4 dürfte an sich egal sein, aber wie das Board in diesem Gehäuse gehalten werden soll, wird mir nicht klar. Es hat große Öffnungen. Kurz, es gefällt mir nicht. Von Matthias G habe ich das pytrack-case gefunden. Es sieht ordentlich aus. Also STL herunterladen, slicen und drucken. Keine Ahnung, welche Antennenanschlüsse er verwendet, aber mein SMA-Pigtail ist viel kleiner. Einmal PLA für die Tonne.

Cue the Music, hole den Messschieber heraus und starte FreeCAD.

Nach einigen Iterationen habe ich mein Gehäuse. Es hat keinen Schlitz für die MicroSD-Karte, aber dafür ein eigenes Fach, in dem die LiPo-Batterie mechanisch sicher sein sollte.

Teile des Gehäuses

Die Montage ist etwas fummelig, bis man den Stempel für den Taster auf dem Pytrack, das Antennenkabel ohne Knick und das Anschlusskabel der LiPo-Batterie verstaut hat.

fast fertig aufgebautes Gerät

Die FreeCAD-Datei und die STL-Dateien sind in meinem Github-Account abgelegt. Es gibt sie aber auch hier Unterteil - STL, Mittelteil - STL, Oberteil - STL und Alles - FreeCAD.

GNSS Positionsbestimmung

Nachdem jetzt die Elektronik jetzt sicher verpackt ist, geht es mit dem Programmieren weiter. Wie bei LoRaWAN gibt es auch eine Anleitung für Pytrack. Der Beispielkode ist in diesem Fall aber etwas merkwürdig.

Das fängt nach dem Import der Module an:

time.sleep(2)
gc.enable()

Warum soll der Mikrocontroller zwei Sekunden schlafen? Danach wird der automatische Speicherbereiniger eingeschaltet. Warum ist das nötig?

Der folgende Kode setzt die Uhrzeit per NTP. Ist das notwendig für die Positionsbestimmung?

rtc = machine.RTC()
rtc.ntp_sync("pool.ntp.org")
utime.sleep_ms(750)
print('\nRTC Set from NTP to UTC:', rtc.now())
utime.timezone(7200)
print('Adjusted from UTC to EST timezone', utime.localtime(), '\n')

Ich gehe davon aus, dass dies alles nicht notwendig ist, um die Position zu bestimmen und probiere die folgenden Zeilen in der EVAS aus.

from L76GNSS import L76GNSS
from pytrack import Pytrack

py = Pytrack()
l76 = L76GNSS(py, timeout=30)

l76.coordinates()

Mist! Es fehlen noch Bibliotheken. Wer aufmerksam die Dokumentation gelesen hat, weiß dies schon… Der Unaufmerksame findet die Information im Abschnitt Software - Installing Libraries. Warum die Pycom-Bibliotheken nicht vorinstalliert sind, erschließt sich mir nicht.

Also schnell noch die pycom-libraries herunterladen und mit rshell nach /flash/lib/ kopieren. Es werden lib/pycoproc/pycoproc.py und pytrack/lib/*.py benötigt.

Doof. Python ist zufrieden, aber l76.coordinates() gibt immer (None, None) aus. Ersetzt man diese Zeile mit l76._read(), so gibt Python Texte aus, die stark nach GPS-Meldungen aussehen.

Die erste Alternative die Pycom angibt, scheint nur die NMEA-Nachrichten zu parsen. Das Holen der Nachrichten vom GNSS-Chip muss wohl noch implementiert werden. Also probieren wir die Alternative L76GNSV4 aus. Die aktuelle Version (vom 2018-12-12) hat einen Klammerfehler in Zeile 287. Korrigiert, auf das Gerät geladen und der folgende Kode liefert meine aktuelle Position. Hurra!

from L76GNSV4 import L76GNSS
from pytrack import Pytrack

py = Pytrack()
l76 = L76GNSS(py, timeout=30)

l76.coordinates()

Im Nachhinein habe ich festgestellt, dass der GNSS-Empfang auf meinem Schreibtisch einfach zu schlecht ist. Es war mehr oder weniger Zufall, dass die zweite Bibliothek besser funktioniert hat…

Fazit und Ausblick

Mit dem Pycom LoPy4 und Pytracker kann man in MicroPython leicht einen TTN-Node erstellen, der seine Position durchgibt. Es ist nicht schwieriger als mit Arduino einen TTN-Node aufzubauen (siehe meinen Artikel auf Maker AG. Allerdings ist es auch nicht wirklich einfacher, wie ich erwartet hatte. Das Ganze benötigt von Pycom noch einigen Feinschliff. Vor allem bei der Qualität der Bibliotheken (insbesondere GNSS) bin ich etwas enttäuscht. Dass ich mit PyMakr nicht zurechtgekommen bin, könnte man auch PlatformIO anlasten, aber dass man sich die Bibliotheken von Pycom aus deren Github-Repository zusammensuchen und auf das Gerät an die richtige Stelle kopieren muss ist ein riesiger Nachteil.

Einen einfachen Node für TTN Mapper konnte ich mit dem oben beschriebene Kode zusammenbasteln. Der läuft allerdings noch nicht stabil genug. Das wird einen weiteren Artikel geben.

Das könnte Sie auch interessieren