查看: 13443|回复: 155

《博哥ESP8266系列4》- 局域网:ESP8266+路由+RGB彩灯+App

  [复制链接]
  • TA的每日心情
    开心
    2018-7-22 00:22
  • 签到天数: 430 天

    [LV.9]以坛为家II

    发表于 2017-9-16 01:14 | 显示全部楼层 |阅读模式
    本帖最后由 单片机菜鸟 于 2017-10-26 09:34 编辑

    一、前言
        楼主研究了几天ESP8266,慢慢对它有一定的了解。之前也写了几篇帖子,仅仅是介绍了基本使用方法。这次我们直接做个实际的小系统,我把它命名为《局域网:ESP8266+路由+RGB彩灯+App》,算是巩固一下所学的知识。
        在这里我们用到了不少知识,大家可以参考以下博文:
        1.ESP8266简介 参考 博哥玩物联网系列1-ESP8266基础知识
       2.蓝牙彩灯 参考 《博哥玩Arduino》- 蓝牙七彩灯基础版
        3.ArduinoJson库 参考 博哥玩物联网系列2-ArduinoJson库
          接下来先上最终的效果,有图有真相:
        5Y6B)A`@GRMBI784])IXGT0.png
        http://v.youku.com/v_show/id_XMzAyNjEwMTMwOA==.html?spm=a2h3j.8428770.3416059.1

          帖子视频看不了的话  直接点这个 链接
    二、设计思路
       
        这里的局域网,楼主理解为手机、ESP8266均连接同一个路由wifi,然后8266是作为服务端,手机作为客户端,手机再通过wifi给8266发送数据,8266接收到数据再把数据分发给Arduino,然后Arduino解析协议数据以达到控制效果。
        设计图如下:
        IMG_1632.JPG

    三、撸代码


       代码烧写分为两个部分:
        1.先烧写代码到ESP8266 烧写方法参考 《博哥ESP8266系列1》- Arduino IDE for esp8266
        代码如下(直接看代码注释):
       
    /** * 日期:2017/09/14 * 功能:wifi lamp 8266端 * 作者:单片机菜鸟 **/ #include <ESP8266WiFi.h> #define MAX_SRV_CLIENTS 3   //最大同时联接数,即你想要接入的设备数量,8266tcpserver只能接入五个,哎 #define led 2    const char* ssid     = "360wifilulu";         // XXXXXX -- 使用时请修改为当前你的 wifi ssid const char* password = "6206908you11011010";         // XXXXXX -- 使用时请修改为当前你的 wifi 密码    const unsigned long BAUD_RATE = 115200;                   // serial connection speed const unsigned long HTTP_TIMEOUT = 5000;               // max respone time from server    WiFiServer server(8266);//你要的端口号,随意修改,范围0-65535 WiFiClient serverClients[MAX_SRV_CLIENTS];    /** * @Desc 初始化操作 */ void setup() {   WiFi.mode(WIFI_AP_STA);     //设置esp8266 工作模式   Serial.begin(BAUD_RATE);   pinMode(led,OUTPUT);   digitalWrite(led, HIGH);   delay(2000);//刚启动模块的话 延时稳定一下   Serial.println();   Serial.println();   Serial.print("Connecting to ");//写几句提示,哈哈   Serial.println(ssid);   WiFi.begin(ssid, password);   //连接wifi   while (WiFi.status() != WL_CONNECTED) {     //这个函数是wifi连接状态,返回wifi链接状态     delay(500);     Serial.print(".");   }   Serial.println("");   Serial.println("WiFi connected");   delay(500);   Serial.println("IP address: ");   Serial.println(WiFi.localIP());//WiFi.localIP()返回8266获得的ip地址   server.begin();   server.setNoDelay(true);  //加上后才正常些 }    /** * @Desc  主函数 */ void loop() {   uint8_t i;   if (server.hasClient()){         for (i = 0; i < MAX_SRV_CLIENTS; i++){             if (!serverClients || !serverClients.connected()){                 if (serverClients) serverClients.stop();//未联接,就释放                 serverClients = server.available();//分配新的                 continue;             }         }         //8266tcpserver只能接入五个  超出的需要释放         WiFiClient serverClient = server.available();         if (serverClient){           serverClient.stop();         }   }      for (i = 0; i < MAX_SRV_CLIENTS; i++){         if (serverClients && serverClients.connected()){             //处理客户端发过来的数据             if (serverClients.available()){                 while (serverClients.available())                     Serial.write(serverClients.read());             }         }    } }


          这里代码功能其实就是把8266当做服务端,8266连接上路由wifi,然后监听连接进来的客户端(这里是手机),正常情况下烧写运行成功打开串口会有如下打印信息:
        %X4P@)UC7@WS1FIOHE@(_E3.png
          这里有我们手机端需要用到的IP地址,端口号固定为8266;
        当然,你也可以直接去你的wifi路由去查找分配的IP地址

        2.烧写代码到Arduino(楼主这里是Mega2560)
         代码如下:
          
    /** * 日期:2017/09/14 * 功能:wifi lamp arduino端 * 作者:单片机菜鸟 **/ #include <SoftwareSerial.h> #include <ArduinoJson.h>    const unsigned long BAUD_RATE = 115200;                   // serial connection speed const size_t MAX_CONTENT_SIZE = 50; const size_t t_bright=1,t_color=2,t_frequency=3,t_switch=4; //#define UNO      //uncomment this line when you use it with UNO board #define MEGA    //uncomment this line when you use it with MEGA board #ifdef UNO SoftwareSerial mySerial(10,11); #endif    #ifdef UNO #define WifiSerial  Serial #define MyDebugSerial mySerial #endif     #ifdef MEGA #define WifiSerial Serial1 #define MyDebugSerial Serial #endif   //该条语句用于使能DEBUG输出信息,屏蔽掉就不会输出debug调试信息 #define DEBUG //该条语句用于使能是共阴RGB  屏蔽掉就是共阳RGB //#define COMMON_GND #ifdef DEBUG #define DBGLN(message)    MyDebugSerial.println(message) #else #define DBGLN(message) #endif #ifdef UNO #define PIN_RED 3 //red 引脚 #define PIN_GREEN 5 //green 引脚 #define PIN_BLUE 6 //blue 引脚 #define PIN_ENABLE 9  //使能引脚 pwm控制亮度 #else #define PIN_RED 2 #define PIN_GREEN 3 #define PIN_BLUE 4 #define PIN_ENABLE 5   #endif int red = 0;//红色 int green = 0;//绿色 int blue = 0;//蓝色 int frequency = 1;//频率 int switch_status = 1;//关闭 or 开启 int bright = 1;//亮度 int type = 4;//当前模式 1亮度 2颜色 3呼吸 4开关 char response[MAX_CONTENT_SIZE]; int fadeValue = 0;//当前亮度 bool isAdd = true;//是否是从暗到亮    /** * @Desc 初始化操作 */ void setup() {   pinMode(PIN_RED, OUTPUT);   pinMode(PIN_GREEN, OUTPUT);   pinMode(PIN_BLUE, OUTPUT);   pinMode(PIN_ENABLE, OUTPUT);      WifiSerial.begin(BAUD_RATE);   #ifdef DEBUG     #ifdef UNO       MyDebugSerial.begin(9600);//软串口9600稳定     #else       MyDebugSerial.begin(BAUD_RATE);     #endif   #endif   DBGLN("Arduino Init End"); }    /** * @Desc  主函数 */ void loop() {   if(WifiSerial.available()>0){     clrEsp8266ResponseBuffer();     int data_size = ReceiveMessage(response, sizeof(response));     if(data_size>0){       //开始解析数据       parseData(response);     }   }   if(type == t_frequency){     //呼吸灯效果     breatheRGB(frequency);   }    } /** * 读取串口缓冲区里面的数据 */ int ReceiveMessage(char* content, size_t maxSize){   //不用 readBytes 因为比较耗时   size_t length = WifiSerial.readBytesUntil('}',content, maxSize);   content[length] = '}';   content[++length] = 0;   DBGLN(content);   return length; } /**      * @Desc 解析json      * 有三种      * 1.亮度控制页面(0 暗 1正常 2亮)      * {      *     "t": 1,      *     "bb": 2      * }      * 2.颜色控制页面      * {      *     "t": 2,      *     "cr": 154,      *     "cg": 147,      *     "cb": 255      * }      * 3.呼吸灯控制页面(0 慢呼吸 1正常 2快)      * {      *    "t": 3,      *    "gf": 1      * }      * 4.开关控制(0关闭 1开启)      * {      *    "t": 4,      *    "ss": 1      * }      **/ bool parseData(char* content) { //    -- 根据我们需要解析的数据来计算JSON缓冲区最佳大小 //   如果你使用StaticJsonBuffer时才需要 //    const size_t BUFFER_SIZE = 1024; //   在堆栈上分配一个临时内存池 //    StaticJsonBuffer<BUFFER_SIZE> jsonBuffer; //    -- 如果堆栈的内存池太大,使用 DynamicJsonBuffer jsonBuffer 代替   DynamicJsonBuffer jsonBuffer;       JsonObject& root = jsonBuffer.parseObject(content);       if (!root.success()) {     Serial.println("JSON parsing failed!");     return false;   }       type = root["t"];   switch(type){     case t_bright:          bright = root["bb"];          brightRGB(bright);          break;     case t_color:          red = root["cr"];          green = root["cg"];          blue = root["cb"];          colorRGB(red,green,blue);          break;     case t_frequency:          frequency = root["gf"];          break;     case t_switch:          switch_status = root["ss"];          bool enable = switch_status == 1;          switchRGB(enable);          break;        }   return true; } /** * 控制灯亮度 */ void brightRGB(int bright){   int level = bright%3;   int bright_level;   switch(level){     case 0://暗  50       bright_level = 50;       break;     case 1://正常 100       bright_level = 100;       break;     case 2://亮  200       bright_level = 200;       break;   }     #ifdef COMMON_GND      //共地      analogWrite(PIN_ENABLE,bright_level);     #else      analogWrite(PIN_ENABLE,255-bright_level);     #endif } /** * 控制RGB颜色 */ void colorRGB(int red, int green, int blue){   #ifdef COMMON_GND      analogWrite(PIN_RED,constrain(red,0,255));      analogWrite(PIN_GREEN,constrain(green,0,255));      analogWrite(PIN_BLUE,constrain(blue,0,255));   #else      analogWrite(PIN_RED,constrain(255-red,0,255));      analogWrite(PIN_GREEN,constrain(255-green,0,255));      analogWrite(PIN_BLUE,constrain(255-blue,0,255));   #endif } /** * 控制亮灭 */ void switchRGB(bool enable){   if(enable){     //打开     #ifdef COMMON_GND      //共地      analogWrite(PIN_ENABLE,255);     #else      analogWrite(PIN_ENABLE,0);     #endif   }else{     //关闭     #ifdef COMMON_GND      //共地      analogWrite(PIN_ENABLE,0);     #else      analogWrite(PIN_ENABLE,255);     #endif   } } /** * 呼吸灯 */ void breatheRGB(int frequency){   int level = frequency%3;   int f_level;   switch(level){     case 0://慢  50       f_level = 3;       break;     case 1://正常 100       f_level = 10;       break;     case 2://快  200       f_level = 20;       break;   }   if(isAdd){     //递增方向      fadeValue +=f_level;      if(fadeValue>=255){        fadeValue = 255;        isAdd =false;      }   }else{     //递减方向     fadeValue -=f_level;      if(fadeValue<=0){        fadeValue = 0;        isAdd =true;      }   }   analogWrite(PIN_ENABLE,fadeValue);   delay(20); } void clrEsp8266ResponseBuffer(void){     memset(response, 0, MAX_CONTENT_SIZE);      //清空 }


        具体的代码功能请直接看注释,无非就是收到8266通过串口发过来的数据然后根据协议解析。楼主这里是用到了Mega2560的串口1来和8266通信,串口0用来打印调试信息。


        当以上两个步骤做完,并且连接好硬件之后,我们就可以用我们的app控制了,前提手机也连入了路由wifi。
        至于App 协议数据的介绍,以前帖子有详细介绍,可以参考 《博哥玩Arduino》Wifi版本 彩灯
       
          LU_EFK(25`]}8JI(Y5}GU7K.png Q}XBDH6@IB?L@2DU{IJHM.png C2V8AL$$`VOKAVXJLBN@K@G.png 9@B]0`6U7X811S3(D%BYU.png U~DSPBY6PULJN3H@YZI`5.png


         正常情况下,串口调试窗口会打印以下数据:
           Z2KFNKD74N7F)8TT9JX]1ZI.png


          注意:最后下载到板子的时候,最好把调试信息去掉,会影响到解析速度。注释掉 #define DEBUG


          最后附上APP下载地址: 下载

            APP源码下载地址
    游客,如果您要查看本帖隐藏内容请回复









    打赏作者鼓励一下!
  • TA的每日心情
    开心
    2018-7-22 00:22
  • 签到天数: 430 天

    [LV.9]以坛为家II

     楼主| 发表于 2018-7-12 00:00 | 显示全部楼层
    zzzlb 发表于 2018-7-11 18:37
    博哥,可以给我发APP源码下载地址吗

    帖子里面有链接
    打赏作者鼓励一下!
  • TA的每日心情
    开心
    2018-7-22 00:22
  • 签到天数: 430 天

    [LV.9]以坛为家II

     楼主| 发表于 2017-9-16 01:15 | 显示全部楼层
    楼主做好冷板凳
    打赏作者鼓励一下!
  • TA的每日心情
    开心
    2017-8-17 22:29
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2017-9-16 12:07 | 显示全部楼层
    赞!很棒的教程!可以加个好友吗?
    如果觉得对你有所帮助的话可以打赏一下我哦(~ ̄▽ ̄)~

    该用户从未签到

    发表于 2017-9-16 13:29 | 显示全部楼层
    博哥666666
  • TA的每日心情
    开心
    2018-7-22 00:22
  • 签到天数: 430 天

    [LV.9]以坛为家II

     楼主| 发表于 2017-9-16 15:22 | 显示全部楼层
    诚哥崽 发表于 2017-9-16 12:07
    赞!很棒的教程!可以加个好友吗?

    哈哈哈  在我这里没什么不可以
    打赏作者鼓励一下!
  • TA的每日心情
    开心
    2018-7-22 00:22
  • 签到天数: 430 天

    [LV.9]以坛为家II

     楼主| 发表于 2017-9-16 15:23 | 显示全部楼层

    一般6666 都要附上点赞
    打赏作者鼓励一下!
  • TA的每日心情
    无聊
    2015-7-25 22:41
  • 签到天数: 1 天

    [LV.1]初来乍到

    发表于 2017-10-28 16:17 | 显示全部楼层
    很好,学习了

    该用户从未签到

    发表于 2017-10-30 12:35 | 显示全部楼层
    好东西,谢谢

    该用户从未签到

    发表于 2017-10-31 10:02 | 显示全部楼层
    不错的帖子,赞
    高级模式  
    您需要登录后才可以回帖 登录 | 立即注册  

    本版积分规则

    热门推荐

    Arduino Uno 电机无法正常工作问题
    Arduino Uno 电机无法正常
    如图,请问代码有什么不对的地方吗 #include #include #include double angle_r
    顔色傳感器
    顔色傳感器
    有會使用顔色傳感器的朋友嗎?請問怎樣識別紅色和藍色,當然能來段代碼就更好了
    Blink——Arduino的Hello World!
    Blink——Arduino的Hello
    本教程节选自《Arduino程序设计基础》 Arduino编程基础(零)——Blink,Arduino的He
    创客集结号项目:太阳能陀螺仪机器人
    创客集结号项目:太阳能陀
    这是一只最简单的全自动机器人,它不像居家电器一样需要电源开关,也不需要人来维护,
    关于蓝牙4.0的问题
    关于蓝牙4.0的问题
    蓝牙4.0始终进不来AT,用的是JDY08 代码 #include SoftwareSerial BT(10, 11); // 接
    Copyright   ©2015-2016  Arduino中文社区  Powered by©Discuz!   ( 蜀ICP备14017632号-3 )
    快速回复 返回顶部 返回列表