液晶模块" title="液晶模块">液晶模块制作温湿度计" title="温湿度计">温湿度计Digital Thermometer" height="375" src="http://files.chinaaet.com/images/20111026/6194c4c9-4595-4678-8376-36637a404e98.jpg" width="521" />
图1
在上次介绍的日历钟的基础上扩展一下:让它具备检测大气温度和湿度的功能,一天24小时不间断运行并定时检测,于是,日历钟就摇身一变成为一个小小温湿度计啦。虽然气象要素很多,不过我们最常用的就是气温和湿度。一个是冷热程度,一个是环境空气中含水蒸气的多少。一般家用温度计很常见,湿度计就比较少,以前有一种干湿球温度计,但是用起来比较麻烦,准确度也不高。现在应用电子技术我们就可以做一个可以同时显示温度、湿度、时间的小仪器" title="仪器">仪器,放在家里以便随时监测我们的小环境。它的特点如下:
1.在单片机ATMega8L-8PU(以下简称M8)和日历钟电路DS1302的基础上,使用一个在工厂经过精密校准的数字式温度、湿度传感器AM2301作为探头;
2.当24小时连续工作时,纵然工作电流仅为几毫安,也不宜使用纽扣电池供电。这次选用可充电的3.6V聚合物锂电池,使它的放置地点可以不受电源限制,可以在室内,也可以在不受阳光直射和雨水接触的室外;
3.具有文字和图形界面,可以显示温度和湿度数值,以及12小时内的湿度变化记录曲线,为什么是湿度曲线呢?因为气温的变化规律一般比较稳定,湿度就不一样了,我们可以从湿度变化趋势估计一下未来的晴雨可能,这比看燕子飞高飞低要靠谱些吧?两个界面用按键切换;
4.具备锂电池线性充电电路,通过USB接口从外部取得5V电源,一边供给充电,一边维持电路继续工作;
全部元器件安装在一块70mm×90mm的小万用板上,正面、背面外形见图1、图2。正面左边那个黑色小乌龟壳就是温湿度探头。
图2 电路板背面元器件分布和连线
电路原理
电路见图3。图形点阵液晶、单片机M8、时钟电路DS1302和上次小小日历钟基本相同,不再重复。有两点稍稍不同:
1.液晶的控制虽然还是通过M8的PD口,但具体接线有所改变,不再占用两根串口线PD0和PD1,目的是为今后可能和外部通信预留接口。这好办,编程时重新定义即可;
2.因为常用电源是带保护板的3.6V充电锂电池(图3中GB2),它放完电会自动切断,为了使DS1302继续工作,必须另外使用一片3V纽扣锂电池CR1225(图3中GB1)作为时钟芯片的后备电池。也可用法拉电容,但较贵。
图3 电路原理图
图4 AM2301的读写时序脉冲示意图
TRH是数字式温湿度传感器 AM2301。它内部有经过校准的电容式湿度传感器和负温度系数热敏电阻(NTC),以及8位单片机。可测量温度范围是-40~+80℃,精度最大±1℃,湿度范围是0%~100%,常温时精度±3%,分辨率都是0.1。温度信号、湿度信号最后都转换为一个40位的二进数串行输出。其中的高16位是湿度,中16位是温度,低8位是校验和,当高16位加中16位等于低8位时,说明测量结果正确,可以采信。它使用单线总线结构,接线很简单,一共就3根线:图3中的R表示红线,接电源(3.3~5.5VΩ),Y表示黄线,是信号线,按照要求需要外接5kΩ上拉电阻R2,接M8的PC5引脚。B表示黑线,接地。
轻触按钮S1~S5还是作校时用,没有变化。
为了给400mAh的锂电池充电,通过USB插头把外部的5V电压加到智能线性充电模块TP4054。另外一个2×2微型自锁开关S6可以选择电池供电,或者电池充电。充电时5V外部电压经稳压器WY1降低为3.3V为VCC供电。
用上蓄电池了,液晶背光也可以“奢侈点”,偶尔用它一下。为此,增加了限流电阻R3和轻触按钮S5。
硬件组装
这个温湿度计电路简单,所需元件不多。除了温湿度传感器和充电模块比较特殊以外,其他都是普通元件。几个电阻和退耦电容都是用的贴片元件,尺寸是 0805,和洞洞板可以很好地配合。当然也可用普通的引线电阻、电容。集成电路使用双列直插插座反装,这样就有效利用了正面液晶屏占用的面积。具体做法和小小日历钟一样。
温湿度传感器和充电模块我都是从淘宝网上买的,搜一下“DHT21”和“TP4054”就可以找到大把,价格不高。温湿度探头的敏感元件都是装在通风透气的乌龟壳内,胶死了打不开,也就不要试图暴力拆解了,以免污染了敏感元件影响性能。
反面焊装IC插座的办法是先把引脚向外折平(这样子它更像小蜈蚣了),然后把引脚尖端稍向下弯,在洞洞板反面定位后,用尖头镊子把引脚尖端逐一捅进焊盘洞洞里,外接引线也插入相应洞洞里,一并焊接。
要注意两个锂电池最后安装,安装前必须先检查已经装好其他元器件和接线的电路板,确认VCC和地端没有短路故障。在焊接前电池先不开封,避免不小心正负极短路,以至于“出师未捷身先死”。带引脚的纽扣电池焊好即固定了,充电电池则用较厚的双面胶粘接在电路板反面固定。完工后四角一定要装上垫柱,避免电路板直接与平面接触。
其他就没有什么诀窍了,也就不再搞看图识物。7cm×9cm的洞洞板安装全部元件很宽松,实际上要想使这个小玩意工作起来,还要靠“软功夫”。下面一一分解。
编程之一:AM2301的读写时序
前面说过,温湿度探子输出的是40位的二进数。在探头进行测量并输出数据前,主控单片机M8和探头有个握手过程,步骤是:
M8的PC5空闲时一直为高,数据线处于释放状态。要启动测量,M8就在PC5输出低,使数据线拉低1ms以上(程序中用的10ms),把PC5转为输入状态,外部上拉电阻R2立即使数据线升高。在40μs以内探头发出响应:把数据线拉低80μs。M8读到这个低电平,知道探头回话了,接着探头也释放数据线80μs,M8就明白随后就是数据了。数据总是以50μs低电平先导,随后并不是以电平高低表示1、0,而是以高电平脉冲宽度表示1、0:70μs表示 1,26~28μs表示0。为了识别1和0,M8可在读先导低电平完成后,延时35μs再次读数据线,如果为高,就是1,如果为低,就是0。探头连续送出 40个低-高脉冲后,再次拉低数据线50μs,结束数据送出。脉冲示意图如图4。
实际使用时还要注意,测量应进行两次:第一次测量后,过2s再测一次,这次M8读出的数据是两秒前的测试数据。如果连续测量,间隔2s最好,无论如何不得小于1s。实际上气温和湿度一般也不会变化那么快。现在做的是每分钟测两次:在0s和2s各测一次,2s读出0s的数据,0s读的是上一分钟的数据,就丢弃了。
编程之二:AM2301的数据格式
如果数据正确(通过检查和校验),就需要把高16位湿度数据换算成十进位的3位数:000到999。在个位和十位间加上小数点,就是湿度的百分值。例如 M8读出的高16位是0B0000001100001101=512+256+8+4+1=781。湿度就是78.1%。温度类似,但是如果温度最高位为 1,意味着零下温度。
编程之三:怎样画出记录曲线
要画出一段时间的记录曲线,也就是在液晶上面按照这也就是在液晶上面按照这段时间顺序记录的数值画出对应的点。
在这块图形液晶画点的基本方法前次已经介绍过,就是先设置列坐标x和页坐标y,再写数据,用LCDSetxy(unsigned x,unsigned y)和LCDWriData(unsigned data)两个函数就可以在x列y页点亮任意8个点。但是如果直接用页坐标来画出通常用垂直坐标(行坐标)表示的点则非常不便。
图5 12小时内的温度变化记录曲线
要按照列坐标x和行坐标h(h从0到63共计64行)来画一个点,而这正是画记录曲线的基础,我们可以变换一下,先用h/8算出h所在的页,例如h为45,那么它就在45/8即5页。而余数h%8就是h在该页的第几位(现在是第5位),让一个数unsigned char tmp=0x01;那把它左移5位得到的数值0x20就是用列坐标和页坐标画点时需要给液晶输入的数值。这些数值对于每次仅仅1个点,从低位到高位只能对应于0x01、0x02、0x04、0x08、0x10、0x20、0x40、0x80这8个数中的一个。这样我们可以捏造一个函数 LCDPutDot(unsigned char x,unsigned h);来在x列,h行画出一个点了,具体代码见后文。形式上用行列坐标参数,实质上还是页列坐标参数,但却方便多了。现在再回到怎样画湿度记录曲线。由于液晶像素的限制,水平只能取128点以下。那么如果每6分钟记录一次,12小时就记录120次,把这120次的湿度数值和液晶的垂直方向点位置(与行坐标成比例)对应起来画一系列点,不就是记录曲线吗?当然垂直方向只有64点,那么我们就取51点,0到50表示0到100。还要提醒的是,液晶的垂直方向,0点在最上面,这和通常的习惯相反。那也没关系,就把(100-h)/2作为垂直坐标就对了,为简单计,可略去小数。
至此几个编程的关键都说完了。按此在程序中加入了新增的函数:
unsigned char DHT21_ReadByte(void);//读探头串行数据
void DHT21_RHT(void);//发起检测,读数
void Show_RHT(void);//显示检测值
void LcdPutDot(unsignedcharx,unsignedcharh);//画点
函数具体内容见附件程序。
为了描绘12小时的记录曲线,还要设立一个120单元的湿度记录数组unsigned charRH_record[120],好在M8的数据区有512字节,还很富裕。
每6分钟往里面顺序填入一个记录,记满后又从0单元开始。
整个程序流程和日历钟基本相同,但有改变:
启动→M8初始化→LCD初始化→检查1302是否已经运行中,如否则要初始化并启动它→读取1302数据→打开显示界面(标题、正文和最下面的显示行)→检测温湿度→延时2秒→给记录数组赋以初值→再次检测温湿度→显示温湿度→进入程序循环。
程序循环是设置一个用于软件计数的静态变量:const unsigned int delta=0;在主循环while(1){}中当delta未达到设定值例如3800前它每次递增,达到设定值后再查键→健处理→如果秒数值改变就刷新日历钟的显示。
有所改变的是如果计时达到1分钟,就开始一次检测温湿度→2秒后再检测并更新温湿度显示→如果是6的整数倍分钟,则还要在湿度记录数组中填入新的湿度记录。
在S4的按键功能触发时就按照湿度记录数组的数值逐一绘点,形成曲线。其中还包括水平和垂直标尺的绘制和当前记录位置指针的绘制。
调试
调试过程和小小日历钟类似,就不重复了。只要元件正常,接线正确,加电后把程序注入M8立刻就可以运行。绘制曲线则要等到1小时以后才画出一小段。经过 12小时曲线完成,你就可以知道过去12小时的湿度变化趋势了。按照我这里来看(番禺郊区),湿度波动还是蛮大的,晴热时可以低到40%,一下暴雨会升高到80%以上。
如果发现温度、湿度显示都为0,那么检查探头接线是否有断开。如果突然不显示了,那么恭喜你!锂电池保护板发挥了作用,没电了!赶快切换S6充电吧!在这个基础上还能进一步改进:找出24小时内的最高温湿度和最低温湿度;设定报警点,实现超限报警以及把信号发送出去等,就靠你啦!
使用
把它充好电,按一下S6,切到电池供电位置就可以了,把它放在桌上、挂在墙上都可以,只要不阳光直射,阴凉通风就可以。充一次电大约需要90分钟,充好后可以用三天以上。