GPS-Track auf dem Display des TTGO anzeigen
Verfasst: Sa 31. Okt 2020, 13:06
Das GPS-Modul GY-GPS56MV2 habe ich im Zusammenhang mit dem Attiny2313 hier schon ausführlich vorgestellt. Hier soll das Modul nun mit dem TTGO T-Display betrieben werden. Zwei große Vorteile bietet es gegenüber dem Attiny2313-System:
Nach dem Start des Programms (s. u.) können Sie als Erstes den gewünschten Maßstab einstellen. Der aktuelle Maßstab wird gelb angezeigt; Sie können mit der Taste A (links oben) Ihre Auswahl ändern. Bestätigen Sie Ihre Wahl anschließend mit dem Taster B (links unten).
Nun sucht das Programm nach Satelliten. Sobald genügend Satelliten zur Verfügung stehen, beginnt die Aufzeichnung des Tracks im Zentrum des Koordinatensystems, hier gekennzeichnet durch einen roten Punkt.
Bei dem Spaziergang in Abb. 2 wurde zunächst südlich vom Startpunkt eine "Runde" gegangen; daran schloss sich ein Weg etwa in Richtung NW an. Das Rastermaß ist hier 0,5 km. Oberhalb des Tracks wird die aktuelle Satelliten-Zeit angegeben.
Es folgt das MicroPython-Programm; die wesentlichen Punkte werden durch die Kommentare erklärt. Die Umrechnung der vom GPS-Modul gelieferten Winkelangaben in Streckenangaben wird ausführlich in der Anlage "Umrechnung" dargelegt.
..
- Das MicroPython-System auf dem ESP32 stellt mächtigere Befehle zur Verfügung als der beim Attiny2313 benutzte BASCOM-Compiler; das macht die Programmierung einfacher.
- Das auf dem Modul integrierte Display erlaubt es, den Track für kleinere Wanderungen oder Spaziergänge anzuzeigen.
Code: Alles auswählen
GY-GPS56MV2-Modul -- TTGO
VCC -- 5 V
GND -- G
TX -- 13 (RX)
Nun sucht das Programm nach Satelliten. Sobald genügend Satelliten zur Verfügung stehen, beginnt die Aufzeichnung des Tracks im Zentrum des Koordinatensystems, hier gekennzeichnet durch einen roten Punkt.
Bei dem Spaziergang in Abb. 2 wurde zunächst südlich vom Startpunkt eine "Runde" gegangen; daran schloss sich ein Weg etwa in Richtung NW an. Das Rastermaß ist hier 0,5 km. Oberhalb des Tracks wird die aktuelle Satelliten-Zeit angegeben.
Es folgt das MicroPython-Programm; die wesentlichen Punkte werden durch die Kommentare erklärt. Die Umrechnung der vom GPS-Modul gelieferten Winkelangaben in Streckenangaben wird ausführlich in der Anlage "Umrechnung" dargelegt.
Code: Alles auswählen
######################################
# GPS-Track mit Massstabauswahl #
# für ESP32-Modul (TTGO T-Display) #
# erstellt am 06.08.2020 #
# von G. Heinrichs #
######################################
# Anschlüsse:
# GY-GPS56MV2-Modul -- TTGO
# VCC -- 5 V
# GND -- G
# TX -- 13 (RX)
from machine import Pin, SPI, UART
from time import sleep
from math import cos, pi
import vga1_8x8 as font0
import vga2_8x16 as font1 # für Sonderzeichen (Umlaute)
import vga1_bold_16x16 as font2
import st7789
# Display initialisieren...
spi = SPI(2, baudrate=20000000, 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) # Landscape
display.init()
display.fill(0) # loeschen; Bildschirm schwarz
########################## Funktionen #############################
# -------------------------- KS und Massstab ----------------------
def rahmen():
display.rect(0, 0, 239, 134, st7789.YELLOW)
display.rect(0, 0 ,20 ,20, st7789.YELLOW)
display.text(font2, 'A', 2, 2, st7789.YELLOW)
display.rect(0, 114 ,20 ,20, st7789.YELLOW)
display.text(font2, 'B', 2, 117, st7789.YELLOW)
def taster_eingabe(): # gibt Taster-Nummer zurück (A = 1, B = 2)
tasterA = Pin(0, Pin.IN, Pin.PULL_UP)
tasterB = Pin(35, Pin.IN) # hat auf dem Board schon einen 100K-Pullup (bei Key)
t = 0
weiter = True
while weiter:
if tasterA.value() == 0:
t = 1
if tasterB.value() == 0:
t = 2
if t > 0:
sleep(0.2)
if tasterA.value() and tasterB.value() == True:
weiter = False
return t
def auswahl_anzeigen(awliste):
for item in awliste:
if item[4]: # if selected...
pixel_pro_km = item[0]
display.text(font1,str(item[0])+item[1],item[2],item[3],st7789.YELLOW)
else:
display.text(font1,str(item[0])+item[1],item[2],item[3],st7789.WHITE)
def massstab_waehlen(awliste): # gibt die ausgewählten Pixel/km als int zurück
global itemindex
weiter = True
while weiter:
rahmen()
auswahl_anzeigen(awliste)
while True:
taster = taster_eingabe()
if taster == 1: # Scrollen
itemindex += 1
itemindex = itemindex % len(auswahlliste)
for item in awliste: # erst alle auf False setzen
item[4] = False
awliste[itemindex][4]=True # dann indiziertes Item auf True
auswahl_anzeigen(awliste)
if taster == 2: # auswählen
return awliste[itemindex][0]
weiter = False
# -------------------------------- GPS ---------------------------------
def get_GPS_set(set): # liefert Liste zu der Kennung "set", z. B. $GPRMC
# warten, bis Line-Feed gefunden...
try:
while True:
zeichen = uart.read(1)
if zeichen == b'\x0a': #'\n'
break
while True:
data = uart.readline()
data_str = str(data, 'UTF-8')
zeile = data_str.split(',')
kennung = zeile.pop(0) # entfernt Element mit dem Index 0 aus zeile und speichert es in kennung
if kennung == set:
set_liste = zeile
if set_liste[2] != '':
break
return set_liste
except:
return []
def ks(n, e, n_start, e_start): # skalierte GPS-Koordinaten -> Display-Koordinaten [x,y]
erg = [0,0]
erg[0] = int(e-e_start) + 120 # x
erg[1] = -int(n-n_start) + 67 # y
return erg
def show_units(pix_pro_km):
for i in range(3):
display.line(10, 17+50*i, 230, 17+50*i, st7789.YELLOW) # horizontale Linien
for i in range(5):
display.line(20+50*i, 7, 20+50*i, 127, st7789.YELLOW) # vertikale Linien
display.text(font0, str(50/pix_pro_km), 25, 70, st7789.YELLOW)
display.text(font0, 'km', 25, 80, st7789.YELLOW)
display.fill_rect(120-2,67-2,5,5,st7789.RED)
############################### Hauptprogramm #########################
# -------------------------- Auswahl des Massstabs --------------------
# Rahmen mit Taster-Kennung, Überschrift
rahmen()
display.text(font2, 'ESP32-GPS', 50, 5)
display.text(font1, 'Mit Taster A scrollen', 35, 25, st7789.RED)
display.text(font1, b'Mit Taster B ausw\x84hlen', 35, 40, st7789.RED)
sleep(2)
# Auswahlliste initialisieren
itemindex = 2 # Standardvorgabe: 100 Pixel pro km
massstab0 = [20, ' Pixel/km ', 35, 60, False]
massstab1 = [50, ' Pixel/km ', 35, 75, False]
massstab2 = [100, ' Pixel/km ', 35, 90, False]
massstab3 = [200, ' Pixel/km ', 35, 105, False]
auswahlliste = [massstab0, massstab1, massstab2, massstab3]
auswahlliste[itemindex][4] = True
# Auswahl durchführen
pixel_pro_km = massstab_waehlen(auswahlliste)
# ---------------------- GPS -----------------------------------------
# UART initialisieren
uart = UART(1, baudrate=9600, bits=8, parity=None, stop=1, tx=12, rx=13, rts=-1, cts=-1, txbuf=256, rxbuf=256, timeout=5000, timeout_char=2)
display.fill(0)
display.text(font0, 'Warte auf Sat-Daten...', 5, 50, st7789.YELLOW)
sleep(1)
scale = 10000*pixel_pro_km/90
# Startposition
GPRMC = get_GPS_set('$GPRMC')
# GPRMC liefert [X]XXYY.ZZZZ; wird umgewandelt in [X]XX°+(YY.ZZZZ/60)°
north = float(GPRMC[2][0:2])+float(GPRMC[2][2:8])/60
east = (float(GPRMC[4][0:3])+float(GPRMC[4][3:9])/60)
# Winkel -> Pixel-Maß
north_wert_start = north * scale # alle weiteren Werte müssen darauf bezogen werden
east_wert_start = east * scale * cos(pi*north/180) # alle weiteren Werte müssen darauf bezogen werden; Breitenkreis-Anpassung
display.fill(0)
show_units(pixel_pro_km)
x0,y0 = ks(north_wert_start, east_wert_start, north_wert_start, east_wert_start)
display.pixel(x0,y0,st7789.GREEN)
# weitere Positionen...
while True:
GPRMC = get_GPS_set('$GPRMC')
time = GPRMC[0]
time = time[0:2] + ':' + time[2:4] + ':' + time[4:6]
display.text(font0, 't: '+time,25,0)
north = float(GPRMC[2][0:2])+float(GPRMC[2][2:8])/60
east = (float(GPRMC[4][0:3])+float(GPRMC[4][3:9])/60)
north_wert_1 = north * scale
east_wert_1 = east * scale * cos(pi*north/180)
x1,y1 = ks(north_wert_1, east_wert_1, north_wert_start, east_wert_start)
display.line(x0,y0,x1,y1,st7789.GREEN)
# letzte Koordinaten merken
x0 = x1
y0 = y1
sleep(1)
..