PVE-FANCTRL

ESP32 + 1.9" ST7789 TFT // Standalone Drive Cooling Fan Controller

LVGL UI DUAL ARC GAUGES CAPTIVE PORTAL 12 THEMES MATRIX KANJI RAIN WEB CONTROL NVS PERSIST mDNS

WHAT IT DOES

Standalone PWM fan controller for drive bay cooling on a TrueNAS / Proxmox box. Drives a single 4-pin PWM fan from a 3.3V GPIO and reads the tach via interrupt. Live RPM and PWM% shown as twin arc gauges on the 1.9" TFT, with a full web UI for remote control. First-boot captive portal handles WiFi setup and theme selection so no credentials are baked into the source. 11 built-in themes from minimal grayscale to full Matrix kanji rain — switchable live from the web UI without a reboot.

WIRING DIAGRAM

ESP32 + 1.9" TFT IDEASPARK 50 FAN% VIN (5V) GND GPIO 26 GPIO 27 3V3 GND // POWER IN — pick ONE A: USB-C → PC / 5V wall wart B: +5V → VIN, GND → GND (mobo USB hdr) TL-9015B 92mm 4-pin PWM 2700 RPM 4-PIN MOLEX 1 GND black 2 +12V yellow 3 TACH green 4 PWM blue 10kΩ tach pull-up 10nF ⚠ tach filter use the GND pin CLOSEST to GPIO 27 12V SUPPLY PC PSU SATA / molex / 12V wall wart + COMMON GROUND RAIL — required PWM (3.3V, 25 kHz) TACH (open-collector) +12V

SVG schematic hidden on mobile — see wiring tables below

DISPLAY PINOUT (handled by TFT_eSPI User_Setup.h)

FUNCTION GPIO NOTES
LCD MOSIGPIO 23VSPI MOSI
LCD SCLKGPIO 18VSPI clock
LCD CSGPIO 15strapping pin (OK)
LCD DCGPIO 2strapping pin (OK)
LCD RSTGPIO 4reset
LCD BLGPIO 32active HIGH — TFT_BACKLIGHT_ON HIGH

Board: ideaspark ESP32 + 1.9" ST7789 170x320 TFT (same as CyberMon)

FAN WIRING (single 4-pin PWM fan)

FROM TO SIGNAL
PSU +12V (yellow)Fan pin 2+12V supply
PSU GND (black)Fan pin 1shared with ESP32 GND
ESP32 GPIO 26Fan pin 4PWM out (3.3V, 25 kHz)
Fan pin 3ESP32 GPIO 27tach in (10 kΩ pull-up to 3.3V)
ESP32 GPIO 27ESP32 GND (closest pin)10 nF tach filter cap — kills PWM crosstalk; must use GND pin closest to GPIO 27
ESP32 GNDPSU GNDcommon ground — required
USB-C (option A)ESP32 boarddefault — PC or 5V/1A wall wart
Mobo USB hdr pin 1 (option B)ESP32 VIN+5V — onboard reg drops to 3.3V
Mobo USB hdr pin 7 (option B)ESP32 GNDD+/D− unused. Pick A or B, not both.

Tested with TL-9015B 92mm 4-pin PWM (15mm slim), 2700 RPM rated. Also confirmed with Corsair 4-pin PWM fans.

⚠ Tach filter cap is required. The 10 nF cap on GPIO 27 must connect to the GND pin physically closest to GPIO 27 on the dev board. A long GND trace forms an LC resonator with the cap and produces more noise, not less. Acceptable cap values: 10–22 nF. Avoid 100 nF — too much filtering attenuates the real tach signal.

"Off at 0%" is fan-dependent. The TL-9015B holds a hardware floor of ~450 RPM at 0% PWM. Fans with full-stop support (most Corsair, Noctua, etc.) will fully stop. To force a stop on a fan that doesn't, add a MOSFET on the +12 V rail.

FIRST-BOOT WORKFLOW

1
Flash the .ino
to the ESP32
2
Connect to
"PVE-FANCTRL-Setup"
open WiFi
3
Captive portal opens
Enter SSID + password
Pick theme
4
ESP32 reboots,
joins WiFi, shows
twin arc gauges

BUILT-IN THEMES (11)

Defaultblack + purple/blue + teal
CyberNetblack + cyan + gold IP
Cyberpunkmagenta on dark purple
Neon Gridcyan on dark blue
Retro Cmdamber terminal
Militarydark green + amber
Noir Neonpink + cyan
ClinicalLIGHT cream + slate
Holographicnavy + light cyan
Greyflat + blue accent
Minimal Darkpure grayscale
Blood & Firecrimson + flame
Matrixphosphor green + falling katakana/kanji rain animation behind the gauges

10 of these are lifted directly from the CyberNetView dashboard's theme system

FACTORY RESET / RE-PORTAL

> Hold BOOT button for 5 seconds while powering on the ESP32

> Serial log prints [portal] wifi credentials wiped

> Captive portal launches on the next boot

> Use this to change WiFi network or pick a different theme via portal

WEB CONTROL

> After WiFi setup, browse to http://<hostname>.local/ (default http://PVE-FANCTRL.local/)

> Control fan PWM with slider + preset buttons (0/25/50/75/100%)

> Live RPM telemetry polls every 2.5s

> Theme dropdown — pick any of 11 themes, applies live to the TFT (no reboot)

> JSON API: GET /api/status, POST /api/set?pct=N, GET /api/theme, POST /api/theme?name=<id>

KEY LIBRARIES

> LVGL 9.4+ (Library Manager — for the UI widgets and CJK font)

> TFT_eSPI (Library Manager — display driver, configured for the Ideaspark pinout)

> Built-in: WiFi, WebServer, ESPmDNS, DNSServer, Preferences

> SquareLine Studio 1.6+ (optional — only if you want to redesign the UI visually)

VIEW SKETCH CODE CAPTIVE PORTAL DETAILS