🎯 Objective
Validate the correctness and stability of the PID-based fan speed controller operating in Automatic Mode. The PID loop continuously adjusts the ebm-papst fan's 12 V PWM duty cycle in response to live sensor data (primarily CO₂ concentration from the SCD41 and optionally temperature/humidity) to maintain configurable setpoints — without manual user intervention. This task covers end-to-end testing of the closed-loop response, real-world tuning of the P, I, and D gains, and verification of all safety constraints and fail-safe behaviors.
📋 Scope & Background
In Automatic Mode the ESPHome pid controller component drives the fan. The process variable (PV) is typically the CO₂ reading from the Sensirion SCD41 (sampled every ~5 s). The setpoint (SP) is a user-defined CO₂ target (e.g. 800 ppm). The controller output maps to a PWM percentage clamped between a configurable minimum and maximum fan speed to protect the motor and guarantee a minimum ventilation rate. The BMP390 may serve as an auxiliary guard (pressure differential monitoring). Secondary PID loops or feedforward terms for temperature control via the NTC thermistors are in scope if already implemented.
✅ Acceptance Criteria
The PID output drives the fan PWM within the defined [min_power, max_power] bounds at all times — no clamping overflow or underflow.
CO₂ levels converge to within ±50 ppm of the setpoint within a reasonable settling time (target: < 10 min from a 400 ppm deviation).
No integral windup occurs when the fan is at its physical limits (anti-windup clamping must be confirmed active).
The system remains stable (no oscillation with amplitude > ±5 % PWM) in steady-state.
Transitions between Manual Mode → Automatic Mode initialize the PID integrator correctly (bumpless transfer).
Watchdog resets, WiFi drops, or sensor read failures do not cause the fan to stall or run at full speed indefinitely.
All tuned gain values (kp, ki, kd) are documented and committed to the YAML package.
🔬 Test Procedure
Baseline hardware check — Confirm SCD41 is returning valid CO₂/temp/hum readings and the fan responds linearly to manual PWM steps (0 %, 25 %, 50 %, 75 %, 100 %).
Open-loop characterization — Log CO₂ response vs. fan speed over ≥ 30 min to estimate the plant's time constant (τ) and dead time (θ). Use this to derive initial PID gains via IMC or Ziegler-Nichols tuning rules.
Closed-loop step response — Set SP = 800 ppm. Introduce a CO₂ disturbance (e.g. exhale near inlet). Record overshoot, rise time, settling time, and steady-state error via the ESPHome logger or the custom web dashboard.
Integral windup test — Force the fan to its min_power limit while CO₂ climbs. Release the clamp and verify the integrator has not wound up (no large overshoot upon release).
Bumpless transfer test — Switch from Manual (fixed 40 % PWM) to Automatic Mode. Confirm the output initializes at ~40 % and transitions smoothly.
Fail-safe / sensor loss test — Simulate an SCD41 read failure. Confirm the system falls back to a safe predefined fan speed (e.g. 60 %) and raises a Home Assistant alert.
Long-duration soak test — Run Automatic Mode for ≥ 4 hours with real occupancy. Monitor for memory leaks, watchdog resets, or thermal drift of the NTC thermistors affecting control.
🎯 Objective
Validate the correctness and stability of the PID-based fan speed controller operating in Automatic Mode. The PID loop continuously adjusts the ebm-papst fan's 12 V PWM duty cycle in response to live sensor data (primarily CO₂ concentration from the SCD41 and optionally temperature/humidity) to maintain configurable setpoints — without manual user intervention. This task covers end-to-end testing of the closed-loop response, real-world tuning of the P, I, and D gains, and verification of all safety constraints and fail-safe behaviors.
📋 Scope & Background
In Automatic Mode the ESPHome pid controller component drives the fan. The process variable (PV) is typically the CO₂ reading from the Sensirion SCD41 (sampled every ~5 s). The setpoint (SP) is a user-defined CO₂ target (e.g. 800 ppm). The controller output maps to a PWM percentage clamped between a configurable minimum and maximum fan speed to protect the motor and guarantee a minimum ventilation rate. The BMP390 may serve as an auxiliary guard (pressure differential monitoring). Secondary PID loops or feedforward terms for temperature control via the NTC thermistors are in scope if already implemented.
✅ Acceptance Criteria
The PID output drives the fan PWM within the defined [min_power, max_power] bounds at all times — no clamping overflow or underflow.
CO₂ levels converge to within ±50 ppm of the setpoint within a reasonable settling time (target: < 10 min from a 400 ppm deviation).
No integral windup occurs when the fan is at its physical limits (anti-windup clamping must be confirmed active).
The system remains stable (no oscillation with amplitude > ±5 % PWM) in steady-state.
Transitions between Manual Mode → Automatic Mode initialize the PID integrator correctly (bumpless transfer).
Watchdog resets, WiFi drops, or sensor read failures do not cause the fan to stall or run at full speed indefinitely.
All tuned gain values (kp, ki, kd) are documented and committed to the YAML package.
🔬 Test Procedure
Baseline hardware check — Confirm SCD41 is returning valid CO₂/temp/hum readings and the fan responds linearly to manual PWM steps (0 %, 25 %, 50 %, 75 %, 100 %).
Open-loop characterization — Log CO₂ response vs. fan speed over ≥ 30 min to estimate the plant's time constant (τ) and dead time (θ). Use this to derive initial PID gains via IMC or Ziegler-Nichols tuning rules.
Closed-loop step response — Set SP = 800 ppm. Introduce a CO₂ disturbance (e.g. exhale near inlet). Record overshoot, rise time, settling time, and steady-state error via the ESPHome logger or the custom web dashboard.
Integral windup test — Force the fan to its min_power limit while CO₂ climbs. Release the clamp and verify the integrator has not wound up (no large overshoot upon release).
Bumpless transfer test — Switch from Manual (fixed 40 % PWM) to Automatic Mode. Confirm the output initializes at ~40 % and transitions smoothly.
Fail-safe / sensor loss test — Simulate an SCD41 read failure. Confirm the system falls back to a safe predefined fan speed (e.g. 60 %) and raises a Home Assistant alert.
Long-duration soak test — Run Automatic Mode for ≥ 4 hours with real occupancy. Monitor for memory leaks, watchdog resets, or thermal drift of the NTC thermistors affecting control.