2f783dbc41
3-zone PWM fan controller (intake/central/outtake) with DS18B20 temp sensors, RPM monitoring, ST7789 LCD display, and Home Assistant integration via ESPHome native API. USB-C PD powered. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
137 lines
4.3 KiB
Markdown
137 lines
4.3 KiB
Markdown
# Rack Fan Controller
|
|
|
|
ESP32-C6 based smart rack/cabinet fan controller with temperature monitoring, automatic PWM fan speed control, and Home Assistant integration via ESPHome.
|
|
|
|
## Features
|
|
|
|
- **3-zone fan control**: Intake, Central, Outtake (2 fans per zone, 6 total)
|
|
- **Temperature monitoring**: 3x DS18B20 sensors (one per zone)
|
|
- **RPM monitoring**: Tachometer reading from one fan per zone
|
|
- **Auto speed control**: Temperature-based PWM ramping with configurable thresholds
|
|
- **Negative pressure**: Outtake fans run slightly faster for dust control
|
|
- **1.47" LCD display**: Real-time temps, RPMs, and fan duty on Waveshare ST7789
|
|
- **Home Assistant**: Full integration via ESPHome native API
|
|
- **USB-C powered**: 65W PD charger -> ZY12PDN 12V trigger -> fans + ESP32
|
|
|
|
## Hardware
|
|
|
|
| Component | Qty | Notes |
|
|
|-----------|-----|-------|
|
|
| Waveshare ESP32-C6 LCD 1.47" | 1 | No-touch version, ST7789 172x320 |
|
|
| Arctic P12 PWM 120mm | 6 | 4-pin, 2 per zone |
|
|
| ZY12PDN USB-C PD trigger | 1 | Set to 12V output |
|
|
| LM2596 buck converter | 1 | 12V -> 5V for ESP32 |
|
|
| DS18B20 waterproof probe | 3 | 1m cable, 1-Wire bus |
|
|
| PWM Y-splitter (4-pin) | 3 | 1-to-2 per zone |
|
|
| KF301 screw terminals | 10 | PCB connections |
|
|
| 4.7kOhm resistor | 1 | DS18B20 pull-up |
|
|
| 5x7cm prototype PCB | 1 | Main board |
|
|
|
|
## GPIO Mapping (Waveshare ESP32-C6 LCD 1.47")
|
|
|
|
### LCD (occupied - do not use)
|
|
| Function | GPIO |
|
|
|----------|------|
|
|
| LCD MOSI | 6 |
|
|
| LCD CLK | 7 |
|
|
| LCD CS | 14 |
|
|
| LCD DC | 15 |
|
|
| LCD RST | 21 |
|
|
| LCD BLK | 22 |
|
|
| RGB LED | 8 |
|
|
| SD MISO | 5 |
|
|
| SD CS | 4 |
|
|
|
|
### Project Pin Assignment
|
|
| Function | GPIO | Notes |
|
|
|----------|------|-------|
|
|
| PWM Intake | 0 | Zone 1 - via Y-splitter to 2 fans |
|
|
| PWM Central | 1 | Zone 2 - via Y-splitter to 2 fans |
|
|
| PWM Outtake | 2 | Zone 3 - via Y-splitter to 2 fans |
|
|
| Tach Intake | 3 | RPM from 1 fan in zone 1 |
|
|
| Tach Central | 10 | RPM from 1 fan in zone 2 |
|
|
| Tach Outtake | 11 | RPM from 1 fan in zone 3 |
|
|
| DS18B20 bus | 9 | All 3 sensors on single 1-Wire bus |
|
|
|
|
## Wiring Diagram
|
|
|
|
```
|
|
USB-C PD Charger (65W+)
|
|
|
|
|
USB-C cable
|
|
|
|
|
v
|
|
ZY12PDN (set to 12V) ----+------ 12V Rail
|
|
| |
|
|
v +--- Y-splitter --- Fan1 + Fan2 (INTAKE)
|
|
LM2596 (out=5V) | |
|
|
| +--- Y-splitter --- Fan3 + Fan4 (CENTRAL)
|
|
v | |
|
|
ESP32-C6 (5V in) +--- Y-splitter --- Fan5 + Fan6 (OUTTAKE)
|
|
|
|
|
+-- GPIO0 (PWM) ----> Intake splitter PWM pin
|
|
+-- GPIO1 (PWM) ----> Central splitter PWM pin
|
|
+-- GPIO2 (PWM) ----> Outtake splitter PWM pin
|
|
|
|
|
+-- GPIO3 (TACH) <--- Fan1 tach (yellow wire)
|
|
+-- GPIO10 (TACH) <-- Fan3 tach (yellow wire)
|
|
+-- GPIO11 (TACH) <-- Fan5 tach (yellow wire)
|
|
|
|
|
+-- GPIO9 (1-Wire) --+-- DS18B20 (intake)
|
|
+-- DS18B20 (central)
|
|
+-- DS18B20 (outtake)
|
|
|
|
|
4.7k pull-up to 3.3V
|
|
```
|
|
|
|
### 4-Pin Fan Connector Pinout
|
|
```
|
|
Pin 1 (Black) = GND
|
|
Pin 2 (Yellow) = +12V
|
|
Pin 3 (Green) = Tach (RPM signal)
|
|
Pin 4 (Blue) = PWM control
|
|
```
|
|
|
|
## Temperature Control Logic
|
|
|
|
| Temp Range | Intake | Central | Outtake | Notes |
|
|
|------------|--------|---------|---------|-------|
|
|
| < 28C | 20% | 20% | 25% | Near-silent baseline |
|
|
| 28-35C | 20-50% | 20-50% | 25-55% | Gentle ramp |
|
|
| 35-42C | 50-80% | 50-80% | 55-85% | Medium cooling |
|
|
| 42-50C | 80-100% | 80-100% | 85-100% | Full cooling |
|
|
| > 50C | 100% | 100% | 100% | Emergency + HA alert |
|
|
|
|
Outtake always runs +5% over intake for slight negative pressure (dust control).
|
|
|
|
## Build & Flash
|
|
|
|
```bash
|
|
# Install ESPHome
|
|
pip install esphome
|
|
|
|
# Validate config
|
|
esphome config esphome/rack-fan-controller.yaml
|
|
|
|
# Flash (first time via USB)
|
|
esphome run esphome/rack-fan-controller.yaml
|
|
|
|
# Subsequent updates via OTA
|
|
esphome run esphome/rack-fan-controller.yaml --device rack-fan-ctrl.local
|
|
```
|
|
|
|
## Home Assistant
|
|
|
|
After flashing, the device auto-discovers in HA via ESPHome integration. Exposed entities:
|
|
|
|
- `sensor.rack_temp_intake` / `central` / `outtake`
|
|
- `sensor.rack_fan_rpm_intake` / `central` / `outtake`
|
|
- `sensor.rack_fan_duty_intake` / `central` / `outtake`
|
|
- `switch.rack_fan_auto_mode` (enable/disable auto control)
|
|
- `number.rack_fan_target_temp` (target temperature setpoint)
|
|
- `number.rack_fan_min_duty` / `max_duty` (manual override range)
|
|
|
|
## License
|
|
|
|
MIT
|