本帖最后由 zhuhai 于 2019-2-26 16:09 编辑
温习下小目标:
1)能测量温湿度(已达到)
2)能远程查看温湿度,历史数据曲线表达,能用手机看曲线[size=14.6667px](已达到)
3)能远程控制设备运行[size=14.6667px](已达到) [size=14.6667px]
上一步已经通过乐联网将实时测得的温湿度传送到了服务器,服务器具有数据下载和历史查询功能。在实际应用中,我们要针对温湿度达到某一值时对设备进行控制,比如打开通风等。乐联网提供了反向控制功能。有TCP方法的,有官方库文件的,官方网站也提供测试平台,一切看上去很完美,但是经过几天来的努力就是无法联上服务器。官方的测试平台也无测联上,显示网关没有开启。官方有个QQ技术群,几次申请加入也没有成功。看来反向控制乐联网是没法做了,有高人看过此文后希望能提供办法,因为乐联的数据查询下载功能还是不错的。
为了实现小目标,继续在网上找,终于发现oneNET不错,可以接入设备多达1000个,太吓人啦。
有了成功联上乐联的经验再联oneNET不再是难事,当然离不开下面三篇参考文选的作者的付出。oneNET控制部分做得很好,可以灵活应用,数据部分不太理想,特别是历史数据,没找到查询的方法,更不用说导出了。所以要完成一个温湿度记录和控制的系统,理想方案是上传数据用乐联,设备控制用oneNET,这个留着下一次做吧。 下图上oneNET控制端,可以自定义,也可以在手机上查看,下面这个曲线图有个缺点,当程序重启时,曲线也重新开始画 第一步接线 ESP8266 MEGA2560 TX –> RX1 GND –> GND CH_PD–>3.3V VCC –> 3.3V RX –> 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, TX void(* resetFunc) (void) = 0; //制造重启命令
const char APIKEY[] = "xA=mlhUSukwcQpFKp2s*****="; // 使用时请修改为你的API KEY -- Please use your own API KEY int32_t DeviceId = 5161*****; // 使用时请修改为你的设备ID -- Please use your own device ID const 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 bps Serial1.begin(115200); pinMode(pinRelay,OUTPUT); //设置pinRelay脚为输出状态 //退出上次联接的透传 int n=0; while (1) { Serial1.println("AT+RST");//重启ESP8266 delay(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){};//缓存清零 }
//联WIFI void 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返回的值 // String get_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; } // //控制继电器 // void con_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); }
//DHT11 String 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");//重启ESP8266 Serial1.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.html 3)初次尝试ESP8266+Onenet实现数据上传和读取
https://www.arduino.cn/forum.php?mod=viewthread&tid=83204&highlight=esp8266
|