From a0795302a9cd7c97655dd0604ec24028ffa24279 Mon Sep 17 00:00:00 2001 From: grabowski Date: Wed, 11 Mar 2026 16:06:48 +0700 Subject: [PATCH] Add CP mode sanity check: validate current limit vs power at min voltage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CP=500W at V=50V needs 10A on the load side — if the supply I_limit is only 20A and the MPPT has conversion losses, this can cause the supply to current-limit and timeout. The check now catches this upfront: CP check: 500W / 50V = 10.0A (limit 20.0A) OK Also raises ValueError if the worst-case current exceeds the limit. Co-Authored-By: Claude Opus 4.6 --- testbench/bench.py | 34 ++++++++++++++++++++++++++++++++-- testbench/gui.py | 9 ++++++++- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/testbench/bench.py b/testbench/bench.py index 1722315..00cfbec 100644 --- a/testbench/bench.py +++ b/testbench/bench.py @@ -564,11 +564,19 @@ class MPPTTestbench: self, max_voltage: float, current_limit: float, + *, + min_voltage: float | None = None, + load_mode: str = "CC", + max_load_setpoint: float = 0.0, ) -> None: """Check that the supply can deliver the requested V and I. Queries the supply's voltage range (max V) and verifies the - requested parameters are within bounds. Raises ValueError if not. + requested parameters are within bounds. For CP mode, also + checks that the supply current limit can deliver the requested + power at the minimum voltage. + + Raises ValueError if the configuration is invalid. """ supply_max_v = self.supply.get_voltage_range() if max_voltage > supply_max_v: @@ -585,6 +593,21 @@ class MPPTTestbench: f"(range {supply_max_v:.0f}V)" ) + # CP mode: at min voltage the load draws max current + if load_mode == "CP" and max_load_setpoint > 0 and min_voltage: + worst_case_i = max_load_setpoint / min_voltage + if worst_case_i > current_limit: + raise ValueError( + f"CP mode: {max_load_setpoint:.0f}W at " + f"{min_voltage:.0f}V needs {worst_case_i:.1f}A " + f"but supply I_limit is {current_limit:.1f}A" + ) + print( + f" CP check: {max_load_setpoint:.0f}W / " + f"{min_voltage:.0f}V = {worst_case_i:.1f}A " + f"(limit {current_limit:.1f}A) OK" + ) + # ── 2D Voltage × Current Sweep ───────────────────────────────────── def sweep_vi( @@ -630,7 +653,14 @@ class MPPTTestbench: # Sanity check max_v = max(abs(v_start), abs(v_stop)) - self.check_supply_capability(max_v, current_limit) + min_v = min(abs(v_start), abs(v_stop)) + max_l = max(abs(l_start), abs(l_stop)) + self.check_supply_capability( + max_v, current_limit, + min_voltage=min_v, + load_mode=load_mode, + max_load_setpoint=max_l, + ) # Auto-correct step directions if v_start < v_stop and v_step < 0: diff --git a/testbench/gui.py b/testbench/gui.py index 6f0be37..a63a8bc 100644 --- a/testbench/gui.py +++ b/testbench/gui.py @@ -1192,7 +1192,14 @@ class TestbenchGUI(tk.Tk): # Sanity check max_v = max(abs(v_start), abs(v_stop)) - bench.check_supply_capability(max_v, current_limit) + min_v = min(abs(v_start), abs(v_stop)) + max_l = max(abs(l_start), abs(l_stop)) + bench.check_supply_capability( + max_v, current_limit, + min_voltage=min_v, + load_mode=load_mode, + max_load_setpoint=max_l, + ) bench.supply.set_current(current_limit) bench.supply.output_on()