查看: 20847|回复: 187

《博哥ESP8266系列8》- 局域网优化篇:ESP8266+路由+RGB彩灯+App

  [复制链接]
  • TA的每日心情
    开心
    2019-5-26 01:05
  • 签到天数: 676 天

    [LV.9]以坛为家II

    发表于 2017-9-19 22:33 | 显示全部楼层 |阅读模式
    本帖最后由 单片机菜鸟 于 2019-2-18 18:14 编辑

    一、前言
          在上一篇 局域网:ESP8266+RGB彩灯 中,我们的WIFI账号和密码都是固定在代码中,这对于我们来说非常不方便(意味着wifi灯如果换了一个wifi热点,那么我就得重新烧写程序)。而在另一篇 ESP8266一键配置 中,我们提到了SmartConfig功能。所谓SmartConfig就是手机App端发送包含WIFI用户名以及密码的UDP广播包,智能终端的WIFI芯片可以接收到该UDP包,只要知道UDP包的组织形式,就可以通过接收到的UDP包解密出WIFI用户名密码,然后智能硬件配置收到的用户名密码到指定的WIFI AP上。
          简洁点,有以下基本步骤:
          1.8266 端调用 WiFi.beginSmartConfig() 等待手机端发出的用户名和密码。
          2.手机端把填写当前网络的密码发送到UDP端口;
          3.8266自动收到连接信息并调用 WiFi.smartConfigDone() 退出等待。      然后楼主在该篇的最后提到了不足之处:
          1. SmartConfig用到乐鑫开发的app,那么我们是否可以把app的功能集成到自己开发的app上呢?
              肯定可以,后面楼主把乐鑫app的代码集成成一个sdk式的module,供Android Studio直接引入使用。
          2.每次启动8266,都需要重新配置,我们是否可以写入到flash中呢?

          那么这一篇就是为了解决上面的两个问题而出现的,我们在WIFI彩灯的基础上给它加入一键配置功能,然后演示我们怎么使用。
          干货来了,先上个视频(帖子视频看不了的话,请点击 这里):
          

    二、撸代码


          简洁点,有以下基本步骤:接下来,要分别烧写两个端的代码,基本上跟 局域网:ESP8266+RGB彩灯 差不多,我重点讲解不一样的地方。
          1.先烧写代码到ESP8266,烧写方法请看楼主前面的帖子,代码如下:
          

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

    /**
    * 日期:2017/09/19
    * 功能:wifi lamp 8266端
    *       加入SmartConfig功能
    * 作者:单片机菜鸟
    **/
    #include <ESP8266WiFi.h>
    #include <EEPROM.h>
    
    #define MAX_SRV_CLIENTS 3   //最大同时联接数,即你想要接入的设备数量,8266tcpserver只能接入五个,哎
    #define led 2
    #define DEBUG //是否开启debug功能
    
    #ifdef DEBUG
    #define DebugPrintln(message)    Serial.println(message)
    #else
    #define DebugPrintln(message)
    #endif
    
    #ifdef DEBUG
    #define DebugPrint(message)    Serial.print(message)
    #else
    #define DebugPrint(message)
    #endif
      
    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];
    
    //ssid和密码结构体
    struct config_type{
      char ssid[32];
      char psw[64];
    };
    
    config_type config;
    int flag = HIGH;//默认当前灭灯
      
    /**
    * @Desc 初始化操作
    */
    void setup() {
      Serial.begin(BAUD_RATE);
      pinMode(led,OUTPUT);
      digitalWrite(led, HIGH);
    
      if(!autoConfig()){
        smartConfig();
        DebugPrint("Connecting to ");//写几句提示,哈哈
        DebugPrintln(ssid);
        while (WiFi.status() != WL_CONNECTED) {
        //这个函数是wifi连接状态,返回wifi链接状态
           delay(500);
           DebugPrint(".");
        }
      }
      
      delay(1000);
      digitalWrite(led, LOW);
      DebugPrintln("IP address: ");
      DebugPrintln(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());
                }
            }
       }
    
       if(Serial.available()>0){
          char ch = Serial.read();
          if(ch == '1'){
            smartConfig();
            delay(1000);
            digitalWrite(led, LOW);
            DebugPrintln("IP address: ");
            DebugPrintln(WiFi.localIP());//WiFi.localIP()返回8266获得的ip地址
          }
       }
    }
    
    /**
    * 自动连接20s 超过之后自动进入SmartConfig模式
    */
    bool autoConfig(){
      WiFi.mode(WIFI_AP_STA);     //设置esp8266 工作模式
      WiFi.begin();
      delay(2000);//刚启动模块的话 延时稳定一下
      DebugPrintln("AutoConfiging ......");
      for(int i=0;i<20;i++){
        int wstatus = WiFi.status();
        if (wstatus == WL_CONNECTED){
          DebugPrintln("AutoConfig Success");
          DebugPrint("SSID:");
          DebugPrintln(WiFi.SSID().c_str());
          DebugPrint("PSW:");
          DebugPrintln(WiFi.psk().c_str());
          return true;
        }else{
          DebugPrint(".");
          delay(1000);
          flag = !flag;
          digitalWrite(led, flag);
        } 
      }
      DebugPrintln("AutoConfig Faild!");
      return false;
    }
    
    /**
    * 开启SmartConfig功能
    */
    void smartConfig()
    {
      WiFi.mode(WIFI_STA);
      delay(2000);
      DebugPrintln("Wait for Smartconfig");
      // 等待配网
      WiFi.beginSmartConfig();
      while (1){
        DebugPrint(".");
        delay(500);
        flag = !flag;
        digitalWrite(led, flag);
        
        if (WiFi.smartConfigDone()){
          //smartconfig配置完毕
          DebugPrintln("SmartConfig Success");
          DebugPrint("SSID:");
          DebugPrintln(WiFi.SSID().c_str());
          DebugPrint("PSW:");
          DebugPrintln(WiFi.psk().c_str());
          strcpy(config.ssid, WiFi.SSID().c_str());
          strcpy(config.psw, WiFi.psk().c_str());
          saveConfig();
          WiFi.mode(WIFI_AP_STA);     //设置esp8266 工作模式
          WiFi.setAutoConnect(true);  // 设置自动连接
          break;
        }
      }
    }
     
    /*
    保存参数到eeprom
     */
    void saveConfig()
    {
      EEPROM.begin(1024);
      uint8_t *p = (uint8_t*)(&config);
      for (int i = 0; i < sizeof(config); i++)
      {
        EEPROM.write(i, *(p + i));
      }
      EEPROM.commit();
    }
     
    /*
       从EEPROM加载参数
    */
    void loadConfig()
    {
      EEPROM.begin(1024);
      uint8_t *p = (uint8_t*)(&config);
      for (int i = 0; i < sizeof(config); i++)
      {
        *(p + i) = EEPROM.read(i);
      }
      EEPROM.commit();
    }


        整个代码的流程是这样的:
        1.8266上电启动后,进入自动连接模式autoConfig(根据上一次成功连接的SSID和密码),最多尝试20s,在尝试连接的过程中,LED灯会每隔1s闪烁一下,表示正在连接状态;如果连接成功,就直接配置8266服务器模式。
        2.如果上面操作失败(可能连接的热点不存在了或者修改了密码),那么会自动进入一键配置模式SmartConfig等待手机一键配置,这个过程是不限制时间的,LED会每隔0.5s闪一下,表示处在SmartConfig状态,这时大家可以去手机端开始一键配置。
         APP下载地址:
    游客,如果您要查看本帖隐藏内容请回复

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


        手机端配置页面:
        3WJO{)WKW2Q1K1%AH042EDE.png
           B@)RGPU2S79[Y[OK8JV3MZ0.png
           C3L@)INWHCP~V1B]NYG38$K.png
       如果提示失败,一般都是因为你的8266模块并没有进入到SmartConfig模式(在已经连接成功的情况下我们怎么再次进入到SmartConfig模式呢?别急,往下看)。


         2.烧写代码到Arduino板子(楼主的是Mega2560)。代码如下:
         

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

    /**
    * 日期:2017/09/19
    * 功能: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控制亮度
    #define PIN_KEY 7// 按键
    #else
    #define PIN_RED 2
    #define PIN_GREEN 3
    #define PIN_BLUE 4
    #define PIN_ENABLE 5
    #define PIN_KEY 6  
    #endif 
    
    int red = 0,green = 0,blue = 0;
    int type = 4;//当前模式 1亮度 2颜色 3呼吸 4开关
    int frequency = 1;//频率
    int switch_status = 1;//关闭 or 开启
    int bright = 1;//亮度
    
    char response[MAX_CONTENT_SIZE];
    int fadeValue = 0;//当前亮度
    bool isAdd = true;//是否是从暗到亮
    
    // 定义记录按键当前状态的变量
    int state_btn;
    // 定义记录按键最近一次状态变化的变量,并初始化状态为LOW。
    int lastButtonState = LOW;
    // 定义记录最近一次抖动的时间变量,并初始化时间为0毫秒。
    long lastDebounceTime = 0;
    // 定义延迟抖动的时间变量
    long debouncdDelay = 60;
      
    /**
    * @Desc 初始化操作
    */
    void setup() {
      pinMode(PIN_RED, OUTPUT);
      pinMode(PIN_GREEN, OUTPUT);
      pinMode(PIN_BLUE, OUTPUT);
      pinMode(PIN_ENABLE, OUTPUT);
      pinMode(PIN_KEY,INPUT);
      
      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);
      }
      checkButton();
    }
    
    /**
    * 读取串口缓冲区里面的数据
    */
    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 checkButton(){
      int buttonState = digitalRead(PIN_KEY);//读取当前按键状态
      if(buttonState != lastButtonState){
         //如果按键发生了变化  则重新设置最近一次抖动的时间
         //方法millis()可以获取当前时间,单位统一为毫秒。
         lastDebounceTime = millis();  
      }
       
      // 判断按键按下状态时间间隔是否大于延迟抖动的时间长度。
      if(millis()-lastDebounceTime>debouncdDelay){
        // 判断当前的按键状态是否和之前有所变化
        if(buttonState != state_btn){
           // 如果发生了变化,
           // 则更新按键状态变量。
           state_btn = buttonState;
           if(state_btn == HIGH){
            //再次确认是否真的按下了按键
             DBGLN("smartconfig");
             WifiSerial.write('1');
           }
        }
      }
      // 更新按键最近一次状态变化的变量
      lastButtonState = buttonState;
    }
    
    void clrEsp8266ResponseBuffer(void){
        memset(response, 0, MAX_CONTENT_SIZE);      //清空
    }

       代码解释:这里我们用到了一个按键,按下按键就给8266发个命令进入SmartConfig模式(Arduino和8266通过串口1通信)。其他的功能还是没有改变,请看上一篇。
       接下来,如果有使能Debug的话,应该会打印以下信息:
        3AP{PV]JLROO$T{Op~]GU.png

        如果有打印以上信息,那么恭喜你,你已经成功一大半了。


       接下来,兑现第二点,SmartConfig用到乐鑫开发的app,那么我们是否可以把app的功能集成到自己开发的app上呢?
       肯定可以,楼主把乐鑫app的代码集成成一个sdk式的module,供Android Studio直接引入使用。
        0R%U4YS{ScY@_IPB_GHXK.png
       需要的麻烦给楼主留言,楼主给你发过去,当然楼主希望你真的去试用了SmartConfig功能,因为我也不确保是否可以在你的8266上起作用,不然就真是白费精神在module上。
       引用方法:在你的app分别调用以下代码:
        3[R_J4PXL`[7{E4]{UHGM29.png    

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

    private void initView() {
            back.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    finish();
                }
            });
            start.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
    
                    //判断是否存在空值
                    String ssid = tv_ssid.getText().toString();
                    String password = et_psw.getText().toString();
    
                    if(TextUtils.isEmpty(ssid)){
                        Toast.makeText(SmartConfigActivity.this, "确定是否连上wifi", Toast.LENGTH_SHORT).show();
                        return;
                    }
    
                    if(TextUtils.isEmpty(password)){
                        Toast.makeText(SmartConfigActivity.this, "密码不能为空", Toast.LENGTH_SHORT).show();
                        return;
                    }
                    String apBssid = EspWifiAdminSimple.getWifiConnectedBssid(SmartConfigActivity.this);
                    smartconfig(ssid,apBssid,password);
                }
            });
        }

        )B(P9}IMPQPAS7YT)J_B.png    

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

    /**
         * @开始一键配置
         **/
        private void smartconfig(final String apSsid, final String apBssid, final String apPassword){
            Log.d("smartconfig","mEdtApSsid = " + apSsid
                    + ", " + " mEdtApPassword = " + apPassword);
            if (task != null && task.getStatus() == AsyncTask.Status.RUNNING) {
                return;
            }
            task = new SimpleDialogTask(this) {
    
                private IEsptouchTask mEsptouchTask;
    
                @Override
                public Object onAsync() {
                    mEsptouchTask = new EsptouchTask(apSsid, apBssid, apPassword, SmartConfigActivity.this);
                    List<IEsptouchResult> resultList = mEsptouchTask.executeForResults(1);
                    return resultList;
                }
    
                @Override
                public void onResult(Object obj) {
                    List<IEsptouchResult> result = (List<IEsptouchResult>) obj;
                    if(result != null && result.size()>0){
                        IEsptouchResult firstResult = result.get(0);
                        // check whether the task is cancelled and no results received
                        if (!firstResult.isCancelled()) {
                            int count = 0;
                            // max results to be displayed, if it is more than maxDisplayCount,
                            // just show the count of redundant ones
                            final int maxDisplayCount = 5;
                            // the task received some results including cancelled while
                            // executing before receiving enough results
                            if (firstResult.isSuc()) {
                                StringBuilder sb = new StringBuilder();
                                for (IEsptouchResult resultInList : result) {
                                    sb.append("配置成功, "
                                            + ",IP地址 = "
                                            + resultInList.getInetAddress()
                                            .getHostAddress() + "\n");
                                    count++;
                                    PreferenceUtil.getInstance().writePreferences(PreferenceUtil.IP,resultInList.getInetAddress()
                                            .getHostAddress());
                                    if (count >= maxDisplayCount) {
                                        break;
                                    }
                                }
                                if (count < result.size()) {
                                    sb.append("\nthere's " + (result.size() - count)
                                            + " more result(s) without showing\n");
                                }
                                onToast(new OnDismissCallbackListener(sb.toString()){
                                    @Override
                                    public void onCallback() {
                                        PreferenceUtil.getInstance().writePreferences(PreferenceUtil.PSW,apPassword);
                                        finish();
                                    }
                                });
                            } else {
                                onToastErrorMsg("配置失败,请确保智能终端打开了一键配置模式");
                            }
                        }
                    }
                }
    
                @Override
                protected void onCancelled() {
                    super.onCancelled();
                    if (mEsptouchTask != null) {
                        mEsptouchTask.interrupt();
                    }
                }
            };
    
            task.startTask("正在配置中,请稍候....");
        }

    三、后续



           这已经是整个系列的第八篇,楼主不确定之后还会不会继续更新,至少近期应该不会更新有关8266,起码真的有干货想推荐给大家哈哈哈。版主说要送我一块板子,说不定我后面的帖子会陆续测评该板子。。。


    博哥自建qq交流群:869920142





    打赏作者鼓励一下!
  • TA的每日心情
    开心
    2019-5-26 01:05
  • 签到天数: 676 天

    [LV.9]以坛为家II

     楼主| 发表于 2017-9-19 22:34 | 显示全部楼层
    楼主坐好第一排冷板凳
    打赏作者鼓励一下!
  • TA的每日心情
    擦汗
    2017-1-10 09:19
  • 签到天数: 1 天

    [LV.1]初来乍到

    发表于 2017-9-19 23:28 | 显示全部楼层
    博哥威武783666741@QQ.COM
  • TA的每日心情
    开心
    2019-5-26 01:05
  • 签到天数: 676 天

    [LV.9]以坛为家II

     楼主| 发表于 2017-9-20 08:45 | 显示全部楼层

    已经发给你了 在Android Studio引入module  按照上面的图在你的app中调用就可以了
    打赏作者鼓励一下!

    该用户从未签到

    发表于 2017-9-20 15:32 | 显示全部楼层
    博哥专业第一顶!评测板子也好啊
  • TA的每日心情
    无聊
    2018-9-9 17:34
  • 签到天数: 3 天

    [LV.2]偶尔看看I

    发表于 2017-10-23 21:17 | 显示全部楼层
    我烧写代码到ESP8266  的代码 为什么会出现错误啊
    if(!autoConfig()){  说是这里的 问题  为什么呢
  • TA的每日心情
    开心
    2019-5-26 01:05
  • 签到天数: 676 天

    [LV.9]以坛为家II

     楼主| 发表于 2017-10-23 22:49 | 显示全部楼层
    haiyang4060 发表于 2017-10-23 21:17
    我烧写代码到ESP8266  的代码 为什么会出现错误啊
    if(!autoConfig()){  说是这里的 问题  为什么呢 ...

    你的看编译错误是什么
    打赏作者鼓励一下!
  • TA的每日心情
    难过
    2017-12-14 15:39
  • 签到天数: 40 天

    [LV.5]常住居民I

    发表于 2017-10-24 05:32 | 显示全部楼层
    博哥威武14455975@qq.com
  • TA的每日心情
    开心
    2019-5-26 01:05
  • 签到天数: 676 天

    [LV.9]以坛为家II

     楼主| 发表于 2017-10-24 09:45 | 显示全部楼层

    上面已经有app连接的了
    打赏作者鼓励一下!
  • TA的每日心情
    无聊
    2018-9-9 17:34
  • 签到天数: 3 天

    [LV.2]偶尔看看I

    发表于 2017-10-24 13:26 | 显示全部楼层
    单片机菜鸟 发表于 2017-10-23 22:49
    你的看编译错误是什么

    哦 谢谢   我弄好了 哈哈哈    可以正常用了  挺好看的 灯
    您需要登录后才可以回帖 登录 | 立即注册  

    本版积分规则

    热门推荐

    74HC595的疑惑终于解开
    74HC595的疑惑终于解开
    对于74HC595的教程中和网上的资料看完还是模糊,于是一边接线测试,一边反复看图研究
    【Arduino】37种传感器系列实验(1)---干簧管模块
    【Arduino】37种传感器系
    37款传感器的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37
    开贴讲讲NRF24L01P,让你彻底搞懂它的工作原理,持续更...
    开贴讲讲NRF24L01P,让你
    *****************************************
    Arduino MEGA 与UNO 通过nRF24L模块通讯
    Arduino MEGA 与UNO 通过n
    之前在深水宝很“实惠”的店铺买了一些原件,随手砍了esp8266以及nRF24L*3 因为缺
    体验OneNET4.0,一起来拼开发板
    体验OneNET4.0,一起来拼
    一、 活动时间2019年04月09日-2019年6月30日 二、活动链接1.登录Arduino中文社区账
    Copyright   ©2015-2016  Arduino中文社区  Powered by©Discuz!   ( 蜀ICP备14017632号-3 )
    快速回复 返回顶部 返回列表