<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[用 ESP32 给笔记本做了套蓝牙温控风扇：温度自己上报，转速自己调]]></title><description><![CDATA[<blockquote>
<p dir="auto"><span class="w10-text-size" style="--w10-text-size:20px"><span class="w10-text-color" style="--w10-text-color:#c0392b">给笔记本做了一套 ESP32 蓝牙温控风扇：电脑自己上报温度，风扇自己调速，不用的时候自动停下来。</span></span></p>
</blockquote>
<p dir="auto">折腾这个主要是嫌原来的散热底座太吵 —— 不管电脑烫不烫，扇子从头转到尾。改成 ESP32 控速之后，轻载时基本听不见声音，跑重活才拉起来。</p>
<h2><span class="w10-text-color" style="--w10-text-color:#b7791f"><img src="https://wlite.cn/assets/plugins/nodebb-plugin-emoji/emoji/android/1f3ac.png?v=2a372b6da06" class="not-responsive emoji emoji-android emoji--clapper" style="height:23px;width:auto;vertical-align:middle" title="🎬" alt="🎬" /> 实际使用演示</span></h2>
<p dir="auto"></p><div class="w10-video-embed"><iframe src="//player.bilibili.com/player.html?bvid=BV1ocZZY6EN4&amp;autoplay=0&amp;danmaku=0" frameborder="no"></iframe></div><p></p>
<hr />
<h2><span class="w10-text-color" style="--w10-text-color:#b7791f"><img src="https://wlite.cn/assets/plugins/nodebb-plugin-emoji/emoji/android/1f5bc.png?v=2a372b6da06" class="not-responsive emoji emoji-android emoji--frame_with_picture" style="height:23px;width:auto;vertical-align:middle" title="🖼" alt="🖼" />️ 效果预览</span></h2>
<p dir="auto"><img src="https://wlite.cn/assets/uploads/esp32-fan-poster.png" alt="ESP32智能温控风扇" class=" img-fluid img-markdown" /></p>
<p dir="auto">整体就是一台压风式散热器 + 一块 ESP32 控制板。PC 上的小工具读取 CPU / GPU 温度，通过蓝牙发过来，板子按温度调风扇转速，OLED 上实时显示两路温度和当前转速。</p>
<hr />
<h2><span class="w10-text-color" style="--w10-text-color:#b7791f"><img src="https://wlite.cn/assets/plugins/nodebb-plugin-emoji/emoji/android/1f4d0.png?v=2a372b6da06" class="not-responsive emoji emoji-android emoji--triangular_ruler" style="height:23px;width:auto;vertical-align:middle" title="📐" alt="📐" /> 系统组成</span></h2>
<p dir="auto"><img src="https://wlite.cn/assets/uploads/esp32-fan-arch-final.png" alt="系统架构" class=" img-fluid img-markdown" /></p>
<p dir="auto">整套分三段：</p>
<ul>
<li><span class="w10-text-color" style="--w10-text-color:#1f6fb2"><strong>PC 端</strong></span> — Windows 上的常驻小工具，读温度、发数据</li>
<li><span class="w10-text-color" style="--w10-text-color:#1f6fb2"><strong>ESP32 端</strong></span> — 接收温度、算转速、驱动风扇、刷新屏幕</li>
<li><span class="w10-text-color" style="--w10-text-color:#1f6fb2"><strong>执行部分</strong></span> — MOSFET 驱动电路 + PWM 风扇</li>
</ul>
<p dir="auto">通信走蓝牙串口，数据是纯文本格式，一行一条：</p>
<pre><code>CPU52.3
GPU47.8
</code></pre>
<p dir="auto">板子收到合法数据会回一个 <code>ACK</code>。这个确认很重要 —— 蓝牙串口经常出现「端口能打开、数据也能写进去，但对端根本没反应」的假连接，有没有 <code>ACK</code> 是判断链路真假的唯一依据。</p>
<hr />
<h2><span class="w10-text-color" style="--w10-text-color:#b7791f"><img src="https://wlite.cn/assets/plugins/nodebb-plugin-emoji/emoji/android/2699.png?v=2a372b6da06" class="not-responsive emoji emoji-android emoji--gear" style="height:23px;width:auto;vertical-align:middle" title="⚙" alt="⚙" />️ 它是怎么工作的</span></h2>
<p dir="auto"><img src="https://wlite.cn/assets/uploads/esp32-fan-flow-final.png" alt="工作流程" class=" img-fluid img-markdown" /></p>
<p dir="auto">从温度到转速的完整链路：</p>
<ol>
<li>PC 端读取 CPU 和 GPU 温度，各取自身最高的传感器读数</li>
<li>每 2 秒通过蓝牙发送一次</li>
<li>ESP32 校验格式和取值范围，通过后回 <code>ACK</code></li>
<li>取两路温度里<strong>较高</strong>的那个，查温度曲线得到目标转速</li>
<li>按限速规则平滑逼近目标，输出 PWM</li>
<li>屏幕同步刷新</li>
</ol>
<p dir="auto">温度到转速的对应关系是条连续曲线，中间做线性插值：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>温度</th>
<th>55°C</th>
<th>60°C</th>
<th>65°C</th>
<th>70°C</th>
<th>75°C</th>
<th>80°C</th>
</tr>
</thead>
<tbody>
<tr>
<td>转速</td>
<td>16%</td>
<td>23%</td>
<td>31%</td>
<td>40%</td>
<td>75%</td>
<td>100%</td>
</tr>
</tbody>
</table>
<p dir="auto">70°C 以下走得很平缓，日常办公基本在 20%~30% 之间，几乎听不见；75°C 开始往上拉，80°C 直接满速。曲线陡的那段留给真正需要散热的时候。</p>
<p dir="auto">转速变化有限速：<strong>升速每秒最多 10%，降速每秒最多 3%</strong>。降速比升速慢是刻意的 —— 温度刚掉一点就把风撤掉，容易来回震荡，听感上就是风扇忽快忽慢。</p>
<hr />
<h2><span class="w10-text-color" style="--w10-text-color:#b7791f"><img src="https://wlite.cn/assets/plugins/nodebb-plugin-emoji/emoji/android/1f5a5.png?v=2a372b6da06" class="not-responsive emoji emoji-android emoji--desktop_computer" style="height:23px;width:auto;vertical-align:middle" title="🖥" alt="🖥" />️ PC 端做了什么</span></h2>
<p dir="auto">上位机是个 Python 小工具，打包成单文件，常驻系统托盘。</p>
<p dir="auto"><span class="w10-text-color" style="--w10-text-color:#7a7a7a">温度读取</span></p>
<p dir="auto">调用 OpenHardwareMonitor 读取硬件传感器。CPU 上通常有好几个温度点（核心、封装、主板），取最高的那个更保险，避免低估了真正的热点。GPU 则同时兼容 NVIDIA / AMD / Intel 三家。读数超出 0~120°C 范围的一律丢掉，防止传感器抖动把异常值传下去。</p>
<p dir="auto"><span class="w10-text-color" style="--w10-text-color:#7a7a7a">找串口</span></p>
<p dir="auto">不会死等某一个固定的 COM 口。优先用配置里指定的，找不到就按设备特征匹配，再找不到就扫所有带蓝牙字样的串口，最后兜底遍历全部可用端口。</p>
<p dir="auto">打不开、写超时，或者连上了但收不到 <code>ACK</code>，都会把这个口标记成「坏的」，<strong>冷却 30 秒以上再跳过</strong>，去试下一个。有意思的是，一旦某个口回了 <code>ACK</code>，它的冷却标记会立刻解除 —— 说明它其实是好的，先前的失败可能只是暂时的。</p>
<p dir="auto"><span class="w10-text-color" style="--w10-text-color:#7a7a7a">休眠唤醒后自动恢复</span></p>
<p dir="auto">电脑睡一觉醒来，蓝牙串口的状态其实是坏的 —— 端口句柄还在，底层链路已经断了。程序靠循环间隔判断这件事：<strong>间隔超过 8 秒就认为刚从休眠恢复</strong>，于是主动断开重连、重新初始化硬件监控，最长给 20 秒的恢复时间。</p>
<p dir="auto"><span class="w10-text-color" style="--w10-text-color:#7a7a7a">开机自启</span></p>
<p dir="auto">首次运行会自动写开机启动项，<strong>不需要管理员权限</strong>。程序换目录了会自动更新路径；发现别处有指向自己的重复启动项也会顺手清掉。用源码方式跑的时候不动启动项，避免把开发机搞乱。</p>
<p dir="auto"><span class="w10-text-color" style="--w10-text-color:#7a7a7a">托盘图标</span></p>
<p dir="auto">托盘图标本身就是一张实时温度曲线 —— 最近 30 个点连成的折线，按温度区间变色（低是绿色、中间橙色、高了红色），下面还标着 CPU 和 GPU 的整数温度。<strong>不用点开窗口，瞄一眼托盘就知道风扇跟没跟上。</strong></p>
<hr />
<h2><span class="w10-text-color" style="--w10-text-color:#b7791f"><img src="https://wlite.cn/assets/plugins/nodebb-plugin-emoji/emoji/android/1f50c.png?v=2a372b6da06" class="not-responsive emoji emoji-android emoji--electric_plug" style="height:23px;width:auto;vertical-align:middle" title="🔌" alt="🔌" /> ESP32 端做了什么</span></h2>
<p dir="auto">固件只做温控这一件事 —— 按键、手动模式、自定义曲线全部去掉了。目标是装好之后就不用再碰它。</p>
<p dir="auto"><span class="w10-text-color" style="--w10-text-color:#7a7a7a">数据校验</span></p>
<p dir="auto">每一行都严格检查：前缀必须是 <code>CPU</code> 或 <code>GPU</code>、数值要能完整解析、数字后面不能拖多余字符、必须在 0~120°C 之间。任何一项不过关，整行丢掉，等下一帧。</p>
<p dir="auto">蓝牙是流式传输，一帧可能被拆成几段到达。固件只认完整的换行符；如果缓冲区里有半截数据、超过 1 秒没等到后续，就把这半截丢掉重来 —— 不会把两次会话的数据拼在一起，也不会因为一个半包把接收卡死。</p>
<p dir="auto"><span class="w10-text-color" style="--w10-text-color:#7a7a7a">两路温度分开计时</span></p>
<p dir="auto">CPU 和 GPU 各自独立计时，<strong>超过 12 秒没更新就判定这一路失效</strong>。这么做是因为有些平台的独显在休眠时会停报温度 —— 如果两路共用一个超时，CPU 明明正常也会被 GPU 拖累成「失效」，把风扇误停了。分开之后，GPU 掉线不影响 CPU 继续控温。</p>
<p dir="auto"><span class="w10-text-color" style="--w10-text-color:#7a7a7a">平滑调速</span></p>
<p dir="auto">目标转速不会一步到位，而是每 100ms 往目标靠一点，配合前面说的升降速限制。温差超过 80°C 时例外 —— <strong>直接满速，不讲平滑，先压温度</strong>。</p>
<p dir="auto">另外风扇冷启动时先用 30% 转 1 秒再进入曲线，因为有些风扇占空比太低根本起转。</p>
<p dir="auto"><span class="w10-text-color" style="--w10-text-color:#7a7a7a">自动休眠</span></p>
<p dir="auto">这是我最想要的一个功能。判断分两层：</p>
<ul>
<li><strong>蓝牙客户端消失</strong> —— 电脑关机、断连、走远了，风扇立刻停</li>
<li><strong>数据超时</strong> —— 连接还在但 12 秒没数据，同样停</li>
</ul>
<p dir="auto">风扇是<strong>立刻停</strong>的，屏幕则要显示一个 <strong>3、2、1</strong> 的倒计时再关。多亮这 3 秒是有用的：能让人看明白设备是「因为没数据才停的」，而不是以为它死机了。倒计时只在一次有效通信结束时触发一次，不会反复闪。</p>
<p dir="auto"><span class="w10-text-color" style="--w10-text-color:#7a7a7a">蓝牙自动重连</span></p>
<p dir="auto">蓝牙偶发假死时，固件有一次有限度的自恢复：只在<strong>曾经通过信、且连续 60 秒收不到数据</strong>时触发，重启一次蓝牙协议栈然后等电脑自己连回来。</p>
<p dir="auto">这里有个我踩过的坑 —— 早期版本掉线后会反复重启蓝牙，结果电脑正常休眠（本来就是该断开）时，风扇端却在不停重启、反复广播。<strong>现在的策略是「断开了就安静等着」</strong>，电脑醒了会自己连回来，设备不需要做多余动作。一个通信周期内只恢复一次。</p>
<p dir="auto"><span class="w10-text-color" style="--w10-text-color:#7a7a7a">残留数据清理</span></p>
<p dir="auto">这个是解决一个很具体的故障：<strong>快速重连的时候，新连接可能读到上一次会话的残留数据</strong>，导致风扇按错误的旧温度跑。</p>
<p dir="auto">现在每次检测到断开（包括断开恰好发生在快速重连期间的情况），都会清掉两路温度的有效标志、清空接收缓冲、把蓝牙缓存里剩的字节一次性读空。之后只接受<strong>新到达</strong>的帧。</p>
<p dir="auto"><span class="w10-text-color" style="--w10-text-color:#7a7a7a">OLED 显示</span></p>
<p dir="auto">128×64 的屏幕，左右两栏大字显示 CPU 和 GPU 温度，底下一行是连接状态（<code>CON</code>）、当前转速（<code>SPEED xx%</code>）和模式（<code>QUIET</code>）。屏幕刷新 200ms，温度无效时显示 <code>--</code>。</p>
<p dir="auto">顺带一提，<strong>OLED 初始化失败的话温控照常跑</strong> —— 显示只是附属功能，不该影响散热。</p>
<hr />
<h2><span class="w10-text-color" style="--w10-text-color:#b7791f"><img src="https://wlite.cn/assets/plugins/nodebb-plugin-emoji/emoji/android/1f527.png?v=2a372b6da06" class="not-responsive emoji emoji-android emoji--wrench" style="height:23px;width:auto;vertical-align:middle" title="🔧" alt="🔧" /> 硬件接线</span></h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>ESP32 引脚</th>
<th>接到哪</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>GPIO 5</code></td>
<td>风扇 MOS 管栅极（PWM 信号）</td>
</tr>
<tr>
<td><code>5V</code></td>
<td>OLED VCC</td>
</tr>
<tr>
<td><code>GND</code></td>
<td>共地</td>
</tr>
<tr>
<td><code>GPIO 21</code></td>
<td>OLED SDA</td>
</tr>
<tr>
<td><code>GPIO 22</code></td>
<td>OLED SCL</td>
</tr>
</tbody>
</table>
<p dir="auto">PWM 频率用 15kHz，超出人耳敏感范围，能少一点驱动噪声。</p>
<p dir="auto"><span class="w10-text-color" style="--w10-text-color:#c0392b"><strong>风扇一定要经过 MOSFET 驱动</strong></span>，GPIO 只能出毫安级的信号，直接带不动风扇。另外 ESP32 和风扇电源必须共地。</p>
<hr />
<h2><span class="w10-text-color" style="--w10-text-color:#b7791f"><img src="https://wlite.cn/assets/plugins/nodebb-plugin-emoji/emoji/android/1f4dd.png?v=2a372b6da06" class="not-responsive emoji emoji-android emoji--memo" style="height:23px;width:auto;vertical-align:middle" title="📝" alt="📝" /> 更新记录</span></h2>
<p dir="auto"></p><div class="w10-collapse" data-w10-collapse><div class="w10-collapse-heading" data-w10-collapse-toggle tabindex="0" aria-expanded="false"><span>2026.09.11 首次发布</span></div><div class="w10-collapse-content"><p></p>
<ul>
<li>ESP32 固件：保留 Quiet 自动温控，移除按键与手动模式</li>
<li>新增自动休眠：无连接 / 无数据自动停风扇、关屏</li>
<li>新增蓝牙自动连接：断线后单次恢复，不周期性重启</li>
<li>新增残留数据清理：断开即清，只接收新帧</li>
<li>上位机：Python 重写，托盘常驻 + 实时温度曲线</li>
<li>温控曲线：七锚点连续插值，80°C 满速<br />
</li></ul></div></div>

<hr />
<h2><span class="w10-text-color" style="--w10-text-color:#b7791f"><img src="https://wlite.cn/assets/plugins/nodebb-plugin-emoji/emoji/android/2b07.png?v=2a372b6da06" class="not-responsive emoji emoji-android emoji--arrow_down" style="height:23px;width:auto;vertical-align:middle" title="⬇" alt="⬇" />️ 项目地址</span></h2>
<blockquote>
<p dir="auto"><span class="w10-text-size" style="--w10-text-size:20px"><span class="w10-text-color" style="--w10-text-color:#c0392b">完整源码与可执行文件都在仓库里</span></span></p>
</blockquote>
<p dir="auto"><a href="https://github.com/gukey/ESP32-CPU-FAN" rel="nofollow ugc">https://github.com/gukey/ESP32-CPU-FAN</a></p>
<p dir="auto">仓库里有完整的 ESP32 固件源码、PC 端源码、编译好的可执行文件、依赖 DLL，以及测试代码。想自己改的话直接拿源码改就行。</p>
<p dir="auto">刷写教程和接线细节仓库里都有说明，硬件部分照着接就行。</p>
<hr />
<h2><span class="w10-text-color" style="--w10-text-color:#b7791f"><img src="https://wlite.cn/assets/plugins/nodebb-plugin-emoji/emoji/android/26a0.png?v=2a372b6da06" class="not-responsive emoji emoji-android emoji--warning" style="height:23px;width:auto;vertical-align:middle" title="⚠" alt="⚠" />️ 注意事项</span></h2>
<ul>
<li><span class="w10-text-color" style="--w10-text-color:#c0392b"><strong>刷固件时一定要先断开散热器的 12V 电源线</strong></span>。USB 的 5V 和 12V 同时接上会冲突，可能烧电脑 USB 控制器甚至烧板子。</li>
<li>上位机是没签名的程序，Windows 或杀毒软件可能报警。介意的话可以先看源码再运行。</li>
<li>温度数据来自硬件传感器，受驱动和主板差异影响可能有偏差。<strong>这只是散热辅助，不能替代主板自身的过热保护。</strong></li>
<li>风扇的最低起动占空比各不相同，如果 30% 转不起来，需要在源码里把这个值调高重新烧录。</li>
</ul>
<hr />
<h2><span class="w10-text-color" style="--w10-text-color:#b7791f"><img src="https://wlite.cn/assets/plugins/nodebb-plugin-emoji/emoji/android/1f64f.png?v=2a372b6da06" class="not-responsive emoji emoji-android emoji--pray" style="height:23px;width:auto;vertical-align:middle" title="🙏" alt="🙏" /> 关于来源</span></h2>
<p dir="auto">这套东西的原始方案来自 <span class="w10-text-color" style="--w10-text-color:#1f6fb2"><strong>究物研社</strong></span> —— 压风式散热器的思路、风扇电路模块都是他们做的。ESP32 温控部分是 <span class="w10-text-color" style="--w10-text-color:#1f6fb2"><strong>DALIAN213</strong></span> 的方案。</p>
<p dir="auto">我这个版本是在他们的基础上继续改的，主要补充了自动休眠、蓝牙自动连接和残留数据清理这几块。借这个机会谢谢两位。</p>
<p dir="auto">原作者方案说明：<a href="https://www.bilibili.com/video/BV1Lr421M7u2" rel="nofollow ugc">https://www.bilibili.com/video/BV1Lr421M7u2</a></p>
]]></description><link>https://wlite.cn/topic/471/用-esp32-给笔记本做了套蓝牙温控风扇-温度自己上报-转速自己调</link><generator>RSS for Node</generator><lastBuildDate>Thu, 17 Sep 2026 03:22:06 GMT</lastBuildDate><atom:link href="https://wlite.cn/topic/471.rss" rel="self" type="application/rss+xml"/><pubDate>Fri, 11 Sep 2026 07:12:20 GMT</pubDate><ttl>60</ttl></channel></rss>