基于ESP8266的阿里云远程实时温度监控
基于ESP8266的远程实时温度监控系统,通过ESP8266开发板采集DHT11温湿度传感器的数据,在连接WIFI接入网络中,将实时采集到的温湿度数据通过MQTT通信协议上云,传送至阿里云网络平台中进行实时的网页显示。同时,网页可以通过开关控制网页上的警示灯的状态,并且利用MQTT通信协议下发指令控制ESP8266的LED灯亮灭;在本地端实现了温湿度数据上报,温度报警,即在温度超过设定的阈值(25℃)后,便开启警报(ESP8266上LED亮红灯、网页上警示灯亮红灯)。
IT行业:机房的环境设备对温度、湿度以及安全性的要求也越来越严格,这是保证计算机系统能够正常运行的基本环境。一旦机房环境设备出现故障,就会影响到计算机系统的运行,对数据传输、存储及系统运行的可靠性构成威胁。
食品行业:温湿度对于食品储存来说至关重要,温湿度的变化会带来食物变质,引发食品安全问题温湿度的监控有利于相关人员进行及时的控制。
档案管理:纸制品对于温湿度极为敏感,不当的保存会严重降低档案保存年限。环境监控云系统,配上排风机,除湿器,加热器,即可保持稳定的温度,避免虫害,潮湿等问题。
温室大棚:植物的生长对于温湿度要求极为严格,不当的温湿度下,植物会停止生长、甚至死亡。环境监控云配合气体传感器,光照传感器等可组成一个数字化大棚温湿度监控系统,控制农业大棚内的相关参数,从而使大棚的效率达到极致。
动物养殖:各种动物在不同的温度下会表现出不同的生长状态,高质高产的目标要依靠适宜的环境来保障。
药品储存:根据国家相关要求,药品保存必须按照相应的温湿度进行控制。根据最新的GMP认证,对于一般的药品的温度存储范围为0-30℃。
烟草行业:烟草原料在发酵过程中需要控制好温湿度,在现场环境方便的情况下可利用温湿度传感器监控温湿度,在环境复杂的现场内,可进行检测控制烟包的温湿度,避免发生虫害,如果操作不当,则会造成原料的大量损失。
基于ESP8266的远程实时温度监控系统,通过ESP8266开发板采集DHT11温湿度传感器的数据,在连接WIFI接入网络中,将实时采集到的温湿度数据通过MQTT通信协议上云,传送至阿里云网络平台中进行实时的网页显示。同时,网页可以通过开关控制网页上的警示灯的状态,并且利用MQTT通信协议下发指令控制ESP8266的LED灯亮灭;在本地端实现了温湿度数据上报,温度报警,即在温度超过设定的阈值(25℃)后,便开启警报(ESP8266上LED亮红灯、网页上警示灯亮红灯)。
ESP8266具有低功耗、紧凑设计和高稳定性等特点。ESP8266拥有完整的且自成体系的Wi-Fi网络功能,既能够独立应用,也可以作为从机搭载于其他主机 MCU运行。当ESP8266独立应用时,能够直接从外接flash中启动。内置的高速缓冲存储器有利于提高系统性能,并且优化存储系统。此外ESP8266只需通过 SPIV/SDIO接口或UART接口即可作为Wi-Fi适配器,应用到基于任何微控制器的设计中。ESP8266集成了天线开关、射频 balun、功率放大器、低噪声放大器、滤波器和电源管理模块。这样紧凑的设计仅需极少的外部电路并且能将PCB的尺寸降到最小。ESP8266还集成了增强版的Tensilica’s L106钻石系列32-bit 内核处理器,带片上SRAM。ESP8266可以通过IO外接传感器和其他设备。软件开发包(SDK)提供了一些应用的示例代码。
ESP8266 的工作温度范围大,且能够保持稳定的性能,能适应各种操作环境。我们将详细看看ESP8266。这是一个无线保真(Wi-Fi)的小工具。它是在芯片(SoC)一个实用系统,它是内置的与TCP/IP协议中,由于这个任意微控制器可以与任何Wi-Fi网络来连接。它有监督的任何其他设备的电源,也可以很容易地下放Wi-Fi网络与其它系统连接。它有片上变异的巨量这是好的为最小的外部电路。该模块是一个极其成本效益的板。ESP8266 内置超低功耗Tensilica L106 32 位 RISC 处理器,CPU 时钟速度最高可达 160 MHz,支持实时操作系统(RTOS) 和 Wi-Fi 协议栈,可将高达 80% 的处理能力留给应用编程和开发。ESP8266 的工作温度范围大,且能够保持稳定的性能,能适应各种操作环境,可以说目前ESP8266目前占据了相当大的市场份额,尤其是米家、百度、阿里等平台都在使用ESP8266。
DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。每个DHT11传感器都在极为精确的温湿度校验室中进行校准。校准系数以程序的形式储存在OTP内存中,传感器内部在检测信号的处理过程中要调用这些校准系数。
DHT11包括一个电阻式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接。其单线制串行接口,使系统集成变得简易快捷。超小的体积、极低的功耗,信号传输距离可达20米以上,使其成为各类应用甚至最为苛刻的应用场合的最佳选则,更加适合本次的远程温度实时监测系统。
DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性与卓越的长期稳定性。传感器包括一个电阻式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接。因此该产品具有品质卓越、超快响应、抗干扰能力强、性价比极高等优点。每个DHT11传感器都在极为精确的湿度校验室中进行校准。校准系数以程序的形式储存在OTP内存中,传感器内部在检测信号的处理过程中要调用这些校准系数。单线制串行接口,使系统集成变得简易快捷。超小的体积、极低的功耗,信号传输距离可达20米以上,使其成为各类应用甚至最为苛刻的应用场合的最佳选则。产品为4针单排引脚封装。连接方便,特殊封装形式可根据用户需求而提供。
MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(Publish/Subscribe)模式的轻量级通讯协议,是为硬件性能低下的远程设备以及网络状况糟糕的情况下而设计的发布/订阅型消息协议,该协议构建于TCP/IP协议上,由IBM在1999年发布,目前最新版本为v3.1.1。MQTT最大的优点在于可以以极少的代码和有限的带宽,为远程设备提供实时可靠的消息服务。做为一种低开销、低带宽占用的即时通讯协议,MQTT在物联网、小型设备、移动应用等方面有广泛的应用。
众所周知,TCP/IP参考模型可以分为四层:应用层、传输层、网络层、链路层。TCP和UDP位于传输层,应用层常见的协议有HTTP、FTP、SSH等。MQTT协议运行于TCP之上,属于应用层协议,因此只要是支持TCP/IP协议栈的地方,都可以使用MQTT。
发布/订阅模式解耦了发布消息的客户(发布者)与订阅消息的客户(订阅者)之间的关系,这意味着发布者和订阅者之间并不需要直接建立联系。
这个模式有以下好处:
发布者与订阅者只需要知道同一个消息代理即可;
发布者和订阅者不需要直接交互;
发布者和订阅者不需要同时在线。
在本项目的数据上传以及指令下发采用的格式均为JSON格式。
JSON中文全称是JavaScript对象标记语言,在这门语言中,一切都是对象。因此,任何支持的类型都可以通过JSON来表示,例如字符串、数字、对象、数组等。其语法规则是:
对象表示为键值对;
数据由逗号分隔;
花括号保存对象;
方括号保存数组。
JSON层次结构简洁清晰,易于阅读和编写,同时也易于机器解析和生成,有效提升网络传输效率。
使用ESP8266和DHT11模块实现温湿度的采集,其硬件接线简单,只需要接好VCC、GND以及信号线即可。DHT11信号线的接线需要依据代码上定义的引脚进行正确接线。若DHT 11读不出数据或读取的数据一直长时间无变化,很有可能是因为电压不够,可采取的措施是换个3.3V或者VIN(可做5V电压输出)引脚接。
当收到阿里云下发的消息(如图红框内所示),则证明有阿里云控制界面的开关按下:
串口监听到灯亮的信息:
串口接收到灯灭的信息:
A、上传一个指令到控制阿里云警示灯亮的代码:
B、控制esp8266警示灯亮的代码:
A、上传一个指令到控制阿里云警示灯亮的代码:
B、控制esp8266警示灯亮的代码:
A、上传一个指令到控制阿里云警示灯灭的代码:
控制esp8266警示灯灭的代码:
B、阿里云控制页面显示和ep8266显示:
达到阈值时警示灯亮
通过阿里云控制页面开关控制警示灯的灭:
完整代码及注释如下:
//调用库
#include
#include
#include
#include
#include //调用DHT库
//定义引脚
DHT dht(D1, DHT11);
/* 连接WIFI SSID和密码 */
#define WIFI_SSID "xxxxxxxxxxxxxx"
#define WIFI_PASSWD "xxxxxxxxxxxxxx"
/* 阿里云提供的设备三元组信息*/
#define PRODUCT_KEY "xxxxxxxxxxxxxx"
#define DEVICE_NAME "xxxxxxxxxxxxxx"
#define DEVICE_SECRET "xxxxxxxxxxxxxx"
#define REGION_ID "xxxxxxxxxxxxxx"
/* 线上环境域名和端口号,不需要改 */
#define MQTT_SERVER PRODUCT_KEY ".iot-as-mqtt." REGION_ID ".aliyuncs.com"
#define MQTT_PORT 1883
#define MQTT_USRNAME "xxxxxxxxxxxxxx"
#define CLIENT_ID "xxxxxxxxxxxxxx"
#define MQTT_PASSWD "xxxxxxxxxxxxxx"
//宏变量申明属性上传和下发的格式
#define ALINK_BODY_FORMAT "{\"id\":\"ESP8266\",\"version\":\"1.0\",\"method\":\"thing.event.property.post\",\"params\":%s}"
#define ALINK_TOPIC_PROP_POST "/sys/a1qR1D5lUTM/ESP8266_DHT11/thing/event/property/post"
//#define event_post " /sys/a1qR1D5lUTM/ESP8266_DHT11/thing/event/ledstate/post"
//变量申明
unsigned long lastMs = 0; //数据更新时间
float RH, T, RH_sum, T_sum; //温湿度取值
unsigned char count = 0; //温湿度采集次数
WiFiClient espClient;
PubSubClient client(espClient);
SHTC3 mySHTC3;
int FLAG = 0; //网页警示灯控制开关信号下发的标志
int f = 1; //温度报警标志
//初始化
void setup()
{
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH);
Serial.begin(115200); //波特率定义
Serial.println("Demo Start");
wifiInit(); //wifi初始化
Wire.begin(D5, D6); //接口申明
unsigned char i = 0;
errorDecoder(mySHTC3.begin());
dht.begin();
}
//回调中断函数
void callback(char *topic, byte *payload, unsigned int length)
{
char param[32];
char jsonBuf[128];
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
payload[length] = '\0';
Serial.println((char *)payload);
Serial.println(payload[2]);
if (payload[2] == 109) //截取阿里云的云平台下发的指令
{
if (FLAG)
{
digitalWrite(LED_BUILTIN, LOW); //开ESP8266主板的指示灯LED
sprintf(param, "{\"ledstate\":%d}", 1); //开网页警示灯的指令
sprintf(jsonBuf, ALINK_BODY_FORMAT, param);
client.publish(ALINK_TOPIC_PROP_POST, jsonBuf);//以jsonBuf的格式上传属性
Serial.println(jsonBuf);
boolean d = client.publish(ALINK_TOPIC_PROP_POST, jsonBuf);
if (d) {
Serial.println("publish Temperature success");
} else {
Serial.println("publish Temperature fail");
}
}
else
{
digitalWrite(LED_BUILTIN, HIGH);
sprintf(param, "{\"ledstate\":%d}", 0);
sprintf(jsonBuf, ALINK_BODY_FORMAT, param);
client.publish(ALINK_TOPIC_PROP_POST, jsonBuf);
Serial.println(jsonBuf);
boolean d = client.publish(ALINK_TOPIC_PROP_POST, jsonBuf);
if (d) {
Serial.println("publish Temperature success");
} else {
Serial.println("publish Temperature fail");
}
}
/*由于云台控制开关指令没按下一次,发送有效数据“1”,复位后无有效数据“0”传送,
故利用开关控制灯的转态,采用取反来作为灯的另一种状态*/
FLAG = !FLAG;
}
}
//wifi初始化
void wifiInit()
{
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASSWD); //连接WiFi
while (WiFi.status() != WL_CONNECTED) //持续不断请求接入网路
{
delay(1000);
Serial.println("WiFi not Connect");
}
Serial.println("Connected to AP");
Serial.println("IP address: "); //打印WIFI的本地IP
Serial.println(WiFi.localIP());
Serial.print("espClient [");
client.setServer(MQTT_SERVER, MQTT_PORT); /* 连接WiFi之后,连接MQTT服务器 */
client.setCallback(callback);
}
//连接MQTT
void mqttCheckConnect()
{
while (!client.connected())
{
Serial.println("Connecting to MQTT Server ...");//MQTT正在连接
if (client.connect(CLIENT_ID, MQTT_USRNAME, MQTT_PASSWD))
{
Serial.println("MQTT Connected!");//MQTT连接成功
}
else
{
Serial.print("MQTT Connect err:");//MQTT连接失败
Serial.println(client.state());
delay(5000);
}
}
}
//利用MQTT上传数据部分
void mqttIntervalPost()
{
char param[32]; //定义容量为32字节的缓存区用于存放参数
char jsonBuf[128]; //定义容量为128字节的缓存区用于存放jsonBuf数据
sprintf(param, "{\"CurrentTemperature\":%f}", T_sum / count); //发送温度平均值
sprintf(jsonBuf, ALINK_BODY_FORMAT, param);
Serial.println(jsonBuf);//打印设备上传至云台的数据
boolean d = client.publish(ALINK_TOPIC_PROP_POST, jsonBuf);//申明增量用于上传成败的持续判断
if (d) {
Serial.println("publish Temperature success");//上传温度成功
} else {
Serial.println("publish Temperature fail");//上传温度失败
}
sprintf(param, "{\"CurrentHumidity\":%f}", RH_sum / count);
sprintf(jsonBuf, ALINK_BODY_FORMAT, param);
Serial.println(jsonBuf);
d = client.publish(ALINK_TOPIC_PROP_POST, jsonBuf);
if (d) {
Serial.println("publish Humidity success");//上传湿度成功
} else {
Serial.println("publish Humidity fail");//上传湿度失败
}
}
void errorDecoder(SHTC3_Status_TypeDef message)//检错函数
{
switch (message)
{
case SHTC3_Status_Nominal : Serial.print("Nominal"); break;
case SHTC3_Status_Error : Serial.print("Error"); break;
case SHTC3_Status_CRC_Fail : Serial.print("CRC Fail"); break;
default : Serial.print("Unknown return code"); break;
}
}
//主函数
void loop()
{
delay(1000); //延时1000毫秒
RH = dht.readHumidity(); //读取湿度数据
T = dht.readTemperature();//读取温度数据
RH_sum += RH;
T_sum += T;
count += 1;
Serial.print("Humidity:"); //向串口打印 Humidity
Serial.print(RH); //向串口打印湿度数据
Serial.print("%");
Serial.print(" Temperature:");
Serial.print(T); //向串口打印温度数据
Serial.println("C");
char param[32];
char jsonBuf[128];
if (millis() - lastMs >= 3000) //数据上传时间间隔
{
lastMs = millis(); //当前时间获取
mqttCheckConnect(); //检查MQTT连接
/* 上报 */
mqttIntervalPost();
count = 0;
RH_sum = 0;
T_sum = 0;
}
if (T >= 25 && f == 1) //温度大于额定阈值(25℃)且f(开灯标志)=1,开灯
{
digitalWrite(LED_BUILTIN, LOW); // 开灯
sprintf(param, "{\"ledstate\":%d}", '1');
sprintf(jsonBuf, ALINK_BODY_FORMAT, param);//上传开警示灯指令
client.publish(ALINK_TOPIC_PROP_POST, jsonBuf);
/*开灯标志加1,不会重复进入开灯状态,
此时网页警示灯控制开关可以对警示灯和LED的状态进行控制*/
f = f + 1;
}
if (T < 25 && f != 1)//温度小于额定阈值(25℃)且f(开灯标志)不等于1,关灯
{
sprintf(param, "{\"ledstate\":%d}", '0');
sprintf(jsonBuf, ALINK_BODY_FORMAT, param);//上传关警示灯指令
client.publish(ALINK_TOPIC_PROP_POST, jsonBuf);
digitalWrite(LED_BUILTIN, HIGH);
f = 1;//标识符复位
}
client.loop();
}