查看: 2716|回复: 4

Arduino+ESP8266自动配网并上传温湿度、光照强度到OneNET

[复制链接]
  • TA的每日心情
    开心
    2018-11-13 12:25
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2018-7-10 11:30 | 显示全部楼层 |阅读模式
    前言:
        从接触ESP8266到现在有一段时间了,也感受到ESP8266的强大,其高性价比给极客者们带来了极大的福音。之前用ESP8266改装了一部遥控车,使其能用手机控制,手机app是用易安卓编制的,遥控车视频挂到b站了,视频地址:https://www.bilibili.com/video/av20141857?from=search&seid=10781143291446850224
        这次是打算用Arduino+ESP8266来实现智能配网以及通过EDP协议上传温度、湿度和光照强度等数据到OneNET平台,也可以用EDP下发命令来实现远程控制。
    所需材料:
        Arduino_pro_mini         1
        ESP8266-12F              1
        USB-TTL串口下载模块       1
        DHT11温湿度传感器        1
        面包板及杜板线           若干
        光敏电阻                 1
        电阻及发光二极管等       若干
    智能配网(Smart Config)
    SmartConfig的过程:
        1、wifi模块通电,没有可用的wifi, 进入混杂模式,开始监(和谐)听覆盖范围内所有WiFi数据帧;
        2、手机APP或微信端发送包含WIFI用户名和WIFI密码的UDP广播包或者组播包;
        3、智能终端的WIFI芯片可以接收到该UDP包,只要知道UDP的组织形式,就可以通过接收到的UDP包解密出WIFI用户名和密码;
        4、然后智能硬件配置收到的WIFI用户名和密码到指定的WIFI AP(路由器)上。
        ESP8266可通过AT指令进入智能配网模式,我所用的AT固件是安信可推出的固件,可在安信可官网里http://wiki.ai-thinker.com/esp8266/sdk下载。配网的AT指令可参考安信可官网http://wiki.ai-thinker.com/esp8266/examples/at_demo里的步骤。通过将AT指令写在pro mini内,再通过外部按钮按下进入配网。
        pro mini通过软串口跟ESP8266通信,而ESP8266用的是3.3V电源,pro mini用的是5V电源,所以串口必须通过电平转换才行,由于身边暂时没有电平转换模块,所以只能通过分压来实现。经过实测,ESP8266跟pro mini软串口通信用115200波特率会出现乱码,所以只能用9600波特率。
        分压和配网按钮接线图如下所示:

    程序如下:

    kittenblock中小学创客名师推荐的图形化编程软件

    #include<SoftwareSerial.h>      //使用软串口的库文件
    #define configkey 2             //配网按钮,按住时候配网
    #define configRED 7             //智能配网失败红灯亮起
    #define configGREEN 8           //智能配网成功绿灯亮起
    #define TcpLED 12               //OneNET的TCP连接灯
    #define EdpLED 6                //OneNET的EDP连接灯
    bool link;                      //判断智能配网是否成功
    bool keyOK=1;                    //判断配网按钮是否可用
    SoftwareSerial mySerial(10, 9);   // RX, TX
    void setup() {
        mySerial.begin(9600);
        pinMode(configkey,INPUT);       //设置按键引脚为输入
        pinMode(configRED,OUTPUT);      //没连上无线网
        pinMode(configGREEN,OUTPUT);    //连上无线网
        pinMode(TcpLED,OUTPUT);         //连上OneNET的TCP
        pinMode(EdpLED,OUTPUT);         //连上OneNET的EDP
    }
    void loop() {
        int buttonState = digitalRead(configkey);
        if(buttonState==0 && keyOK==1){                   //按钮被按下时
            mySerial.print("+++");
            delay(100);
            mySerial.print("+++");
            delay(100);
            digitalWrite(TcpLED, HIGH);
            analogWrite(EdpLED,255);
            digitalWrite(configGREEN, HIGH);
            digitalWrite(configRED, HIGH);
            while (!doCmdOk("AT+CWSTARTSMART=3", "OK",5));   //启动智能配网
            t1=0;
            Serial.println("Smartconfig Start");
            digitalWrite(testLED, HIGH);
            while (!doConfigOK("smartconfig connected wifi"));
            t1=0;
        if(link==1){
          Serial.println("do Config OK");
          digitalWrite(configGREEN, LOW);
          digitalWrite(testLED, LOW);
          while (!doCmdOk("AT+CIPSTART=\"TCP\",\"183.230.40.39\",876","CONNECT",5));    //OneNET的TCP透传
          t1=0;
          digitalWrite(TcpLED, LOW);                      //tcp连接指示灯亮
          Serial.println("TCP connect OK");
          while (!doCmdOk("AT+CIPMODE=1", "OK",5));       //透传模式
          t1=0;
          while (!doCmdOk("AT+CIPSEND", ">",5));          //开始发送
          t1=0;
          link=1;
          edp_connect=0;
          keyOK=0;
          Serial.println("Start send");
        } else {
          Serial.println("do Config ERROR");
          digitalWrite(configRED, LOW);
          digitalWrite(testLED, LOW);
        }
        while (!doCmdOk("AT+CWSTOPSMART", "OK",5));         //不管ESP8266有没有连上wifi,都要释放内存
        t1=0;
      }
    等待串口命令结果函数

    kittenblock中小学创客名师推荐的图形化编程软件

    booldoCmdOk(String data, char keyword[], int timeout){      //给ESP8266发送AT指令,在次数timeout范围内回应正确就返回TURE
         bool result = false;
         if (data != ""){                    
            mySerial.println(data);    //发送AT指令
            Serial.print("SEND: ");
            Serial.println(data);
         }
         while (!mySerial.available());      // 等待模块回复
         delay(200);
         if (mySerial.find(keyword)){        //返回值判断
            Serial.println("do cmd OK");
            response=1;
            result = true;
         } else {
            Serial.println("do cmd ERROR");
            result = false;
         }
         while(mySerial.read()>= 0){}   //清空串口接收缓存
         delay(800); //指令时间间隔
         t1++;
         if(t1>=timeout){         //超过设定时间,跳出循环,并返回回应判断response的值
            result = true;
            response=0;
         }
         return result;
    }
    配网时等待串口回复函数

    kittenblock中小学创客名师推荐的图形化编程软件

    booldoConfigOK(char keyword1[]){       //开启智能配网
         bool result1 = false;
         linktime=0;
         while (!mySerial.available()){  // 等待模块回复,10秒内要配网完成
            t1++;
            delay(1000);
            if(t1 >= 10){
               linktime=1;
               link=0;
               result1 = true;
               Serial.println("Config timeout");
               break;            //超过时间串口没收到信号就跳出
            }
         }
         if(linktime==0){
            delay(200);
            if (mySerial.find(keyword1)){   //返回值判断
               link=1;
               result1 = true;
            } else {
               link=0;
               result1 = false;
            }
            while(mySerial.read()>= 0){}   //清空串口接收缓存
            delay(500); //指令时间间隔
         }
         return result1;
    }
    EDP连接
        通过OneNET官网的库文件edp.c,可以很简单的连接到OneNET平台。当成功连接到平台时,会收到0x20 0x02 0x00 0x00,可以用这个信号来判断是否连接上。

    kittenblock中小学创客名师推荐的图形化编程软件

    
    if(link==1){               //当wifi连接上后,执行下面程序
        if (!edp_connect){
            while(mySerial.read()>= 0){}   //清空串口接收缓存
            packetSend(packetConnect(ID, KEY));             //发送EPD连接包
            while (!mySerial.available());                 //等待EDP连接应答
            delay(200);
            if ((tmp = mySerial.readBytes(rcv_pkt.data, sizeof(rcv_pkt.data))) > 0 ){    
              rcvDebug(rcv_pkt.data, tmp);
              if (rcv_pkt.data[0] == 0x20 && rcv_pkt.data[1] == 0x02 && rcv_pkt.data[2] == 0x00 && rcv_pkt.data[3] == 0x00)
              {
                edp_connect = 1;
                analogWrite(EdpLED,0);
                Serial.println("EDP connected.");
              }
              else
                Serial.println("EDP connect error.");
            }
            packetClear(&rcv_pkt);
          }
      }
    光敏电阻
        光敏电阻通过分压,并通过模拟口A0输入到pro mini,接线电路图如下:
        通过分压后,读出的值在0~1024之间,数值越大,说明光线约弱,有点不太直观,于是我用个简单的函数将数值控制在0~100之间,并且数值越大,光线约强。

    kittenblock中小学创客名师推荐的图形化编程软件

    
    #define lightread A0      //光敏电阻读取的数值
    ld_x=analogRead(lightread);   //光敏电阻接收的信号,信号是模拟值
    ld=(4490-4*ld_x)/49;
    温湿度传感器
        温湿度传感器DHT11接线如下图所示:

    kittenblock中小学创客名师推荐的图形化编程软件

    
    #include <dht11.h>     //使用DHT11的库文件
    #define DHT11PIN A1    //DHT11温湿度模块数值
    int wd;                //温度
    int sd;                //湿度
    int chk = DHT11.read(DHT11PIN);       //读DHT11
    wd = (float)DHT11.temperature;        //获取温度
    sd = (float)DHT11.humidity;           //获取湿度
    上传数据到OneNET平台

    kittenblock中小学创客名师推荐的图形化编程软件

    if (edp_connect && trigger){
         Serial.print("temperature : "); Serial.println(wd);      //串口打印温度
         Serial.print("humidity : "); Serial.println(sd);         //串口打印湿度
         Serial.print("LigthRead_x : "); Serial.println(ld_x);    //串口打印亮度(读值)
         Serial.print("LigthRead_y : "); Serial.println(ld);      //串口打印亮度(计算值)
         Serial.println(" ");
         sprintf(wd1,"%d",wd);       //int型转换char型
         sprintf(sd1,"%d",sd);       //int型转换char型
         sprintf(ld1,"%d",ld);       //int型转换char型
         packetSend(packetDataSaveTrans(NULL, "tem", wd1));    //发送的数据必须为字符串
         delay(100);
         packetSend(packetDataSaveTrans(NULL, "hum", sd1));  
         delay(100);
         packetSend(packetDataSaveTrans(NULL, "light", ld1));
         delay(2000);
      }
    EDP下发控制命令
        在OneNET平台开发者中心创建应用,在元件库里拉出一个开关按钮。按钮的EDP命令内容填datastr:{V}
        接收EDP命令并解析的程序:

    kittenblock中小学创客名师推荐的图形化编程软件

    
    while(mySerial.available()){     
         readEdpPkt(&rcv_pkt);
         if (isEdpPkt(&rcv_pkt)){
            pkt_type = rcv_pkt.data[0]; 
            switch (pkt_type){
               case CMDREQ:
               char edp_command[50];
               char edp_cmd_id[40];
               long id_len, cmd_len, rm_len;
               char datastr[20];
               char val[10];
               memset(edp_command, 0,sizeof(edp_command));    //置0
               memset(edp_cmd_id, 0,sizeof(edp_cmd_id));      //置0
               edpCommandReqParse(&rcv_pkt,edp_cmd_id, edp_command, &rm_len, &id_len, &cmd_len);  //按照EDP命令请求协议,解析数据
               Serial.print("rm_len: ");
               Serial.println(rm_len, DEC);
               delay(10);
               Serial.print("id_len: ");
               Serial.println(id_len, DEC);
               delay(10);
               Serial.print("cmd_len: ");
               Serial.println(cmd_len, DEC);
               delay(10);
               Serial.print("id: ");
               Serial.println(edp_cmd_id);
               delay(10);
               Serial.print("cmd: ");
               Serial.println(edp_command);
               sscanf(edp_command,"%[^:]:%s", datastr, val);
               if (atoi(val) == 1){         //atoi(),int转换为char,把一个整数转换为字符串。
                    Serial.println("LEDon");   // 使Led亮
                    digitalWrite(testLED, HIGH);
               }
               else if(atoi(val) == 0){
                    Serial.println("LEDoff");   // 使Led灭
                    digitalWrite(testLED, LOW);
               }
               packetSend(packetDataSaveTrans(NULL,datastr,val)); //将新数据值上传至数据流
               break;
          default:
               Serial.print("unknown type:");
               Serial.println(pkt_type, HEX);
               break;
               }
          }
      }
    最后的接线图:
    电脑端界面:


    文章标签:
    Arduino
    ESP8266
    OneNET
    智能配网
    AT配网



  • TA的每日心情
    奋斗
    2018-12-29 20:27
  • 签到天数: 69 天

    [LV.6]常住居民II

    发表于 2018-8-10 18:01 | 显示全部楼层
    为什么看不到图啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊
  • TA的每日心情
    慵懒
    2019-2-19 17:33
  • 签到天数: 53 天

    [LV.5]常住居民I

    发表于 2018-10-7 22:22 | 显示全部楼层
    是学习的好榜样啊,谢谢!不过代码好像不全啊,能不能传一份全的仔细学习学习啊。

    该用户从未签到

    发表于 2018-10-8 22:33 | 显示全部楼层
    esp8266本来就可直接上传,里面cpu比mini强大n倍
  • TA的每日心情
    慵懒
    2018-10-12 14:47
  • 签到天数: 20 天

    [LV.4]偶尔看看III

    发表于 2018-10-11 16:13 | 显示全部楼层
    esp8266本来就自带mcu直接用连传感器岂不更省事?
    您需要登录后才可以回帖 登录 | 立即注册  

    本版积分规则

    热门推荐

    博哥零基础教你玩转ESP8266(十三) ESP8266WiFiGeneric库
    博哥零基础教你玩转ESP826
    帖子导航帖 博哥零基础教你玩转ESP8266(一) 重识ESP8266 博哥零基础教你玩转ESP8266
    求助!WeMos D1 WiFi怎么接0.96寸OLED?(ㄒoㄒ)
    求助!WeMos D1 WiFi怎么
    求助!WeMos D1 WiFi怎么接0.96寸OLED?(ㄒoㄒ) 想用WeMos D1 WiFi接收服务器的数据然
    串口发送16进制指令求助
    串口发送16进制指令求助
    我准备串口发出16进制指令到我的外置设备 代码如下图 我分别监控ARDUINO的tx口和USB口
    一文教你选择Arduino开发板,小白进
    一文教你选择Arduino开发
    笔者在2016年接触了Arduino,跳了万条坑,行了千里弯,到今天也算是Arduino的一
    大神们!1602显示屏上的MQ2浓度示数不是实时监测的何解
    大神们!1602显示屏上的MQ
    本人小白,刚刚接触arduino,长时间的查阅资料后,通过复制修改代码接线实现了DHT11实
    Copyright   ©2015-2016  Arduino中文社区  Powered by©Discuz!   ( 蜀ICP备14017632号-3 )
    快速回复 返回顶部 返回列表