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

Arduino中文社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 3336|回复: 0

我的Arduino之路-实现物联网应用(4)

[复制链接]
发表于 2019-2-26 16:05 | 显示全部楼层 |阅读模式
本帖最后由 zhuhai 于 2019-2-26 16:09 编辑

温习下小目标:
1)能测量温湿度(已达到)
2)能远程查看温湿度,历史数据曲线表达,能用手机看曲线
[size=14.6667px](已达到)
3)能远程控制设备运行
[size=14.6667px](已达到)
[size=14.6667px]
上一步已经通过乐联网将实时测得的温湿度传送到了服务器,服务器具有数据下载和历史查询功能。在实际应用中,我们要针对温湿度达到某一值时对设备进行控制,比如打开通风等。乐联网提供了反向控制功能。有TCP方法的,有官方库文件的,官方网站也提供测试平台,一切看上去很完美,但是经过几天来的努力就是无法联上服务器。官方的测试平台也无测联上,显示网关没有开启。官方有个QQ技术群,几次申请加入也没有成功。看来反向控制乐联网是没法做了,有高人看过此文后希望能提供办法,因为乐联的数据查询下载功能还是不错的。
1.png
2.png
3.png
4.png

为了实现小目标,继续在网上找,终于发现oneNET不错,可以接入设备多达1000个,太吓人啦。
5.png

有了成功联上乐联的经验再联oneNET不再是难事,当然离不开下面三篇参考文选的作者的付出。oneNET控制部分做得很好,可以灵活应用,数据部分不太理想,特别是历史数据,没找到查询的方法,更不用说导出了。所以要完成一个温湿度记录和控制的系统,理想方案是上传数据用乐联,设备控制用oneNET,这个留着下一次做吧。
下图上oneNET控制端,可以自定义,也可以在手机上查看,下面这个曲线图有个缺点,当程序重启时,曲线也重新开始画
6.png
第一步接线
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

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|Archiver|手机版|Arduino中文社区

GMT+8, 2024-11-28 11:34 , Processed in 0.101888 second(s), 18 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表