(* ===================================================================== 23_fb_headroom.st - FB_HEADROOM, section 4.4 Pure calculation. No control action, no alarms. Reference condition, WRPS-PRO-001 7.3 and pass 1 test 14: level 4.00 m, inflow 165 L/s, one pump at 120 L/s NetInflow = 45.0 L/s -> %QW7 = 450 VolToSpill = (6.0 - 4.0) * 120 = 240 m3 TimeToSpill = 240 * 1000 / 45 = 5333.3 s -> %QW5 = 5333 ===================================================================== *) FUNCTION_BLOCK FB_HEADROOM VAR_INPUT Level : REAL; (* m *) Inflow : REAL; (* L/s, unfiltered *) TotalDischarge : REAL; (* L/s *) END_VAR VAR_OUTPUT InflowFilt : REAL; (* L/s, 30 s lag *) NetInflow : REAL; (* L/s *) VolToSpill : REAL; (* m3 *) VolToLSHH : REAL; (* m3 *) TimeToSpill : INT; (* s, 32767 = drawing down *) TimeToLSHH : INT; (* s, 32767 = drawing down *) END_VAR VAR CONSTANT SCAN_S : REAL := 0.1; (* must match TASK INTERVAL *) TAU_S : REAL := 30.0; (* inflow filter time constant *) AREA_M2 : REAL := 120.0; SPILL_M : REAL := 6.000; LSHH_M : REAL := 5.500; MIN_NET : REAL := 0.5; (* L/s, below this the figure is meaningless - drawing down *) NO_TIME : INT := 32767; MAX_TIME : REAL := 32767.0; END_VAR VAR Primed : BOOL := FALSE; t : REAL; END_VAR (* --- Inflow filter. First-order lag, 30 s. Primed on the first scan rather than ramping from zero: without this the reference figure in test 14 would take ~2 minutes to settle and would not reproduce exactly on demand. ---------------- *) IF NOT Primed THEN InflowFilt := Inflow; Primed := TRUE; ELSE InflowFilt := InflowFilt + (Inflow - InflowFilt) * SCAN_S / TAU_S; END_IF; NetInflow := InflowFilt - TotalDischarge; VolToSpill := (SPILL_M - Level) * AREA_M2; VolToLSHH := (LSHH_M - Level) * AREA_M2; IF VolToSpill < 0.0 THEN VolToSpill := 0.0; END_IF; IF VolToLSHH < 0.0 THEN VolToLSHH := 0.0; END_IF; (* --- Time to spill weir ------------------------------------------- *) IF NetInflow <= MIN_NET THEN TimeToSpill := NO_TIME; ELSE t := VolToSpill * 1000.0 / NetInflow; IF t >= MAX_TIME THEN TimeToSpill := NO_TIME; ELSIF t < 0.0 THEN TimeToSpill := 0; ELSE TimeToSpill := REAL_TO_INT(t); END_IF; END_IF; (* --- Time to LSHH -------------------------------------------------- *) IF NetInflow <= MIN_NET THEN TimeToLSHH := NO_TIME; ELSE t := VolToLSHH * 1000.0 / NetInflow; IF t >= MAX_TIME THEN TimeToLSHH := NO_TIME; ELSIF t < 0.0 THEN TimeToLSHH := 0; ELSE TimeToLSHH := REAL_TO_INT(t); END_IF; END_IF; END_FUNCTION_BLOCK