Ein RYS352A-Micropython-Modul

Hier werden einzelne Projekte mit MicroPython vorgestellt
Antworten
Heinrichs
Beiträge: 185
Registriert: Do 21. Okt 2010, 18:31

Ein RYS352A-Micropython-Modul

Beitrag von Heinrichs » Mi 8. Mai 2024, 10:12

Um Programme übersichtlicher zu gestalten, erstellen wir eine Klasse RYS352A, welche neben der schon in dem Beitrag RYS352A-Daten mit dem TTGO lesen vorgestellten Methode get_data noch weitere nützliche Methoden besitzt. Diese Klasse speichern wir unter dem Namen rys352a.py im Flash-Speicher unseres TTGO ab.

Hier zunächst der Code von rys352a.py :

Code: Alles auswählen

class RYS352A():
    def __init__(self, uart, ticks_ms):
        self.uart = uart
        self.ticks_ms = ticks_ms
        self.timeout = 2000 # Timeout-Zeit in ms
               
    def get_data(self, data_id):
        try:
            time0 = self.ticks_ms()
            self.uart.readline()
            while True:
                gnss_list = []
                data = self.uart.readline() # Bytestring
                data_str = str(data, 'UTF-8') # String
                row = data_str.split(',')
                id = row.pop(0)
                if id == data_id:
                    gnss_list = row
                    break
                if (self.ticks_ms() - time0) > self.timeout:     
                    print('Error: ' + data_id + '-Timeout')
                    break
		return gnss_list 
        except BaseException as err:
            print('Fehler:', err)
            return []
        
    def send_cmd(self, cmd):
        cmd = bytes(cmd, 'UTF-8')
        self.uart.write(cmd + b'\r\n')
        
    def read_item(self):
        data = self.uart.readline() # Bytestring
        data_str = str(data, 'UTF-8') # String
        return data_str


Und so wird eine Instanz gnss von RYS352A erzeugt:

Code: Alles auswählen

from machine import UART
from utime import ticks_ms
from rys352a import RYS352A

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)

gnss = RYS352A(uart, ticks_ms)

Mit Hilfe des Konstruktors werden uart und ticks_ms zu Eigenschaften der RYS352A-Klasse. Als weitere Eigenschaft wird noch timeout (mit dem Standardwert 2000) festgelegt. Dieser Wert kann vom Benutzer geändert werden, z. B. mit

gnns.timeout = 3500


Werfen wir jetzt einen Blick auf die Methoden unserer RYS352A-Klasse:
  • get_data entspricht im Wesentlichen der Methode get_data (mit Timeout), welche wir im Kapitel 2 vorgestellt haben.
  • Mit send_cmd können wir sogenannte PAIR-Kommandos an das RYS352A-Modul senden. Damit kann man z. B. bestimmen, welche Satellitensysteme benutzt werden sollen. Mehr dazu im Kapitel 4!
  • Mit read_item können wir den gerade im Lesepuffer befindlichen Datensatz (als String) erhalten.

Eine Anwendung der RYS352A-Klasse

Mit der soeben vorgestellten Klasse können wir recht einfach GNSS-Daten auf dem Display anzeigen lassen (s. Abb. 1).

Display_mit_GPS_Daten_neu_klein.jpg
Abb. 1
Display_mit_GPS_Daten_neu_klein.jpg (125.82 KiB) 20262 mal betrachtet

Zunächst die nötigen Importe und Instanziierungen:

Code: Alles auswählen

from machine import UART
from time import sleep
from utime import ticks_ms
from machine import Pin, SPI
import vga1_16x16 as font1
import vga2_8x16 as font2
import st7789
from rys352a import RYS352A

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)

id = 1 # id = 2 z. B. für Firmware V1.12 u. V1.14, id = 1 für V1.18 u. V.1.20
spi = SPI(id, baudrate=20_000_000, polarity=1, sck=Pin(18), mosi=Pin(19))
	display = st7789.ST7789(spi, 135, 240, reset=Pin(23, Pin.OUT), cs=Pin(5, Pin.OUT), dc=Pin(16, Pin.OUT), backlight=Pin(4, Pin.OUT), rotation=3)
