I’m controlling a PWM fan (Noctua) inside a small homelab rack with an ESP32-C6 (ESPHome). The fan speed is set based on a temperature reading. I’d love feedback on whether my control logic is optimal or if I should switch approach (e.g. PID).
Current setup
- Temperature sensor: Sonoff SNZB-02P (Zigbee, via ZHA)
- Fan: Noctua PWM, driven by an ESP32-C6 via a
numberentity (fan_target_percent, 0-100%) - Control logic: a Home Assistant automation with a linear proportional curve: 31°C → 0%, 36°C → 100%, linear in between
- The automation triggers on temperature change and every 5 minutes as a safety net
- It only writes the new value if it differs from the current one (to avoid unnecessary writes)
A quirk with the Zigbee sensor
The SNZB-02P only reports every 30-60 minutes when the temperature is stable (it reports on change / max interval to save battery). When the temperature moves, it reports more often. That’s why I added the 5-minute time_pattern trigger as a fallback.
My questions
- For this kind of slow-changing thermal system, is a linear proportional curve good enough, or would a PID controller give meaningfully better results (more stable temperature, less fan hunting)?
- Given the Zigbee sensor’s infrequent reporting when stable, does it even make sense to use PID (which usually wants regular sampling)? Would a faster local sensor on the ESP (e.g. DS18B20) be a prerequisite for PID to work well?
- Should the control logic live in Home Assistant (as now) or be moved entirely into the ESP (ESPHome climate/PID + local sensor) for autonomy and faster response?
- Any tips on tuning the curve itself — e.g. is a linear ramp the best shape, or would a different curve (steeper near the top) make more sense?
Happy to share my full ESPHome config and the automation YAML if useful. Thanks in advance for any insight!