1. 项目概述与设计思路
最近几年夏天是越来越热了,晚上睡觉不开窗通风简直没法过。但问题也随之而来——早上经常睡过头,或者匆匆忙忙出门,完全忘了把窗户关上。等到中午太阳一晒,外面热浪滚滚,室内好不容易攒了一晚上的凉气,全被热空气给换走了,回家一开门,那股热浪扑面而来的感觉,别提多糟心了。相信不少朋友都有过类似的经历。为了解决这个“健忘”带来的小麻烦,我琢磨着得做个能自动提醒的小玩意儿。核心需求很简单:实时比较室内和室外的温度,一旦室外温度反超室内,就立刻发出提醒,告诉我“该关窗了”。这就是今天要分享的“基于LM35与ATtiny13A的简易温度比较器”项目的由来。
当然,它的用途远不止于此。你可以把它当作一个通用的温度阈值报警器,比如监控鱼缸水温是否过高、温室大棚是否需要通风、或者电脑机箱的散热是否异常。其核心原理是利用两个LM35模拟温度传感器,分别采集两个不同位置(如室内、室外)的温度信号,然后将这两个模拟电压值送入一颗超低功耗的微控制器ATtiny13A中进行比较。当满足预设条件(比如“室外温度 > 室内温度 + 阈值”)时,MCU会驱动一个LED灯闪烁或者让蜂鸣器鸣响,从而实现报警功能。整个系统结构简单、成本低廉,非常适合电子爱好者、嵌入式初学者作为入门练手项目,也能为一些简单的智能家居或环境监控场景提供切实可用的解决方案。
2. 核心器件选型与原理剖析
2.1 温度传感核心:LM35详解
为什么选择LM35?在众多温度传感器中,LM35以其出色的线性度和易用性脱颖而出,特别适合模拟电路和单片机入门。它不是通过复杂的数字协议(如I2C、单总线)通信,而是直接输出一个与摄氏温度成线性正比的模拟电压信号。其核心特性是:输出电压每升高10mV,对应温度升高1°C。例如,在25°C时,其输出电压典型值为250mV;在0°C时,输出为0mV。这种“10mV/°C”的比例系数使得后续的信号处理变得极其直观。
注意:LM35的供电电压范围是4V到30V,但在本项目中我们使用5V供电。其静态电流约50μA,自热效应极低,在静止空气中温度误差小于0.5°C,精度足以满足日常环境监测。它有三个引脚:VCC(电源正)、VOUT(模拟输出)、GND(电源负)。使用时,输出端直接连接到单片机的ADC(模数转换器)输入引脚即可。
这里有一个关键点需要理解:ATtiny13A的ADC参考电压我们通常选择其内部的2.56V基准。那么,LM35的测量范围就受限于这个参考电压。2.56V / 0.01V/°C = 256°C。理论上能测到256°C,但实际上LM35自身的工作温度范围是-55°C ~ 150°C,而我们的环境监测通常就在-10°C到50°C之间,所以2.56V的基准绰绰有余,并且能在这个小温度范围内提供更高的ADC分辨率。
2.2 控制大脑:ATtiny13A的考量
选用ATtiny13A,主要是看中了它的“小而美”。作为一款8位AVR微控制器,它仅有1KB的Flash程序存储器、64字节的SRAM和64字节的EEPROM,引脚也只有8个。资源如此紧凑,为何还用?因为我们的任务足够简单:读取两个ADC通道,做一个比较运算,然后控制一个输出引脚。这完全在ATtiny13A的能力范围内。
它的优势非常明显:超低功耗。在活跃模式下,1MHz时钟、3V供电时,电流仅300μA左右;在掉电模式下,电流可以低于1μA。这对于由电池供电(如本项目计划的2节AA电池)的设备来说至关重要,可以极大地延长续航时间。此外,它内置了10位精度的ADC,正好用来读取LM35的模拟电压。虽然只有4个ADC通道(PB2-PB5),但我们只需要两个,PB3和PB4是不错的选择(对应Arduino引脚编号的A3,A2)。剩下的引脚,PB0、PB1可以作为数字输出驱动LED或蜂鸣器,PB5(RESET)要小心使用,如果不禁用,它只能作为复位引脚。
实操心得:对于ATtiny13A,新手最容易混淆的是引脚功能映射和编程方式。它不能用Arduino IDE直接通过USB线烧录,必须借助一个额外的编程器(如USBASP)。在代码中,也要注意直接操作AVR的寄存器,或者使用经过适配的“ATTinyCore”等板卡支持包来以Arduino风格编写。
2.3 外围电路与电源设计
除了核心的传感器和MCU,一个可靠的项目还需要稳定的电源和清晰的信号路径。我们计划使用2节AA电池(串联约3V)供电,然后通过一个5V升压稳压模块(如基于ME2188或FP6291的模块)为整个系统提供稳定的5V电压。为什么升压到5V?一是为了满足LM35最佳工作电压(4V以上),二是为ATtiny13A提供稳定电源以确保ADC精度。
报警输出部分,可以选择LED加限流电阻,或者有源蜂鸣器。LED更省电,蜂鸣器提醒效果更显著。驱动它们很简单,因为ATtiny13A的IO引脚在5V电压下可以输出高达20mA的电流(但整个芯片有总电流限制),直接驱动一个LED(串联一个220Ω-1kΩ的电阻)或一个5V有源蜂鸣器(注意电流,太大需加三极管驱动)毫无压力。我还预留了一个想法:这个输出引脚甚至可以驱动一个微型继电器,从而控制一个风扇或者一个更大的警示灯,扩展性很强。
3. 硬件电路设计与焊接要点
3.1 电路原理图解读
整个系统的电路原理图其实非常简洁。核心连接如下:5V电源正极(VCC)同时连接到ATtiny13A的VCC引脚(引脚8)、两个LM35的VCC引脚(引脚1)。电源地(GND)则连接到ATtiny13A的GND(引脚4)、两个LM35的GND(引脚3)以及LED的阴极(或蜂鸣器的负端)。
信号连接是重点:第一个LM35(假设用于室内)的输出引脚(引脚2)连接到ATtiny13A的PB3(引脚2,ADC3)。第二个LM35(用于室外)的输出连接到PB4(引脚3,ADC2)。ATtiny13A的PB0(引脚5)或PB1(引脚6)设置为数字输出模式,连接到LED阳极,LED阴极通过一个限流电阻(计算如下)接GND。
限流电阻计算:假设红色LED正向压降约为1.8V-2.2V,我们取2.0V。ATtiny13A输出高电平约为VCC(5V)。期望的LED电流一般在5-20mA之间,我们取一个适中的10mA。根据欧姆定律 R = (VCC - V_LED) / I = (5V - 2V) / 0.01A = 300Ω。可以选择330Ω的标准电阻,此时电流约为(5-2)/330≈9mA,亮度足够且安全。
3.2 PCB布局与焊接实操
对于这种小型项目,使用万用板(洞洞板)进行焊接是最快速灵活的选择。布局时,遵循“电源路径清晰,信号走线简短”的原则。建议将ATtiny13A(如果是DIP-8封装)放在板子中央,5V升压模块固定在板子一侧。两个LM35传感器则通过长约1-2米的杜邦线或双绞线引出,这样方便将它们分别放置于室内和室外。
焊接顺序建议:先焊接电源相关的元件,包括电源插座、升压模块的输入输出滤波电容(如果模块自带则无需额外添加)。然后焊接ATtiny13A的插座(强烈建议使用IC座,避免焊接损坏芯片)。接着焊接连接LM35的排针座和LED及电阻。最后,再进行所有飞线连接。
注意事项:
- 静电与过热:焊接LM35和ATtiny13A时,确保电烙铁接地良好,温度控制在350°C左右,焊接时间不宜过长,避免烫坏敏感半导体。
- 极性:注意所有有极性元件的方向:电解电容、LED、有源蜂鸣器、IC芯片的缺口方向。
- 电源检查:焊接完成后,先不要插入MCU和传感器。用万用表测量5V和GND之间是否短路,电压是否正确。确认无误后再通电测试。
- 传感器引线:长距离连接LM35时,虽然其输出阻抗低,抗干扰能力较强,但最好使用屏蔽线或双绞线,并将屏蔽层单点接地,以减少环境噪声对微小模拟信号(几十到几百毫伏)的干扰。
3.3 结构组装与防护
电路板焊接测试无误后,就需要考虑外壳和整体装配了。一个合适的外壳不仅能保护电路,还能让项目更美观、实用。你可以使用现成的塑料项目盒,也可以3D打印一个定制外壳。关键是要为以下部分开孔:两个LM35的引线出口、LED指示灯或蜂鸣器出声孔、电源开关。
对于室外放置的LM35传感器,需要做好防水和防晒处理。一个简单有效的方法是将传感器头部(金属封装部分)涂抹导热硅脂后,塞入一段短的铜管或不锈钢管中,管口用热熔胶或环氧树脂密封,这样既能保证热传导,又能防雨。引线端同样要用热缩管或胶水做好密封。室内传感器则可以简单放置,或者也做一个小外壳,避免直接接触物体导致测温不准(我们测的是空气温度)。
4. 软件编程与逻辑实现
4.1 开发环境搭建与芯片编程
给ATtiny13A编程,你需要一个编程器。最常见且廉价的选择是USBASP。连接方式如下:USBASP的MOSI、MISO、SCK、RST、VCC、GND分别连接到ATtiny13A对应的PB0(MOSI)、PB1(MISO)、PB2(SCK)、PB5(RESET)、VCC、GND。注意,有些USBASP需要连接一个10uF电容到其复位引脚才能稳定工作,具体看型号说明。
软件方面,你可以选择纯AVR开发(如Atmel Studio、PlatformIO),或者使用Arduino IDE进行“伪装”开发。对于新手,Arduino IDE更友好。你需要先安装ATTinyCore板卡支持包。安装好后,在“工具”菜单下依次选择:“开发板:ATtiny”、“处理器:ATtiny13”、“时钟:内部9.6MHz”(或1.2MHz以降低功耗)、“编程器:USBASP”。然后就可以像编写普通Arduino程序一样编写代码,最后点击“通过编程器上传”即可。
关键步骤:设置熔丝位。熔丝位决定了芯片的一些底层配置,如时钟源、启动延时、看门狗等。对于我们的应用,通常使用内部9.6MHz RC振荡器,并禁用看门狗(除非你程序需要)。在Arduino IDE中,ATTinyCore通常提供了安全的默认熔丝设置。对于高级用户,如果使用.hex文件直接烧录,需要确认熔丝位是否与编程环境匹配。原项目提到“fuses can remain default”,对于ATtiny13A,通常意味着使用内部9.6MHz时钟,这是出厂默认设置之一,但为了保险,最好用编程软件(如avrdude配合USBASP)读取并确认一下。
4.2 核心代码逻辑解析
程序的逻辑非常清晰,主要包含以下几个部分:
- 初始化:配置用于ADC的引脚(PB3, PB4)为输入,配置报警输出引脚(如PB0)为输出。初始化ADC,设置参考电压为内部的2.56V,并选择适当的预分频器使ADC时钟在50-200kHz之间以获得最佳精度。
- ADC读取函数:编写一个函数,传入ADC通道号(如3或2),启动一次转换,等待转换完成,然后读取10位的ADC结果并返回。这个结果是一个0-1023之间的整数,对应0V到2.56V的电压。
- 温度计算与比较:在主循环中,分别读取两个通道的ADC值。将ADC值转换为电压:
电压 = ADC值 * 2.56 / 1024。再将电压转换为温度:温度 = 电压 * 100(因为10mV/°C,所以100倍就是摄氏度)。现在你得到了室内温度(T_in)和室外温度(T_out)。 - 比较逻辑与报警:实现你想要的比较逻辑。最简单的逻辑是:如果
T_out > T_in,则触发报警。但为了防抖和增加灵活性,可以引入一个“迟滞阈值”(Hysteresis),例如:当T_out > T_in + 1.0时开启报警;当T_out < T_in + 0.5时才关闭报警。这样可以避免在临界点附近报警器频繁开关。一旦满足报警条件,就将报警输出引脚置高(驱动LED亮或蜂鸣器响);否则置低。 - 低功耗优化(可选):为了省电,可以在每次读取和比较后,让MCU进入空闲模式或掉电模式一段时间(比如用看门狗定时器唤醒,设置8秒睡眠),然后再进行下一次测量。这能大幅降低平均功耗。
4.3 代码示例与关键参数
下面提供一个简化版的Arduino风格代码框架,展示了核心逻辑:
// 引脚定义 const int indoorSensorPin = A3; // ATtiny13A的PB3, ADC3 const int outdoorSensorPin = A2; // ATtiny13A的PB4, ADC2 const int alarmPin = 0; // ATtiny13A的PB0 // 参数定义 const float hysteresis = 1.0; // 迟滞阈值,单位°C bool alarmState = false; float tempIndoor, tempOutdoor; void setup() { pinMode(alarmPin, OUTPUT); digitalWrite(alarmPin, LOW); // 配置ADC参考电压为内部2.56V analogReference(INTERNAL2V56); // 注意:ATTinyCore中可能用 INTERNAL2V56 // 对于ATtiny13A,内部参考是2.56V,但Arduino函数可能叫INTERNAL1V1,需查核心文档 // 更底层的方法是直接操作ADMUX寄存器,例如:ADMUX = _BV(REFS1) | _BV(REFS0); // 内部2.56V } int readADC(int channel) { ADMUX = _BV(REFS1) | _BV(REFS0) | (channel & 0x07); // 设置参考和通道 delayMicroseconds(200); // 等待输入稳定 ADCSRA |= _BV(ADSC); // 启动转换 while (ADCSRA & _BV(ADSC)); // 等待转换完成 return ADC; } float readTemperature(int sensorPin) { int adcValue = readADC(sensorPin == indoorSensorPin ? 3 : 2); // 根据引脚映射通道 float voltage = adcValue * 2.56 / 1024.0; float temperature = voltage * 100.0; // 转换为摄氏度 return temperature; } void loop() { tempIndoor = readTemperature(indoorSensorPin); tempOutdoor = readTemperature(outdoorSensorPin); if (tempOutdoor > (tempIndoor + hysteresis)) { alarmState = true; } else if (tempOutdoor < (tempIndoor + hysteresis - 0.5)) { // 关闭报警的阈值略低,形成迟滞 alarmState = false; } digitalWrite(alarmPin, alarmState ? HIGH : LOW); delay(5000); // 每5秒测量一次,可根据需要调整 }注意:以上代码是概念性框架。实际使用ATTinyCore时,
analogReference(INTERNAL2V56)可能不可用,需要直接配置AVR寄存器。具体寄存器操作需要查阅ATtiny13A的数据手册。这是从Arduino过渡到底层AVR编程的一个小门槛,但也是学习嵌入式的好机会。
5. 系统调试与性能优化
5.1 上电调试与传感器校准
硬件焊接和软件烧录完成后,就是激动人心的上电调试阶段。首先,不接室外传感器,只接室内传感器。用万用表测量LM35的输出电压,同时读取单片机通过ADC计算出的温度值。你可以用嘴向LM35哈气(升温)或用冰块靠近(降温),观察电压和读数变化是否正常。计算关系应该是:电压值(V)* 100 ≈ 温度值(°C)。由于ADC和基准电压存在微小误差,两个传感器之间也可能有偏差,因此可能需要一个简单的软件校准。
软件校准可以在代码中引入一个偏移量(Offset)。例如,在一个已知温度(如室温25°C)下,读取传感器A的值为24.5°C,那么就可以为传感器A设置一个+0.5°C的偏移。更简单的方法是计算两个传感器的相对一致性:将它们紧挨着放在同一环境中,读取温度值T1和T2,在后续比较时,将T2减去一个固定的差值(T2-T1),使得它们“看起来”测得的温度相同。这样,即使绝对温度有偏差,也不影响“谁比谁热”的比较逻辑。
5.2 功耗测试与续航评估
本项目的一个设计目标是低功耗。为了评估实际续航,你需要测量系统在不同状态下的工作电流。使用万用表的电流档,串联在电池和升压模块输入端之间进行测量。
- 主动测量模式:MCU全速运行,ADC转换,LED熄灭。电流主要来自ATtiny13A(约几mA)、两个LM35(每个约50μA)和升压模块自身的静态电流(效率高的模块可能低至几十μA)。假设总计5mA。
- 报警模式:在主动测量电流基础上,加上LED的电流(约9mA),总计约14mA。
- 睡眠模式(如果实现):MCU进入掉电模式,定时由看门狗唤醒。此时ATtiny13A电流可降至1μA以下,LM35和升压模块静态电流成为主导。假设总计100μA。
假设使用2节AA碱性电池,总容量约2000mAh。如果系统每5秒唤醒工作100ms(电流5mA),其余时间睡眠(电流100μA),那么平均电流可以估算得非常低。粗略计算,续航可达数月甚至一年。如果不使用睡眠,持续工作电流14mA,续航则只有2000mAh / 14mA ≈ 143小时,约6天。由此可见,实现睡眠模式对电池供电设备至关重要。
5.3 抗干扰与稳定性提升
在实际部署中,尤其是室外传感器引线较长时,可能会引入干扰。除了之前提到的使用双绞线/屏蔽线,还可以在软件上做文章:
- 数字滤波:不要只依赖单次ADC采样。可以对每个通道连续采样多次(如16次),然后取平均值或中位值,这能有效抑制随机噪声。
- 软件迟滞:前面已经提到,在比较逻辑中加入迟滞,可以防止温度在阈值附近微小波动时导致的报警输出抖动。
- 看门狗定时器:启用ATtiny13A的内部看门狗,设置一个合适的超时时间(如8秒)。在程序主循环中定期喂狗。如果程序因为干扰跑飞,看门狗超时会导致芯片复位,让系统恢复工作。这是一种重要的可靠性保障措施。
6. 功能扩展与进阶玩法
基础的温度比较报警功能实现后,这个小小的平台还有很大的扩展空间,你可以根据自己的兴趣和需求进行改造。
6.1 输出方式的多样化
报警输出不限于LED和蜂鸣器。你可以用MCU的IO口控制一个单路继电器模块,当温度条件触发时,继电器吸合,可以直接接通或切断一个220V交流电的设备,比如一个小风扇、一个警示灯,甚至自动关窗器(如果窗户是电动的)。如果使用固态继电器(SSR),控制会更加安静和长寿。另外,你也可以驱动一个微型振动马达,做成一个静音的震动提醒装置,放在枕头下或口袋里。
6.2 显示与交互的加入
虽然ATtiny13A的IO口和资源有限,但通过巧妙的编程,仍然可以驱动一个简单的数码管或OLED显示屏来实时显示室内外温度值。例如,可以使用一个I2C接口的0.96寸OLED屏,但ATtiny13A没有硬件I2C,需要用软件模拟(软件I2C),这会占用两个IO口并增加代码复杂度。更简单的方法是使用一个TM1637驱动的4位数码管模块,它只需要两个IO口(CLK, DIO)和简单的时序通信。加入显示后,设备就从一个简单的报警器升级成了一个迷你温度监测站。
6.3 逻辑复杂化与智能化
当前的逻辑是简单的“A > B + 阈值”。你可以让它更智能:
- 多段报警:设置多个温度阈值。例如,
T_out > T_in + 2°C时LED慢闪,T_out > T_in + 5°C时LED快闪并蜂鸣。 - 时间控制:结合ATtiny13A的内部定时器或外部RTC模块,实现“仅在白天8点到晚上10点启动监测”这样的功能,避免夜间不必要的报警。
- 数据记录:虽然ATtiny13A的EEPROM只有64字节,但精打细算的话,可以每隔一小时记录一次温度数据(比如只记录一个字节的整数温度值),实现几天的简单数据追溯。
6.4 传感器网络的雏形
如果你有多个这样的节点,可以设想一个更宏大的应用:每个节点负责监测一个房间或一个区域的温度,并通过简单的无线模块(如433MHz ASK发射模块)将报警状态发送到一个中央接收器。中央接收器再用一个功能更强的MCU(如Arduino Uno或ESP8266)汇总信息,并通过网络上报或进行更复杂的联动控制。这样,你就构建了一个分布式的温度监测网络原型。
这个基于LM35和ATtiny13A的项目,麻雀虽小,五脏俱全。它涵盖了模拟信号采集、单片机编程、低功耗设计、传感器应用等多个嵌入式系统的基础知识点。从想法到实现,从焊接调试到功能扩展,整个过程充满了动手的乐趣和解决问题的成就感。它不仅仅是一个关窗提醒器,更是一个可以无限发挥创意的电子积木平台。希望你在复现和改进这个项目的过程中,能真正感受到嵌入式开发的魅力。