smart-fans-system
PublicLoading 3D model… large boards can take a moment.
🌀 Smart Fan Controller
服务器智能风扇控制系统
ESP32-S3 powered server fan management — 4-channel PWM, multi-sensor, MQTT, Web dashboard, Home Assistant
🌐 Project Page · 📖 Deploy Guide · 🔧 Hardware Guide · 📡 MQTT Protocol
目录 / Contents
🏗️ 系统架构
┌──────────────────────────────────── 服务器机柜 ─────────────────────────────────────┐
│ │
│ ┌─────────────────────────────┐ USB-CDC ┌──────────────────────────────┐ │
│ │ ESP32-S3-N16R8 (固件) │ ◄──────────────► │ Go Agent (Linux 守护进程) │ │
│ │ │ │ │ │
│ │ 4× 25kHz PWM 风扇控制 │ MQTT │ · nvidia-smi GPU 监控 │ │
│ │ 4× PCNT Tach 转速反馈 │ ◄──────────────► │ · /proc/stat CPU 利用率 │ │
│ │ BME280 温湿度气压 │ │ · /proc/meminfo 内存 │ │
│ │ DS18B20 远程温度探头 │ │ · systemd 服务自启动 │ │
│ │ 12V/5V/3.3V 电源监控 │ └──────────────────────────────┘ │
│ │ WS2812B RGB 状态 LED │ │
│ │ OTA 固件空中升级 │ │
│ └─────────────────────────────┘ │
│ │ SATA 15Pin (12V + 5V) │
└───────────────┼─────────────────────────────────────────────────────────────────────┘
│ WiFi ─── MQTT Broker (Mosquitto)
│ │
┌─────┴──────┐ ┌─────────┼──────────┐ ┌─────────────────────┐
│ Web APP │ │ Home │ │ │ 其他 MQTT 客户端 │
│ React+Node │ │Assistant│ auto-disc│ │ (Node-RED / 脚本) │
└─────┬──────┘ └─────────┴──────────┘ └─────────────────────┘
│ WebSocket 实时推送
└── Dashboard · 风扇控制 · 告警配置 · 历史图表 · 设备管理
✨ 功能特性
| 特性 | 说明 |
|---|---|
| 🌡️ 多传感器温度 | BME280 板载(温湿度气压)+ DS18B20 远程探头 + ESP32 内部温度 + GPU/CPU(Go Agent) |
| 🌀 4路独立风扇 | 25 kHz PWM 精准调速 + PCNT 转速反馈(RPM),停转检测 |
| 📈 双模控制曲线 | 固定查表(LUT)线性插值 + PID 自适应,每路独立配置 |
| ⚡ 电源监控 | 12V / 5V / 3.3V 实时采样,欠压/过压告警,断电保护电容 |
| 🔔 智能告警 | 4类规则(温度/停转/电压/WiFi),三级状态机,2分钟去重,LED+MQTT通知 |
| 🌐 Web 控制台 | React 仪表盘,实时 WebSocket 推送,风扇曲线编辑器,历史趋势图 |
| 🏠 Home Assistant | MQTT Discovery 自动创建实体(11个传感器 + 2路风扇控制 + 4个告警传感器) |
| 🔄 OTA 固件更新 | MQTT / USB-CDC 双触发,3阶段回滚保护(启动/网络/MQTT确认) |
| 🖥️ Go Linux Agent | nvidia-smi GPU 监控 + /proc 系统采集,单二进制,systemd 服务 |
| 🔌 SATA 直取供电 | 服务器 SATA 电源口供电,5V→AMS1117-3.3V LDO,12V 直供风扇 |
🚀 快速开始
前置要求
# ESP-IDF v5.3+(固件编译)
. $IDF_PATH/export.sh
# Go 1.22+(Agent)
go version # go version go1.22 linux/amd64
# Node.js 20+(Web 控制台)
node --version # v20.x.x
# Mosquitto(MQTT Broker)
mosquitto -v # 2.x.x
1 — 烧录固件
cd firmware
idf.py set-target esp32s3
idf.py build
idf.py -p /dev/ttyACM0 flash monitor
# 首次上电后长按配网键(3s),连接 FanCtrl-XXXXXX 热点配网
2 — 部署 Go Agent(Linux 服务器)
cd agent
make build
sudo bash install.sh # 安装到 /usr/local/bin + systemd 服务
# 编辑配置
sudo nano /etc/smart-fan-agent/config.yaml # 填入 MQTT broker 地址和串口路径
sudo systemctl start smart-fan-agent
3 — 启动 Web 控制台
# 后端
cd web/backend && npm install && npm start # http://localhost:3001
# 前端(开发模式)
cd web/frontend && npm install && npm run dev # http://localhost:5173
4 — Home Assistant 集成
# 复制 YAML 配置到 HA 并重启
cp -r ha/ /config/packages/fan-controller/
# HA 自动发现设备,无需手动配置
完整部署说明见 docs/deploy.md
🔧 硬件规格
| 参数 | 规格 |
|---|---|
| 主控 | ESP32-S3-N16R8(16MB Flash + 8MB Octal PSRAM) |
| 供电 | SATA 15Pin(12V + 5V),板载 AMS1117-3.3 LDO |
| 风扇 | 4路 4Pin 25kHz PWM(Intel 规范),SATA 12V 直供 |
| 传感器 | BME280(I2C, GPIO17/18)+ DS18B20(1-Wire, GPIO16, 支持4个) |
| 电平转换 | 74AHCT125(ESP32 3.3V → 5V PWM 信号),Tach 5V→3.3V 分压 |
| LED | WS2812B-2020 RGB(3.3V 供电,GPIO48 RMT,5种状态模式) |
| 按键 | WiFi 配网(GPIO38,长按3s/10s),复位(EN 引脚) |
| 通信 | WiFi 802.11b/g/n + USB-CDC 原生(无需转串口芯片) |
| 保护 | PTC 保险丝 + 肖特基防反接 + TVS ESD + 断电保护电容 |
| PCB | 80mm × 60mm,双层 FR4,嘉立创可打样 |
🔑 关键硬件设计决策
- 12V ADC 分压:
100kΩ + 20kΩ(ADC 输入≤2.0V,防止超出 ESP32-S3 ADC 上限3.1V) - WS2812B 3.3V 供电:3.3V 时 VIH_min=2.31V < ESP32 VOH=3.0V ✅;若5V供电则逻辑电平不足
- 不使用 SATA 3.3V 引脚:改用 5V→LDO 方案,电流裕量更大且无 PWDIS 兼容性问题
💻 软件组件
smart-fans-system/
├── firmware/ # ESP32-S3 固件(ESP-IDF v5.3, C语言)
│ ├── components/ # 13个独立驱动组件
│ │ ├── power_monitor/ # ADC1 电源监控(仅ADC1,避开ADC2/WiFi冲突)
│ │ ├── fan_pwm/ # LEDC 25kHz PWM(LEDC_LOW_SPEED_MODE)
│ │ ├── fan_tach/ # PCNT 转速计(RPM = pulses×60÷2)
│ │ ├── bme280/ # I2C BME280(Bosch 补偿算法,int64_t 防溢出)
│ │ ├── ds18b20/ # OneWire DS18B20(CRC8 + ROM 搜索)
│ │ ├── status_led/ # WS2812B RMT(5种模式:正常/警告/错误/配网/OTA)
│ │ ├── wifi_manager/ # WiFi STA+AP + Captive Portal + 指数退避重连
│ │ ├── mqtt_client/ # MQTT(LWT 遗嘱 + 50条 Flash 离线队列)
│ │ ├── usb_console/ # USB-CDC 串口控制台(6+命令,JSON响应)
│ │ ├── flash_storage/ # NVS配置 + Wear Levelling 循环日志
│ │ ├── fan_curve/ # LUT插值 + PID Anti-windup + 紧急模式(>80°C)
│ │ ├── alert_manager/ # 4类告警规则 + NORMAL/WARNING/CRITICAL状态机
│ │ └── ota_handler/ # esp_https_ota + 3阶段回滚保护
│ └── test/ # 12个 Unity 单元测试
│
├── agent/ # Go Linux Agent
│ ├── internal/monitor/ # GPU(nvidia-smi)+ 系统(/proc)采集器
│ ├── internal/mqtt/ # MQTT 发布/订阅(paho.mqtt.golang)
│ └── internal/usb/ # USB-CDC 串口双向中继
│
├── web/ # Web 控制台
│ ├── backend/ # Express + MQTT + WebSocket(2秒推送)
│ │ └── src/routes/ # 8+端点 + Zod 参数校验
│ └── frontend/ # React + TypeScript + Vite + Recharts
│ ├── pages/ # Dashboard · Fans · Alerts · History · Devices
│ └── components/ # TemperatureGauge · FanCard · VoltageBar · CurveEditor
│
├── ha/ # Home Assistant MQTT Discovery 配置
├── hardware/ # 硬件设计文件(KiCad + Gerber + BOM)
├── test/ # 端到端集成测试 + 冒烟测试脚本
└── docs/ # 部署指南 + 硬件组装指南 + MQTT协议规范
📊 Web 控制台
浏览器访问 http://server-ip:5173(开发)或 nginx 反代后访问。
- Dashboard — 实时温度仪表(RadialBarChart)、风扇 RPM/占空比图表、电压进度条、告警横幅
- Fans — 4路独立调速滑块(AUTO/MANUAL 切换)、LUT 曲线可视化编辑、PID 参数面板
- Alerts — 4类告警规则开关+阈值配置、告警历史时间线(最近100条)
- History — 温度/转速趋势图(Recharts LineChart)、时间范围选择(1h/6h/24h/7d)、CSV 导出
- Devices — 在线状态监控、OTA 固件更新触发、设备重启(二次确认)
🏠 Home Assistant 集成
设备上电后约30秒,HA 通过 MQTT Discovery 自动识别并创建:
| 实体类型 | 数量 | 说明 |
|---|---|---|
| 传感器(Sensor) | 11 | 温度×4 + 湿度 + 气压 + 电压×3 + 风扇RPM×4 |
| 风扇(Fan) | 2 | 0~100% 调速控制(command_topic 指令) |
| 二进制传感器 | 4 | 温度告警 / 停转告警 / 电压异常 / 设备在线 |
无需自定义集成,标准 MQTT Discovery 协议,兼容所有支持该协议的自动化平台。
🛠️ 开发指南
ESP-IDF 已知陷阱(来自实战踩坑)
| # | 陷阱 | 正确做法 |
|---|---|---|
| 1 | esp_timer_get_time() 用 uint32_t 接收 | 必须 int64_t,72分钟后溢出 |
| 2 | SNTP 在 WIFI_EVENT_STA_CONNECTED 启动 | 必须在 IP_EVENT_STA_GOT_IP 启动 |
| 3 | esp_mqtt_client_start() 在WiFi事件处理器中 | 用 FreeRTOS Timer 延迟调用 |
| 4 | sscanf 解析 JSON | 始终用 cJSON 库 |
| 5 | vTaskDelay 在事件处理器内 | 改用 esp_rom_delay_us() |
| 6 | LEDC 硬件渐变 + WiFi 并发 | 手动步进(独立任务),不用 ledc_set_fade_with_time() |
运行单元测试
cd firmware && idf.py build && idf.py -p /dev/ttyACM0 flash test
cd agent && go test ./... -v
cd web && npm test
运行冒烟测试
chmod +x test/smoke_test.sh
./test/smoke_test.sh <mqtt_host> <api_host>
# 预期输出: PASS=12 FAIL=0
📄 许可证
MIT License — 自由使用、修改和分发。
本项目为个人 DIY 项目,不提供任何形式的商业支持或质量保证。
Made with ❤️ for homelab enthusiasts · ⭐ Star on GitHub
Ask about this board
No comments yet. Be the first to ask about this board.