我的Arduino之路-实现物联网应用(4)
本帖最后由 zhuhai 于 2019-2-26 16:09 编辑温习下小目标:
1)能测量温湿度(已达到)
2)能远程查看温湿度,历史数据曲线表达,能用手机看曲线(已达到)
3)能远程控制设备运行(已达到)
上一步已经通过乐联网将实时测得的温湿度传送到了服务器,服务器具有数据下载和历史查询功能。在实际应用中,我们要针对温湿度达到某一值时对设备进行控制,比如打开通风等。乐联网提供了反向控制功能。有TCP方法的,有官方库文件的,官方网站也提供测试平台,一切看上去很完美,但是经过几天来的努力就是无法联上服务器。官方的测试平台也无测联上,显示网关没有开启。官方有个QQ技术群,几次申请加入也没有成功。看来反向控制乐联网是没法做了,有高人看过此文后希望能提供办法,因为乐联的数据查询下载功能还是不错的。
为了实现小目标,继续在网上找,终于发现oneNET不错,可以接入设备多达1000个,太吓人啦。
有了成功联上乐联的经验再联oneNET不再是难事,当然离不开下面三篇参考文选的作者的付出。oneNET控制部分做得很好,可以灵活应用,数据部分不太理想,特别是历史数据,没找到查询的方法,更不用说导出了。所以要完成一个温湿度记录和控制的系统,理想方案是上传数据用乐联,设备控制用oneNET,这个留着下一次做吧。 下图上oneNET控制端,可以自定义,也可以在手机上查看,下面这个曲线图有个缺点,当程序重启时,曲线也重新开始画 第一步接线ESP8266MEGA2560TX–> RX1GND –> GND CH_PD–>3.3VVCC –> 3.3VRX–> TX1 DHT11 MEGA2560+–>5V out–>8-–>GND 继电器 MEGA2560+–>5V 控制端–>7-–>GND 第2步代码程序用到二个串口,串口0接电脑,用于监视和调试,分析报错信息,串口1接ESP8266用于WIFI联网,程序中加入了错误处理机制防止程序死机。代码如下:#include <stdlib.h>#include <SoftwareSerial.h>#include <dht11.h> dht11 DHT11;#define DHT11PIN 8//DHT11//SoftwareSerial Serial1(10, 11); // 定义软串口RX, TXvoid(* resetFunc) (void) = 0; //制造重启命令
const char APIKEY[] = "xA=mlhUSukwcQpFKp2s*****="; // 使用时请修改为你的API KEY -- Please use your own API KEYint32_t DeviceId = 5161*****; // 使用时请修改为你的设备ID -- Please use your own device IDconst char DS_Temp[] = "TEMP"; // 数据流 温度TEMP -- Stream "TEMP"const char DS_Hum[] = "HUMI"; // 数据流 湿度HUMI -- Stream "HUMI"char DataStreams[] = "light"; // 数据流 LIGHT -- Stream "LIGHT"
String comdata = ""; char terminator = 'succ';
#define SB1 "T1" #define SB2 "H1" int pinRelay=7; //管脚D7连接到继电器模块的信号脚int error_time=1;//报错次数unsigned long endtime = 0;//开机时长
void setup() {Serial.begin(9600);// opens serial port, sets data rate to 9600 bpsSerial1.begin(115200);pinMode(pinRelay,OUTPUT); //设置pinRelay脚为输出状态//退出上次联接的透传int n=0;while (1){ Serial1.println("AT+RST");//重启ESP8266delay(1000);Serial1.println("AT"); //指令测试delay(500); if(Serial1.find("OK"))//接收指令正常则返回OK { Serial.println("ESP8266 : OK"); delay(2000); break; } else { Serial1.print("+++"); //退出透传 delay(5000); Serial.print("waiting...exit..TCP."); Serial.println(n); } delay(1000); n=n+1; if (n>5){RestSys();//重启程序} }//退出上次联接的透传
connectWiFi();delay(1000);Serial1.println("AT+CIPMUX=0");//单连接模式delay(500);Serial1.println("AT+CWMODE=1");//透传模式delay(500);Serial1.println("AT+CIPMODE=1");//STA模式delay(500);Serial1.println("AT+CIPSERVER=0");delay(500);Serial1.println("AT+CIPSEND");//进入透传开始发送数据delay(5000);}
void loop() {//取 温湿度 数据while (1){ if (read_DHT11()=="true"){break;}else{delay(1000);}}//延时到间隔30秒点位while (1){ endtime=millis()/1000;if(fmod(endtime,30)==0){ break;} else{delay(1000);}} //发送 温湿度 数据while (1){ String sendstr = "{\"" + String(DS_Temp)+ "\":" + String((float)DHT11.temperature, 2) + ",\"" + String(DS_Hum) + "\":" + String((float)DHT11.humidity, 2)+ "}";send_data(sendstr);get_string();//转存串口1数据到变量delay(500);if(comdata.indexOf("succ")>0){ endtime=millis(); Serial.print(ceil(endtime/1000));//转化成秒取整 Serial.print(" send: "+sendstr); Serial.println(": OK");error_time=1;break;}else {Serial.print("send data: error ..");//没有收到返回信息再发,超过10次重启Serial.println(error_time); error_time=error_time+1;delay(500); if (error_time>10){RestSys();//重启程序 }}delay(1000); } //发送 温湿度 数据//结束
//取开关状态while (1){ get_data();//发送get取开关状态 get_string();//转存串口1数据到变量delay(500);if(comdata.indexOf("value")>0){Serial.println(comdata);con_led1();//控制继电器error_time=1;break;}else {Serial.print("get data: error ..");//没有收到返回信息再发,超过5次重启Serial.println(error_time); error_time=error_time+1;delay(500); if (error_time>5){RestSys();//重启程序 }}delay(1000); } //取开关状态//结束
while(Serial1.read()>= 0){};//缓存清零}
//联WIFIvoid connectWiFi(){Serial1.println("AT+CWJAP=\"zhu\",\"12345678\"");int n=0;while (1){ delay(1000);if(Serial1.find("OK")) // if(Serial1.find("WIFI CONNECTED")) { Serial.println("WIFI link: OK"); delay(4000); connectserver(); break; } else { Serial.print("waiting...WIFI..."); Serial.println(n); } delay(1000); n=n+1; if (n>15){RestSys();//重启程序} }}
//联TCP服务器void connectserver(){//Serial1.println("AT+CIPSTART=\"TCP\",\"192.168.10.24\",8080");//Serial1.println("AT+CIPSTART=\"TCP\",\"api.lewei50.com\",80");Serial1.println("AT+CIPSTART=\"TCP\",\"api.heclouds.com\",80");int n=0;while (1){ if(Serial1.find("OK")||Serial1.find("CONNECTED")) { delay(1000); Serial.println("TCP server: OK"); // delay(1000); break; } else { Serial.print("waiting TCPserver .."); Serial.println(n); }delay(2000); n=n+1; if (n>10){RestSys();//重启程序} } }
//发送数据void send_data(String sendstr){//Serial.println("send_data run....."); while(Serial1.read()>= 0){}//清空串口缓存Serial1.println("POST /devices/516109775/datapoints?type=3 HTTP/1.1");delay(200);Serial1.print("api-key:");Serial1.println(APIKEY);delay(200);Serial1.println("Host: api.heclouds.com");delay(200);Serial1.print("Content-Length:");Serial1.println(sendstr.length());delay(200);Serial1.println("Connection:close");delay(200);Serial1.println();delay(200);Serial1.println(sendstr);delay(200);Serial1.flush();//等待要发送的串口数据发送完毕}
////获取串口1返回的值//Stringget_string(){//Serial.println("get_string run....."); delay(2000); if (Serial1.available() > 0)//判读是否串口有数据 { if(Serial1.find("HTTP"))//串口是否有有效数据 { String comdata1 = "";//缓存清零 while (Serial1.available() > 0)//循环串口是否有数据 { comdata1 += char(Serial1.read());//叠加数据到comdata delay(2);//延时等待响应 } if (comdata1.length() > 0)//如果comdata有数据 { comdata = ""; comdata = comdata1; } }else{ comdata = "error data"; } }else { comdata="error data"; }return comdata; }
////取开关状态//void get_data(){//Serial.println("get_data run....."); Serial1.println("GET /devices/516109775/datapoints?datastream_id=light HTTP/1.1");delay(200);Serial1.print("api-key:");Serial1.println(APIKEY);delay(200);Serial1.println("Host: api.heclouds.com");delay(200);Serial1.println("Connection:close");delay(200);Serial1.println();delay(200);}
////分析返回的开关状态值//int get_state(String temp_c){//Serial.println("get_state run....."); int state1=1; if (temp_c.length() > 0)//如果comdata有数据 { int i1,i2; i1=temp_c.indexOf("value"); i2=temp_c.indexOf("}]",i1); temp_c= temp_c.substring(i1,i2); temp_c.replace("value\":",""); temp_c.trim(); //Serial.println("temp_c to int:"+String(temp_c.toInt())); state1=temp_c.toInt(); if (i1==-1){//取值错误时返回-1 state1=-1; } }return state1; }////控制继电器//voidcon_led1(){//Serial.println("con_led1 run....."); int a=get_state(comdata);//Serial.println(String(a));delay(500);
if (a==0){ Serial.println("close led"); digitalWrite(pinRelay,LOW);//输出LOW电平,继电器模块断开 }if (a==1) { Serial.println("open led"); digitalWrite(pinRelay,HIGH);//输出HIGH电平,继电器模块闭合 }delay(1000); }
//DHT11String read_DHT11(){int chk = DHT11.read(DHT11PIN);delay(1500);//时间短会取不到数据 Serial.print("Read DHT11: ");switch (chk){ case DHTLIB_OK: Serial.println("DHT11: OK"); return "true"; break; case DHTLIB_ERROR_CHECKSUM: Serial.println("DHT11: Checksum error"); return "false"; break; case DHTLIB_ERROR_TIMEOUT: Serial.println("DHT11:Time out error"); return "false"; break; default: Serial.println("DHT11:Unknown error"); return "false"; break;}}
////重启系统void RestSys(){Serial1.print("+++"); //退出透传delay(1000);Serial1.println("AT+RST");//重启ESP8266Serial1.println("AT+CWQAP");//断开当前连接的WiFi
resetFunc();//重启程序} 参考资料(感谢作者们的分享精神):1)ARDUINO MEGA2560 经过ESP8266 WIFI模块上传温湿度数据到 OneNet 服务器http://www.cnblogs.com/Mysterious/p/5734104.html 2)Arduino+ESP8266连接OneNet网上传数据的简单代码https://www.arduino.cn/thread-45177-1-1.html3)初次尝试ESP8266+Onenet实现数据上传和读取
https://www.arduino.cn/forum.php?mod=viewthread&tid=83204&highlight=esp8266
页:
[1]