找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3266|回复: 0
收起左侧

带无线更新的基于esp8266和blinker的小爱语音控制智能灯

[复制链接]
ID:47972 发表于 2021-2-8 13:52 | 显示全部楼层 |阅读模式
  前段时间看了ESP8266点灯的视频,想着自己也DIY一个。
上网搜了资料,买来ESP-8266-12F和继电器模块,开始动手制作。
制作过程省略,要是有不太明白的地方可以找度娘,一搜一大把,我这就偷个懒。
……制作的过程中遇到的问题与大家分享一下。
     1.最先遇到的就是每次下载程序都得插在电脑上下载,因为我用的免费版的,blinker一旦更新库文件或者与小爱的接口,咱们的灯就控制不了。 这就很麻烦了,不可能每次更新都去拆装一下灯吧。于是又找度娘商量了一下,度娘给了我一个http_update的例程,把这个例程加入进去,程序更新是解决了,可是电脑得开web服务器,不过总算是不用拆装灯具了。
     2.第二个问题就是设备ID是固化在程序里的,如果我做好2个或5个设备(blinker免费版最多5个独立设备),更新的时候岂不是得生成5个更新包,万一更新的时候弄错了,后续使用就很麻烦。这个问题得解决掉,查看8266 库的时候发现8266是可以将FLASH当作EEPROM来操作的,于是把设备ID在下载程序后第一次运行就存在EEPROM里,后面就只要读出来就可以了。这样不管几个设备,更新程序都可以通用了。
    3.第三个问题就是WIFI配置。与设备ID一样,网上例程都是将WIFI SSID和PASSWORD固化在程序里的。如果只是测试用是没问题的,只要不改WIFI密码,或者改WIFI密码的时候先给灯的程序更新一下.......咱这个不是得装灯里面吗?这就又是个麻烦。好在blinker app里面就带有WIFI配网
  操作路径:打开blinker app => 点左上角的几条横线 => 点开发者 => 点开发工具 =>ApConfig,输入你的WIFI名称和密码,然后打开你要配置的设备,就可以愉快的点开始配置了。
