code wiki / (root) / nx_vessel_io_test.nx

nx_vessel_io_test.nx source

↩ module page · 59 lines · 2542 B

1// nx_vessel_io_test.nx -- smoke for nx_vessel_io (H1, hardware-in-the-loop). 2// 3// Proves the real control software regulates against IMPERFECT hardware: 4// - sensor quantizes to the ADC resolution (1) 5// - PWM actuator is on below the duty, off above (2-3) 6// - sensor LAG: a laggy probe reads below true during a ramp (4-5) 7// - HIL: the R1 controller, reading a NOISY+LAGGY sensor, drives the H0 8// physics twin into the setpoint neighborhood (6-7) and NEVER reaches 9// culture-kill (8) -- the control design validated pre-build 10// Exit code = failed assertion number; 0 = all pass. 11 12import "nx_syscalls.nx" 13import "nx_ferment_safety.nx" 14import "nx_ferment_thermal.nx" 15import "nx_vessel_thermal.nx" 16import "nx_vessel_io.nx" 17 18func main() -> i64 { 19 // --- sensor quantization (instant, 0.1 C ADC, +/-0.1 C noise) --- 20 let s: *NxSensor = nx_sensor_new(20000, 1000, 100, 100) 21 let m: i64 = nx_sensor_update(s, 43050, 5) 22 if m % 100 != 0 { return 1 } 23 24 // --- PWM actuator --- 25 if nx_heater_pwm(600, 300) != 1000 { return 2 } 26 if nx_heater_pwm(600, 700) != 0 { return 3 } 27 28 // --- sensor lag: a laggy probe trails the true temperature on a ramp --- 29 let sl: *NxSensor = nx_sensor_new(20000, 200, 0, 0) 30 var i: i64 = 0 31 while i < 5 { 32 nx_sensor_update(sl, 40000, i) 33 i = i + 1 34 } 35 let lagged: i64 = nx_sensor_update(sl, 40000, 6) 36 if lagged >= 40000 { return 4 } // still catching up 37 if lagged <= 20000 { return 5 } // but climbing 38 39 // --- HARDWARE-IN-THE-LOOP: R1 controller + noisy/laggy sensor + twin --- 40 let env: *NxFermentSafetyEnvelope = nx_ferment_safety_envelope_default(1) 41 let ctrl: *NxFermentThermal = nx_ferment_thermal_new(env, 43000, 700, 4, 0, 4000000, 1000) 42 let twin: *NxVesselThermal = nx_vessel_thermal_new(16744, 50000, 1000, 20000) 43 let sens: *NxSensor = nx_sensor_new(20000, 300, 100, 100) // 30% lag, 0.1C ADC, +/-0.1C noise 44 var truet: i64 = 20000 45 var maxt: i64 = truet 46 var step: i64 = 0 47 while step < 400 { 48 let meas: i64 = nx_sensor_update(sens, truet, step) 49 let duty: i64 = nx_ferment_thermal_step(ctrl, meas) 50 truet = nx_vessel_thermal_step(twin, truet, duty, 60) 51 if truet > maxt { maxt = truet } 52 step = step + 1 53 } 54 if truet < 39000 { return 6 } // regulated up to the setpoint band 55 if truet > 47000 { return 7 } // bounded (no runaway) 56 if maxt >= 55000 { return 8 } // SAFETY holds under realistic IO 57 58 return 0 59}