RYS352A-Daten mit dem TTGO lesen
Verfasst: Di 7. Mai 2024, 15:31
In dem Beitrag Das GNNS-Modul RYS352A hatte ich das RYS352A-Modul der Firma REYAX vorgestellt und damit auch schon erste Tests mit Hilfe des Programms VisualGPSView durchgeführt. Nun wollen wir die NMEA-Datensätze mit Hilfe des TTGO T-Display zur Anzeige bringen. In einem ersten Schritt lassen wir alle Datensätze auf dem Thonny-Terminal anzeigen. Danach werden wir gezielt bestimmte Datensätze anzeigen lassen.
Alle Datensätze auf dem Terminal anzeigen
Das RY352A-Modul wird folgendermaßen an den TTGO angeschlossen:
Das Programm DataReceiver.py für den Empfang und die Anzeige der Datensätze im Terminal von Thonny besteht nur aus wenigen Zeilen:
Zunächst wird der UART-Konstruktor aus dem machine-Modul importiert. Mit diesem wird in der nächsten Zeile die Instanz uart erzeugt: Der 1. Parameter zeigt an, dass der ESP32 die Firmware-Uart 1 benutzen soll. In den weiteren Parametern werden die Protokollparameter (115.200 baud - 8 Bit - kein Paritätsbit - 1 Stop-Bit), die Pins für TxD und RxD sowie die Länge ihrer Puffer angegeben. Auf die Angaben für rts und cts könnte man auch verzichten.
Mit der Programmzeile uart.readline() wird ein Datensatz aus dem Lesepuffer der UART gelesen. Je nach Einschaltvorgang kann es sein, dass dieser erste Datensatz nicht vollständig ist. Deswegen lassen wir ihn beiseite.
In der darauf folgenden Endlos-Schleife wird zunächst ein (vollständiger) Datensatz gelesen. Er liegt zunächst als Bytestring vor und wird in der nächsten Zeile in einen String umgewandelt. In der letzten Zeile wird diese Zeichenkette mit der print-Funktion im Terminal ausgegeben. Der Parameter end =' ' sorgt dafür, dass kein automatischer Zeilenvorschub vorgenommen wird. Dies ist sinnvoll, weil die Zeichenkette data_str gemäß dem NMEA-Protokoll mit den Steuerzeichen <CR><LF> endet.
Datensätze mit vorgegebener ID anzeigen
Meist interessiert man sich nur für ganz bestimmte Datensätze. In diesem Abschnitt zeigen wir, wie man diese aus dem Strom von Datensätzen herausfiltern kann. Hierzu werden wir die NMEA-Zeichenketten jeweils in eine Liste umwandeln, deren Elemente aus den einzelnen Parametern des Datensatzes besteht. Dies wird sich auch in Hinblick auf die weitere Auswertung der Datensätze als sinnvoll herausstellen.
Unsere erste Version sieht so aus:
Die Bezeichnung des gewünschten Datensatzes gibt man über die input-Funktion an. Der Datensatz wird dann durch die Funktion get_data geliefert; dabei werden mittels try-except unerwartete Fehler abgefangen; im Falle eines solchen Fehlers ist der Rückgabewert der Funktion eine leere Zeichenkette.
Durch while True: wird eine Endlos-Schleife eingeleitet. In ihr wird zunächst ein Datensatz gelesen und mit der split-Methode in eine Liste (mit dem Namen row) umgewandelt, deren Elemente aus den einzelnen Parametern des Datensatzes besteht. Durch die Anweisung id = row.pop(0) wird das erste Element der Liste (die Datensatz-ID) aus der Liste entfernt und in id gespeichert. Wenn nun diese mit der gesuchte ID (data_id) übereinstimmt, dann wird row in gnss_list gespeichert und die Endlos-Schleife mit break abgebrochen. Danach wird gnss_list zurückgegeben und mittels print(get_data(ID)) auf dem Terminal ausgegeben.
Dem aufmerksamen Leser ist sicherlich schon aufgefallen, dass unser Programm noch einen Mangel aufweist: Wenn unsere Funktion get_data nämlich keinen passender Datensatz finden kann (weil es z. B. keinen Datensatz mit dieser ID gibt), dann wird unsere “Endlos-Schleife” tatsächlich niemals enden. Einen einfachen Ausweg bietet hier eine time-out-Kontrolle: Dazu speichern wie unmittelbar vor der Schleife einen Zeitstempel:
time0 = ticks_ms()
Innerhalb der Schleife fügen wir schließlich nach der Überprüfung von id die folgenden Zeilen ein:
Dadurch wird nun die Schleife (mit einer entsprechenden Fehlermeldung) abgebrochen, wenn die Zeitspanne beim Durchlaufen der Schleife den Wert von timeout überschreitet. Diesen Wert habe ich zu Beginn der get_data-Funktion auf 2000 ms festgelegt:
timeout = 2000
Da die Funktion ticks_ms() nicht zum Standardvokabular gehört, müssen wir sie zu Beginn des Programms importieren:
from utime import ticks_ms
Das so ergänzte Programm finden Sie im Anhang unter dem Dateinamen RYS352A_ID_Receiver_2.py.
.
Alle Datensätze auf dem Terminal anzeigen
Das RY352A-Modul wird folgendermaßen an den TTGO angeschlossen:
RYS352A-Modul | TTGO |
VCC (5) | 3 V |
GND (2) | G |
TxD (3) | RX (13) |
RxD (4) | TX (12) |
Das Programm DataReceiver.py für den Empfang und die Anzeige der Datensätze im Terminal von Thonny besteht nur aus wenigen Zeilen:
Code: Alles auswählen
# DataReceiver.py
from machine import UART
uart = UART(1, baudrate=115_200, bits=8, parity=None, stop=1, tx=12, rx=13, rts=-1, cts=-1, txbuf=256, rxbuf=256, timeout=5000, timeout_char=2)
uart.readline() # entfernt ggf. unvollständigen Datensatz
while True:
data = uart.readline() # Bytestring
data_str = str(data, 'UTF-8') # String
print(data_str, end ='')
Mit der Programmzeile uart.readline() wird ein Datensatz aus dem Lesepuffer der UART gelesen. Je nach Einschaltvorgang kann es sein, dass dieser erste Datensatz nicht vollständig ist. Deswegen lassen wir ihn beiseite.
In der darauf folgenden Endlos-Schleife wird zunächst ein (vollständiger) Datensatz gelesen. Er liegt zunächst als Bytestring vor und wird in der nächsten Zeile in einen String umgewandelt. In der letzten Zeile wird diese Zeichenkette mit der print-Funktion im Terminal ausgegeben. Der Parameter end =' ' sorgt dafür, dass kein automatischer Zeilenvorschub vorgenommen wird. Dies ist sinnvoll, weil die Zeichenkette data_str gemäß dem NMEA-Protokoll mit den Steuerzeichen <CR><LF> endet.
Datensätze mit vorgegebener ID anzeigen
Meist interessiert man sich nur für ganz bestimmte Datensätze. In diesem Abschnitt zeigen wir, wie man diese aus dem Strom von Datensätzen herausfiltern kann. Hierzu werden wir die NMEA-Zeichenketten jeweils in eine Liste umwandeln, deren Elemente aus den einzelnen Parametern des Datensatzes besteht. Dies wird sich auch in Hinblick auf die weitere Auswertung der Datensätze als sinnvoll herausstellen.
Unsere erste Version sieht so aus:
Code: Alles auswählen
# RYS352A_ID_Receiver_1.py
from machine import UART
uart = UART(1, baudrate=115_200, bits=8, parity=None, stop=1, tx=12, rx=13, rts=-1, cts=-1, txbuf=256, rxbuf=256, timeout=5000, timeout_char=2)
# Dabei sind die Parameter tx, rts, cts, txbuf eigentlich nicht erforderlich.
def get_data(data_id):
try:
uart.readline() # entfernt unvollständigen Datensatz
while True:
data = uart.readline() # Bytestring
data_str = str(data, 'UTF-8') # String
row = data_str.split(',') # Liste
id = row.pop(0)
if id == data_id:
gnss_list = row
break
return gnss_list
except:
return []
ID = input('ID (z. B. $GNRMC): ')
print(get_data(ID))
Die Bezeichnung des gewünschten Datensatzes gibt man über die input-Funktion an. Der Datensatz wird dann durch die Funktion get_data geliefert; dabei werden mittels try-except unerwartete Fehler abgefangen; im Falle eines solchen Fehlers ist der Rückgabewert der Funktion eine leere Zeichenkette.
Durch while True: wird eine Endlos-Schleife eingeleitet. In ihr wird zunächst ein Datensatz gelesen und mit der split-Methode in eine Liste (mit dem Namen row) umgewandelt, deren Elemente aus den einzelnen Parametern des Datensatzes besteht. Durch die Anweisung id = row.pop(0) wird das erste Element der Liste (die Datensatz-ID) aus der Liste entfernt und in id gespeichert. Wenn nun diese mit der gesuchte ID (data_id) übereinstimmt, dann wird row in gnss_list gespeichert und die Endlos-Schleife mit break abgebrochen. Danach wird gnss_list zurückgegeben und mittels print(get_data(ID)) auf dem Terminal ausgegeben.
Dem aufmerksamen Leser ist sicherlich schon aufgefallen, dass unser Programm noch einen Mangel aufweist: Wenn unsere Funktion get_data nämlich keinen passender Datensatz finden kann (weil es z. B. keinen Datensatz mit dieser ID gibt), dann wird unsere “Endlos-Schleife” tatsächlich niemals enden. Einen einfachen Ausweg bietet hier eine time-out-Kontrolle: Dazu speichern wie unmittelbar vor der Schleife einen Zeitstempel:
time0 = ticks_ms()
Innerhalb der Schleife fügen wir schließlich nach der Überprüfung von id die folgenden Zeilen ein:
Code: Alles auswählen
if (ticks_ms() - time0) > timeout:
print('Error: ' + data_id + '-Timeout')
break
timeout = 2000
Da die Funktion ticks_ms() nicht zum Standardvokabular gehört, müssen wir sie zu Beginn des Programms importieren:
from utime import ticks_ms
Das so ergänzte Programm finden Sie im Anhang unter dem Dateinamen RYS352A_ID_Receiver_2.py.
.