# Maxxfan Smart Controller A WiFi-enabled smart controller for the Maxxfan Deluxe 6401K using ESP32 and BTS7960 motor driver. Transform your manual RV fan into a remotely controllable smart device with variable speed control, bidirectional operation, and smooth motor ramping. ## 🌟 Features - **WiFi Remote Control** - Control your fan from anywhere on your network - **Variable Speed Control** - 0-100% speed adjustment via web interface - **Bidirectional Operation** - Switch between exhaust and intake modes - **Smooth Motor Ramping** - Gradual speed changes prevent mechanical stress - **Real-time Status** - Live updates of fan mode, current speed, and target speed - **Ramping Visualization** - See when speed changes are in progress - **Mobile-Friendly Interface** - Responsive web design works on phones and tablets - **Enhanced Error Handling** - Visual connection status and error messages - **CORS Support** - Cross-origin requests properly handled - **Compact Design** - Optimized for ESP32 memory constraints - **Connection Status** - Shows "Connected", "Connecting", or "Error" status - **REST API** - Enhanced JSON API for integration with home automation systems - **Watchdog Protection** - Automatic system recovery from crashes - **Homebridge Compatible** - Easy integration with HomeKit ## 🔧 Hardware Requirements ### Main Components - **ESP32 Development Board** (tested with SparkFun ESP32 Thing Plus) - **BTS7960 Motor Driver Module** (43A high-power motor driver) - **Maxxfan Deluxe 6401K** (or compatible 12V DC fan) - **12V Power Supply** (adequate for your fan's current draw) ### Wiring Connections ``` ESP32 GPIO → BTS7960 Pin GPIO 18 → R_EN (Right Enable) GPIO 19 → L_EN (Left Enable) GPIO 21 → R_PWM (Right PWM) GPIO 22 → L_PWM (Left PWM) GPIO 13 → LED (Status Indicator) 3.3V → VCC (Logic Power) GND → GND BTS7960 → Fan Motor B+ → Fan Positive B- → Fan Negative Power Supply 12V → BTS7960 Motor Power + Fan Power Input GND → Common Ground ``` ## 🚀 Quick Start ### Prerequisites - Docker installed on Ubuntu (recommended) or Mac - ESP32 connected via USB - WiFi network credentials ### 1. Set Up Development Environment ```bash # Create project directory mkdir ~/maxxfan-controller cd ~/maxxfan-controller # Pull official ESP-IDF Docker image (v5.x recommended) docker pull espressif/idf:latest # Create new ESP-IDF project docker run --rm -v $PWD:/project -w /project -it espressif/idf:latest idf.py create-project maxxfan-controller exit ``` ### 2. Configure WiFi Credentials Edit the WiFi credentials in `main/maxxfan-controller.c`: ```c #define WIFI_SSID "YOUR_WIFI_NAME" #define WIFI_PASS "YOUR_WIFI_PASSWORD" ``` ### 3. Build and Flash ```bash cd maxxfan-controller # Build docker run --rm -v $PWD:/project -w /project -it espressif/idf:latest idf.py build # Flash (replace /dev/ttyUSB0 with your device) docker run --rm -v $PWD:/project -w /project --device=/dev/ttyUSB0 -it espressif/idf:latest idf.py flash -p /dev/ttyUSB0 # Monitor serial output docker run --rm -v $PWD:/project -w /project --device=/dev/ttyUSB0 -it espressif/idf:latest idf.py monitor -p /dev/ttyUSB0 ``` ### 4. Access Web Interface 1. Note the IP address from serial monitor output: ``` I (xxx) HTTP_MOTOR: got ip:192.168.1.123 ``` 2. Open your browser and navigate to: `http://192.168.1.123` ## 🌐 Enhanced Web Interface The improved web interface provides: - **Real-time Status Display** - Current fan mode, speed, and target speed - **Ramping Indicator** - Visual feedback when speed changes are in progress - **Quick Controls** - One-click buttons for common operations - **Speed Slider** - Precise speed adjustment (0-100%) - **Real-time Updates** - Status refreshes every 1 second for live ramping visualization - **Error Handling** - Visual connection status and network error feedback - **Persistent State** - Settings maintained across page reloads - **Memory Optimized** - Compact HTML (~2KB) ensures reliable loading ### Controls Available - **Turn OFF** - Stops the fan completely - **Exhaust (50%)** - Sets exhaust mode at 50% speed with smooth ramping - **Intake (50%)** - Sets intake mode at 50% speed with smooth ramping - **Custom Speed** - Use slider + "Set Exhaust/Intake Speed" buttons ### Motor Ramping Features - **Smooth Startup** - Motors start at minimum speed (10%) then ramp to target - **Gradual Changes** - Speed changes in 5% increments every 50ms - **Direction Changes** - Proper sequencing prevents mechanical stress - **Visual Feedback** - Ramping indicator shows when changes are in progress ## 📡 Enhanced REST API ### Get Status ```bash GET /status ``` Enhanced Response: ```json { "mode": "exhaust", "current_speed": 65, "target_speed": 80, "ramping": true } ``` ### Control Fan ```bash POST /fan Content-Type: application/json { "mode": "exhaust", // "off", "exhaust", or "intake" "speed": 75 // 0-100 } ``` ### Example cURL Commands ```bash # Turn fan off (immediate stop) curl -X POST http://192.168.1.123/fan -H "Content-Type: application/json" -d '{"mode":"off","speed":0}' # Set exhaust mode at 80% (with ramping) curl -X POST http://192.168.1.123/fan -H "Content-Type: application/json" -d '{"mode":"exhaust","speed":80}' # Set intake mode at 60% (with ramping) curl -X POST http://192.168.1.123/fan -H "Content-Type: application/json" -d '{"mode":"intake","speed":60}' # Get current status (includes ramping state) curl http://192.168.1.123/status ``` ## 🏠 Homebridge Integration Add to your Homebridge `config.json`: ```json { "accessories": [ { "accessory": "HTTP-FAN", "name": "Maxxfan", "getUrl": "http://192.168.1.123/status", "setUrl": "http://192.168.1.123/fan", "on": { "setOn": "http://192.168.1.123/fan", "setOff": "http://192.168.1.123/fan" }, "speed": { "setSpeed": "http://192.168.1.123/fan" } }, { "accessory": "HTTP-SWITCH", "name": "Maxxfan Direction", "getUrl": "http://192.168.1.123/status", "setUrl": "http://192.168.1.123/fan", "mapOn": "intake", "mapOff": "exhaust" } ] } ``` Requires: `npm install -g homebridge-http-accessory` ## 🔧 Technical Details ### Enhanced Motor Control Logic The BTS7960 is a dual H-bridge motor driver with improved control sequencing: - **Exhaust Mode**: R_EN=HIGH, L_EN=LOW, PWM on R_PWM pin - **Intake Mode**: R_EN=LOW, L_EN=HIGH, PWM on L_PWM pin - **Off Mode**: Both enables LOW, PWM stopped - **Ramping**: Gradual speed changes using FreeRTOS timers ### Motor Ramping Configuration ```c #define RAMP_STEP_MS 50 // Time between ramp steps (50ms) #define RAMP_STEP_SIZE 5 // PWM duty change per step (~2% speed) #define MIN_MOTOR_SPEED 10 // Minimum speed to overcome inertia ``` ### PWM Configuration - **Frequency**: 1kHz (optimal for motor control) - **Resolution**: 8-bit (256 levels of speed control) - **Speed Range**: 0-100% mapped to 0-255 PWM duty cycle ### Memory Optimization The web interface HTML has been optimized to ~2KB (down from ~8KB) to ensure: - Complete page loading without truncation - Reliable JavaScript execution - Proper function definitions and event handling - Stable operation on ESP32's limited memory ### Safety & Reliability Features - **Watchdog Timer**: Automatic system recovery from crashes - **Enable Sequencing**: Enable pins activated before PWM signals - **Direction Switching**: Proper delays prevent shoot-through current - **Error Handling**: Robust JSON parsing and HTTP error responses - **CORS Headers**: Cross-origin support for web integrations - **Compact HTML**: Optimized web interface for ESP32 memory constraints - **Real-time Updates**: 1-second polling for live status updates - **Visual Feedback**: Connection status and ramping progress indicators ## 🛠️ Development ### Project Structure ``` maxxfan-controller/ ├── main/ │ ├── maxxfan-controller.c # Enhanced application code │ └── CMakeLists.txt # Build configuration ├── CMakeLists.txt # Project configuration └── sdkconfig # ESP-IDF configuration ``` ### Key Components - **GPIO Control**: Direct hardware pin management - **LEDC PWM**: Hardware PWM generation for speed control - **FreeRTOS Timers**: Motor ramping control - **Task Watchdog**: System reliability monitoring - **WiFi Station**: Connect to existing network - **HTTP Server**: Built-in ESP-IDF web server with CORS support - **JSON Parsing**: cJSON library for enhanced API requests ### Building from Source The project uses ESP-IDF v5.x with these main dependencies: - `driver/gpio.h` - GPIO control - `driver/ledc.h` - PWM generation - `esp_http_server.h` - Web server - `esp_task_wdt.h` - Watchdog timer - `freertos/timers.h` - Motor ramping timers - `cJSON.h` - JSON parsing - `esp_wifi.h` - WiFi connectivity ## 📋 Troubleshooting ### Common Boot Messages (Normal) ``` W (501) spi_flash: Detected size(16384k) larger than the size in the binary image header(2048k) ``` This warning is normal - your ESP32 has more flash than the project uses. ### WiFi Connection Issues - Verify SSID and password in code - Check 2.4GHz network (ESP32 doesn't support 5GHz) - Monitor serial output for connection status ### Motor Not Responding - Check all wiring connections - Verify 12V power supply to BTS7960 - Ensure common ground between ESP32 and motor circuit - Test with multimeter on enable pins (should show 3.3V when active) - Check for ramping messages in serial output ### Web Interface Issues - Confirm IP address from serial monitor - Check browser developer console (F12) for JavaScript errors - Look for CORS or network errors - Try different browser or incognito mode ### JavaScript Console Errors If you see "Unexpected end of script" or "Can't find variable" errors: - These indicate HTML truncation due to memory constraints - The current compact HTML should resolve these issues - Check browser developer console (F12) for specific errors - Verify complete page load by viewing page source - If errors persist, try clearing browser cache and refreshing ### Connection Status Issues If the web interface shows "Connection Error": - Check that ESP32 is connected to WiFi (serial monitor should show IP) - Verify you're accessing the correct IP address - Check that both devices are on the same network - Try accessing `/status` endpoint directly: `http://[ESP32_IP]/status` - Look for CORS-related errors in browser console ### Watchdog Timer Messages If you see watchdog errors, check: - Main loop is running (should see periodic status updates) - No infinite loops in code - Adequate task stack sizes ### Serial Port Issues (Ubuntu) ```bash # Add user to dialout group sudo usermod -a -G dialout $USER # Check available ports ls /dev/tty* | grep -E "(USB|ACM)" # Fix permissions if needed sudo chmod 666 /dev/ttyUSB0 ``` ### Flash Size Warning Fix (Optional) To use full 16MB flash and eliminate warning: ```bash idf.py menuconfig # Navigate to: Serial flasher config → Flash size → 16MB ``` ## 🔒 Security Considerations ### Current Implementation - **Open Access**: No authentication required - **Local Network Only**: Not accessible from internet - **HTTP Only**: Unencrypted communication - **CORS Enabled**: Allows cross-origin requests ### Recommended Improvements for Production - **Network Isolation**: Use dedicated IoT VLAN - **Basic Authentication**: Add username/password protection - **HTTPS**: Enable SSL/TLS encryption - **Firewall Rules**: Restrict access to specific devices ## 📄 License This project is open source. Use at your own risk. Always follow electrical safety practices when working with 12V systems. ## 🤝 Contributing Feel free to submit issues, feature requests, or pull requests to improve this project. ## ⚠️ Disclaimer This project involves working with electrical systems and motor control. Always: - Follow proper electrical safety practices - Use appropriate fuses and circuit protection - Test thoroughly before permanent installation - Ensure adequate ventilation and mounting - Check local electrical codes and regulations The authors are not responsible for any damage or injury resulting from the use of this project.