Files
roro9stack/docs/milestones/M2.md
T
twislaandClaude Opus 5.5 db265fb757 Trim task stacks and buffers by measurement: +15 KB with IRC up
Peak stack use was measured through each task's worst case (an
ECDSA-checked install over Wi-Fi and from SD, get/put, a core dump
fetch, an IRC TLS handshake); stacks are now peak plus about 2 KB: loop
8 -> 6 KB, update 8 -> 5, storage 10 -> 6, irc 8 -> 6. The Debug Build's
console ring goes 6 -> 4 KB, serial TX 2 -> 1 KB, the GNSS UART buffer
1 KB -> 512 B.

On the device, with IRC on TLS: 46 KB free (was 31), an 18 KB low (was
9.4). The re-run of every worst case left at least 1.6 KB of stack free
in each task.

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

6.1 KiB
Raw Blame History

M2 — GNSS

Status: steps 1–6 done on the device (branch m2). Open: the heap floor during a TLS handshake (below).

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: with IRC on TLS, first 33 KB free and a 12.6 KB low (floor 40 KB; v0.2.1 had a 79 KB low). Not a GNSS cost: the OTA and Debug Build work added task stacks, a console ring, serial buffers, mDNS and two TCP servers. Trimmed by measurement: each task's peak stack was measured through its worst case (an ECDSA-checked install over Wi-Fi and from SD, get/put, a core dump fetch, an IRC TLS handshake), then stacks were set to peak plus about 2 KB: loop 8→6 KB, update 8→5, storage 10→6, irc 8→6; the console ring 6→4 KB, serial TX 2→1 KB, GNSS UART 1 KB→512 B. After: 46 KB free with IRC connected, an 18 KB low. The steady state clears the floor; the TLS handshake peak doesn't yet. Next candidates: mbedTLS dynamic buffers (custom sdkconfig), one network task for the update and debug listeners, mDNS on demand.

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.