Skip to content

mari: channel hopping for beacons and scanning#165

Merged
geonnave merged 4 commits into
DotBots:developfrom
geonnave:beacon-hopping-synced
Jul 3, 2026
Merged

mari: channel hopping for beacons and scanning#165
geonnave merged 4 commits into
DotBots:developfrom
geonnave:beacon-hopping-synced

Conversation

@geonnave

@geonnave geonnave commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Nodes could drop and then get stuck rescanning for many seconds, only recovering
when the RF environment changed (someone moving nearby, etc). Root cause: data
slots already hop channels, but the entire beacon/join path was pinned to one
frequency (MARI_FIXED_SCAN_CHANNEL = 37 / 2402 MHz). A static multipath null at
that frequency at a node's location traps a rescanning node - it cannot hear a
single beacon until the environment shifts. No frequency diversity, no way out.

This gives the beacon/join path the same frequency diversity the data slots
already have, in three parts, all behind one build flag (MARI_ENABLE_BEACON_HOPPING
in models.h; with it off, behaviour is unchanged and everything stays on
MARI_FIXED_SCAN_CHANNEL, so it is an easy A/B on a logic analyzer):

  • Beacon TX + synced RX: each of the 3 leading beacon cells uses its own
    advertising channel (cell offset 0 -> 37, 1 -> 38, 2 -> 39). Gateway and synced
    nodes both derive the channel from the cell, so they rendezvous with no extra
    coordination.
  • Cold scan: rotates one advertising channel per scan round and syncs to the
    first gateway it hears; a round that finds nothing retries on the next channel,
    so a faded channel is escaped within a round or two. Reuses the existing
    scan-retry loop (no sweep-then-pick), and selecting per round keeps every
    reading inside mr_scan_select's freshness window.
  • Background/handover scan: rotates the listen channel once per slotframe via
    slotframe_counter, so successive slotframes sweep all three channels and a
    neighbour is found on any non-faded channel within ~3 slotframes.

Known follow-up (cosmetic): the synced-RX beacon from a node's own gateway still
records its RSSI under the fixed channel rather than the real received channel.
That entry is excluded from handover selection and the hysteresis reads RSSI from
the received packet (not the scan list), so no decision changes.

Validated: node (nRF52840) and gateway (nRF5340) build clean via SES; testbed
validation underway.

geonnave added 4 commits July 2, 2026 16:28
Gateway TX and a synced node's beacon-slot RX both derive the channel
from the cell's channel_offset, so they rendezvous with no extra
coordination. Unsynced scanning still uses MARI_FIXED_SCAN_CHANNEL, so
cold join is not fully diversified yet. Toggle via MARI_ENABLE_BEACON_HOPPING.

AI-assisted: Claude Opus 4.8
Each cold-scan round dwells ~one slotframe on a single advertising channel
and syncs to the first gateway heard; a round that finds nothing retries on
the next channel (37/38/39), so a faded channel is escaped within a round or
two. Reuses the existing scan-retry loop, no sweep-then-pick. Background scan
still uses the fixed channel.

AI-assisted: Claude Opus 4.8
Reuses slotframe_counter (new mr_scheduler_get_slotframe_counter accessor)
to listen on 37 + counter%3 each bg-scan burst. A full handover scan spans
one slotframe so it covers one channel; successive slotframes sweep all
three, finding a neighbour on any non-faded channel within ~3 slotframes.
Gated by MARI_ENABLE_BEACON_HOPPING.

AI-assisted: Claude Opus 4.8
@geonnave

geonnave commented Jul 3, 2026

Copy link
Copy Markdown
Contributor Author

Tested with 100 nodes under different configurations. Yet to test handover case.

@geonnave

geonnave commented Jul 3, 2026

Copy link
Copy Markdown
Contributor Author

Handover works!

@geonnave geonnave merged commit 94555c3 into DotBots:develop Jul 3, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant