我的Arduino之路-实现物联网应用(4)-Arduino中文社区 - Powered by Discuz! Archiver

zhuhai 发表于 2019-2-26 16:05

我的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]
查看完整版本: 我的Arduino之路-实现物联网应用(4)