audio bus crypto display ez global gps keyboard mesh net radio sprite storage synth system wifi

GPS receiver for location, time, and navigation data

Interfaces with the optional GPS module for position, altitude, speed, and satellite-synchronized time. The GPS runs continuously in the background once initialized, updating location data as fixes are acquired. Can auto-sync the system clock from GPS time for accurate timestamps without network access.

Functions

get_chip_info() → table|nil Cached chip identification (last successful query_chip())
ez.gps.get_chip_info() -> table|nil
Same fields as query_chip() but reads the cached result without re-querying. nil until query_chip() has succeeded once.
get_last_info_sentence() → string Most recently captured proprietary or TXT NMEA sentence
ez.gps.get_last_info_sentence() -> string
Returns the verbatim text of the last "$P..." or "$GxTXT" sentence the module emitted. These are typically responses to commands sent via send_command(), or vendor status messages. Empty string if the module hasn't emitted one since boot (or since reset_stats()).
Returns: Sentence string, e.g. "$GPTXT,01,01,02,SW=URANUS5,V5.1.0.0*1D"
get_location() → table|nil Get current GPS location
ez.gps.get_location() -> table|nil
Returns the current GPS position with latitude, longitude, and altitude. The 'valid' field indicates if the GPS has a fix. The 'age' field shows milliseconds since the last valid position update - use this to detect stale data (age > 5000ms suggests no recent fix). Returns nil if GPS not initialized.
Returns: Table with lat, lon, alt, valid, age (ms since last fix), or nil if not initialized
local loc = ez.gps.get_location()
if loc and loc.valid then
print(string.format("Position: %.6f, %.6f", loc.lat, loc.lon))
print(string.format("Altitude: %.1f m", loc.alt))
if loc.age > 5000 then
print("Warning: GPS data is stale")
end
end
get_movement() → table|nil Get speed and heading
ez.gps.get_movement() -> table|nil
Returns current speed and heading from GPS. Speed is in km/h and course is compass heading in degrees (0-360, where 0=North, 90=East). These values require movement to be accurate - when stationary, course may be unreliable.
Returns: Table with speed (km/h) and course (degrees), or nil if not initialized
local mov = ez.gps.get_movement()
if mov then
print(string.format("Speed: %.1f km/h", mov.speed))
print(string.format("Heading: %.0f°", mov.course))
end
get_satellites() → table|nil Get satellite info
ez.gps.get_satellites() -> table|nil
Returns satellite tracking information. Count is the number of satellites used in the position fix. HDOP (Horizontal Dilution of Precision) indicates fix quality: <1 is ideal, 1-2 is excellent, 2-5 is good, >5 is poor. Lower HDOP means better position accuracy.
Returns: Table with count and hdop (horizontal dilution of precision), or nil if not initialized
local sat = ez.gps.get_satellites()
if sat then
print(string.format("Satellites: %d", sat.count))
if sat.hdop < 2 then
print("Excellent accuracy")
elseif sat.hdop < 5 then
print("Good accuracy")
else
print("Poor accuracy")
end
end
get_signal_enabled() → boolean|nil Read a UBX CFG-SIGNAL-* key from the chip
ez.gps.get_signal_enabled(key_id, [timeout_ms]) -> boolean|nil
Sends UBX-CFG-VALGET for the key and blocks for the reply. Returns true / false for the boolean value, or nil on timeout.
get_stats() → table|nil Get GPS parsing statistics
ez.gps.get_stats() -> table|nil
Returns diagnostic statistics about GPS data processing. Useful for debugging GPS issues. 'chars' is total bytes received, 'sentences' is valid NMEA sentences with fix data, 'failed' is checksum errors (indicates noise or wiring issues if high). A high failed/sentences ratio suggests signal problems.
Returns: Table with chars processed, sentences with fix, failed checksums, initialized flag
local stats = ez.gps.get_stats()
if stats then
print("Chars received:", stats.chars)
print("Valid sentences:", stats.sentences)
print("Failed checksums:", stats.failed)
if stats.failed > stats.sentences * 0.1 then
print("Warning: high checksum failure rate")
end
end
get_time() → table|nil Get GPS time
ez.gps.get_time() -> table|nil
Returns UTC time from the GPS module. GPS time is highly accurate (atomic clock synchronized) and available even without a position fix. The 'valid' field indicates if the time data is valid. The 'synced' field shows if the system clock has been synchronized to GPS time via sync_time().
Returns: Table with hour, min, sec, year, month, day, valid, synced, or nil if not initialized
local t = ez.gps.get_time()
if t and t.valid then
print(string.format("UTC: %04d-%02d-%02d %02d:%02d:%02d",
t.year, t.month, t.day, t.hour, t.min, t.sec))
end
init() → boolean Initialize the GPS module
ez.gps.init() -> boolean
Initializes the UART connection to the GPS module. Must be called before using any other GPS functions. On the T-Deck, the GPS shares UART2 and uses 9600 baud. Returns false if the serial port could not be configured.
Returns: true if initialization successful
if ez.gps.init() then
print("GPS ready")
else
print("GPS init failed")
end
is_valid() → boolean Check if GPS has a valid location fix
ez.gps.is_valid() -> boolean
Quick check if GPS currently has a valid position fix. This is equivalent to checking get_location().valid but more efficient when you only need to know fix status. Use this for status indicators or to gate GPS-dependent features.
Returns: true if location is valid
if ez.gps.is_valid() then
status_bar:set_gps_icon("fix")
else
status_bar:set_gps_icon("searching")
end
query_chip() → table|nil Identify the GNSS chip via UBX-MON-VER
ez.gps.query_chip([timeout_ms]) -> table|nil
Sends UBX-MON-VER and blocks (up to timeout_ms, default 800) for the receiver's reply. On success returns { sw = "...", hw = "..." } with the firmware/hardware version strings. Returns nil on timeout or when the chip doesn't speak UBX (the L76K variant won't respond).
local info = ez.gps.query_chip()
if info then print("Chip:", info.hw, "FW:", info.sw) end
reset_stats() Zero the diagnostics counters and clear cached fix state
ez.gps.reset_stats()
Useful when debugging: snapshot the current running totals so subsequent get_stats() calls start from zero again. Also forgets the last position/satellite numbers so stale values don't linger on screen until the next NMEA arrives. The underlying parser keeps running; only the reported counters are rebased.
send_command() → boolean Send a proprietary NMEA command to the GPS module
ez.gps.send_command(body) -> boolean
Accepts the body of an NMEA sentence — everything between '$' and '*'. The XOR checksum and CRLF terminator are appended automatically. Used to send vendor-specific configuration commands (e.g. $PCAS04 to select constellations on a Quectel L76K). Fire-and-forget; any response from the module shows up in get_last_info_sentence() once the line completes.
Returns: true if the UART is open and the command was written
ez.gps.send_command("PCAS06,0")  -- query firmware version
ez.gps.send_command("PCAS04,7")  -- enable GPS+BDS+GLONASS on L76K
set_signal_enabled() → boolean Toggle a UBX CFG-SIGNAL-* key
ez.gps.set_signal_enabled(key_id, enabled, [timeout_ms]) -> boolean
Sends UBX-CFG-VALSET writing the L1-typed key to RAM, BBR and Flash so the change persists across reboots. Blocks until UBX-ACK arrives or timeout fires. Returns true on ACK, false on NAK / timeout. Common key IDs (u-blox M10): 0x1031001F GPS, 0x10310020 SBAS, 0x10310021 Galileo, 0x10310022 BeiDou, 0x10310024 QZSS, 0x10310025 GLONASS
sync_time() → boolean Sync system time from GPS
ez.gps.sync_time() -> boolean
Sets the ESP32 system clock from GPS UTC time. This provides accurate time even without network connectivity. The sync is only performed if GPS has valid time data. After syncing, ez.system.get_time() will return accurate UTC. Consider calling this once after GPS gets a fix, or periodically to correct drift.
Returns: true if time was synced successfully
if ez.gps.sync_time() then
print("System clock synced to GPS")
local t = ez.system.get_time()
print("Current UTC:", t.hour, t.min, t.sec)
end
update() Process incoming GPS data, call from main loop
ez.gps.update()
Reads and parses NMEA sentences from the GPS serial buffer. Should be called frequently (every frame or every 100ms) to prevent buffer overflow. The main loop already calls this automatically, so you typically don't need to call it manually unless using GPS in a custom loop.
-- Manual GPS polling loop
while true do
ez.gps.update()
local loc = ez.gps.get_location()
if loc and loc.valid then
print(loc.lat, loc.lon)
end
ez.system.delay(100)
end