PyRaspBeta

GPS module

The NEO-6M GPS module (GY-NEO6MV2) costs $15 and reports position, time, speed and course as NMEA sentences once a second on a plain serial line. It is the simplest "sensor" interface on the Pi: no I²C registers, no timing-critical GPIO — just text. Two wires carry the data (TX → the Pi's RXD, RX → the Pi's TXD), plus power and ground. After power-up it needs about half a minute to find satellites; the module's blue LED blinks once a second only once it has a fix. The GPS over serial page covers the parsing side in depth.

GPS module

Pins

PinWhat it isType
VCCSupply 3.3–5 Vpower
RXUART in (from the Pi's TXD)io
TXUART out (to the Pi's RXD)io
GNDGroundground
SettingTypeRangeDefault
baudenum4800, 9600, 19200, 38400, 57600, 1152009600

In circuit.py:

The baud setting matches the port's speed — leave it at 9600 unless you know the module was reconfigured. The module's TX is an output, so it goes to the Pi's receive pin; RX goes to the Pi's transmit pin.

Wiring it in circuit.py

circuit.py
from wiring import *

pi = Pi()

gps = GPS()

pi.V3_3 >> gps.vcc                      # 2.7–5.5 V: 3.3 V is plenty
gps.gnd >> pi.GND
gps.tx >> pi.RXD                        # module talks, Pi listens
gps.rx >> pi.TXD                        # Pi talks, module listens

On a real Pi you must first disable the serial console (raspi-config → Interface → Serial) so the kernel does not fight your program for /dev/serial0; the simulator opens the port directly. RXD/TXD are GPIO15 and GPIO14, the header's dedicated UART pins.

Driving it in main.py

main.py
import serial
import pynmea2

port = serial.Serial("/dev/serial0", baudrate=9600, timeout=2)

while True:
    line = port.readline()
    if not line.startswith(b"$GPRMC"):
        continue
    fix = pynmea2.parse(line.decode("ascii", "ignore"))
    if fix.status == "A":
        print(f"{fix.latitude:.5f}, {fix.longitude:.5f}")
    else:
        print("waiting for a fix")

readline() returns bytes, so decode before parsing. The RMC sentence carries the status (A fixed, V not) and the decimal-degree latitude/longitude; GGA adds satellites and altitude, VTG speed and course. With the default 27-second cold start, the example spends its first seconds printing "waiting for a fix" — which is exactly what real code must tolerate.

Electrical notes

  • Supply is 2.7–5.5 V; current is about 45 mA, so use the 5 V rail if the 3V3 budget is tight elsewhere.
  • Default baud is 9600; update rate is 1 Hz; horizontal accuracy is about 2.5 m.
  • Cold and warm start take about 27 s, a hot start about 1 s. The first fixes after power-on are marked V (invalid) until enough satellites are tracked — four is the minimum for a 3D fix.
  • The UART is 3.3 V logic, which is what the Pi's header uses; no level shifting is needed at 3.3 V supply.
  • Serial console, dtoverlay=disable-bt or raspi-config: on a real Pi the header UART is shared with Bluetooth on some models, so /dev/serial0 is the alias that keeps working.

Simulator vs real hardware

  • The position is the World's location, plus metre-scale wander that drifts like a real fix (a jitterM knob, 2.5 m by default) and a circular path when the feed is set to walking or driving. The timestamp inside the sentences is the simulated world clock.
  • Checksums are computed with the real NMEA XOR, so parsing and validation code behave identically. There is no UBX binary protocol, no USB serial adapters and no PPS output pin — PPS is internal only.
  • The coldStartS knob (27 s by default) governs time-to-first-fix; with no fix the position fields are empty and the status is V, matching a real cold start.
  • Two modules can share the UART, and bytes sent at the wrong baud rate arrive garbled with framing errors, exactly as on hardware.

Going deeper

Further reading