github ruvnet/RuView v0.6.8-esp32
ESP32 firmware v0.6.8 — ESP-NOW mesh EMA smoother (ADR-110 Wave 4)

latest releases: v1218, v1217, v1216...
5 hours ago

ESP32 CSI Node firmware v0.6.8

Tag: v0.6.8-esp32
Date: 2026-05-23
Branch: adr-110-esp32c6 (PR #764)
ADR: ADR-110 P9 + Wave 4 — ESP-NOW mesh offset smoothing landed in firmware

What's new vs v0.6.7

ESP-NOW cross-board sync offset is now EMA-smoothed inside the firmware
(c6_sync_espnow.c). Every consumer of c6_sync_espnow_get_epoch_us()
including future ADR-029/030 multistatic CSI fusion — gets bounded-jitter
timestamps without re-implementing the filter host-side.

  • Filter: fixed-point EMA y += (raw − y) >> 3, α = 1/8
  • Effective window: ≈ 8 samples = 0.8 s at the 10 Hz beacon rate
  • Suppression: 3.95× stdev (411.5 µs → 104.1 µs), 4.70× peak-to-peak
  • Drift preservation: tracks +30 µs/min crystal skew within 2 µs/min of raw
  • Throughput: 99.56 % cross-board match over 5 min, 0 TX failures
  • ADR-110 §2.4 ≤100 µs multistatic alignment target empirically met

New API surface:

  • int64_t c6_sync_espnow_get_offset_us_smoothed(void) — raw access to the EMA
  • c6_sync_espnow_get_epoch_us() now returns timestamps stamped from the
    smoothed offset once the follower has heard a leader beacon
  • Diag log line gains smoothed=… field alongside offset_us=…

Raw offset getter c6_sync_espnow_get_offset_us() stays unchanged for
diagnostics. v0.6.6/v0.6.7 fleets see identical wire behavior — the
smoothing only affects what get_epoch_us() returns to in-firmware
consumers.

Binary cost: +32 bytes (one int64 + one bool + the getter). C6 build
still 45 % partition slack on 4 MB single-OTA.

Full empirical evidence in WITNESS-LOG-110 §A0.10.

Known gap (tracked in WITNESS §A0.11)

CSI frames don't yet carry the synced timestamp in the wire bytes — the
ADR-018 frame format has no timestamp field. Mesh substrate is shipped
and quantified; surfacing the synced clock into per-frame timestamps
needs either an ADR-018 v2 (breaking) or a separate UDP sync packet
(backwards-compatible). Likely path: separate sync packet, ships in a
future release once ADR-029/030 multistatic fusion lights up.

Build artifacts

Target Binary Size Partition slack
esp32s3 (8 MB) esp32-csi-node-s3-8mb.bin 1093 KB 47 %
esp32c6 (4 MB) esp32-csi-node-c6-4mb.bin 1019 KB 45 %

SHA-256 sums in SHA256SUMS.txt.

Flash

Same flash command as v0.6.7 — only the app slot changed.

# ESP32-S3 on COM9 (8 MB)
python -m esptool --chip esp32s3 -p COM9 -b 460800 write_flash \
  0x0     bootloader-s3.bin \
  0x8000  partition-table-s3.bin \
  0xf000  ota_data_initial-s3.bin \
  0x20000 esp32-csi-node-s3-8mb.bin

# ESP32-C6 on COM12 (4 MB)
python -m esptool --chip esp32c6 -p COM12 -b 460800 write_flash \
  0x0     bootloader-c6.bin \
  0x8000  partition-table-c6.bin \
  0xf000  ota_data_initial-c6.bin \
  0x20000 esp32-csi-node-c6-4mb.bin

Validation

Verified live on COM9 + COM12 ESP32-C6 boards during the loop:

  • 99.56 % cross-board ESP-NOW match over 5 min (2701 beacons, 0 TX fail)
  • EMA suppression 3.95× confirmed against raw measurement
  • Leader election fires correctly (lower-EUI wins)
  • Sync offset preserves crystal drift trajectory

Don't miss a new RuView release

NewReleases is sending notifications on new releases.