Meteorological information collection device

气象信息采集装置

Brief: I’ve made a device to collect meteorological information like temperature、humidity、pressure and so on. It has solar panel and Li-battery to make sure continually available. The device bases on the Arduino platform and works once an hour to collect sensors’s information then upload to remote server.

由于单位地处偏远,没有可用的准确的天气预报,今年冬天雾霾又实在很重,于是就想自己做个硬件实时采集气象数据发到服务器,供微信订阅号查询。

首先想到的是基于arduino平台,搭建各种传感器的数据采集端,通过联网模块发送至服务器(参见:生活小助手订阅号python后台),然后服务器对数据进行记录和格式处理,当打开微信订阅号发送查询请求时,服务器再将结果返回。

硬件模块:

温湿度模块,由于冬天室外可达零下十几度,为了保证测量范围和精度,放弃常用的DHT11选择DHT22,5V/1.5mA,仅占用一个数字IO口。

RTC模块,根据时间信息进行程序控制。比如晚上降低采集频率节省电能。选择DS1302,1~2mA,占用两个数字IO口,另有一个片选口。

Wifi模块ESP8266,开始设想的是用GSM模块发送,但是功耗较大不容易控制,用wifi模块的弊端是采集器周围必须有wifi覆盖,限制了采集器的放置。5V,66mA,工作电流大,但是不必常开,休眠电流小,uA级可忽略,使用uart总线。

降雨检测模块(定性)。5V/5mA,占用一个模拟输入口。

气压检测模块BMP180,3.3V/1~2mA,使用SPI总线。

PM2.5模块,选择的是某宝国产的模块,5V/150mA,空载48mA。由于PM2.5耗电巨大,故增加继电器模块当不需要PM2.5工作的时候使得PM2.5断电,选择常开继电器,工作时通电闭合电路使得PM2.5模块工作。串联合适的电阻,使得继电器工作电流控制在约5mA(2~4mA触发),uart总线。

主控选择简单易用的Arduino平台,选择mini为了降低模块整体大小能放到气象箱内。3.3V/20mA,休眠电流微安级可忽略。

太阳能电池板:峰值可达12V/3W,给3.7V2600mAh的充满电只需4个小时。

3.3V降压稳压模块,因为很多模块是3.3V工作的,所以需要降压,用的是AMS1117-3.3V。

5V升压稳压模块,主要是将单节锂电池的电压升至5V以支持部分模块工作,某宝买的,没有型号。

全模块待机电流约15mA,满负荷工作时约380mA,每次采集全部信息需要1分钟,按照每小时采集一次,全天需要的电能约5V/512mAh,3.7V2600mAh锂电池按照90%转换效率,可以支持4.5天的工作时长,而太阳能电池板在即使阴天也能提供一定的输出,因而,理论上该装置是可以持续工作的。

【连线】:

电路图就不画了(我自己是手画了个图就照着焊了=_=!),合理分配引脚,没什么多余的外围电路元件,都是引用的模块。。。

【代码】:

这里引用了三个库,DS1302、BMP180、DHT,主要是因为这三个涉及数据封装解析,其他的雨滴模块直接读取,PM2.5和ESP8266都是直接读写串口。

先注意这句,是继电器控制引脚,为了节省电能设置的常开(电路断)继电器,耗电大的几个模块如ESP8266、PM2.5都通过继电器模块控制,工作前需要闭合继电器,工作结束需要断开。继电器控制很简单,数字IO口基本操作。

先说简单的,【雨滴模块】:

引脚定义

定义了两个引脚,一个模拟IO一个数字IO,因为是定性检测,所以设置好阈值后一般判断数字IO即可。

初始化:

检测:

【PM2.5模块】:

由于ESP8266需要串口,为保证ESP8266工作正常,将通信速率低的PM2.5模块(9600bps)设置为软件串口,保证通信速率高的ESP8266(115200bps)正常工作减小芯片运算压力,上述代码定义了软件模拟串口的收发引脚以及PM2.5的相关命令。PM_SAMP_MAX宏定义PM2.5采样次数,PM2.5模块的说明书里有介绍,为保证精度最好在模块开机并运行稳定后做多次采样。这里定义的软件模拟串口PMSerial也同于调试模式下的调试信息输出。

