diff --git a/goodwe_controller/test_control.py b/goodwe_controller/test_control.py index 3436d8f..ec1943b 100644 --- a/goodwe_controller/test_control.py +++ b/goodwe_controller/test_control.py @@ -41,15 +41,19 @@ check("proportional step (gain 0.6)", d.target_w == 300) d = compute(prev_w=0, grid_w=-500, actual_w=0, tuning=T) check("export drives charging", d.target_w == -300) -# Clamp -d = compute(prev_w=1900, grid_w=1000, actual_w=1900, tuning=Tuning(max_w=2000, slew_w=5000)) +# Clamp. +# ⚠️ integrator_max_w is lifted clear of max_w so that the OUTPUT clamp is the +# mechanism under test. Left at the default the integrator bound truncates +# first, these two assertions pass on that alone, and deleting the output clamp +# fails nothing - the same masking that hid the integrator freeze. +TCLAMP = Tuning(max_w=2000, slew_w=5000, integrator_max_w=5000) +d = compute(prev_w=1900, grid_w=1000, actual_w=1900, tuning=TCLAMP) check("clamped to max_w", d.target_w == 2000) # Slew: from 0 with a huge error, no more than slew_w in one cycle. d = compute(prev_w=0, grid_w=5000, actual_w=0, tuning=Tuning(max_w=5000, slew_w=1000)) check("slew limits one cycle", d.target_w == 1000) -d = compute(prev_w=-1900, grid_w=-1000, actual_w=-1900, - tuning=Tuning(max_w=2000, slew_w=5000)) +d = compute(prev_w=-1900, grid_w=-1000, actual_w=-1900, tuning=TCLAMP) check("clamped to -max_w", d.target_w == -2000) d = compute(prev_w=0, grid_w=-5000, actual_w=0, tuning=Tuning(max_w=5000, slew_w=1000)) check("slew limits one cycle, charging", d.target_w == -1000) @@ -132,7 +136,12 @@ check("integrator bound binds independently of the output clamp", d.i_w == 1000 and d.target_w == 1000) # Freeze = may not wind further in the direction it is already pushing. -TF = Tuning(saturation_w=500, saturation_cycles=3) +# ⚠️ max_w is raised WELL above the fixtures on purpose. At the default 2000 +# the integrator bound truncates a wound value back to exactly 2000 and +# satisfies these assertions on its own, so deleting the freeze outright +# failed nothing - the clamp was standing in for the mechanism under test. +# Any fixture here must sit clear of every rail, or it tests the rail. +TF = Tuning(saturation_w=500, saturation_cycles=3, max_w=5000) f1 = compute(prev_w=2000, grid_w=800, actual_w=0, tuning=TF, sat_count=3, i_w=2000.0) check("frozen: integration does not wind further", f1.i_w == 2000.0 and f1.frozen) f2 = compute(prev_w=2000, grid_w=-800, actual_w=0, tuning=TF, sat_count=3, i_w=2000.0)