RP2040-GEEK
GPS Datenlogging
Anleitung für die Firmware CircuitPython
Bildbox 1 (klick hier)
RP2040-GEEK
GPS Datenlogging
Anleitung für die Firmware CircuitPython
Bildbox 1 (klick hier)
In dieser Anleitung werden die geogr. Koordinaten (Längen- und Breitengrad) mit Hilfe des Moduls 'seeed Grove Air 530' bestimmt und
auf dem Pico-GEEK angezeigt bzw. aufgezeichnet. Damit lässt sich z.B. die Entfernung von einem vorgegebenen Ort bestimmen oder ein
Datentracking durchführen. Für rund 25 Euro (RP2040-GEEK: 13 Euro + GPS-Modul: 12 Euro) kann man also seinen eigenen GPS-Tracker
bauen.
Hardware
- RP2040-GEEK incl. mitgelieferte Kabel
- seeed Grove - GPS Modul (Air530) incl. mitgelieferte Antenne
- (Powerbank zur Stromversorgung, Einsatz autark im Freien)
Los gehts
Das GPS-Modul wird über 'UART' mit dem Pico-GEEK' verbunden, d.h. wir brauchen vier Anschlüsse. Auf dem GPS-Modul benutzen
wir dafür VIN, GND, GPS_TXD und GPS_RXD. TX ist der Pin am Microcontroller, der Daten vom GPS-Modul
empfängt. Es handelt sich um einen Logikpegel von 3,3 V. Die Daten werden standardmäßig mit 9600 Baud übertragen.
RX ist der Pin am Microcontroller, mit dem die Daten an das GPS-Modul gesendet werden können. Es können 3,3-V- oder 5-V-Logik
verwenden werden. Es gibt einen Logikpegelumsetzer.
Standardmäßig werden 9600-Baud-Daten erwartet. Für die Tests habe ich wie im Bild sichtbar zunächst Headerleisten mit
jeweils 5 Stiften an die Platine gelötet. Später werden die Kabel platzsparender direkt an das Modul gelötet.
Bei 'UART' verwendet der Pico üblicherweise GPIO 0 für TX, GPIO 1 für RX bzw. GPIO 4 für TX, GPIO 5 für RX.
Aus der Beschriftung auf dem Pico-Geek ist zu entnehmen,
dass wir mit GPIO 4 und GPIO5 arbeiten können (siehe unteres Bild). Die Spannung 3,3 V und die Masse greifen wir uns aus der vierpoligen
Buchse (I2C/ADC) ab.
In einer Anleitung zur Nutzung von 'UART' beim RP-Pico schreibt Adafruit:
Set Uart0: TX = board.GP0 and RX = board.GP1 or Uart1: TX = board.GP4 and RX = board.GP5
uart = busio.UART(board.GP4, board.GP5, baudrate=9600, timeout=10)
These are the defaults you should use for the GPS FeatherWing.For other boards set RX = GPS module TX, and TX = GPS module
RX pins.
Was folgt daraus? D.h. schließen Sie das grüne Kabel GP5 (RX am Board) an GPS_TXD des Moduls und das
blaue Kabel GP4 (TX am Board) an GPS_RXD des Moduls an (siehe Foto oben).
Es folgt der eigentliche Programmcode. Zunächst wird die Bibliothek 'adafruit_gps.mpy' benötigt, die Sie
hier
herunterladen, entpacken und in den 'lib_Ordner' kopieren können. Im unteren Kasten ist der neue Programmcode bis einschließlich
der Definition des 'UART' Moduls. Er stimmt in den Zeilen 1 bis 62 mit dem Code in den bisherigen Anleitungen, bis auf das Laden
von 'adafruit_gps' in Zeile 13, überein. Und die Initialisierung der SD-Karte hätte es in diesem Beispiel noch nicht gebraucht.
Das ist dann später schon vorhanden.
1 import os
2 import time
3 import board
4 import busio
5 import sdcardio
6 import digitalio
7 import storage
8 from fourwire import FourWire
9 from adafruit_display_text import label
10 import terminalio
11 import displayio
12 from adafruit_st7789 import ST7789
13 import adafruit_gps
14
15 # Display initialisieren
16 lcd_cs=board.GP9
17 lcd_dc=board.GP8
18 lcd_reset=board.GP12
19 # Release any resources currently in use for the displays
20 displayio.release_displays()
21 spi = busio.SPI(board.GP10, board.GP11)
22 display_bus = FourWire(spi, command=lcd_dc, chip_select=lcd_cs, reset=lcd_reset)
23 display = ST7789(display_bus, rotation=90, width=240, height=135, rowstart=40, colstart=53)
24 # Make the display context
25 splash = displayio.Group()
26 display.root_group = splash
27
28 # Make a background color fill
29 color_bitmap = displayio.Bitmap(display.width, display.height, 3)
30 color_palette = displayio.Palette(3)
31 color_palette[0] = 0x660088
32 color_palette[1] = 0x000000
33 color_palette[2] = 0xffffff
34 bg_sprite = displayio.TileGrid(color_bitmap, pixel_shader=color_palette, x=0, y=0)
35 splash.append(bg_sprite)
36
37 # Draw a label
38 text_area = label.Label(font=terminalio.FONT, text="\n RP2040 GEEK\n\n it work's" , color=0xFFFF00, scale=2, line_spacing=1 )
39 text_group = displayio.Group(x=15, y=10)
40 text_group.append(text_area) # Subgroup for text scaling
41 splash.append(text_group)
42
43 # SD Karte mounten
44 SD_SCK = board.GP18
45 SD_MOSI = board.GP19
46 SD_MISO = board.GP20
47 cs = board.GP23
48
49 try:
50 card = busio.SPI(SD_SCK, SD_MOSI, SD_MISO)
51 sdcard = sdcardio.SDCard(card, cs)
52 vfs = storage.VfsFat(sdcard)
53 storage.mount(vfs, "/sd")
54 text_area.text = "\n SD-Karte\n erfolgreich\n gemountet."
55
56 except OSError as exc:
57 error = exc.errno
58 print(error)
59 text_area.text = "\n\n keine SD-Karte\n\n vorhanden."
60
61 time.sleep(2)
62
63 # Set Uart0: TX = board.GP0 and RX = board.GP1 (or Uart1: TX = board.GP4 and RX = board.GP5)
64 uart = busio.UART(board.GP4, board.GP5, baudrate=9600, timeout=10)
65
66 # Create a GPS module instance.
67 gps = adafruit_gps.GPS(uart, debug=False) # Use UART/pyserial
68 # gps = adafruit_gps.GPS_GtopI2C(i2c, debug=False) # Use I2C interface
69
70 # Turn on the basic GGA and RMC info (what you typically want)
71 gps.send_command(b"PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0")
72 # Set update rate to once a second (1hz) which is what you typically want.
73 gps.send_command(b"PMTK220,1000")
74 # Main loop runs forever printing the location, etc. every second.
75 last_print = time.monotonic()
76
In den Zeilen 63 bis 76 habe ich mich weitesgehend an einer Anleitung zur Einrichtung des 'GPS-Moduls' bei Adafruit
orientiert. Entscheidend für die Funktion ist der obige Hinweis zu den GPIO's und die Definition von 'UART 1' in
Zeile 64. In den Zeilen 66 bis 73 werden Einstellungen vorgenommen, die für die Funktion notwendig sind. Zeile 75
stellt in der 'while-Schleife' die Zeit für die Wiederholungen bereit. Es folgt die 'while-Scheife':
77 while True:
78 gps.update()
79 # Every second print out current location details if there's a fix.
80 if time.monotonic() - last_print < 4.0:
81 if gps.satellites is not None:
82 if gps.speed_knots == None:
83 gps.speed_knots = 0
84 text_area.text = ("\nSat. : " + str(gps.satellites) + "\nGeschw.: " + str(gps.speed_knots*1.852) +
85 " km/h\nHoehe : " + str(gps.altitude_m) + " m")
86 else:
87 text_area.text = "\n z.Z. kein\nSatellitenempfang\n bitte warten"
88 else:
89 #print("Latitude: {0:.7f} Grad".format(gps.latitude))
90 #print("Longitude: {0:.7f} Grad".format(gps.longitude))
91 #print("Präziser Breitengrad: {} Grad, {:2.2f} Min".format(
92 # gps.latitude_degrees, gps.latitude_minutes))
93 #print("Präziser Längengrad: {} Grad, {:2.2f} Min".format(
94 # gps.longitude_degrees, gps.longitude_minutes))
95 ##print("Fix quality: {}".format(gps.fix_quality))
96 ## Some attributes beyond latitude, longitude and timestamp are optional
97 ## and might not be present. Check if they're None before trying to use!
98 #if gps.satellites is not None:
99 # print("# Anzahl Satelliten: {}".format(gps.satellites))
100 #if gps.altitude_m is not None:
101 # print("Höhe: {} meters".format(gps.altitude_m))
102 #if gps.speed_knots is not None:
103 # print("Geschwindigkeit: {} Knoten".format(gps.speed_knots))
104 #if gps.track_angle_deg is not None:
105 # print("Spurwinkel: {} degrees".format(gps.track_angle_deg))
106 ##if gps.horizontal_dilution is not None:
107 ## print("Horizontale Streubreite: {}".format(gps.horizontal_dilution))
108 ##if gps.height_geoid is not None:
109 ## print("Height geoid: {} meters".format(gps.height_geoid))
110 if gps.satellites is not None:
111 lat = gps.latitude
112 lon = gps.longitude
113 text_area.text = ("\nLatitude:\n {0:.7f}".format(lat) +
114 "\nLongitude:\n {0:.7f}".format(lon))
115 else:
116 text_area.text = "\n z.Z. kein\nSatellitenempfang\n bitte warten"
117 if time.monotonic() - last_print >= 10.0:
118 last_print = time.monotonic()
119
In der Schleife wird alle 4 Sekunden zwischen der Anzeige von 'Latitude, Longitude' und der Anzahl
der Satelliten, Geschwindigkeit und der Höhe gewechselt. Dabei enthält gps.update() (Zeile 78) jeweils die aktuellen Werte.
Die auskommentierten Zeilen 89 bis 109 ermöglichen es Ihnen, noch eine ganze Reihe weiterer Werte anzeigen zu lassen. Experimentieren Sie
einfach ein wenig damit, indem Sie die Kommentierung entfernen.
Ein letzter Hinweis:
Wenn das Programm gestartet wird, erscheint zunächst die Ausgabe: z.Z. kein Satellitenempfang, bitte warten. Beachten Sie
dabei eine Besonderheit des GPS-Moduls, welche in den technischen Daten wie folgt angegeben wird: "30s Zeit für Kaltstart und
4s Zeit für Warmstart" . Also ein klein wenig Geduld und dann
viel Spass und Erfolg beim Ausprobieren.
Bei 'UART' verwendet der Pico üblicherweise GPIO 0 für TX, GPIO 1 für RX bzw. GPIO 4 für TX, GPIO 5 für RX. Aus der Beschriftung auf dem Pico-Geek ist zu entnehmen, dass wir mit GPIO 4 und GPIO5 arbeiten können (siehe unteres Bild). Die Spannung 3,3 V und die Masse greifen wir uns aus der vierpoligen Buchse (I2C/ADC) ab.
In einer Anleitung zur Nutzung von 'UART' beim RP-Pico schreibt Adafruit:
Set Uart0: TX = board.GP0 and RX = board.GP1 or Uart1: TX = board.GP4 and RX = board.GP5
uart = busio.UART(board.GP4, board.GP5, baudrate=9600, timeout=10)
These are the defaults you should use for the GPS FeatherWing.For other boards set RX = GPS module TX, and TX = GPS module RX pins.
Was folgt daraus? D.h. schließen Sie das grüne Kabel GP5 (RX am Board) an GPS_TXD des Moduls und das blaue Kabel GP4 (TX am Board) an GPS_RXD des Moduls an (siehe Foto oben).
Es folgt der eigentliche Programmcode. Zunächst wird die Bibliothek 'adafruit_gps.mpy' benötigt, die Sie hier herunterladen, entpacken und in den 'lib_Ordner' kopieren können. Im unteren Kasten ist der neue Programmcode bis einschließlich der Definition des 'UART' Moduls. Er stimmt in den Zeilen 1 bis 62 mit dem Code in den bisherigen Anleitungen, bis auf das Laden von 'adafruit_gps' in Zeile 13, überein. Und die Initialisierung der SD-Karte hätte es in diesem Beispiel noch nicht gebraucht. Das ist dann später schon vorhanden.
1 import os 2 import time 3 import board 4 import busio 5 import sdcardio 6 import digitalio 7 import storage 8 from fourwire import FourWire 9 from adafruit_display_text import label 10 import terminalio 11 import displayio 12 from adafruit_st7789 import ST7789 13 import adafruit_gps 14 15 # Display initialisieren 16 lcd_cs=board.GP9 17 lcd_dc=board.GP8 18 lcd_reset=board.GP12 19 # Release any resources currently in use for the displays 20 displayio.release_displays() 21 spi = busio.SPI(board.GP10, board.GP11) 22 display_bus = FourWire(spi, command=lcd_dc, chip_select=lcd_cs, reset=lcd_reset) 23 display = ST7789(display_bus, rotation=90, width=240, height=135, rowstart=40, colstart=53) 24 # Make the display context 25 splash = displayio.Group() 26 display.root_group = splash 27 28 # Make a background color fill 29 color_bitmap = displayio.Bitmap(display.width, display.height, 3) 30 color_palette = displayio.Palette(3) 31 color_palette[0] = 0x660088 32 color_palette[1] = 0x000000 33 color_palette[2] = 0xffffff 34 bg_sprite = displayio.TileGrid(color_bitmap, pixel_shader=color_palette, x=0, y=0) 35 splash.append(bg_sprite) 36 37 # Draw a label 38 text_area = label.Label(font=terminalio.FONT, text="\n RP2040 GEEK\n\n it work's" , color=0xFFFF00, scale=2, line_spacing=1 ) 39 text_group = displayio.Group(x=15, y=10) 40 text_group.append(text_area) # Subgroup for text scaling 41 splash.append(text_group) 42 43 # SD Karte mounten 44 SD_SCK = board.GP18 45 SD_MOSI = board.GP19 46 SD_MISO = board.GP20 47 cs = board.GP23 48 49 try: 50 card = busio.SPI(SD_SCK, SD_MOSI, SD_MISO) 51 sdcard = sdcardio.SDCard(card, cs) 52 vfs = storage.VfsFat(sdcard) 53 storage.mount(vfs, "/sd") 54 text_area.text = "\n SD-Karte\n erfolgreich\n gemountet." 55 56 except OSError as exc: 57 error = exc.errno 58 print(error) 59 text_area.text = "\n\n keine SD-Karte\n\n vorhanden." 60 61 time.sleep(2) 62 63 # Set Uart0: TX = board.GP0 and RX = board.GP1 (or Uart1: TX = board.GP4 and RX = board.GP5) 64 uart = busio.UART(board.GP4, board.GP5, baudrate=9600, timeout=10) 65 66 # Create a GPS module instance. 67 gps = adafruit_gps.GPS(uart, debug=False) # Use UART/pyserial 68 # gps = adafruit_gps.GPS_GtopI2C(i2c, debug=False) # Use I2C interface 69 70 # Turn on the basic GGA and RMC info (what you typically want) 71 gps.send_command(b"PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0") 72 # Set update rate to once a second (1hz) which is what you typically want. 73 gps.send_command(b"PMTK220,1000") 74 # Main loop runs forever printing the location, etc. every second. 75 last_print = time.monotonic() 76
77 while True: 78 gps.update() 79 # Every second print out current location details if there's a fix. 80 if time.monotonic() - last_print < 4.0: 81 if gps.satellites is not None: 82 if gps.speed_knots == None: 83 gps.speed_knots = 0 84 text_area.text = ("\nSat. : " + str(gps.satellites) + "\nGeschw.: " + str(gps.speed_knots*1.852) + 85 " km/h\nHoehe : " + str(gps.altitude_m) + " m") 86 else: 87 text_area.text = "\n z.Z. kein\nSatellitenempfang\n bitte warten" 88 else: 89 #print("Latitude: {0:.7f} Grad".format(gps.latitude)) 90 #print("Longitude: {0:.7f} Grad".format(gps.longitude)) 91 #print("Präziser Breitengrad: {} Grad, {:2.2f} Min".format( 92 # gps.latitude_degrees, gps.latitude_minutes)) 93 #print("Präziser Längengrad: {} Grad, {:2.2f} Min".format( 94 # gps.longitude_degrees, gps.longitude_minutes)) 95 ##print("Fix quality: {}".format(gps.fix_quality)) 96 ## Some attributes beyond latitude, longitude and timestamp are optional 97 ## and might not be present. Check if they're None before trying to use! 98 #if gps.satellites is not None: 99 # print("# Anzahl Satelliten: {}".format(gps.satellites)) 100 #if gps.altitude_m is not None: 101 # print("Höhe: {} meters".format(gps.altitude_m)) 102 #if gps.speed_knots is not None: 103 # print("Geschwindigkeit: {} Knoten".format(gps.speed_knots)) 104 #if gps.track_angle_deg is not None: 105 # print("Spurwinkel: {} degrees".format(gps.track_angle_deg)) 106 ##if gps.horizontal_dilution is not None: 107 ## print("Horizontale Streubreite: {}".format(gps.horizontal_dilution)) 108 ##if gps.height_geoid is not None: 109 ## print("Height geoid: {} meters".format(gps.height_geoid)) 110 if gps.satellites is not None: 111 lat = gps.latitude 112 lon = gps.longitude 113 text_area.text = ("\nLatitude:\n {0:.7f}".format(lat) + 114 "\nLongitude:\n {0:.7f}".format(lon)) 115 else: 116 text_area.text = "\n z.Z. kein\nSatellitenempfang\n bitte warten" 117 if time.monotonic() - last_print >= 10.0: 118 last_print = time.monotonic() 119
In der Schleife wird alle 4 Sekunden zwischen der Anzeige von 'Latitude, Longitude' und der Anzahl der Satelliten, Geschwindigkeit und der Höhe gewechselt. Dabei enthält gps.update() (Zeile 78) jeweils die aktuellen Werte. Die auskommentierten Zeilen 89 bis 109 ermöglichen es Ihnen, noch eine ganze Reihe weiterer Werte anzeigen zu lassen. Experimentieren Sie einfach ein wenig damit, indem Sie die Kommentierung entfernen.
Ein letzter Hinweis:
Wenn das Programm gestartet wird, erscheint zunächst die Ausgabe: z.Z. kein Satellitenempfang, bitte warten. Beachten Sie dabei eine Besonderheit des GPS-Moduls, welche in den technischen Daten wie folgt angegeben wird: "30s Zeit für Kaltstart und 4s Zeit für Warmstart" . Also ein klein wenig Geduld und dann
viel Spass und Erfolg beim Ausprobieren.