查看: 2095|回复: 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-15 00:51
  • 签到天数: 65 天

    [LV.6]常住居民II

    发表于 2018-8-10 18:01 | 显示全部楼层
    为什么看不到图啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊
  • TA的每日心情
    无聊
    2018-10-7 22:04
  • 签到天数: 44 天

    [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直接用连传感器岂不更省事?
    您需要登录后才可以回帖 登录 | 立即注册  

    本版积分规则

    热门推荐

    KittenBot杯第六届开源硬件开发大赛启动啦
    KittenBot杯第六届开源硬
    大赛简介: 第六届开源硬件开发大赛由Arduino中文社区发起 由KittenBot冠名赞助
    教你如何自制一款遥控器,让你的项目变成遥控的!!!
    教你如何自制一款遥控器,
    自从上次制作了一块集成了电机驱动的最小板之后,我就发现现在市场上一块便宜且功能又
    编译报错,困扰我几天了。。。。有没有大神
    编译报错,困扰我几天了。
    安装了这个以后 新建一个,选了一块板子什么也没有敲,编译也报错,如下图 版本是1.
    博哥零基础教你玩转ESP8266(六) STA连接 —— 我想连上你
    博哥零基础教你玩转ESP826
    帖子导航: 博哥零基础教你玩转ESP8266(一) 重识ESP8266 博哥零基础教你玩转ESP8266
    i3结构3D打印机制作资料
    i3结构3D打印机制作资料
    文件太大,无法上传,提供个下载链接 https://github.com/Lighter-z/3D-i3-Prusa
    Copyright   ©2015-2016  Arduino中文社区  Powered by©Discuz!   ( 蜀ICP备14017632号-3 )
    快速回复 返回顶部 返回列表