Files
roro9stack/docs/milestones/M2.md
T
twislaandClaude Opus 5.5 fff28af961 Rebuild the framework with smaller TLS buffers (ADR 0006)
custom_sdkconfig makes pioarduino regenerate the ESP-IDF libraries:
asymmetric TLS buffers (16 KB in, 4 KB out) and dynamic buffers that
free handshake-only data once connected. The rebuild also follows the
board: no PSRAM, 8 MB flash. The project now carries the partition
table the hybrid build needs (identical to the framework's: the app
slots must not move under updates over the air). Generated files are
ignored.

Debug Build, GNSS on, IRC on TLS: 78 KB free and a 59 KB low (M2 began
at 31 KB and 12.6 KB; the floor is 40 KB). The full stress set passes
on it: refused installs over Wi-Fi and from SD, put/get, screenshot,
core dump decode, Probation; under all of it at once, the low is 46 KB.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
2026-10-04 23:32:29 +02:00

6.0 KiB
Raw Blame History

M2 — GNSS

Status: done on the device (branch m2): every "Done when" item below is met.

Measured

  • Cold start ($PCAS10,2) to a 3D Fix, by a window: 73 s, 5 satellites used of 8 in view. A restart of the ESP32 alone keeps the receiver's Fix (the Cap stays powered).

  • By a window: 3D Fix from GPS, GLONASS, Galileo and BeiDou, up to 14 of 17 satellites used, HDOP 1.0–1.3.

  • Heap, Debug Build, GNSS on, IRC on TLS (floor 40 KB; v0.2.1 had a 79 KB low):

    Free Lowest
    Start of M2 31 KB 12.6 KB
    Stacks and buffers trimmed by measurement 46 KB 18 KB
    mDNS removed 54 KB 34 KB
    Framework rebuilt with smaller TLS buffers (ADR 0006) 78 KB 59 KB

    Under the heaviest combined load measured (IRC, two refused installs, a 1.6 MB put and get), the low is 46 KB. The cost had come mostly from the OTA and Debug Build work, not GNSS. Stacks were set to measured peak plus about 2 KB (loop 6 KB, update 5, storage 6, irc 6); after a TLS handshake the irc task has 1.7 KB left. IRC can now be stopped by hand (/quit in any state, irc stop), which frees its TLS memory.

Goal: the device knows where it is and what time it is without a network: a GNSS Service in the background, a GNSS App with the position and a sky view of the satellites, the clock set from satellites when there's no NTP, and Tracks recorded to the SD card.

Hardware: the Cap LoRa-1262 carries an ATGM336H-6N (AT6668), multi-constellation (GPS, BeiDou, Galileo, GLONASS, QZSS), with a ceramic antenna. NMEA over UART, 115200 8N1. Measured (step 1, gnss probe): RX GPIO 15, TX GPIO 13, 115200 8N1, as in Meshtastic's board file; M5Stack's page names GPIO 8 and 9, which are the internal I2C bus the keyboard controller sits on. Output is NMEA 4.10 style: GN RMC, VTG and GGA, one GSA per constellation with the system ID (1 GPS, 2 GLONASS, 3 Galileo, 4 BeiDou, 5 QZSS) in its last field, and a GSV sequence per constellation and signal (GP, GL, GA, …) with the signal ID last. RMC carries a time even without a Fix (status V), so only a Fix makes it trustworthy.

Decisions (design round 2026-10-04)

# Decision
Q58 Settings has a GNSS On/Off switch, On by default. Off puts the receiver in standby. Measured: $PCAS12,<seconds> (CASIC) stops its output within a second, for up to at least 65535 s, and any command wakes it within a second; Off sends PCAS12,65535 (renewed hourly), On sends a hot start, PCAS10,0.
Q59 The GNSS App has two views, switched with Tab. Position: latitude, longitude, altitude, speed, course, Fix (none / 2D / 3D), satellites used and in view, HDOP, UTC time. Sky: the satellites placed by azimuth and elevation, coloured by constellation, filled when used in the Fix.
Q60 "Radar" in M2 means the Sky view. A radar of other Nodes by distance and bearing needs the mesh: M4.
Q61 The Status Bar shows a GNSS mark: absent when off, muted while searching, normal with a 2D Fix, with the satellite count with a 3D Fix.
Q62 GNSS time sets the clock once there's a Fix, and refreshes it every 10 minutes. Revised in step 3: the clock's trust order from M0 (Mesh < NTP < GNSS) already ranks GNSS above NTP, which is right: GNSS time is at least as accurate. So GNSS also corrects a clock NTP set, not only an unset one.
Q63 A Track is started and stopped in the GNSS App. It's written as GPX to /gnss/tracks/<YYYYMMDD-HHMMSS>.gpx, a point every 5 s when the position moved more than 5 m. It keeps recording with the App closed, with a Toast on start and stop and a Status Bar mark, and gets its own Storage Clean-up category.
Q64 Coordinates in decimal degrees plus the Maidenhead locator; a Settings switch for degrees, minutes and seconds. Metric units only.
Q65 The position never leaves the device in M2. Sharing it over the mesh, and at what precision, is decided in M4.
Q66 Our own NMEA parser, host-tested: RMC, GGA, GSA and GSV, with each talker ID mapped to its constellation. TinyGPSPlus (named in ADR 0001) doesn't track the satellite list across constellations, which the Sky view needs.
Q67 The receiver keeps its defaults (all constellations, 1 Hz). No receiver settings. Time to first fix is measured and recorded here.
Q68 Debug aids: gnss status, and gnss nmea on/off to stream the raw sentences to the console (USB serial and Debug Console). Raw NMEA is never written to the card.

Lesson (step 3): the first probe also tried the pins swapped, driving the receiver's output line from the ESP32 for about a second. The receiver then went silent until a full power cycle (an ESP32 restart doesn't cut the Cap's power). Never drive GPIO 15.

Done when

  • The GNSS Service reads NMEA in the background whatever App is on screen, and a 3D Fix appears outdoors.
  • The GNSS App shows the Position and Sky views, both live.
  • The Status Bar shows the GNSS mark per Q61.
  • With no Wi-Fi, the clock is set from GNSS after the first Fix.
  • A Track records while the App is closed, survives the screen turning off, and opens as valid GPX on the PC.
  • Settings → GNSS Off stops it (and the Status Bar mark goes away); On brings it back.
  • Free heap stays above about 40 KB with GNSS, Wi-Fi, IRC on TLS and the UI running.

Work breakdown

  1. Hardware check: a gnss probe command reads the candidate UART pins and reports which carries NMEA, at what baud rate, and which talker IDs. Then the standby command (Q58) and a first time to first fix.
  2. NMEA parser (host-tested): checksum, RMC, GGA, GSA, GSV across constellations, merged into one GNSS state (Fix, position, time, satellites).
  3. GNSS Service: UART on its own task, the parser, gnss status and gnss nmea, Settings On/Off.
  4. Clock from GNSS (Q62), and the Status Bar mark (Q61).
  5. GNSS App: Position view, Maidenhead and coordinate formats (host-tested), then the Sky view.
  6. Tracks: the 5 s / 5 m rule and GPX writing (host-tested), background recording, Clean-up category.