Add tune-param-vsweep command for parameter sweeps across voltage range
Automates running tune-param at multiple voltages, saves per-voltage CSVs compatible with plot-tune, and prints a summary table. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -631,6 +631,88 @@ def cmd_tune_param(bench: MPPTTestbench, args: argparse.Namespace) -> None:
|
||||
tuner.plot_sweep(results, show=True)
|
||||
|
||||
|
||||
def cmd_tune_param_vsweep(bench: MPPTTestbench, args: argparse.Namespace) -> None:
|
||||
"""Sweep an STM32 parameter across a range of voltages."""
|
||||
from testbench.stm32_link import STM32Link
|
||||
from testbench.tuner import Tuner
|
||||
|
||||
with STM32Link(args.stm32_port, args.stm32_baud) as link:
|
||||
if not link.ping():
|
||||
print("STM32 not responding!")
|
||||
return
|
||||
|
||||
tuner = Tuner(bench, link, settle_time=args.settle)
|
||||
|
||||
# Build voltage list
|
||||
v = args.v_start
|
||||
voltages = []
|
||||
while v <= args.v_stop + args.v_step / 2:
|
||||
voltages.append(v)
|
||||
v += args.v_step
|
||||
|
||||
n_param_steps = int(abs(args.stop - args.start) / abs(args.step)) + 1
|
||||
total = n_param_steps * len(voltages)
|
||||
est_s = total * args.settle + len(voltages) * args.settle * 2 # settle + initial settle per voltage
|
||||
est_m = est_s / 60
|
||||
|
||||
print(f"Voltage sweep: {args.param} across {len(voltages)} voltages")
|
||||
print(f" Voltages: {', '.join(f'{v:.0f}V' for v in voltages)}")
|
||||
print(f" Param range: {args.start} -> {args.stop} (step {args.step})")
|
||||
print(f" {n_param_steps} param steps x {len(voltages)} voltages = {total} points")
|
||||
print(f" Estimated time: {est_m:.1f} min")
|
||||
print()
|
||||
|
||||
# Determine output prefix
|
||||
prefix = args.output or args.param
|
||||
|
||||
all_results: list = []
|
||||
csv_files: list[str] = []
|
||||
|
||||
for vi, voltage in enumerate(voltages):
|
||||
print(f"\n{'='*60}")
|
||||
print(f" Voltage {vi+1}/{len(voltages)}: {voltage:.0f}V")
|
||||
print(f"{'='*60}")
|
||||
|
||||
results = tuner.sweep_param(
|
||||
param_name=args.param,
|
||||
start=args.start,
|
||||
stop=args.stop,
|
||||
step=args.step,
|
||||
voltage=voltage,
|
||||
current_limit=args.current_limit,
|
||||
load_mode=args.load_mode,
|
||||
load_value=args.load_value,
|
||||
settle_time=args.settle,
|
||||
)
|
||||
all_results.extend(results)
|
||||
|
||||
# Save per-voltage CSV
|
||||
csv_name = f"{prefix}_{voltage:.0f}V.csv"
|
||||
tuner.write_csv(results, csv_name)
|
||||
csv_files.append(csv_name)
|
||||
|
||||
# Summary
|
||||
print(f"\n{'='*60}")
|
||||
print("VOLTAGE SWEEP SUMMARY")
|
||||
print(f"{'Voltage':>8} {'Best':>8} {'Efficiency':>12} {'Temp':>6}")
|
||||
print("-" * 40)
|
||||
for voltage in voltages:
|
||||
pts = [p for p in all_results
|
||||
if abs(p.voltage_set - voltage) < 0.5 and 0 < p.meter_eff < 110]
|
||||
if pts:
|
||||
best = max(pts, key=lambda p: p.meter_eff)
|
||||
print(f"{voltage:>7.0f}V {best.param_value:>8.1f} "
|
||||
f"{best.meter_eff:>11.2f}% {best.stm_etemp:>5.0f}C")
|
||||
else:
|
||||
print(f"{voltage:>7.0f}V {'N/A':>8} {'N/A':>12} {'N/A':>6}")
|
||||
print(f"{'='*60}")
|
||||
|
||||
print(f"\nSaved {len(csv_files)} CSV files:")
|
||||
for f in csv_files:
|
||||
print(f" {f}")
|
||||
print(f"\nRun: uv run bench plot-tune {' '.join(csv_files)}")
|
||||
|
||||
|
||||
def cmd_tune_deadtime(bench: MPPTTestbench, args: argparse.Namespace) -> None:
|
||||
"""Optimize deadtime for each current bracket."""
|
||||
from testbench.stm32_link import STM32Link
|
||||
@@ -1193,6 +1275,21 @@ examples:
|
||||
p_tp.add_argument("--no-plot", action="store_true", help="Skip plot")
|
||||
p_tp.add_argument("-o", "--output", help="CSV output file")
|
||||
|
||||
# tune-param-vsweep
|
||||
p_tv = sub.add_parser("tune-param-vsweep", help="Sweep an STM32 parameter across a voltage range")
|
||||
p_tv.add_argument("--param", required=True, help="Parameter name (e.g. dt_10_20A, vfly_kp)")
|
||||
p_tv.add_argument("--start", type=float, required=True, help="Param start value")
|
||||
p_tv.add_argument("--stop", type=float, required=True, help="Param stop value")
|
||||
p_tv.add_argument("--step", type=float, required=True, help="Param step size")
|
||||
p_tv.add_argument("--v-start", type=float, required=True, help="Start voltage (V)")
|
||||
p_tv.add_argument("--v-stop", type=float, required=True, help="Stop voltage (V)")
|
||||
p_tv.add_argument("--v-step", type=float, required=True, help="Voltage step (V)")
|
||||
p_tv.add_argument("--current-limit", type=float, required=True, help="Supply current limit (A)")
|
||||
p_tv.add_argument("--load-mode", choices=["CC", "CP"], default="CP", help="Load mode")
|
||||
p_tv.add_argument("--load-value", type=float, default=200.0, help="Load setpoint (A or W)")
|
||||
p_tv.add_argument("--settle", type=float, default=3.0, help="Settle time per step (s)")
|
||||
p_tv.add_argument("-o", "--output", help="Output prefix for CSVs (default: param name)")
|
||||
|
||||
# tune-deadtime
|
||||
p_td = sub.add_parser("tune-deadtime", help="Optimize deadtime for each current bracket")
|
||||
p_td.add_argument("--dt-start", type=int, default=14, help="Min deadtime ticks (default: 14)")
|
||||
@@ -1245,6 +1342,7 @@ examples:
|
||||
"stm32-read": cmd_stm32_read,
|
||||
"stm32-write": cmd_stm32_write,
|
||||
"tune-param": cmd_tune_param,
|
||||
"tune-param-vsweep": cmd_tune_param_vsweep,
|
||||
"tune-deadtime": cmd_tune_deadtime,
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user