不用风杯的DIY热式风速计:原理、电路、3D打印与标定全解析
玩风速计这个念头最早是因为我在楼顶搭了个小型气象观测点。成品三杯风速计不是买不起是真的用着闹心轴承转个半年就开始卡顿低风速时风杯纹丝不动阵风来了又因为惯性冲过头。后来我干脆拆了成品开始自己折腾一台“不走寻常路”的家用风速计——不装风杯、不要转轴、没有螺旋桨全机唯一的活动部件是空气本身。这篇文章就从头到尾拆解一下我是怎么做出来的从原理选型、电路设计、3D打印结构到家庭条件下的校准和数据换算。整个过程预算控制在50元以内适合玩单片机、做气象站、或者单纯对传感器原理好奇的朋友参考。我走的路线是“热式风速测量”说白了就是利用气流带走热量的特性来反推风速。这类方案在工业级的热线风速仪里已经用了几十年但家用DIY的案例不多网上能找到的资料要么是理论推导一长串要么就是“照着焊就完了”没有解释为什么。这篇文章会把原理、电路、代码、结构、标定整个链条串起来把我踩过的坑也一并摊开希望能给想动手的朋友省点时间。1. 为什么要做一台“不循规蹈矩”的风速计1.1 传统风杯风速计的痛点风杯式风速计的物理原理很简单风杯在风压下转动转速和风速成正比再用磁铁或光电编码器把转速变成脉冲信号。机械结构看着皮实但实际用在家里有几个绕不开的问题。首先是启动风速。风杯和转轴之间总有静摩擦风速低于某个临界值时风杯根本不动。我手头那台成品风速计的标称启动风速是0.5m/s听着不高可我家楼顶平时最常出现的就是0.2到1m/s的微风等于大半时间内它都在“装死”。其次是轴承磨损风杯长期暴露在户外灰尘和水汽进入轴承之后阻力会越来越大读数就会越来越不可信。最后是响应速度风杯的转动惯量决定了它跟不上阵风的快速变化拿它测“瞬时风速”基本是在看一个低通滤波后的平均值。对比之下热式风速计没有任何机械运动部件没有启动阻力的问题低风速下灵敏度反而最高。一个玻璃封装的负温度系数热敏电阻NTC也就两三块钱响应速度还比机械结构快一个量级。对我来说这就是“非传统”方案最实在的理由。1.2 家用场景真正需要什么家庭气象观测和气象站的专业测量诉求差别很大。专业站点要的是全风速段的精度从0.1m/s的微风到30m/s以上的台风都要求误差可控。但家用场景通常只关心两个问题今天风大不大以及瞬间有没有阵风。这意味着测量重点应该放在0.2到10m/s这个区间。这个区间恰好是传统机械风速计的低灵敏度区却是热式风速计的“主场”。另外家用设备还要考虑免维护、无噪音、体积小。我不希望楼顶挂一个张牙舞爪的机械装置更不想隔几个月就爬上去换轴承。热式方案只需要一根竖直的管子加上一小块电路做完之后扔在角落几年不用管。还有一点是DIY的容错率。风杯风速计的机械加工精度直接决定测量质量而热式方案的核心是电子和控制逻辑精度更多靠标定来解决。对没有精密机床的家庭作坊来说电子方案的复现门槛显然更低。2. 方案选型为什么不选超声波、差压和机械式2.1 几种“正确但昂贵”的选项做风速测量有超声波时差法、皮托管差压法、机械风杯法、热式法四条路。我一开始也纠结过要不要上超声波毕竟无活动部件、精度高、还能测风向听起来是终极方案。但一对超声波收发探头的价格就能劝退大多数DIY玩家而且超声波测风需要精确测量微秒级的飞行时间差电路复杂度完全不是单片机加个ADC能搞定的。家庭自制超声波风速计的成品案例调试周期通常按月计算。皮托管差压法相对便宜核心是一个差压传感器。但问题在于风速和动压是平方关系1m/s时动压不到1Pa普通的MEMS差压传感器在这个量级上噪声都压不住必须用高精度差压计价格又上去了。更麻烦的是皮托管有严格的方向性放置偏一点读数就偏家用很难保证气流总是对准管口。2.2 热式方案的取舍逻辑热式风速计在工业上分热线式和热膜式两种。热线式用极细的铂丝或钨丝做敏感元件响应快但细丝容易断不适合民用。热膜式用陶瓷基底上的薄膜电阻抗冲击能力强但热膜探头通常是成套卖的价格不低。我在DIY时选了NTC热敏电阻作为发热兼感温元件。因为NTC足够便宜、体积小、热容低、电阻变化率大配合一个普通的10位ADC就能读到明显的电压变化。和需要低噪声放大电路的热电偶或铂电阻相比NTC的分压信号直接就能进单片机省去了一堆模拟前端。同时我也评估了“买一个成品热式风速探头来改装”这条路。成品探头确实精度高但它通常自带完整的放大和补偿电路接口和输出格式不透明反而失去DIY的意义。自制的价值不在于逼近专业仪器的精度而在于把原理吃透做出一个自己能理解和修改的系统。所以最终选择是用低成本NTC自搭敏感元件通过标定曲线解决精度问题。3. 核心原理风速是如何“带走”热量的3.1 热平衡模型和King定律热式风速测量的基础是热平衡。电流流过NTC时产生焦耳热一部分热量通过引线传导走一部分辐射掉剩下的靠空气对流带走。在没有风的时候传感器温度会稳定在一个高于环境温度的平衡点。一旦气流经过对流散热增强传感器的温度就会下降。描述这种散热关系的经典公式是King定律。它最初用于描述无限长圆柱体在横向气流中的热损失经过简化后可以写成P (A B·√v) × (T_s - T_a)P是加热功率v是风速T_s是传感器表面温度T_a是环境温度A和B是常数。这个公式的核心含义是温差固定时加热功率和风速的平方根成正比。反过来说如果加热功率固定温度和风速之间也存在着单调的关系。NTC的电阻值随温度变化所以当风速改变时传感器电阻改变分压点的电压也随之改变。我们要做的就是把“电压-风速”这条关系曲线标定出来再在固件里做逆运算。关键在于这条曲线不是线性的低风速段电压变化明显高风速段逐渐饱和所以后端的校正逻辑很重要。3.2 两种工作模式的区别热式风速计有两种经典的驱动方式。第一种叫恒流/恒压模式直接给NTC施加固定的电流或电压风速改变时传感器的温度和电阻跟着变通过测量电阻变化推算风速。这种方式电路最简单但受环境温度影响大因为风速不变时环境温度一变传感器温度也跟着变输出就会飘。第二种叫恒温差模式通过反馈电路控制加热功率让传感器始终高于环境温度一个固定值。因为温差恒定King定律里的(T_s - T_a)项就是常数此时加热功率和风速就是单一函数关系免去了环境温度的补偿。恒温差模式精度高、稳定性好但需要一个反馈控制环电路复杂度高不少。我做的版本选择了“先用恒压模式跑通再手工做环境温度补偿”的策略。原因很现实恒温差电路里的比例积分控制器参数调起来费劲在原型阶段容易把太多时间耗在电路调试上。先让整个测量链路跑通拿到可信的数据再考虑升级到恒温差模式这才是个人项目该有的节奏。4. 硬件搭建30块钱搞定的传感器电路4.1 元件选型的几个关键点NTC选型上我建议选R25阻值10kΩ、B值3435K的玻璃封装热敏电阻。玻璃封装的好处是热容小、响应快、且防潮性能比环氧封装好。环氧封装的NTC热容太大风速变化后读数变化慢半拍做恒压模式会让人很崩溃。选10kΩ是因为这个阻值下自热温升比较适中配合5V供电串联一个10kΩ固定电阻后静态功耗大约在零点几毫瓦到几毫瓦之间既能产生明显的自热又不至于过热损坏。另一个关键点是耗散系数。NTC规格书里通常会给一个耗散系数mW/℃它表示每升高1℃需要消耗的功率。耗散系数越小的NTC在同样的电流下自热温升越大灵敏度越高。但也不能太小否则稍微有点风温度就掉得厉害容易进入非线性区。玻璃封装NTC的耗散系数一般在1到3mW/℃之间做风速计比较合适。参考电压方面不要直接用单片机内部参考。我建议用一个独立的2.5V或3.3V基准电压源芯片比如TL431或者便宜的电压基准模块给串联分压电路供电。因为热式测量本质上是靠自热功率变化来感知风速如果电源电压漂移自热功率就会变读数自然不准。这一步省了后面无数麻烦。4.2 电路连接与采样基础电路结构很简单。把NTC和固定电阻串联接在基准电压和地之间中间抽头接单片机的ADC引脚。关键是“哪一头”接到ADC上。我采用的做法是NTC接在VREF和ADC之间固定电阻接地。这样风速增大时NTC温度下降、阻值增大分压点电压升高。你也可以反过来接只要在标定的时候保持一致即可。我用的是ESP32开发板它的ADC是12位分辨率足够感知微弱变化了。实测中无风时ADC原始读数大约在1600到1800左右视环境温度而定单位风速变化引起的读数变化在低风速段能达到每米每秒几百个ADC码值完全够用。如果手头是Arduino Uno的10位ADC也没问题分辨率在0.1m/s级别。接线时注意将NTC的引线尽量短避免长导线接收环境电磁噪声。如果安装位置离单片机远建议在ADC引脚到地之间加一个0.1uF的陶瓷电容做硬件滤波。还有一个细节NTC引线本身也是散热通道所以引线要用细一点的并且传感器靠近头部的位置最好留出一小段裸线在空气中避免导线把热量直接导走导致读数迟钝。4.3 环境温度补偿不可缺少恒压模式下输出随风速变化但也随环境温度变化。这是NTC热风速计最大的坑。我在初期测试时发现同一个风扇档位晚间和午间读到的ADC值能差出12%原因就是环境温度改变导致传感器的基准温度也跟着变。解决思路是增加一颗不发热的NTC专门测量环境温度。这颗NTC不要有自热通过较大的串联电阻限制电流并把它放在传感器附近但不受加热影响的位置。然后按以下公式修正ΔT T_s - T_a恒压模式下我们无法直接测T_s但可以通过NTC的阻值间接推算。实际做法是做一个二维标定表横轴是环境温度纵轴是测量通道电压表中存的是风速。或者更简单一点利用King定律的形式把风速反算公式修改成包含环境温度项的修正系数。我用了一个更工程化的方案先做一组不同环境温度下的初始标定然后拟合一个“补偿系数随环境温度变化”的经验公式在固件里实时计算。效果可以把误差从12%压到3%以内家庭使用足够了。后面做的恒温差版本就不用这么麻烦这也是我给想进一步探索的朋友指的方向。5. 软件逻辑从ADC读数到风速换算5.1 采样、滤波与响应速度的平衡NTC的信号本质上是微弱且连续变化的模拟量。单片机ADC采样单次读数波动比较大直接拿单点数据换算风速结果会像心电图一样抖。我采取的方法是10Hz采样率用一个滑动窗口对最近30个点取平均相当于输出3秒的移动平均。这个平滑度适合看“持续风速”但阵风会被抹掉。如果既想看平均风速又想看阵风就同时跑两个滤波器——一个滑动窗口3秒一个滑动窗口0.5秒。3秒均值作为“平均风速”记录0.5秒均值的最大值作为“阵风风速”。这样固件里只是多开一个数组的事但数据呈现的效果完全不同。值得注意的是NTC本身有热惯量温度变化需要时间所以即使软件不加任何滤波输出也不是瞬时值。我实测玻璃封装NTC的热时间常数大约在10到20秒——不是指电热调节的反应而是指自热温升在风速突变后重新平衡的时间。这意味着热式风速计天然适合测平均风速瞬时性并非强项。要做高频阵风测量得用更细的铂丝或热膜探头那是另一个梯度的问题。5.2 非线性校正的策略风速和分压电压的关系不是直线低风速段曲线陡高风速段曲线平缓。如果直接用线性映射0到2m/s的数据会挤在很小的电压区间里误差很大。我采用的办法是标定后在固件里查表加线性插值。查表法思路清晰把标定获得的数据(风速, ADC值)按ADC值排序写入一个数组。换算时先二分查找找到ADC值所在的区间然后对风速做线性插值。数组长度不需要很长13个标定点加上插值就能覆盖0到15m/s的量程每段插值的误差远小于传感器本身的非线性误差。如果你习惯用公式也可以对标定数据做幂函数拟合形如v a × (x - x0)^b其中x是ADC读数。这个公式在低风速段拟合效果不错但到了高风速段偏差会明显变大需要分段拟合。我最终没有使用公式拟合因为查表法更直观也便于后期增减标定点。5.3 固件里的实现示例下面是一段简化后的Arduino代码读取NTC分压值、经过滑动平均、再查表插值输出风速。#define ADC_PIN 34 #define N_POINTS 13 // 标定表{ADC值, 风速m/s}按ADC升序排列 const float calTable[N_POINTS][2] { {1450, 0.0}, {1520, 0.5}, {1620, 1.0}, {1720, 1.8}, {1820, 3.0}, {1900, 4.5}, {1970, 6.0}, {2030, 8.0}, {2090, 10.0}, {2140, 12.0}, {2180, 14.0}, {2210, 16.0}, {2240, 18.0} }; const int windowSize 30; int buf[windowSize]; int idx 0; float readWindSpeed() { int raw analogRead(ADC_PIN); buf[idx] raw; idx (idx 1) % windowSize; long sum 0; for (int i 0; i windowSize; i) sum buf[i]; int avg sum / windowSize; if (avg calTable[0][0]) return calTable[0][1]; if (avg calTable[N_POINTS-1][0]) return calTable[N_POINTS-1][1]; for (int i 0; i N_POINTS-1; i) { if (avg calTable[i][0] avg calTable[i1][0]) { float ratio (float)(avg - calTable[i][0]) / (calTable[i1][0] - calTable[i][0]); return calTable[i][1] ratio * (calTable[i1][1] - calTable[i][1]); } } return -999; // 数据异常 }这段代码的核心思路很直白滑动窗口消除抖动查表处理非线性。实际运行时把readWindSpeed()每秒调用一次输出就已经非常平滑了。你也可以在插值之前先对ADC取自然对数再插值能进一步压低高风速段的误差但对于家庭场景线性插值已经够用。6. 3D打印外壳结构设计比电路更影响精度6.1 传感器到底该怎么“放”传感器放置的结构决定了这东西测的是“真实风速”还是“某个角落的乱流”。一开始我偷懒直接把NTC裸露在外用一根杆子撑起来结果读数受风向影响极大同一阵风换个方向能差出30%。原因是热式探头本质上对气流的来流方向敏感。气流垂直吹过圆柱体和水平掠过圆柱体散热效率完全不同。要解决这个问题一个常见思路是设计一个多孔均流罩让气流从四面八方进入一个腔体在内部形成相对稳定的混合流场传感器放在腔体中心。我最后打印的是一个竖直安装的圆柱形腔体顶部封住侧面均匀开了一圈直径6mm的圆孔孔距15mm共三层。传感器固定在腔体正中央用一根从底部穿入的细不锈钢管支撑。风从任意方向吹来都会通过开孔进入腔体并绕过传感器方向敏感性大幅下降。实测下来不同风向的读数偏差从30%降到了8%以内对家用设备来说可以接受了。6.2 防晒、防雨、防尘的实用细节户外设备最大的环境干扰源是太阳辐射。阳光直射会让外壳温度升高壳体本身变成一个散热器和辐射源靠近壳壁的传感器读数会被严重干扰。解决方式有三条腿撑着第一外壳颜色用白色PLA或PETG材质都行白色反射大部分可见光和红外。第二传感器不要靠近壳壁放在腔体中心离壁面至少15mm。第三外壳壁之间留出通风间隙让空气可以流动避免壳内形成静态高温层。防雨方面顶部要做成封闭的侧面开孔的位置要低于顶盖否则雨水会顺着开孔流进去。底部留两个3mm的排水孔万一有水汽凝结可以排出去。防尘是个长期问题棉签可以清理外壳内壁传感器上的灰尘会影响散热系数导致标定曲线漂移。我建议每隔三个月把传感器拆下用酒精轻轻擦拭一次。6.3 安装位置直接影响数据可信度安装位置如果错了再好的传感器也白搭。家用气象观测的通用建议是离地至少1.5米远离建筑物边缘和屋顶设备至少2米。因为靠近墙体时墙面会产生摩擦湍流读数会系统性偏低而靠近空调外机时热风会直接烤传感器读数会明显偏高。我自己把传感器装在楼顶女儿墙上方的一根2米不锈钢管上远离了空调外机和排风口。装好后做了个简单测试手拿成品风速计在传感器旁边蹲守十分钟两边的读数趋势基本吻合误差在0.5m/s以内。这个精度虽然比不上专业气象站但对家用来说已经足够可靠。7. 家庭标定没有风洞也能校准7.1 标定设备和布置思路热式风速计的标定是“重头戏”但家庭环境没有标准风洞怎么办我用的是最笨但是可行的办法一台可调速的直流风扇加一台手持叶轮风速计作为参考标准。叶轮风速计的精度虽然有限但作为相对参考设备已经足够。标定环境的搭建有几个关键细节。第一风扇出风口前要留一段距离我取的是30到50厘米这段距离上的气流相对平稳避免了紧贴风扇时叶片涡流带来的干扰。第二参考风速计和自制传感器要并排放置在同一截面上不能一前一后否则测的是不同位置的气流。第三房间里关门关窗尽量让环境气流稳定。然后给风扇配一个可调电源通过调节电压改变风速。为什么用可调电源而不是风扇自带档位因为档位之间的风速间隔太大标定点不够密拟合出来的曲线就不平滑。用可调电源我可以在0到8m/s的范围内任意取十几个风速点。7.2 数据采集与曲线拟合实际操作时每调整一次风扇电压等3分钟让传感器热平衡后再用手机记录参考风速计的读数和自制传感器的ADC值。这里要强调一下必须等稳定后再读数。NTC的热惯量会导致读数在改变风速后缓慢爬升或下降这个过程通常需要一分钟以上急着记录会让数据整体偏“歪”。我记录了一组典型数据风扇电压(V)参考风速(m/s)ADC读数00.014503.00.815304.01.516205.02.517306.04.018507.06.019708.08.520809.011.0217010.014.02250这些数据直接填进代码里的calTable数组就完成了固件层面的标定。如果想更高精度可以再用Python做一次多项式拟合来平滑并插值出更多中间点。我试过用三阶多项式拟合ADC到风速的逆函数在1到10m/s区间内拟合误差在0.2m/s以内已经超过热敏电阻本身的重现性了。7.3 标定中的典型问题标定过程最常见的坑是“参考设备本身也在漂移”。手持叶轮风速计如果电量不足转速测量会有偏差所以标定前先确认参考设备电池电量。另一个坑是风扇的摆头功能必须关掉标定期间风扇要固定朝向否则风场一直在变永远等不到稳定。最容易被忽略的干扰是人的存在。人站在风扇和传感器之间身体会挡风产生尾流数据自然不准。我后来把整个标定装置放在桌面上用长跳线连接传感器人退到两米外用手机远程看读数数据质量明显上了一个台阶。标定完成之后再把传感器装回楼顶的安装位置整个项目就算正式落地了。8. 踩坑记录与后续改进方向8.1 我踩过的五个坑第一个坑是阳光直射导致的零点漂移。NTC探头在太阳下和阴影里无风时的ADC读数能差出100个码值换算成风速能差出0.8m/s。这个问题的根源是传感器自身被加热了热平衡模型不再成立。后来我在传感器上方加了一个白色遮阳帽并让传感器悬空在腔体中央情况才真正改善。第二个坑是引线过长导致的噪声叠加。最初为了把单片机放在室内我用了一根3米的杜邦线连接传感器结果ADC读数跳得厉害加再多的软件滤波也无济于事。后来我把单片机也移到室外密封盒里只用短线和传感器连接噪声立刻小了一个数量级。家庭小项目里模拟信号的长距离传输能避免就尽量避免。第三个坑是固定电阻的温漂。我最初用普通金属膜电阻做串联分压冬天和夏天的读数基准会发生偏移。后来换成了低温漂电阻25ppm/℃零点偏移大幅减小。这可能是在整个项目里最值得的几块钱投入。第四个坑是标定曲线在低风速段的过度外推。King定律在风速趋近于零时会失效因为自然对流仍然存在自由对流散热占主导。我的标定最低点是0m/s无风状态但0.2m/s的微风数据点是没法稳定复现的所以标定曲线在0到0.5m/s这段不要做精确性承诺把它当作定性感知就好。第五个坑是安装后的长期漂移。传感器在户外工作两个月后表面积了一层肉眼几乎看不见的灰尘测量值比刚标定时偏低约10%。后来我在固件里加了一个“干刷校准”功能用电机带动毛刷定期清理传感器表面不过家庭版直接定期手工擦洗更靠谱。8.2 值得尝试的升级方向热式风速计这个平台很适合继续往上堆功能。最值得做的升级是把恒压模式改成恒温差模式加一个运算放大器反馈环让传感器温度相对环境温度恒定在30℃左右。这样就不用手工做环境温度补偿了低风速段的测量稳定性还能再上一个台阶。第二个方向是加一个风向测量通道。在传感器腔体的四个方向各放一颗NTC比较不同方向传感器的散热差异就能粗测风向。精度达不到专业的超声波测风阵但判断出八个方位已经足够家庭使用。第三个方向是数据接入。ESP32自带WiFi把风速数据发送到Home Assistant或者自建的MQTT服务端就能和温湿度、气压数据一起做可视化。我后来就是把这台风速计并入了自己的小型气象站风雨天的时候看实时风速曲线感受非常直观。最后说一个我在实际使用中发现的细节热式风速计在1m/s以下的微风段表现远远超过我原来那台风杯成品机。家里阳台上那种手背几乎感觉不到的气流它都能稳定地读出0.3到0.5m/s的数据这在机械式设备上是不可想象的。这也让我觉得所谓“非传统”并不是为了标新立异而是在认真比较了所有方案后选择了一条真正适合自己场景的技术路线。如果你也想给家里添一台风速计不妨试试这个思路元器件成本不高过程本身也很有趣。