Skip to content

feat(perf): PWM-phase histogram of zero-crossings (v4) — hump mechanism identified#29

Merged
AlexKlimaj merged 1 commit into
ark-releasefrom
feat/zc-phase-histogram
Jul 6, 2026
Merged

feat(perf): PWM-phase histogram of zero-crossings (v4) — hump mechanism identified#29
AlexKlimaj merged 1 commit into
ark-releasefrom
feat/zc-phase-histogram

Conversation

@AlexKlimaj

Copy link
Copy Markdown
Member

The diagnostic proposed after #23's refutation: a 32-bin histogram of the PWM phase (TIM1->CNT/ARR) at which each accepted zero-cross fired. Captured at ISR entry (pre-confirm), committed on accept only, monotonic u16 bins differenced by the host per steady tail. Perf struct v4 (148 B); host decodes v1–v4; includes DWARF array-member sizing support and a frozen v3 compat fixture. 137 offline tests, both build variants clean.

First capture answers the question (runs/phase-hist-probe, jitter_probe)

The phase distributions are massively non-uniform — and the structure identifies the hump mechanism:

point duty off-time detections in bins 0-2 (uniform: 9.4%) jitter
t30 24% 76% 27.1% 4.9%
t60 61% 39% 35.9% 23.5%
t70 71% 29% 30.8% 18.6%
t90 90% 10% 25.8% 7.2%
t100 100% 0% 12.8% (≈uniform) 2.9%

Two features, consistent at every point:

  1. A large pile-up in bins 0–2 — immediately after PWM turn-on — scaling with the off-time fraction, and
  2. Heavy depletion of the bins covering the PWM off-period (at t60, bins ~17–31 are nearly empty out of 45k events; the off-edge sits at bin ~19.5). At t100 there is no off-time and the distribution is nearly flat — and jitter is at its floor.

The mechanism

Zero-crossings that occur during the PWM off-time cannot be detected; they surface as comparator edges at the next turn-on. Detection is quantized to the PWM grid by up to the full off-window (~19 µs at t60, on a 66 µs commutation interval). Those quantized timestamps feed commutation_intervaladvance/waitTime, so the control loop schedules the next window off a corrupted measurement and hunts — which is why measured jitter (23%) is several times the direct quantization error (~4%), and why the hump lives where commutation frequency approaches PWM frequency (the walk through the off-window beats slowly). It also explains every prior negative result: coarse/fine sampling, glitch tolerance, and #23's blanking all operate at the detection instant — none of them can see a crossing the comparator was blind to.

Proposed next experiment (cheap, concrete)

Turn-on pile-up timestamp compensation: for detections landing within the first ~2 bins after turn-on when duty < 100%, the true crossing occurred somewhere in the preceding off-window — subtract half the off-window duration (duty and ARR are both known) from thiszctime. On average this halves the quantization error, and more importantly decouples the commutation loop from the PWM grid, which should collapse the hunting amplification. Fully measurable with this histogram + the jitter metric via the interleaved A/B protocol.

Merging this PR adds the instrument (report-only metrics: zc_phase_peak_ratio/peak_bin + full histogram per steady point); the compensation experiment would be its own PR.

🤖 Generated with Claude Code

…erf struct v4

The discriminator instrument for the beat-band jitter hump investigation:
bin = TIM1 phase of the comparator edge at ISR entry (captured before the
confirm loop can smear it, committed only on accept, gated on stable
running). Monotonic u16 bins wrap naturally; the host differences
consecutive snapshots per-bin mod 2^16.

Host: v4 decode with repeat-count field support ('32H' -> tuple), DWARF
array-member sizing in elf.py (array DIEs carry no byte_size; resolve
element size x subrange count), one semicolon-joined CSV cell,
zc_phase_window() metrics (per-steady-point peak bin/ratio + full
histogram), sim model, frozen v3 probe fixture. 137 offline tests.

First hardware capture (runs/phase-hist-probe) already answers the
question the instrument was built for - see PR.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@AlexKlimaj AlexKlimaj merged commit 7423ec9 into ark-release Jul 6, 2026
@AlexKlimaj AlexKlimaj deleted the feat/zc-phase-histogram branch July 6, 2026 18:25
AlexKlimaj added a commit that referenced this pull request Jul 6, 2026
Appends the demag compensation block after v4's zc_phase_hist histogram
(renumbered from v4 during the rebase: #29 took v4 on ark-release):
demag_events (u32, monotonic mirror of main.c demag_happened),
blanking_len_last/max (u16, measured demag time in INTERVAL_TIMER ticks
from demagEdgeRoutine). Fed from the main-loop snapshot path - zero ISR
cost. host_cmd stays frozen at offset 60; total size 148 -> 156 bytes.

Host: FIELDS_V5 + decode, DWARF vintage probe (demag_events marker),
model columns, fw_demag_events metric (per steady tail and per run,
wrap-safe u32 delta, None on pre-v5 firmware), report column, sim demag
mirror of injected desyncs, tests incl. u32 wrap and v2/v3/v4 back-compat.

Co-authored-by: dakejahl <37091262+dakejahl@users.noreply.github.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011pvp2XLcgsviGSVn9PaaP6
AlexKlimaj added a commit that referenced this pull request Jul 7, 2026
Appends the demag compensation block after v4's zc_phase_hist histogram
(renumbered from v4 during the rebase: #29 took v4 on ark-release):
demag_events (u32, monotonic mirror of main.c demag_happened),
blanking_len_last/max (u16, measured demag time in INTERVAL_TIMER ticks
from demagEdgeRoutine). Fed from the main-loop snapshot path - zero ISR
cost. host_cmd stays frozen at offset 60; total size 148 -> 156 bytes.

Host: FIELDS_V5 + decode, DWARF vintage probe (demag_events marker),
model columns, fw_demag_events metric (per steady tail and per run,
wrap-safe u32 delta, None on pre-v5 firmware), report column, sim demag
mirror of injected desyncs, tests incl. u32 wrap and v2/v3/v4 back-compat.

Co-authored-by: dakejahl <37091262+dakejahl@users.noreply.github.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011pvp2XLcgsviGSVn9PaaP6
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