code wiki / _hdl_build / nx_heater_pid.nx
nx_heater_pid.nx
buildroot/runtime/_hdl_build/nx_heater_pid.nx
about
nx_heater_pid.nx -- SOVEREIGN PRINTER ARC rung 1b: integer PID heater control + a first-order
thermal plant simulator to prove it against (deterministic sim = the oracle until real hardware).
This is the loop that holds the hotend at temperature UNDER LOAD -- the flip side of the jam
physics (nx_jam_check says what temp is needed; this loop is what must HOLD it when melt load
rises). Units: temperature in MILLI-degC, PWM output 0..255, gains scaled by /1000.
PID: u = (Kp*e + Ki*acc_e + Kd*(e - e_prev)) / 1000, clamped 0..255
ANTI-WINDUP: the integral accumulator is clamped so a long heat-up can't overshoot-lock.
PLANT: T' = T + (u * k_heat - (T - T_amb) * k_loss / 1000) per tick (first-order RC model).
HONEST SCOPE: plant constants are a MODEL (sim oracle); the bare-metal port reads a real
thermistor ADC + drives a real MOSFET -- flagged next rung (cortex_m/esp32 backends exist).
LAWS: struct-free, integer-only. license_tier: ORIGINAL
dependencies 1 imports · 1 importers
imports: nx_syscalls.nx
imported by: nx_printer_ctl_test.nx
structs
| none |
consts
| 13 | const HP_MAGIC_1000000: i64 = 1000000 |
| 15 | const HP_PWM_MAX: i64 = 255 |
| 16 | const HP_ISEP_MC: i64 = 10000 // integral SEPARATION: only integrate within +/-10C of target |
functions
| 20 | func hp_pid_init(st: *i64, acc_clamp: i64) -> i64 called by 1: hp_sim |
| 26 | func hp_pid_tick(st: *i64, target_mc: i64, current_mc: i64, kp: i64, ki: i64, kd: i64) -> i64 called by 1: hp_sim |
| 47 | func hp_plant_tick(t_mc: i64, t_amb_mc: i64, pwm: i64, k_heat: i64, k_loss: i64) -> i64 |
| 54 | func hp_sim(target_mc: i64, t0_mc: i64, t_amb_mc: i64, |