9 Commits
Author SHA1 Message Date
janikandClaude Fable 5 158e1ccf03 stm32_link: sync iin_avg_ma comment with live firmware protocol
Firmware now runs BOTH iin limits (IIN_MAX reverse-feed and the IIN_MIN
forward OCP, raised to -47A) on the 8-sample boxcar; wire format is
unchanged (verified field-by-field against the live code64 console,
including a synthetic-frame decode). Note the field is a raw int16 mA
cast and wraps at +-32.768A (observed +26.5A at a true -39.0A) -- the
float iin field is the honest monitor above that.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 17:06:00 +07:00
janikandClaude Fable 5 465455d427 GUI sweep: converter-collapse abort + measured finish-time estimate
The mid-sweep abort only watched the supply readback (~0V = supply
protection tripped), so a DUT-side collapse sailed past it: run
2026-07-07 10:58, Vout 48->3.1V at Vin=55V with the supply still up at
55V/0A, sweep kept stepping the 75V column through garbage. Add a
second abort when the load voltage drops below half the expected Vout;
the message names the STM32 limit/fault bits from the last frame
before the brownout blackout (the MCU rides the Vout rail).

Status line now appends ETA hh:mm (N pts, ~M min left): remaining
grid is deterministic (feasibility-gated steps), per-point cost is not
(instrument round-trips vary per setup), so it is a running average of
measured point times (thermal holds excluded) extrapolated over the
remaining feasible points. Grid size is printed at sweep start.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 14:39:48 +07:00
janikandClaude Fable 5 f709d634e8 bench-plot: per-file Vin-bin checkbox picker for combining runs
Combining multiple CSVs pooled everything blindly; when two runs cover
the same Vin bin the user now gets a checkbox grid (row per Vin bin,
column per file, counts per cell, overlapping bins highlighted) to
decide per bin which file contributes. Opens automatically on overlap;
--pick forces it (also useful to cut bad columns from a single file),
--no-pick suppresses it for scripted use.

Also: picker/file-dialog windows force themselves to the foreground
(spawned from the GUI button, Windows opened them hidden behind the
GUI); unreadable or still-being-written (empty) CSVs are skipped with a
note instead of killing the run; fatal errors show a messagebox since
stderr is invisible when launched from the GUI.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 16:59:34 +07:00
janikandClaude Fable 5 ca5f0fe9c2 GUI: non-blocking disconnect, never close VISA sessions under the worker
Pressing Disconnect with the instruments powered off froze the GUI
(apparent crash, 2026-07-06 15:52): worker.join(5) expired while the
worker sat in multi-second VISA timeouts, then bench.close() ran on the
GUI thread -- each driver close() first writes local() to the dead
device (stacked timeouts) and closing a session under an in-flight read
can also take NI-VISA down natively.

_disconnect now detaches the UI immediately and runs all instrument
teardown on a background thread; if the worker is still stuck in I/O
after a 15s join the sessions are deliberately left open (OS reclaims
them at exit) instead of being closed under a live read. Reconnecting
while a teardown is still releasing the instruments is refused with a
console hint.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 16:59:20 +07:00
janikandClaude Fable 5 5b168439e8 GUI sweep: supply-trip protection after the 80V OVP shutdown
Run 2026-07-06 13:08: stepping 78->80V released the 46A load mid-ramp,
the supply output overshot to 80.46V and a protection (OVP by all log
evidence) shut it down; the sweep then logged garbage rows for the rest
of the grid. Three fixes:

- release the load down to l_start BEFORE each supply voltage step
  (down-steps only; descending load sweeps keep the gated path)
- OVP preflight: query the programmed OVP level at sweep start, abort
  under 2V margin above the sweep max, warn under 5V
