# GPU Fan Controller Usermod This usermod allows WLED to control PWM PC fans based on GPU temperature data received from an external source (typically a Python script running on your PC). ## Features - **Web API Integration**: Receives GPU temperature via HTTP API - **Fixed Speed Mode**: Set a constant fan speed (0-100%) - **Temperature Curve Mode**: Automatically adjusts fan speed based on temperature - **Visual Curve Editor**: Interactive web-based graph editor at `/gpu-fan.htm` - **Up to 5 Curve Points**: Define custom temperature-to-speed mappings - **Safety Fallback**: Automatically runs at 100% if temperature data is lost - **WLED UI Integration**: Control and monitor from the WLED web interface - **Live Temperature Display**: See current GPU temp and fan speed in real-time ## Hardware Requirements - ESP32 development board (ESP32 Dev Module recommended) - 4-pin PWM PC fan (12V) - 12V power supply for the fan - Common ground connection between ESP32 and power supply ## Wiring | Fan Pin | Connection | |---------|------------| | GND (Black) | ESP32 GND + 12V PSU GND | | +12V (Yellow) | 12V Power Supply + | | PWM (Blue) | ESP32 GPIO 13 (configurable) | | TACH (Green) | Not used | **Important:** - Connect 12V power supply GND to ESP32 GND (common ground) - DO NOT connect +12V to any ESP32 pins ## Installation ### Option 1: Using platformio_override.ini (Recommended) 1. Copy the `GPU_Fan_Controller` folder to `wled00/usermods/` 2. Create or edit `platformio_override.ini` in the WLED root directory: ```ini [env:esp32dev_gpu_fan] extends = env:esp32dev build_flags = ${env:esp32dev.build_flags} -D USERMOD_GPU_FAN_CONTROLLER -D PWM_FAN_PIN=13 custom_usermods = GPU_Fan_Controller ``` 3. Build and upload: ```bash pio run -e esp32dev_gpu_fan -t upload ``` 4. Upload the custom page (optional but recommended): ```bash pio run -e esp32dev_gpu_fan -t uploadfs ``` ### Option 2: Manual Integration 1. Copy `GPU_Fan_Controller.cpp` to `wled00/usermods/GPU_Fan_Controller/` 2. Add to your build flags: ``` -D USERMOD_GPU_FAN_CONTROLLER ``` ## Visual Curve Editor Access the visual curve editor at: `http://YOUR_WLED_IP/gpu-fan.htm` ![Curve Editor Screenshot](curve-editor.png) Features: - **Drag points** on the graph to adjust temperature/speed mappings - **Live temperature indicator** shows current GPU temp on the graph - **Real-time updates** - see fan speed change as you adjust - **Table view** for precise value entry - **Add/remove points** - use 2-5 curve points - **Mode toggle** - switch between Fixed and Curve modes ## Configuration ### Via WLED Web Interface Navigate to Config → Usermods to configure: - **enabled**: Enable/disable the fan controller - **pwm-pin**: GPIO pin for PWM output (default: 13) - **mode**: 0 = Fixed, 1 = Curve - **fixed-speed**: Speed percentage when in fixed mode - **timeout-ms**: Temperature timeout in milliseconds (default: 10000) - **curve-t1 to curve-t5**: Temperature points (°C) - **curve-s1 to curve-s5**: Speed points (%) - **curve-points**: Number of curve points to use (2-5) ### Via JSON API ```json { "GPU-Fan": { "enabled": true, "mode": 1, "fixed-speed": 50, "curve-points": 4, "curve-t1": 30, "curve-s1": 30, "curve-t2": 50, "curve-s2": 50, "curve-t3": 70, "curve-s3": 75, "curve-t4": 85, "curve-s4": 100 } } ``` ## API Endpoints ### Update Temperature Send GPU temperature to the controller: ```http POST /json/state Content-Type: application/json { "GPU-Fan": { "temperature": 65.5 } } ``` ### Set Manual Speed ```http POST /json/state Content-Type: application/json { "GPU-Fan": { "speed": 75 } } ``` ### Set Mode ```http POST /json/state Content-Type: application/json { "GPU-Fan": { "mode": 1 } } ``` Where mode: 0 = Fixed, 1 = Curve ### Get Status ```http GET /json/info ``` Response includes GPU temperature, fan speed, and mode in the "u" (user) object. ## Python GPU Monitor Script Use the included `gpu_temp_monitor.py` script to send GPU temperatures to the ESP32: ### Installation ```bash pip install requests nvidia-ml-py # OR for multi-vendor support: pip install requests gpustat ``` ### Usage ```bash # Basic usage python gpu_temp_monitor.py --wled-ip 192.168.1.100 # Specify GPU type python gpu_temp_monitor.py --wled-ip 192.168.1.100 --gpu-type nvidia # Custom update interval python gpu_temp_monitor.py --wled-ip 192.168.1.100 --interval 3 ``` ### Running as a Service #### Windows (Task Scheduler) Create a batch file and add to startup: ```batch @echo off python C:\path\to\gpu_temp_monitor.py --wled-ip 192.168.1.100 ``` #### Linux (systemd) Create `/etc/systemd/system/gpu-fan-monitor.service`: ```ini [Unit] Description=GPU Fan Controller Monitor After=network.target [Service] Type=simple User=yourusername ExecStart=/usr/bin/python3 /path/to/gpu_temp_monitor.py --wled-ip 192.168.1.100 Restart=always RestartSec=10 [Install] WantedBy=multi-user.target ``` Enable and start: ```bash sudo systemctl enable gpu-fan-monitor sudo systemctl start gpu-fan-monitor ``` ## Temperature Curve The default curve provides quiet operation at low temperatures and aggressive cooling at high temperatures: | Temperature | Fan Speed | |-------------|-----------| | ≤30°C | 30% | | 50°C | 50% | | 70°C | 75% | | ≥85°C | 100% | Speeds between points are linearly interpolated. ## Troubleshooting ### Fan not spinning 1. Check wiring connections 2. Verify the fan is PWM-compatible (4-pin) 3. Check that 12V power supply is adequate 4. Try a different GPIO pin ### Temperature not updating 1. Check the Python script is running 2. Verify ESP32 IP address is correct 3. Check firewall settings 4. Test with: `curl -X POST http://ESP32_IP/json/state -H "Content-Type: application/json" -d '{"GPU-Fan":{"temperature":50}}'` ### Curve not saving 1. Make sure to click "Save" in the curve editor 2. Check the browser console for errors 3. Try refreshing the page and re-saving ### WLED doesn't show the usermod 1. Ensure the build flag `-D USERMOD_GPU_FAN_CONTROLLER` is set 2. Rebuild and re-upload the firmware 3. Check serial output for initialization messages ## Technical Details - **PWM Frequency**: 25kHz (Intel 4-pin fan specification) - **PWM Resolution**: 8-bit (0-255) - **Default GPIO**: 13 (configurable) - **Update Interval**: 2 seconds - **Safety Timeout**: 10 seconds (runs at 100% if no temperature data) - **Max Curve Points**: 5 ## License This usermod is released under the same license as WLED (MIT). ## Credits - WLED project: https://github.com/wled/WLED - PWM fan control techniques adapted from various ESP32 fan controller projects