GPS-Track auf dem Display des TTGO anzeigen

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

GPS-Track auf dem Display des TTGO anzeigen

Beitrag von Heinrichs » 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:
  • 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.
Da sowohl beim ESP32 als auch beim GPS-Modul die Signalleitungen mit einem 3,3V-Pegel arbeiten, sind obendrein keine Pegelanpassungen erforderlich. Die Anschlüsse werden folgendermaßen vorgenommen:

Code: Alles auswählen


GY-GPS56MV2-Modul  --  TTGO 
VCC                --  5 V
GND                --  G
TX                 --  13 (RX)

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

Massstab_waehlen.jpg
Abb. 1: Maßstab wählen
Massstab_waehlen.jpg (28.32 KiB) 5595 mal betrachtet

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.

track.jpg
Abb. 2: Ein Track
track.jpg (28.99 KiB) 5593 mal betrachtet

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)


..
Dateianhänge
Umrechnung.pdf
Erläuterungen zur Umrechnung von Winkeln auf Strecken
(69.65 KiB) 773-mal heruntergeladen

Antworten