- dead-supply abort: supply readback ~0V mid-sweep drops the garbage
  point, queries which protection fired (OVP/OV/OC/OP/OT) via
  _supply_trip_cause, reports it, and stops -- collected points are
  still ramped down and saved

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 14:49:07 +07:00
janikandClaude Fable 5 668ce30a1d GUI: I limit field is the environment input-current limit, no hardcoded 20A
The 20A PSU ceiling was hardcoded and clamped user entries, which breaks
benches with a different supply. Now the sweep I limit field IS the max
input current allowed for the test environment: used verbatim as the
supply CC limit and as the step-rejection / measured-backstop ceiling.
Manual supply-current clamp removed; manual CC/CP load gate now checks
against the I limit field value. PSU_MAX_CURRENT_A is reduced to
INPUT_LIMIT_DEFAULT_A (initial field value only).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 12:53:44 +07:00
janikandClaude Fable 5 7f8672d7b9 GUI: live STM32 telemetry + sweep guards + auto-logging + bench-plot
- stm32_link.py: port to the live 114-byte broadcast protocol (magic
  0xAA55AA55, odd parity 8-O-1, 100 Hz publish, repetition-validated,
  no CRC); 39 params incl. adc4_trig_phase/iin_zero_sum, CLEAR_FLAGS,
  30-bit flag table; commands stay CRC-16 framed; Telemetry aliases
  BroadcastData, efficiency uses iout_slow and eff_net subtracts P_sys
- gui_workers.py: STM32Worker reader thread with counter dedup, rate/
  loss counters, 20 s graph history, full-rate telemetry CSV writer
- gui.py: right-side telemetry panel (link state, power + EFF net,
  heatsink/board temps, Vfly group, control, HRTIM, status-flag
  checkboxes, fault registers), Vfly + selectable corr/phase-ofs
  graphs, 20 s rolling window on all plots, dual CSV logging (merged
  stm_* columns + <stem>_telem.csv), logging on by default into
  logs/data_<timestamp>.csv, Plot Eff button
- sweep guards: PSU 20 A input-current gate (conservative estimate +
  measured backstop + I-limit clamp), thermal pause at 57/77 C holding
  the load at 1 A until cooled 5 C below threshold, CC range pinned to
  R2 for the whole run with empirical range-max readback rejection
- plot_eff.py + bench-plot entry point: efficiency vs Vin vs current
  maps from any logged CSV (sweep / data log / telem autodetect), file
  dialog when launched without args
- bench.py: HIOKI FAST response speed, 5 s settle defaults; cli.py
  stm32-read prints the full broadcast; README + .gitignore updates

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 18:06:02 +07:00
janikandClaude Opus 4.8 606858228c gui: default load port COM11 to match this bench
Completes the port migration (CLI already defaults to COM11/COM4); the
GUI toolbar field still hardcoded COM1. Supply/meter stay "auto".

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 12:31:50 +07:00
janikandClaude Opus 4.8 d2dfc73f9e tooling: sync bench + debug console to live STM32 protocol
The mppt-testbench Python tooling had drifted from the flashed firmware
(bundled fw e7a23a3 vs live 1b85532) and could no longer communicate:

- stm32_link.py: CRC8 -> CRC-16/CCITT-FALSE; telemetry 68B -> 78B
  (btemp, cmp_outer/inner, iout_slow, vfly_ofs_applied); add PTYPE_INT16
  and commands 0x12-0x18; replace PARAMS with the current 37-param map
  (single dt_normal, no dt brackets; test_corr/phase_ofs, phase PI,
  precharge PI, duty dither; vfly_active 0-3).
- tuner.py: retire per-bracket deadtime; sweep the single dt_normal.
- cli.py: update tune-deadtime, help/examples, btemp readout;
  default ports COM11 (load) / COM4 (stm32).
- debug console TUI: sync protocol.py/app.py/status_bar/telemetry_panel
  from live (new command keys, link RX/TX/loss stats, single dead-time,
  new telemetry fields, param-write auto-retry); add duty_fft.py.
- README: rewrite parameter table, deadtime section, ports, keybindings.

Verified: protocol round-trip self-tests + live `bench stm32-read`
reading all 37 params over COM4.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 12:03:51 +07:00