Initial commit: ESP32-C6 rack fan controller with ESPHome

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>
This commit is contained in:
jazzymc
2026-04-12 16:09:00 +00:00
commit 2f783dbc41
5 changed files with 733 additions and 0 deletions
+136
View File
@@ -0,0 +1,136 @@
# 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