display.init()
display.fill(0)
display.rect(0,0,239,24,st7789.WHITE) # Titel mit Rahmen...
display.text(font1, 'TTGO-GNSS', 48, 5)

gnss = RYS352A(uart, ticks_ms)

Die in Abb. 1 aufgeführten Daten entnehmen wir den Datensätzen $GNRMC, $GNGGA und $GNVTG. Die zugehörigen Datensatz-Listen werden im Rahmen einer Endlos-Schleife ermittelt; deren Elemente liefern uns jeweils die gewünschten Parameter:

Code: Alles auswählen

while True:
    RMC_list = gnss.get_data('$GNRMC')
    GGA_list = gnss.get_data('$GNGGA')
    VTG_list = gnss.get_data('$GNVTG')
    
    # Block 1 (Koordinaten)    
    display.rect(0, 35, 239, 24, st7789.RED)
    display.text(font2,N_S_to_degree(RMC_list[2]),5,40)
    display.text(font2, RMC_list[3], 95, 40)
    display.text(font2,E_W_to_degree(RMC_list[4]),130,40)
    display.text(font2, RMC_list[5], 225, 40)    

    # Block 2 (Uhrzeit, Anzahl der Satelliten)
    display.rect(0, 70, 239, 24, st7789.BLUE)
    display.text(font2, 'Zeit: ' + time_to_h_min_s(GGA_list[0]), 5, 75)
    display.text(font2, 'Anz. Sat.: ' + GGA_list[6], 130, 75)    

    # Block 3 (Höhe bzgl. Geoid, Geschwindigkeit über Grund)
    display.rect(0, 105, 239, 24, st7789.GREEN)
    display.text(font2, 'h(Geo): ' + GGA_list[8] + ' m', 5, 110)
    display.text(font2, 'v: ' + VTG_list[6] + ' km/h', 130, 110)

    sleep(2)

Dabei bietet sich bei einigen Parametern eine Umformatierung an: So schreiben wir statt der (abkürzenden) NMEA-Breiten-Angabe 5110.6341 üblicherweise 51̊ 10,6341'.

Die entsprechende Umformatierung geschieht durch die folgende Funktion:

Code: Alles auswählen

def N_S_to_degree(s) -> bytes: # Angaben für N/S in Grad umwandeln
    v1 = s[0:2]
    v2 = s[2:4]
    v3 = s[5:9]
    return bytes(v1, 'UTF-8')+b'\xF8'+bytes(v2+'.'+v3+chr(39), 'UTF-8')
Dabei benutzen wir hier Byte-Strings, weil wir hierüber auch Sonderzeichen auf dem Display anzeigen lassen können; Informationen zu den Sonderzeichen beim TTGO T-Display, insbesondere auch eine Sonderzeichentabelle, finden Sie in meinem Beitrag Das Display: Eigenschaften und Programmierung mit MicroPython.

Die text-Methode von display kann übrigens sowohl mit Strings als auch mit Byte-Strings arbeiten; eine Konvertierung brauchen wir hier also nicht vornehmen.

Für die Umformatierung der Längen- bzw. Zeit-Angaben setzen wir die folgenden beiden Funktionen ein:

Code: Alles auswählen

def E_W_to_degree(s) -> bytes: # Angaben für E/W in Grad umwandeln
    v1 = s[0:3]
    v2 = s[3:5]
    v3 = s[6:10]
    return bytes(v1, 'UTF-8')+b'\xF8'+bytes(v2+'.'+v3+chr(39), 'UTF-8')

def time_to_h_min_s(s) -> bytes: # Angaben in hh:mm:ss umwandeln
    v1 = s[0:2]
    v2 = s[2:4]
    v3 = s[4:6]
    return v1+':'+v2+':'+v3


Das gesamte Programm finden Sie in der Anlage unter dem Dateinamen RYS352A_Position_Datetime_more_Display.py.

.
Dateianhänge
RYS352A_Position_Datetime_more_Display.zip
(2.33 KiB) 1702-mal heruntergeladen

Antworten