Skip to content

feat(sim): run the firmware on a simulated 3-phase grid - #169

Merged
FredM67 merged 1 commit into
devfrom
sim/grid-harness
Sep 30, 2026
Merged

FredM67 merged 1 commit into
devfrom
sim/grid-harness

Conversation

@FredM67

@FredM67 FredM67 commented Sep 30, 2026

Copy link
Copy Markdown
Owner

Summary

grid_sim runs the unmodified production firmware in simavr, connected to a simulated 3-phase installation. With it, the regulation, load priorities, ISR timing and switching instants can be checked without hardware or sun, locally (Linux/WSL) and in CI. Details are in sim/README.md.

How it works

  • Grid signals: the 6 ADC inputs receive 50 Hz voltage and current waves, computed at the exact CPU cycle of each conversion.
  • Loads: each load pin drives a load of known power on a given phase, through a zero-crossing triac driver. A pin change only takes effect at the next zero crossing of that phase.
  • Grid current: on each phase, the scenario's surplus minus the loads that are conducting. That is what the firmware measures and regulates.
  • Measured:
    • ADC conversion period;
    • ADC ISR duration, cycle-exact (average and maximum), and overruns: ISR calls longer than one conversion, after which a sample may be taken on the wrong channel;
    • sample sets per mains cycle, read from the firmware's own datalog;
    • per load: switch-ons, energy, and the switching latency to the zero crossing, rising or falling;
    • grid import and export.
  • Scenarios are text files with expectations; make check fails on any unmet one. Three are included: no surplus, surplus steps, clouds.

simavr ADC fix

simavr's ADC does not time free-running conversions correctly: with this firmware it converts every ~256 CPU cycles instead of 1664. sim/avr_adc.c is upstream's file with that fix, linked ahead of libsimavr.a. grid_sim checks the conversion period on every run and fails if it's wrong. With the fix, the firmware reports 32 sample sets per mains cycle, as on the real board. The bug could be reported upstream later.

Validation on dev

  • The firmware reads back 230.00 V and exactly the powers the simulator generates.
  • Loads come in by priority.
  • The grid averages −19.6 W and −20.1 W over the regulation windows, which is REQUIRED_EXPORT_IN_WATTS = 20 W.
  • 60 s of simulated time take ~16 s.

First use: the three open PRs

The same scenarios were run on the firmware of each branch:

dev #163 integer bucket #160 remote units #162 predictive
ADC ISR average 364 cycles 350 364 380
ADC ISR worst case 2012 (126 µs) 1392 (87 µs) 2006 2037
ISR overruns (surplus steps, 60 s) 10 0 10 1928
Grid average, target −20 W −19.6 / −20.1 W identical identical −17.8 / −17.1 W
L1 load: delay, crossing 7.7 ms, falling same same 1.5 ms, rising
L2 load 4.4 ms, rising same same 8.3 ms, rising
L3 load 1.0 ms, falling same same 5.0 ms, falling

CI

A new Grid simulation job builds the basic firmware and runs make -C sim check. The summaries go to the job summary, and the traces are uploaded as an artifact. The scenarios allow at most 40 overruns per run (dev: 10-18), as a regression guard: #162 in its current form would fail it.

Limits

  • The scenarios match the default config.h.
  • No RF.
  • Ideal sine waves and ideal triac drivers.
  • simavr models the peripherals; it does not reproduce them exactly.

The pre-commit hooks leave the vendored avr_adc.c as upstream wrote it (no reformatting).

🤖 Generated with Claude Code

grid_sim runs the unmodified production firmware in simavr and connects it
to a simulated installation: the 6 ADC inputs get 50 Hz voltage and current
waves computed at the exact cycle of each conversion, and the load pins
drive loads through zero-crossing triac drivers. The grid current is the
scenario's surplus minus the conducting loads, as the firmware measures it.

Measured: ADC conversion period, cycle-exact ADC ISR duration and overruns,
sample sets per mains cycle (from the firmware's datalog), per-load
switching and latency to the zero crossing, grid import/export.

- Scenarios are text files with expectations (pin states, grid average,
  ISR overruns, sample sets); `make check` fails on any unmet one.
  Three scenarios: no surplus, surplus steps, clouds.
- simavr's ADC does not time free-running conversions correctly (~256 CPU
  cycles instead of 1664 with this firmware): sim/avr_adc.c is upstream's
  file with that fix, linked ahead of libsimavr.a. grid_sim checks the
  conversion period on every run.
- CI: new "Grid simulation" job, builds the basic firmware and runs every
  scenario; summaries in the job summary, traces as an artifact.
- pre-commit: the vendored avr_adc.c is kept as upstream (no reformatting).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@FredM67
FredM67 merged commit b30e1cc into dev Sep 30, 2026
9 checks passed
@FredM67
FredM67 deleted the sim/grid-harness branch September 30, 2026 17:48
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