初始化:

应用的时候直接和普通串口一样PMSerial.print()、PMSeiral.read(),具体的使用方法,如模块开机、信息采集、信息解析需要参考对应的模块文档。不过好在市面上多数模块使用方法几乎相同,所以并不是大问题,可以参考网上其他教程或资料。无非是指定格式的字节数组收发和处理,模块交互设计比较友好(发一个命令,返回一个结果),不是大问题,这里不重点描述。

【ESP8266】:

虽然ESP8266只涉及串口通信,但是可能因为模块设计或通信速率较高(115200bps)的原因,因为容易出错,首先是电压需要控制在3.3V,我试过当整个模块用usb接口供电,模块就不能正常工作,没有深入排查,暂时不能明确是电压不足还是电源波纹等因素干扰。

先定义wifi连接命令宏以及连接远程服务器命令宏:

由于存在发送失败的可能,因而定义最大重发次数:

封装发送AT指令函数:

定义了两个ESAPI_SEND,只用该函数做示例,ESP8266模块的AT指令通信模式下,每发送一个AT指令,模块都将有一个应答。该函数的第一个参数为AT指令,第二个参数为应答中的匹配关键字段,若应答字符串中匹配到了该关键字,则返回应答成功。

封装连接服务器并向服务器发送消息函数:

初始化并向服务器报告开机状态:

【DHT22】:

引用Arduino平台的DHT11库,DHT11和DHT22用法完全一样,只是模块量程、精度不同罢了。

初始化:

采集:

采集的时候传入引脚,然后直接查询类成员。

【BMP180】:

走捷径可以直接google一篇博文参考,否则看看库文件以及模块文档。

初始化:

信息采集:

为了方便观看这里删除了注释和调试信息,原代码保留了很多注释,里面说的很详细,这里稍微介绍下,如果要用BMP180测海拔,需要提前获取基准海拔气压,比如测山上海拔,需要山脚的气压和海拔,测高差则只需基准面气压值。这个也很好理解。BMP180测气压需要先测温度,因为温度和气压是相关的。getTemperature和startPressure函数均返回需要等待的毫秒数,最后getPressure获取气压和温度值。

【DS1302】:

这个就是很常见的模块了,网上封装了很多的库,自定义了通信协议,根据文档的时序逻辑也可以自己尝试写库。当然这种轮子没必要反复造,造过几次就可以了:)。这里和时钟结合的是用了Arduino的EEPROM,用来存储同步RTC的时间信息。原本设计是从服务器获取时间(定期同步)或通过软串口获取(按键触发),该程序里偷了个懒,仅调试模式下可以同步RTC时间信息,还是直接改源码设置时间,不是很方便,同时时间也不够准。

宏定义:

初始化设置:

时间获取:

【休眠】:

这里重点提一下Arduino的休眠省电模式,因为这个在平时DIY用的不多,但是对于户外连续工作的装置还是很有用的:

【引用自网络http://www.geek-workshop.com/thread-12261-1-1.html】

在需要睡眠的地方调用EnterSleepMode();进入休眠。Arduino程序主循环中依次采集模块的输出,然后将结果汇总通过wifi模块发送到指定服务器,每个循环结束进入睡眠状态节省电能。更多休眠相关信息可以参考如下网站:

http://www.gammon.com.au/forum/?id=11497

http://swf.com.tw/?p=525

程序调试输出:

可以看到PM2.5的测定需要一段时间才能稳定。其中电池的测量是用模拟引脚读取,5V对应1024,因而771实际约3.76V。

图1 半成品电路

图2 电路完工

图3 装箱

图4 成品外观

如有疑问,可以留言!

【附录】

代码及相关资料链接:

Code:【AutoWeather

BMP180

DHT22-AM2302

DS3231

Enerlib

PM2.5

RainDetection

ESP8266

 

发表评论