mirror of
https://github.com/liquidraver/ZephCore.git
synced 2026-10-15 21:49:55 +00:00
gps time sync improvement
This commit is contained in:
@@ -802,7 +802,9 @@ Loading also range-checks `freq`/`sf`/`bw` and falls back to the compile-time de
|
||||
### 7.3 GPS (`adapters/gps/`)
|
||||
|
||||
- State machine: OFF → ACQUIRING → STANDBY (with warm standby on supported hardware)
|
||||
- 3 consecutive good fixes (≥4 satellites) required before reporting
|
||||
- 5 consecutive good fixes required before reporting. A good fix is a satellite solution (GGA quality
|
||||
GNSS or DGNSS) with ≥4 satellites; an estimated fix (quality 6, dead reckoning) counts as no fix,
|
||||
because its time is the module's own clock and its position the last one
|
||||
- Multi-constellation: GPS+GLONASS+Galileo+BeiDou with fallback
|
||||
- T1000-E / MeshTracker X1 (AG3335): multi-GPIO power sequencing; standby is the module's RTC backup sleep
|
||||
(`$PAIR650,0` before `GPS_EN` is cut, VRTC kept, a `GPS_RTC_INT` pulse wakes it)
|
||||
@@ -820,8 +822,8 @@ Loading also range-checks `freq`/`sf`/`bw` and falls back to the compile-time de
|
||||
|
||||
`gps_wake_interval_ms` (initialised from `prefs.gps_interval`) controls the mode:
|
||||
|
||||
- **Duty cycling** (`gps_wake_interval_ms > 0`): after acquiring 3 good fixes the GPS powers down; the state machine wakes it again after the configured standby interval. The fix callback fires and then the GPS sleeps.
|
||||
- **Always-on** (`gps_wake_interval_ms == 0`): the GPS never powers down. `consecutive_good_fixes` is reset after each promotion so the 3-fix gate cycles continuously, streaming fresh positions. Flash writes and fix callbacks are rate-limited to once per `gps_acquire_timeout_ms` to avoid hammering storage.
|
||||
- **Duty cycling** (`gps_wake_interval_ms > 0`): after acquiring 5 good fixes the GPS powers down; the state machine wakes it again after the configured standby interval. The fix callback fires and then the GPS sleeps.
|
||||
- **Always-on** (`gps_wake_interval_ms == 0`): the GPS never powers down. `consecutive_good_fixes` is reset after each promotion so the 5-fix gate cycles continuously, streaming fresh positions. Flash writes and fix callbacks are rate-limited to once per `gps_acquire_timeout_ms` to avoid hammering storage.
|
||||
|
||||
`gps_set_poll_interval_sec(0)` switches to always-on live; persisted via `prefs.gps_interval` (set by `set gps duty 0`).
|
||||
|
||||
|
||||
@@ -55,3 +55,26 @@ first, which a long press cannot meet: every long press asked for the confirmati
|
||||
|
||||
The confirmation is a second **hold**. A short press pages on instead, which on the Power Off page
|
||||
goes back to the first page.
|
||||
|
||||
## GPS: a fix could set the clock to an old time
|
||||
|
||||
On a repeater with a GPS, a fix could set the clock hours back. The next fix usually put it right
|
||||
again, but until then the node's adverts and replies carried the old time, and mesh time sync was not
|
||||
allowed to correct it.
|
||||
|
||||
Right after waking, a GPS receiver can report an estimated position for a few seconds: its last
|
||||
position and its own clock, before any satellite has confirmed them. These were accepted as a fix.
|
||||
If the receiver's clock had not kept time while it slept, that old time was written to the node.
|
||||
|
||||
- **Only positions solved from satellites count as a fix**, and five in a row are needed (was three).
|
||||
A fix takes about two seconds longer.
|
||||
- This applies to every board with a GPS.
|
||||
|
||||
It was reported on a SenseCAP Solar P1 with `set gps standby` raised to 48 hours, which keeps the
|
||||
receiver powered while it sleeps. With the default (one hour) a repeater switches the receiver off
|
||||
between its 48-hour fixes.
|
||||
|
||||
Good to know: a telemetry request from a logged-in client (anything above guest) wakes a repeater's
|
||||
GPS for a fresh fix, so the GPS can run more often than the `gps duty` interval.
|
||||
|
||||
Thanks to **Innocent Killer 101** for the report and the measurements.
|
||||
|
||||
+1
-1
@@ -950,7 +950,7 @@ config ZEPHCORE_GPS_FIX_TIMEOUT_SEC
|
||||
GPS will be powered off after this timeout.
|
||||
Default 120s — 30s was too aggressive for Air530Z / MAX-7Q warm
|
||||
starts in marginal sky conditions; the acquire loop would time out
|
||||
before the 3-consecutive-good-fix gate could promote. Applies to
|
||||
before the consecutive-good-fix gate could promote. Applies to
|
||||
wake cycles where the module kept its state; the first acquisition
|
||||
and every wake after a full power-off use
|
||||
ZEPHCORE_GPS_FIRST_FIX_TIMEOUT_SEC.
|
||||
|
||||
@@ -71,17 +71,20 @@ enum gps_state {
|
||||
|
||||
static enum gps_state gps_current_state = GPS_STATE_OFF;
|
||||
static uint8_t consecutive_good_fixes = 0;
|
||||
static bool first_fix_acquired = false; /* True after first 3-good-fix cycle since enable. Cleared on gps_enable(false) and at boot. */
|
||||
static bool first_fix_acquired = false; /* True after the first validated fix since enable. Cleared on gps_enable(false) and at boot. */
|
||||
static bool first_acquire_used = false; /* True once the one-time long cold-start window has ended (fix or timeout). Cleared on gps_enable(false) and at boot. */
|
||||
static bool standby_powered_off = false; /* The last standby was the full power-off (interval past gps_standby_max_sec), so the wake after it is a cold start. Set on every standby, cleared on gps_enable(false). */
|
||||
static bool gps_time_synced = false; /* True after GPS syncs RTC. Starts false at boot (RTC reset),
|
||||
* set true after 3 good fixes, cleared when GPS disabled. */
|
||||
* set true by a validated fix, cleared when GPS disabled. */
|
||||
static int64_t last_fix_uptime_ms = 0; /* k_uptime when last validated fix was acquired */
|
||||
static int64_t standby_start_ms = 0; /* k_uptime when standby started (for next-wake calc) */
|
||||
static uint64_t standby_interval_ms = 0; /* How long standby lasts (for next-wake calc) */
|
||||
|
||||
#define GPS_GOOD_FIX_COUNT 3 /* Need 3 consecutive good fixes */
|
||||
#define GPS_MIN_SATELLITES 4 /* Minimum satellites for valid fix */
|
||||
/* A validated fix is GPS_GOOD_FIX_COUNT consecutive good fixes. A good fix is
|
||||
* a satellite solution (see gps_fix_is_real()) with GPS_MIN_SATELLITES. Why:
|
||||
* devdocs/lld/10-peripherals-power.md, "Fix validation". */
|
||||
#define GPS_GOOD_FIX_COUNT 5
|
||||
#define GPS_MIN_SATELLITES 4
|
||||
|
||||
/* Acquire windows (Kconfig) and the duty interval (prefs, set at boot). */
|
||||
static const uint32_t gps_acquire_timeout_ms = CONFIG_ZEPHCORE_GPS_FIX_TIMEOUT_SEC * 1000U;
|
||||
@@ -223,6 +226,14 @@ static void gps_post_fix_locked(const struct gnss_data *data)
|
||||
atomic_or(&pending_gps_actions, GPS_ACTION_FIX);
|
||||
}
|
||||
|
||||
/* True for a position and time solved from satellites. An estimated fix (GGA
|
||||
* quality 6, dead reckoning) is the module's last position and its own clock,
|
||||
* so it counts as no fix. */
|
||||
static bool gps_fix_is_real(enum gnss_fix_status status)
|
||||
{
|
||||
return status == GNSS_FIX_STATUS_GNSS_FIX || status == GNSS_FIX_STATUS_DGNSS_FIX;
|
||||
}
|
||||
|
||||
/* GNSS callback - called when new fix data is available */
|
||||
static void gnss_data_cb(const struct device *dev, const struct gnss_data *data)
|
||||
{
|
||||
@@ -244,7 +255,7 @@ static void gnss_data_cb(const struct device *dev, const struct gnss_data *data)
|
||||
|
||||
k_mutex_lock(&gps_mutex, K_FOREVER);
|
||||
|
||||
if (data->info.fix_status >= GNSS_FIX_STATUS_GNSS_FIX) {
|
||||
if (gps_fix_is_real(data->info.fix_status)) {
|
||||
/* Reject (0,0): the parser can publish a valid fix status with lat/lon not
|
||||
* yet filled (GGA ahead of RMC). It is never a real fix. */
|
||||
if (data->nav_data.latitude == 0 && data->nav_data.longitude == 0) {
|
||||
|
||||
@@ -57,7 +57,7 @@ void gps_format_diagnostics(char *out, size_t out_size);
|
||||
typedef void (*gps_enable_callback_t)(bool enabled);
|
||||
void gps_set_enable_callback(gps_enable_callback_t cb);
|
||||
|
||||
/* GPS fix callback - called when GPS acquires a validated fix (3 consecutive good fixes)
|
||||
/* GPS fix callback - called when GPS acquires a validated fix (5 consecutive satellite fixes)
|
||||
* Parameters: latitude (degrees), longitude (degrees), utc_time (Unix timestamp,
|
||||
* 0 if the fix carried no usable date). Runs on the main thread, from
|
||||
* gps_process_event(), so it may set the clock and prefs directly. */
|
||||
|
||||
Reference in New Issue
Block a user