
1. 项目概述与核心思路最近在整理工作室时发现手头有几个闲置的Arduino Uno和一堆传感器模块一直想做个既实用又能把知识点串起来的小项目。正好夏天快到了桌面上的小风扇总是需要手动开关于是萌生了做一个能根据室温自动调节风速的智能风扇的想法。这不仅仅是让风扇“自动化”更是一个完整的嵌入式系统小型实践涵盖了传感器数据采集、微控制器MCU处理、PWM电机控制和人机交互LCD显示这几个核心环节。这个项目的核心目标很明确制作一个能实时监测环境温度并据此自动无级调节风扇转速的系统同时将当前温度清晰地显示在屏幕上。它本质上是一个典型的闭环控制系统。输入是TMP36温度传感器采集的模拟电压信号经过Arduino Uno作为控制器转换为温度值并进行逻辑判断输出则是通过电机驱动模块改变施加在直流电机上的PWM占空比从而控制风扇转速。LCD屏则提供了系统状态的实时反馈。选择Arduino平台主要是看中其极低的上手门槛和庞大的社区支持能让开发者快速聚焦于系统逻辑和算法本身而非复杂的底层寄存器配置。整个系统非常适合电子爱好者、嵌入式入门学习者以及创客教育。通过它你可以亲手触摸到物联网IoT中最基础的“感知-决策-执行”链路。下面我将从设计思路、硬件选型、电路搭建、代码编写到最后的组装调试完整地复盘这个项目的实现过程并分享一些在调试过程中积累的、教科书上不一定写的实战经验。2. 硬件选型与核心元件解析一个项目的成功一半取决于前期的硬件选型是否合理。这里的“合理”意味着在满足功能、性能和成本要求的前提下选择最可靠、最易用的组件。下面我详细拆解一下本项目中用到的几个核心元件并解释为什么选它们。2.1 控制核心Arduino Uno R3Arduino Uno几乎是所有入门项目的首选这次也不例外。它基于ATmega328P微控制器拥有14路数字I/O口其中6路可做PWM输出和6路模拟输入口对于本项目来说绰绰有余。其5V的工作电压与大部分传感器、模块兼容极大地简化了电路设计。更重要的是其丰富的库支持和几乎“傻瓜式”的编程环境Arduino IDE让开发者能快速验证想法。相比于更强大的ESP32或树莓派PicoUno在单纯的逻辑控制和PWM输出上更纯粹没有无线功能带来的复杂度更适合作为学习闭环控制的平台。注意市面上有原版、兼容版等多种Uno。对于学习项目质量可靠的兼容板完全足够但务必确保其USB转串口芯片如CH340、CP2102的驱动已在你的电脑上正确安装这是后续上传代码的前提。2.2 温度感知TMP36模拟温度传感器温度传感器的选择很多比如数字式的DS18B20、DHT11以及模拟式的LM35、TMP36。我选择TMP36主要基于以下几点考量模拟输出输出是与温度成线性关系的电压值无需复杂的单总线或I2C协议直接用Arduino的模拟输入引脚读取即可代码简单直观非常适合教学和原理演示。精度与范围常温下精度可达±2°C测量范围-40°C到125°C完全覆盖室内环境需求。供电简单仅需2.7V至5.5V电源与Arduino的5V系统完美匹配。TMP36的输出电压与温度的关系是输出电压 (V) (温度 °C * 0.01) 0.5。也就是说25°C时输出电压约为0.75V。这个公式是后续代码中温度计算的基础。它的封装很小有三个引脚使用时方向至关重要平的一面朝向自己从左至右依次为VCC电源、Vout信号、GND地。2.3 动力执行直流减速电机与驱动模块风扇需要动力我选择了一个140 RPM转/分钟的直流减速电机。减速电机扭矩大、转速较低且平稳适合直接驱动自制的轻质风扇叶片。普通直流电机的转速控制需要通过PWM脉冲宽度调制来实现而Arduino的数字引脚输出电流很小约20mA无法直接驱动电机。因此一个电机驱动模块是必需的。项目中提到了“Sparkfun Motor Driver”这很可能是一块基于L293D或类似芯片的双H桥驱动模块。这类模块的核心是一个H桥电路它允许你控制电机的方向和速度。通过给输入引脚不同的逻辑电平组合可以控制电机正转、反转或刹车。而速度控制则是将Arduino的PWM引脚连接到驱动模块的使能端ENABLE通过改变PWM的占空比来调节电机的平均电压从而实现调速。实操心得L293D这类芯片在工作时会有一定的压降约1.4V-2V这意味着电机两端的电压会比电源电压低。如果你发现电机最高转速不如预期可以考虑使用压降更小的驱动方案比如TB6612FNG或者直接用MOS管搭建H桥。2.4 信息显示16x2字符型LCD屏为了直观显示温度我选用了一块经典的1602 LCD16列2行。它通过并行接口8位或4位模式与控制器通信。虽然相比OLED屏更耗电、体积大但其无需驱动芯片初始化、在各种光照条件下可视性好的特点使其在基础项目中非常可靠。本项目使用4位数据模式这样可以节省4个I/O口。屏幕的对比度通过一个10KΩ电位器来调节这是这类LCD屏的标准接法。2.5 其他关键部件面包板和跳线用于快速搭建和修改电路原型是开发阶段的必备品。10KΩ电位器用于调节LCD对比度。本质上是一个可变电阻通过分压为LCD的VO引脚对比度调节端提供0-5V的可调电压。电源在开发阶段USB供电足够。如果独立使用可以考虑用一个5V/1A以上的手机充电器或电池组通过Uno的Vin引脚供电。3. 电路系统搭建与接线详解电路连接是整个项目的物理骨架正确的接线是系统正常工作的基础。下面我将按照信号流和电源分配的逻辑详细讲解每一步的接线原理和注意事项而不仅仅是罗列连接表。3.1 电源系统构建为所有元件供能任何电子系统稳定可靠的电源是第一位的。我们的系统中有数字部件Arduino, LCD和模拟部件TMP36还有电机这种大电流感性负载。不当的电源布线会导致电压不稳、传感器读数跳动甚至单片机复位。操作步骤与原理建立公共电源轨在面包板的两侧通常有标有“”和“-”的长条这就是电源轨。我们用两根跳线建议红色接正极黑色接负极将Arduino Uno上的“5V”引脚连接到面包板一侧的“”轨将“GND”引脚连接到同一侧的“-”轨。这样面包板这一侧的电源轨就拥有了5V和GND。贯通电源轨为了布线方便通常需要面包板两侧的电源轨都是连通的。因此在面包板的另一端再用两根跳线将左侧的“”轨与右侧的“”轨连接左侧的“-”轨与右侧的“-”轨连接。至此整个面包板就有了统一的5V和GND网络。重要提示电机在启动和换向时会产生很大的瞬间电流和反向电动势可能通过电源线干扰微控制器和传感器。虽然在本项目小电机情况下问题可能不明显但良好的习惯是如果条件允许可以考虑为电机驱动模块使用独立的电源需共地或者至少在电机的电源引脚附近并联一个100μF的电解电容和一个0.1μF的瓷片电容以吸收高频和低频噪声。3.2 温度传感器TMP36接线TMP36的接线非常简单体现了模拟传感器的便捷性。供电将传感器的VCC引脚最左用跳线连接到面包板的“”轨5VGND引脚最右连接到“-”轨。信号输出将传感器的Vout引脚中间连接到Arduino的模拟输入引脚A0。Arduino Uno的ADC模数转换器会将A0引脚上的0-5V电压转换为0-1023的整数值。方向验证务必确保传感器方向正确将传感器有字、平的一面朝向你自己引脚朝下从左到右就是VCC, Vout, GND。接反很可能烧毁传感器。3.3 电机驱动模块接线这是接线中相对复杂但至关重要的一环。我们以常见的L293D模块为例进行说明。模块上通常会有两排引脚一排控制信号一排电源电机接口。控制端连接连接Arduino使能端ENA连接Arduino的任意一个PWM引脚如引脚6。PWM信号将通过这里控制电机速度。输入1IN1 输入2IN2连接Arduino的两个普通数字引脚如引脚4和5。通过设置这两个引脚的高低电平组合来控制电机方向。例如(HIGH, LOW)为正转(LOW, HIGH)为反转(LOW, LOW)或(HIGH, HIGH)为刹车/停止。逻辑电源VCC连接面包板的“”轨5V为驱动芯片内部的逻辑电路供电。逻辑地GND连接面包板的“-”轨与Arduino共地。动力端连接连接电机和电源电机电源VS连接外部电源正极。注意如果电机电压也是5V可以将其与逻辑电源VCC短接都接5V。如果电机需要更高电压如9V、12V则必须接入相应的电源且该电压不能超过驱动模块的最大额定电压。电机地GND连接外部电源负极并且必须与Arduino的GND连接在一起形成共同参考地。电机输出AOUT1 OUT2直接连接直流电机的两根线。电机的转向取决于IN1/IN2的逻辑如果发现转向与预期相反只需交换这两根线即可。3.4 LCD显示屏接线4位模式为了节省I/O口我们采用4位数据模式。这意味着我们只使用DB4-DB7这4根数据线。电源与对比度VCC引脚2接“”轨5V。GND引脚1接“-”轨。V0引脚3接电位器的中间抽头。电位器两端分别接“”轨和“-”轨。旋转电位器即可调节屏幕对比度直到字符清晰显示。控制线与数据线RS寄存器选择引脚4接Arduino数字引脚12。用于选择发送的是指令如清屏还是数据如要显示的字符。RW读/写引脚5接地“-”轨。因为我们只向LCD写数据不读取所以直接置为低电平。E使能引脚6接Arduino数字引脚11。在数据/指令稳定后需要一个高脉冲来锁存数据。D4-D7数据线引脚11-14分别接Arduino数字引脚5, 4, 3, 2。注意这里D4-D7对应的是LCD引脚不要与电机驱动的输入引脚混淆如果引脚冲突需要调整。背光可选A阳极引脚15通过一个约220Ω的限流电阻接“”轨5V。K阴极引脚16接“-”轨。3.5 电位器接线10K电位器有三个引脚。两端的引脚分别接“”轨和“-”轨中间的抽头接LCD的V0引脚引脚3。这样就构成了一个可调分压电路为V0提供0-5V的可调电压。4. 核心代码逻辑与程序设计硬件搭建好后灵魂在于软件。代码不仅要实现功能更要清晰、健壮、易于调整。我将代码分为几个模块进行讲解。4.1 库引用与引脚定义首先我们需要包含驱动LCD的库并定义所有用到的引脚。#include LiquidCrystal.h // 引入LCD库 // 引脚定义 const int tempSensorPin A0; // 温度传感器接模拟口A0 const int motorPWM 6; // 电机速度控制(PWM)接数字口6 const int motorIN1 4; // 电机方向控制IN1 const int motorIN2 5; // 电机方向控制IN2 // 初始化LCD参数对应RS, E, D4, D5, D6, D7的引脚 LiquidCrystal lcd(12, 11, 5, 4, 3, 2);这里使用const int来定义引脚常量而不是直接写数字提高了代码的可读性和可维护性。LiquidCrystal对象的初始化参数顺序必须与你的实际接线一致。4.2 全局变量与参数设定我们需要定义系统运行的一些关键参数这些参数直接影响温控的响应特性。// 温控参数 float currentTemp 0.0; // 当前温度变量 int fanSpeed 0; // 风扇速度0-255 unsigned long previousMillis 0; // 用于非阻塞式定时 const long interval 1000; // 采样/更新间隔毫秒 // 温度阈值可根据需要调整 const float tempThresholdLow 24.0; // 低于此温度风扇停止 const float tempThresholdMid 26.0; // 中速起始温度 const float tempThresholdHigh 28.0; // 全速起始温度使用unsigned long和millis()函数来实现非阻塞延时这样在等待采样间隔时程序不会卡住为后续添加其他功能如按钮交互留出空间。温度阈值是控制逻辑的核心需要根据个人舒适度和传感器校准情况进行调整。4.3 初始化设置setup函数在setup()函数中我们需要初始化所有用到的硬件接口。void setup() { // 初始化串口通信用于调试可选 Serial.begin(9600); // 初始化电机控制引脚为输出模式 pinMode(motorIN1, OUTPUT); pinMode(motorIN2, OUTPUT); pinMode(motorPWM, OUTPUT); // 设置电机初始状态为停止 digitalWrite(motorIN1, LOW); digitalWrite(motorIN2, LOW); analogWrite(motorPWM, 0); // PWM输出为0电机不转 // 初始化LCD设置显示范围为16列2行 lcd.begin(16, 2); // 打印初始静态信息 lcd.print(Temp: ); lcd.setCursor(0, 1); // 移动到第二行开头 lcd.print(Fan: ); }初始化电机时将其设置为停止状态是一个好习惯可以防止上电瞬间电机的意外抖动。LCD的初始信息打印可以提升用户体验。4.4 温度读取与计算函数这是获取环境信息的关键一步。我们需要从TMP36读取模拟值并准确转换为摄氏度。float readTemperature() { // 1. 读取模拟值0-1023 int sensorValue analogRead(tempSensorPin); // 2. 将模拟值转换为电压Arduino ADC参考电压为5V // ADC分辨率是10位2^101024所以每单位对应的电压是 5.0 / 1024.0 float voltage sensorValue * (5.0 / 1024.0); // 3. 根据TMP36特性将电压转换为温度摄氏度 // TMP36输出电压每摄氏度10mV0°C时输出500mV。 // 公式温度 (电压 - 0.5) * 100 float temperature (voltage - 0.5) * 100.0; return temperature; }计算过程解析analogRead()返回0-1023的整数对应0V-5V。电压计算电压 读数 * (5.0 / 1024.0)。这里用1024.0是因为ADC有1024个离散台阶0-1023。温度计算这是TMP36特有的转换公式。电压 - 0.5是减去0°C时的偏置电压500mV* 100是因为灵敏度是10mV/°C即100°C/V。校准提示理论上如此但实际中USB供电的5V可能并非精确的5.00V且TMP36本身有误差。为了提高精度可以引入“校准因子”。用一个准确的温度计如水银温度计测出当前室温同时读取系统计算出的温度两者差值即为系统误差。可以在代码最后加上一个固定的偏移量进行补偿例如temperature temperature 1.5; // 假设系统普遍偏高1.5度。4.5 核心控制逻辑与风扇调速函数这是项目的大脑根据读取的温度决定风扇的转速。我采用了分段线性控制的方法比简单的开关控制更平滑比复杂的PID控制更易于理解和实现。int calculateFanSpeed(float temp) { int speed 0; if (temp tempThresholdLow) { speed 0; // 温度低风扇停转 } else if (temp tempThresholdLow temp tempThresholdMid) { // 在低阈值和中阈值之间速度从0线性增加到128约50%占空比 speed map(temp * 10, tempThresholdLow * 10, tempThresholdMid * 10, 0, 128); } else if (temp tempThresholdMid temp tempThresholdHigh) { // 在中阈值和高阈值之间速度从128线性增加到255100%占空比 speed map(temp * 10, tempThresholdMid * 10, tempThresholdHigh * 10, 128, 255); } else { speed 255; // 温度超过高阈值全速运转 } // 确保速度值在0-255的合法范围内 speed constrain(speed, 0, 255); return speed; } void setFanSpeed(int speed) { // 设置电机方向为正转根据你的接线可能需要调整IN1/IN2电平 digitalWrite(motorIN1, HIGH); digitalWrite(motorIN2, LOW); // 通过PWM设置速度 analogWrite(motorPWM, speed); }逻辑解析map()函数是Arduino提供的非常实用的线性映射函数。这里将温度值映射到PWM值。因为map()处理整数所以将温度乘以10转换为整数进行操作。constrain()函数确保计算出的速度值不会超出PWM范围0-255。在setFanSpeed中我固定了电机为正转。如果你需要反转可以修改digitalWrite的参数。停止电机可以将速度设为0或者将IN1和IN2都设为LOW。4.6 主循环loop函数与信息更新主循环以非阻塞的方式定时执行采样、计算、控制和显示。void loop() { unsigned long currentMillis millis(); // 获取当前时间 // 每隔 interval 毫秒执行一次 if (currentMillis - previousMillis interval) { previousMillis currentMillis; // 更新时间戳 // 1. 读取温度 currentTemp readTemperature(); // 2. 计算风扇速度 fanSpeed calculateFanSpeed(currentTemp); // 3. 设置风扇速度 setFanSpeed(fanSpeed); // 4. 更新LCD显示 lcd.setCursor(6, 0); // 移动到“Temp: ”后面 lcd.print( ); // 用空格清除旧数据5位字符加小数点 lcd.setCursor(6, 0); lcd.print(currentTemp, 1); // 显示温度保留一位小数 lcd.setCursor(5, 1); // 移动到“Fan: ”后面 lcd.print( ); // 清除旧数据 lcd.setCursor(5, 1); lcd.print(fanSpeed); // 显示PWM速度值 // 如果想显示百分比可以lcd.print(map(fanSpeed, 0, 255, 0, 100)); // 5. 可选串口输出调试信息 Serial.print(Temperature: ); Serial.print(currentTemp); Serial.print( C, Fan Speed: ); Serial.println(fanSpeed); } // 此处可以添加其他非实时任务如按键扫描 }显示优化技巧在更新LCD数字部分时先打印空格覆盖旧数据再打印新数据。这是因为LCD不会自动清除单个字符。如果不这样做当新数字位数比旧数字少时如从“100”变成“25”会残留旧的“0”字符。5. 系统组装、调试与外壳制作当电路和代码都准备好后就可以将它们整合成一个独立的设备并处理那些在纯开发板上不会遇到的问题。5.1 从面包板到稳定原型在面包板上测试成功后下一步是构建一个更稳定的原型为装入外壳做准备。焊接可以考虑将核心电路Arduino、驱动模块、传感器、LCD接口焊接在一块洞洞板万用板上。这比面包板更牢固接触更可靠。焊接时注意先规划好布局电源线和地线可以走得粗一些。导线处理使用不同颜色的硅胶导线区分电源红、地黑和信号线黄、绿等。长度要合适避免过于杂乱。对于电机这类有振动的部件导线连接点最好用热熔胶或扎带固定防止因振动而脱落。独立供电测试拔掉USB线尝试用一个5V/2A的电源适配器通过Arduino的DC插座或Vin引脚供电。测试系统是否正常工作。这能排除USB供电能力不足特别是驱动电机时导致的问题。5.2 自制风扇叶片与动力连接原项目使用纸板制作叶片这是一个低成本且有效的方法。材料选择选择轻质且有一定强度的材料如薄的塑料板、硬卡纸或轻木片。重量越轻对电机负载越小启动和调速越灵敏。叶片设计设计4片对称的桨形叶片。面积越大风量越大但阻力也越大。需要根据电机扭矩来平衡。可以先剪一个小尺寸的进行测试。动平衡这是关键叶片必须对称且重量一致。制作时最好先画出模板然后依样裁剪。组装后可以将中心轴水平架起轻轻拨动叶片观察它是否会在任意位置停下。如果总在同一个位置停下说明该位置较重需要修剪或粘贴配重如一小片胶带到对称位置进行调整。不平衡的叶片会导致电机剧烈振动、噪音大甚至损坏轴承。与电机轴连接直流减速电机的输出轴通常很细。可以用一小段热缩管或橡胶管套在轴上增加直径和摩擦力然后用胶水将叶片底座固定在上面。也可以使用联轴器但对于这种小项目用AB胶或热熔胶仔细粘牢即可。5.3 外壳设计与制作外壳不仅是为了美观更能保护电路、规整线束、引导气流。功能规划外壳需要开孔的地方包括LCD屏幕窗口、温度传感器感应孔避免被内部电路热量影响、风扇出风口、电源线入口、USB编程口可选如果以后不常修改代码可以封上。散热考虑Arduino的稳压芯片、电机驱动芯片在工作时都会发热。必须在外壳上特别是对应这些芯片的位置开设通风孔。可以使用手钻或烙铁开出一排小孔。材料与固定使用项目中的Sparkfun包装盒是个巧妙的点子。也可以用亚克力板、3D打印件或现成的塑料盒。内部用尼龙柱、螺丝或强力双面胶/魔术贴Velcro固定电路板。务必确保金属引脚或焊点不会接触到导电的外壳如金属盒造成短路。传感器位置温度传感器最好通过延长线引到外壳外部或紧贴外壳的进气孔以确保测量的是环境空气温度而不是设备内部积热。5.4 系统集成与总装将所有部件装入外壳是最后一步需要耐心和细心。顺序很重要建议先将电机固定在外壳的预定位置如顶部或侧面。然后固定主电路板。最后连接电机线、传感器线和LCD屏。线束管理用扎带或线卡将导线捆扎整齐避免它们碰到风扇叶片或缠结在一起。过长的线可以盘起来固定。最终功能测试合上外壳前接通电源进行完整的功能测试用手温加热传感器观察风扇转速是否变化LCD显示是否正常。确认一切无误后再最终封闭外壳。6. 常见问题排查与性能优化在实际制作中你几乎一定会遇到一些问题。下面是我在多次类似项目中总结的排查清单和优化建议。6.1 上电无反应或LCD不显示检查电源用万用表测量Arduino的5V和GND引脚之间是否有5V电压。USB口是否接触良好外部电源适配器是否输出正常检查LCD对比度这是最常见的问题旋转电位器慢慢调节屏幕可能会从全黑变为全白在中间某个位置字符才会显现。检查接线重点检查LCD的RS、E、D4-D7引脚是否与代码定义和实际接线完全一致。一根线接错就可能导致无显示或乱码。检查背光如果屏幕有背光但不亮检查背光引脚A、K是否接好限流电阻是否合适或损坏。6.2 温度读数不准或跳动大传感器供电噪声确保TMP36的电源引脚VCC上并联了一个0.1μF的瓷片电容并且电容尽量靠近传感器引脚。这可以滤除电源线上的噪声。代码公式错误再次核对readTemperature()函数中的计算公式特别是0.5V的偏移量和100的倍数关系。ADC参考电压默认使用Arduino的5V作为ADC参考。如果USB供电电压不稳读数就会漂移。可以尝试使用analogReference(INTERNAL);改为使用芯片内部稳定的1.1V基准但此时需要重新推导电压转换公式因为输入电压范围变成了0-1.1V。软件滤波在代码中实现软件滤波。最简单的是“移动平均滤波”即连续读取N次如10次然后取平均值作为最终结果。这能有效平滑读数。float readTemperatureSmooth() { const int numReadings 10; float sum 0; for (int i 0; i numReadings; i) { sum readTemperature(); // 调用之前的单次读取函数 delay(10); // 短时间延迟避免读取过快 } return sum / numReadings; }6.3 电机不转或转动异常驱动模块使能确认驱动模块的使能引脚ENA是否已连接PWM信号并且代码中analogWrite的值大于0。方向控制引脚确认IN1和IN2的电平设置是否正确。用digitalWrite设置一组电平后用万用表测量一下输出端OUT1, OUT2之间是否有电压。电源功率不足电机启动电流很大。如果使用USB供电可能因电流限制导致Arduino复位或电机无力。换用外部电源适配器如9V/1A通过Vin引脚供电。PWM频率Arduino Uno的引脚5和6的PWM默认频率约为980Hz对于电机驱动来说通常没问题。但如果听到电机有尖锐的噪音可以尝试调整PWM频率通过操作定时器寄存器属于进阶内容。6.4 风扇控制逻辑不理想阈值设置不当tempThresholdLow,Mid,High需要根据你的实际体感温度进行调整。可以先通过串口监视器观察当前室温对应的PWM值然后调整阈值使得在感到热时风扇能加速到令人舒适的程度。控制过于频繁如果温度在阈值附近微小波动会导致风扇频繁启停或变速体验不好。可以引入“迟滞”功能。例如停止温度设为24°C但启动温度设为25°C。这样温度在24-25度之间时风扇状态保持不变避免了抖动。// 简单的迟滞控制示例 float tempOn 25.0; float tempOff 24.0; bool fanState false; void updateFanWithHysteresis(float temp) { if (temp tempOn) { fanState true; } else if (temp tempOff) { fanState false; } // 根据fanState控制风扇 digitalWrite(motorIN1, fanState ? HIGH : LOW); digitalWrite(motorIN2, LOW); analogWrite(motorPWM, fanState ? 255 : 0); // 这里简化成开关控制 }6.5 系统稳定性与扩展思考抗干扰电机是主要的干扰源。确保电机电源线和信号线不要平行走线尽量分开。在电机两端并联一个续流二极管如1N4007阴极接电源正阳极接电机负可以吸收电机产生的反向电动势保护驱动芯片。功能扩展这个系统是一个很好的基础平台可以轻松扩展增加手动模式添加一个按钮可以在自动温控和手动调速模式间切换。远程控制增加一个蓝牙模块如HC-05或Wi-Fi模块如ESP-01S通过手机APP控制风扇和设置温度阈值。数据记录增加一个SD卡模块定时将温度和风扇速度记录到文件中用于分析环境变化。多级调速与显示将简单的PWM数值显示优化为直观的“低速”、“中速”、“高速”图标或进度条显示在LCD上。这个项目从构思到实现最深的体会是“软硬结合”的魅力。每一个硬件连接都对应着代码里的一行定义每一个逻辑判断都影响着物理世界的转动。调试过程中万用表和串口监视器是你最忠实的朋友。当风扇随着你手掌的温度缓缓加速屏幕上数字跳动的那一刻所有的麻烦都值了。它不仅仅是一个风扇更是一个你亲手赋予生命的、可感知环境并做出反应的微型智能系统。希望这个详细的复盘能帮助你少走弯路顺利创造出你自己的智能温控装置。