Skip to content

feat(firmware): size the ESP-NOW beacon period to the provisioned fleet - #1819

Open
clonea1 wants to merge 1 commit into
ruvnet:mainfrom
clonea1:contrib/espnow-beacon-scaling
Open

feat(firmware): size the ESP-NOW beacon period to the provisioned fleet#1819
clonea1 wants to merge 1 commit into
ruvnet:mainfrom
clonea1:contrib/espnow-beacon-scaling

Conversation

@clonea1

@clonea1 clonea1 commented Sep 4, 2026

Copy link
Copy Markdown

BEACON_PERIOD_MS is a fixed 100 ms per node. That is fine for two or three
boards and wrong for nine: every node beacons independently, so the aggregate
rate scales with fleet size while the airtime available to CSI does not. On a
nine-node fleet the beacons alone consume a large share of the same 50 fps
budget the CSI rate gate is trying to protect, and the symptom is not a mesh
failure -- it is CSI frames quietly not arriving.

The period is now derived from the provisioned fleet size:

budget = BEACON_GATE_FPS - BEACON_AP_BUDGET_FPS
period = ((n - 1) * 1000 / budget) * BEACON_MARGIN_NUM / BEACON_MARGIN_DEN

BEACON_AP_BUDGET_FPS reserves what the associated AP contributes to the same
airtime sum, since the node does not control that traffic. The margin is
headroom over the bare inequality rather than sizing to the exact limit.
Results are clamped to BEACON_PERIOD_MIN_MS..BEACON_PERIOD_MAX_MS so a
mis-provisioned fleet size cannot produce a period that either floods the
channel or effectively disables sync.

An explicit NVS value overrides the derivation; 0 means derive. That exists for
benching, and the init log states which path was taken, because a node that
silently chose a different period from its peers is difficult to spot.

Requires tdm_node_count to be provisioned, which it already is for TDM slot
assignment -- no new provisioning step.


Rebased onto current main before opening: staged before today's seven merges, so it needed replaying to avoid reading as a revert of them. Clean rebase, no files deleted.

BEACON_PERIOD_MS is a fixed 100 ms per node. That is fine for two or three
boards and wrong for nine: every node beacons independently, so the aggregate
rate scales with fleet size while the airtime available to CSI does not. On a
nine-node fleet the beacons alone consume a large share of the same 50 fps
budget the CSI rate gate is trying to protect, and the symptom is not a mesh
failure -- it is CSI frames quietly not arriving.

The period is now derived from the provisioned fleet size:

    budget = BEACON_GATE_FPS - BEACON_AP_BUDGET_FPS
    period = ((n - 1) * 1000 / budget) * BEACON_MARGIN_NUM / BEACON_MARGIN_DEN

BEACON_AP_BUDGET_FPS reserves what the associated AP contributes to the same
airtime sum, since the node does not control that traffic. The margin is
headroom over the bare inequality rather than sizing to the exact limit.
Results are clamped to BEACON_PERIOD_MIN_MS..BEACON_PERIOD_MAX_MS so a
mis-provisioned fleet size cannot produce a period that either floods the
channel or effectively disables sync.

An explicit NVS value overrides the derivation; 0 means derive. That exists for
benching, and the init log states which path was taken, because a node that
silently chose a different period from its peers is difficult to spot.

Requires tdm_node_count to be provisioned, which it already is for TDM slot
assignment -- no new provisioning step.

Co-Authored-By: claude-flow <ruv@ruv.net>
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