代码我和电路图我放附件里了,需要的朋友可以下载参考一下。
51hei.png
  1. #define BLINKER_PRINT Serial
  2. #define BLINKER_MIOT_LIGHT
  3. #define BLINKER_WIFI
  4. #define BLINKER_APCONFIG
  5. #include <Blinker.h>
  6. #include <Arduino.h>   
  7. #include <ESP8266WiFi.h>
  8. #include <ESP8266WiFiMulti.h>
  9. #include <ESP8266HTTPClient.h>
  10. #include <ESP8266httpUpdate.h>
  11. #include <EEPROM.h>         ";
  12.   char eep1=0;
  13.   char eep2=5;
  14. int addr = 3900;//避开blinker使用的eeprom地址
  15. char  tmp = 0;
  16. bool oState = false;
  17. bool switch_state = true;
  18. int counter = 0;
  19. float pai =0;
  20. bool UpDate = false;  //系统升级标志
  21. char auth[] = "xxxxxxxxxx";//上一步中在blinker app中获取到的Secret Key
  22. char up_date_path["http://xxxxxxxxxxxx/file.bin"];//更新固件的具体http地址,只试过http,没试过https不知道可不可行
  23. // 新建组件对象
  24. BlinkerButton Button1("btn-put");//灯开关组件
  25. BlinkerButton Button2("btn-upd");//升级用的开关组件
  26. BlinkerNumber Number1("num-abc");
  27. ESP8266WiFiMulti WiFiMulti;
  28. void read_skey()
  29.    {
  30.      EEPROM.begin(4096);
  31.      for(tmp=0;tmp<12;tmp++)
  32.       {
  33.        auth[tmp]=EEPROM.read(addr+tmp);
  34.       }  
  35.      EEPROM.end();
  36.      Serial.println("EEPROM_read OK:");
  37.      Serial.println(auth);
  38.    }
  39. void write_skey()
  40.      {
  41.       EEPROM.begin(4096);
  42.       EEPROM.write(addr+14,0x42);//auth码存储标志
  43.       EEPROM.write(addr+15,0xbd);//auth码存储标志反码
  44.       for(tmp=0;tmp<12;tmp++)
  45.       {
  46.        EEPROM.write(addr+tmp,auth[tmp]);
  47.       
  48.        }  
  49.       if (EEPROM.commit())
  50.        {
  51.            Serial.println(auth);
  52.            Serial.println("EEPROM successfully committed");   
  53.         }
  54.       else
  55.        {
  56.       Serial.println("ERROR! EEPROM commit failed");
  57.        }
  58.        EEPROM.end();
  59.    }
  60. /* 小米设备状态查询回调函数 */
  61. void miotQuery(int32_t queryCode)
  62. {
  63.     BLINKER_LOG("MIOT Query codes: ", queryCode);

  64.     switch (queryCode)
  65.     {
  66.         case BLINKER_CMD_QUERY_ALL_NUMBER :
  67.             BLINKER_LOG("MIOT Query All");
  68.             BlinkerMIOT.powerState(oState ? "on" : "off");
  69.             BlinkerMIOT.print();
  70.             break;
  71.         case BLINKER_CMD_QUERY_POWERSTATE_NUMBER :
  72.             BLINKER_LOG("MIOT Query Power State");
  73.             BlinkerMIOT.powerState(oState ? "on" : "off");
  74.             BlinkerMIOT.print();
  75.             break;
  76.         default :
  77.             BlinkerMIOT.powerState(oState ? "on" : "off");
  78.             BlinkerMIOT.print();
  79.             break;
  80.     }
  81. }
  82. // 按下按键即会执行该函数
  83. void button1_callback(const String & state)
  84. {
  85.      if (state=="on")
  86.      {
  87.        BLINKER_LOG("get button state: ", state);
  88.        digitalWrite(LED_BUILTIN, LOW);
  89.        Button1.print("on");
  90.        switch_state = true;
  91.      }else if (state=="off")
  92.      {
  93.        BLINKER_LOG("get button state: ", state);
  94.        digitalWrite(LED_BUILTIN, HIGH);
  95.        Button1.print("off");
  96.        switch_state = false;   
  97.      }
  98. }
  99. void heartbeat()//自定义心跳包的返回
  100. {

  101.     if (switch_state)
  102.       {
  103.         //BUILTIN_SWITCH.print("on");
  104.         Button1.print("on");
  105.       }
  106.     else
  107.     {
  108.       //BUILTIN_SWITCH.print("off");
  109.       Button1.print("off");
  110.     }

  111. }
  112. //按下此键改变升级状态,进行http升级
  113. void button2_callback(const String & stage)
  114.      {
  115.       UpDate = true;
  116.       }
  117. // 如果未绑定的组件被触发,则会执行其中内容
  118. void dataRead(const String & data)
  119. {
  120.     BLINKER_LOG("Blinker readString: ", data);
  121.     counter++;
  122.     Number1.print(counter);
  123.     if (counter>0xfff0)counter=0;
  124. }
  125. void miotPowerState(const String & state) //小爱语音控制函数
  126. {
  127.    
  128.     if (state == BLINKER_CMD_ON) {
  129.         digitalWrite(LED_BUILTIN, LOW);
  130.         BlinkerMIOT.powerState("on");
  131.         BlinkerMIOT.print();
  132.         Button1.print("on");
  133.         switch_state = true;
  134.     }
  135.     else if (state == BLINKER_CMD_OFF) {
  136.         digitalWrite(LED_BUILTIN, HIGH);
  137.         BlinkerMIOT.powerState("off");
  138.         BlinkerMIOT.print();
  139.         Button1.print("off");
  140.         switch_state = false;
  141.     }
  142.     BLINKER_LOG("need set power state: ", state);
  143. }

  144. void setup() {

  145.   Serial.begin(115200);
  146.   Serial.println();
  147.   Serial.println();
  148.   Serial.println();
  149.     #if defined(BLINKER_PRINT)
  150.         BLINKER_DEBUG.stream(BLINKER_PRINT);
  151.     #endif
  152. EEPROM.begin(4096);
  153.    eep1=EEPROM.read(addr+14);  //ID存储标志
  154.    eep2=255-EEPROM.read(addr+15);//ID存储标志反码
  155.    EEPROM.end();
  156.    if (eep1==eep2)
  157.      {
  158.       read_skey();
  159.       Serial.println("EEPROM read OK.");
  160.       }
  161.     else
  162.      {
  163.       write_skey();
  164.       }
  165.   Serial.print("WiFi Connected!");
  166.     // 初始化有LED的IO
  167.     pinMode(LED_BUILTIN, OUTPUT);
  168.     digitalWrite(LED_BUILTIN, LOW);
  169.     //   Blinker.begin(auth, ssid, pswd);  //初始化blinker
  170.     Blinker.begin(auth);  //使用blinker app配网,这里只需要ID就行,如果预置WIFI配置就用上面一行代码
  171.     //注册回调函数
  172.     Blinker.attachHeartbeat(heartbeat);
  173.     Blinker.attachData(dataRead);
  174.     BlinkerMIOT.attachPowerState(miotPowerState);
  175.     Button1.attach(button1_callback);
  176.     Button2.attach(button2_callback);
  177.     BlinkerMIOT.attachQuery(miotQuery);
  178.     ESPhttpUpdate.onStart(update_started);
  179.     ESPhttpUpdate.onEnd(update_finished);
  180.     ESPhttpUpdate.onProgress(update_progress);
  181.     ESPhttpUpdate.onError(update_error);
  182. }

  183. void update_started() {
  184.   Serial.println("CALLBACK:  HTTP update process started");
  185. }

  186. void update_finished() {
  187.   Serial.println("CALLBACK:  HTTP update process finished");
  188.   UpDate = false;
  189.   digitalWrite(LED_BUILTIN, HIGH);
  190. }

  191. void update_progress(int cur, int total) {
  192.   Serial.printf("CALLBACK:  HTTP update process at %d bytes of %3.1f %%total\n", cur, (float)cur/(float)total*100.0);
  193. }

  194. void update_error(int err) {
  195.   Serial.printf("CALLBACK:  HTTP update fatal error code %d\n", err);
  196.   UpDate = false;
  197.       if (switch_state)   //更新失败则恢复灯的开关状态。
  198.       {
  199.         digitalWrite(LED_BUILTIN, LOW);
  200.         Button1.print("on");
  201.       }
  202.     else
  203.     {
  204.       digitalWrite(LED_BUILTIN, HIGH);
  205.       Button1.print("off");
  206.     }
  207.   Button2.print("update error");
  208. }

  209. void loop() {
  210.   // wait for WiFi connection
  211.   Blinker.run();
  212.   if (UpDate) {  //接收到更新指令,进入更新程序
  213.      if (switch_state){
  214.        digitalWrite(LED_BUILTIN, HIGH);
  215.      }
  216.     else{
  217.       digitalWrite(LED_BUILTIN, LOW); //灯状态取反表示进入更新模式
  218.     }
  219.     WiFiClient client;
  220.     t_httpUpdate_return ret = ESPhttpUpdate.update(client, up_date_path);//更新固件
  221.     switch (ret) {
  222.       case HTTP_UPDATE_FAILED:
  223.         Serial.printf("HTTP_UPDATE_FAILD Error (%d): %s\n", ESPhttpUpdate.getLastError(), ESPhttpUpdate.getLastErrorString().c_str());
  224.         break;

  225.       case HTTP_UPDATE_NO_UPDATES:
  226.         Serial.println("HTTP_UPDATE_NO_UPDATES");
  227.         break;

  228.       case HTTP_UPDATE_OK:
  229.         Serial.println("HTTP_UPDATE_OK");
  230.         break;
  231.     }
  232.   }
  233. }

复制代码

blinker_esp_8266_httpUpdate.rar (735.03 KB, 下载次数: 28)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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