ESP8266系列模块初始化成可以OTA,通过Web页进行升级(1)-Arduino中文社区 - Powered by Discuz!

Arduino中文社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 7496|回复: 1

ESP8266系列模块初始化成可以OTA,通过Web页进行升级(1)

[复制链接]
发表于 2018-10-16 19:54 | 显示全部楼层 |阅读模式
本帖最后由 wherestheway 于 2018-10-16 20:11 编辑

大家好,下面分享一下本人的一些经验。ESP8266系列模块(有ESP-01、ESP-12)具有WiFi功能,Arduino常常与之相连实现无线上网。其实,ESP8266系列模块不但具有WiFi功能,还具有MCU功能,可以对IO脚进行输入输出控制,完全可以替代Arduino模块。还可以通过域名直接访问(局域网内),实现Web页无线升级。
图片4.png
图片3.png
升级界面:
图片5.png
下面是代码:

  1. /*
  2. 日期:2018.8.12
  3. Arduino IDE 版本:1.8.6
  4. ESP8266 for Arduino 版本:2.4.2
  5. 芯片:WeMos D1 mini[/color][/font][/align][align=left][font=等线][color=#000000]功能:初始化芯片,使其具有Web Browser OTA升级功能,NTP时间获取     
  6. 通过h t t p://D1-mini.local/可以访问状态
  7. 通过h t t p://D1-mini.local/update可以进行OTA升级
  8. */[/color][/font][/align][align=left][font=等线][color=#000000]#include <ESP8266WiFiMulti.h>
  9. #include <WiFiUdp.h>
  10. #include <ESP8266WebServer.h>
  11. #include <ESP8266LLMNR.h>
  12. #include <ESP8266HTTPUpdateServer.h>
  13. #include<time.h>
  14. #include <Ticker.h>
  15. ADC_MODE(ADC_VCC);[/color][/font][/align][align=left][font=等线][color=#000000]const char *host = "D1-mini";     //节点名,web update server hostname[/color][/font][/align][align=left][font=等线][color=#000000]//数字输出管脚定义
  16. byte board_led = 2;   //D1-mini板载灯脚,D4
  17. //byte board_led = 1; //ESP-01板载灯脚[/color][/font][/align][align=left][font=等线][color=#000000]// 获取NTP时间相关配置
  18. unsigned int localPort = 2390;        // 本地端口,侦听UDP packets
  19. IPAddress timeServerIP;              //时间服务器动态IP地址
  20. //const char* ntpServerName = "time.nist.gov";//时间服务器域名
  21. const char* ntpServerName = "cn.pool.ntp.org";//国内时间服务器域名
  22. const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message
  23. byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets
  24. unsigned long NTPtime;                //获取的NTP时间(秒)
  25. unsigned long nowtime;                //实时时间(毫秒)
  26. unsigned long savetime;               //获取NTP时间时,对应的系统时间(millis)
  27. bool NTP_got = 0;                     //成功获取NTP时间,1为成功,0为失败
  28. #define Detect_Interval   3000        // 检测周期,3秒
  29. unsigned int next_Detect_Time;        //下次检测时间[/color][/font][/align][align=left][font=等线][color=#000000]//创建对象[/color][/font][/align][align=left][font=等线][color=#000000]Ticker slow_ticker;                       //用于板载灯慢闪烁控制
  30. WiFiUDP udp;                              //获取NTP时间需要
  31. ESP8266WebServer httpServer(80);        //用于web服务器
  32. ESP8266HTTPUpdateServer httpUpdater;   //用于代码OTA更新
  33. ESP8266WiFiMulti wifiMulti;             //多WiFi名称登陆[/color][/font][/align][align=left][font=等线][color=#000000]void setup() {
  34.     Serial.begin(115200);
  35.     delay(10);
  36.     Serial.println();
  37.     Serial.println("D1 Initialize");
  38.     //Serial.setDebugOutput(true);
  39.     pinMode(board_led,OUTPUT);      //设置板载灯脚为输出状态
  40.    
  41.     digitalWrite(board_led,LOW);    //点亮板载灯(低电平有效),开始连接WiFi[/color][/font][/align][align=left][font=等线][color=#000000]    //预置WiFi名称和密码,这样模块在家和单位就都可以使用了
  42.     wifiMulti.addAP("WiFi名称", "密码");//家
  43.     wifiMulti.addAP("WiFi名称", "密码");//单位
  44.     //还可以再加,好像最多为6个
  45.    
  46.     wifi_conn();//连接WiFi
  47.     //WiFi.printDiag(Serial);
  48. }

  49. void loop() {[/color][/font][/align][align=left][font=等线][color=#000000]    nowtime = (millis()-savetime)/1000 + NTPtime;   //现在时间计算赋值

  50.     // Handle http server.
  51.     httpServer.handleClient();[/color][/font][/align][align=left][font=等线][color=#000000]    //再次获得时间
  52.     if( (millis() > next_Detect_Time && !NTP_got) || millis() < 250){
  53.         //如果获取NTP时间失败,并累计超过3秒,再或模块系统时间清零,重新获取
  54.         Serial.print("begin fetch NTP time again\r\n");   
  55.         fetchNTPtime();
  56.         next_Detect_Time = millis() + Detect_Interval;  //设置下次检测时间
  57.     }
  58.    
  59.     //在下面输入你的代码
  60.     Serial.print("ESP.getVcc(): ");
  61.     Serial.println(ESP.getVcc());[/color][/font][/align][align=left][font=等线][color=#000000]    delay(2500);
  62. }[/color][/font][/align][align=left][font=等线][color=#000000]void fetchNTPtime(){//获取NTP时间[/color][/font][/align][align=left][font=等线][color=#000000]  //通过域名获取IP地址
  63.   WiFi.hostByName(ntpServerName, timeServerIP); [/color][/font][/align][align=left][font=等线][color=#000000]  sendNTPpacket(timeServerIP); // 调用这个函数,向时间服务器发请求
  64.   // wait to see if a reply is available
  65.   delay(1000);
  66.   
  67.   int cb = udp.parsePacket();
  68.   if (!cb) {//没有接收到数据
  69.     //Serial.println("no packet yet");
  70.     NTP_got = 0;
  71.   }
  72.   else {//接收到数据[/color][/font][/align][align=left][font=等线][color=#000000]    udp.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer[/color][/font][/align][align=left][font=等线][color=#000000]    //从接收包第40个字节开始的4个字为节时间戳,先分别赋值到2 word
  73.     unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
  74.     unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
  75.     //合并4字节成长整型,这就是NTP时间(从1900.1.1开始的秒数)
  76.     // this is NTP time (seconds since Jan 1 1900):
  77.     unsigned long secsSince1900 = highWord << 16 | lowWord;
  78.     //Serial.print("Seconds since Jan 1 1900 = " );
  79.     //Serial.println(secsSince1900);[/color][/font][/align][align=left][font=等线][color=#000000]    // now convert NTP time into everyday time:
  80.     //Serial.print("Unix time = ");
  81.     // Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
  82.     const unsigned long seventyYears = 2208988800UL;
  83.     // subtract seventy years:
  84.     NTPtime = secsSince1900 - seventyYears;
  85.     NTPtime += 8 * 3600;//北京时间,东八区修正
  86.     NTP_got = 1;
  87.     //Serial.print("got NTP time\r\n");
  88.     savetime = millis();//获得NTP时间的系统时刻
  89.   }[/color][/font][/align][align=left][font=等线][color=#000000]    nowtime = (millis()-savetime)/1000 + NTPtime;[/color][/font][/align][align=left][font=等线][color=#000000]    //打印小时、分钟和秒:
  90.     Serial.print("The Beijing time is ");
  91.     Serial.println(displaytime(nowtime));
  92. }[/color][/font][/align][align=left][font=等线][color=#000000]//发送NTP请求到指定IP地址的时间服务器
  93. unsigned long sendNTPpacket(IPAddress& address)
  94. {
  95.   //Serial.println("sending NTP packet...");
  96.   //将缓冲区里所有字节清零
  97.   memset(packetBuffer, 0, NTP_PACKET_SIZE);
  98.   // 准备NTP请求数据
  99.   packetBuffer[0] = 0b11100011;   // LI, Version, Mode
  100.   packetBuffer[1] = 0;     // Stratum, or type of clock
  101.   packetBuffer[2] = 6;     // Polling Interval
  102.   packetBuffer[3] = 0xEC;  // Peer Clock Precision
  103.   // 8 bytes of zero for Root Delay & Root Dispersion
  104.   packetBuffer[12]  = 49;
  105.   packetBuffer[13]  = 0x4E;
  106.   packetBuffer[14]  = 49;
  107.   packetBuffer[15]  = 52;[/color][/font][/align][align=left][font=等线][color=#000000]  // all NTP fields have been given values, now
  108.   // you can send a packet requesting a timestamp:
  109.   udp.beginPacket(address, 123); //NTP requests are to port 123
  110.   udp.write(packetBuffer, NTP_PACKET_SIZE);
  111.   udp.endPacket();
  112.    
  113. }[/color][/font][/align][align=left][font=等线][color=#000000]void handleRoot() {
  114.   IPAddress local_ip;[/color][/font][/align][align=left][font=等线][color=#000000]  String message = "<!DOCTYPE HTML>";  
  115.   message += "<html><head><meta charset="UTF-8"><title>初始化芯片</title>";  
  116.   message += "</head><body><div align="center">";
  117.   message += "<div id="container" style="width:600px">";
  118.   
  119.   message += "<div id="header" style="background-color:#FFB3B3;">";
  120.   message += "<h2 style="margin-bottom:0;">D1-mini芯片连接成功!</h2></div>";
  121.   message += "<div id="hoststatus" style="background-color:#FFE5E5;height:160px;width:600px;float:left;"><form><br>";
  122.   message += "模块时间:";
  123.   message += displaytime(nowtime);
  124.   message += " 星期";
  125.    switch (weekday(nowtime)){
  126.      case 0 :
  127.         message += "一";
  128.         break;
  129.      case 1 :
  130.         message += "二";
  131.         break;
  132.      case 2 :
  133.         message += "三";
  134.         break;
  135.      case 3 :
  136.         message += "四";
  137.         break;
  138.      case 4 :
  139.         message += "五";
  140.         break;
  141.      case 5 :
  142.         message += "六";
  143.         break;
  144.      case 6 :
  145.         message += "日";
  146.    }
  147.   
  148.   message += "<br><br><div id="SSID">SSID:";
  149.   message += WiFi.SSID();
  150.   message += "</div><div id="IP_Address">IP 地址:";
  151.   local_ip = WiFi.localIP();  
  152.   for (uint8_t i=0; i<3; i++){
  153.     message += local_ip[i];
  154.     message += ".";   
  155.   }
  156.   message += local_ip[3];
  157.   message += "<br><br><a href="/update">点击这里</a> 进入OTA升级界面";
  158.   message += "</div></div></body></html>";  
  159.     httpServer.send ( 200, "text/html", message );  
  160. }[/color][/font][/align][align=left][font=等线][color=#000000]void handleNotFound(){
  161.   //digitalWrite(board_led, 1);
  162.   String message = "File Not Found\n\n";
  163.   message += "URI: ";
  164.   message += httpServer.uri();
  165.   message += "\nMethod: ";
  166.   message += (httpServer.method() == HTTP_GET)?"GET":"POST";
  167.   message += "\nArguments: ";
  168.   message += httpServer.args();
  169.   message += "\n";
  170.   for (uint8_t i=0; i<httpServer.args(); i++){
  171.     message += " " + httpServer.argName(i) + ": " + httpServer.arg(i) + "\n";
  172.   }
  173.   httpServer.send(404, "text/plain", message);
  174.   //digitalWrite(board_led, 0);
  175. }[/color][/font][/align][align=left][font=等线][color=#000000]String displaytime(unsigned long nt)
  176. {
  177.     //显示日期,小时、分钟和秒:
  178.     String dt;
  179.     time_t nowtm;   
  180.     struct tm *timeinfo;   
  181.             //time( &nowtime );   
  182.             //timeinfo = localtime( &nowtime );   
  183.     nowtm = nt;
  184.     timeinfo = localtime(&nowtm);
  185.     int xtn = timeinfo->tm_year + 1900;   
  186.     int xty = timeinfo->tm_mon + 1;   
  187.     int xtr = timeinfo->tm_mday;   
  188.     int xts = timeinfo->tm_hour;  
  189.     int xtf = timeinfo->tm_min;  
  190.     int xtm = timeinfo->tm_sec;[/color][/font][/align][align=left][font=等线][color=#000000]    dt += xtn;
  191.     dt += "-";
  192.     dt += xty;
  193.     dt += "-";
  194.     dt += xtr;
  195.     dt += " ";
  196.     if (xts < 10 ) {
  197.       // 前10小时加“ ”
  198.       dt += ' ';
  199.     }
  200.     dt += xts;
  201.     dt += ":";
  202.     if (xtf < 10 ) {
  203.       // 前10分加“0”
  204.       dt += '0';
  205.     }
  206.     dt += xtf;
  207.     dt += ":";
  208.     if (xtm < 10 ) {
  209.       // 前10秒加“0”
  210.       dt += '0';
  211.     }
  212.     dt += xtm;[/color][/font][/align][align=left][font=等线][color=#000000]    return dt;
  213. }[/color][/font][/align][align=left][font=等线][color=#000000]byte weekday(unsigned long nt)
  214. {
  215.     //显示星期数:周一为0,周二为1,周三为2,周四为3,周五为4,周六为5,周日为6
  216.     byte wd;
  217.     time_t nowtm;   
  218.     struct tm *timeinfo;   
  219.             //time( &nowtime );   
  220.             //timeinfo = localtime( &nowtime );   
  221.     nowtm = nt;
  222.     timeinfo = localtime(&nowtm);
  223.     int xtn = timeinfo->tm_year + 1900; //年份
  224.     int xty = timeinfo->tm_mon + 1;     //月份
  225.     int xtr = timeinfo->tm_mday;        //日
  226.     int xtc = xtn / 100;                //世纪
  227.     xtn = xtn % 100;                    //年数[/color][/font][/align][align=left][font=等线][color=#000000]    if (xty < 3){   //如果是一月或二月,需要修正
  228.         xtn --;
  229.         xty += 12;
  230.     }
  231.         wd = (xtn + int(xtn * 0.25) + int(xtc * 0.25) - xtc * 2 + int((xty + 1) * 2.6) + xtr - 2) % 7;
  232.     return wd;
  233. }[/color][/font][/align][align=left][font=等线][color=#000000]void led_blink(byte pin)
  234. { //指定pin脚改变其状态
  235.   bool state = digitalRead(pin);  // 获得pin脚当前状态
  236.   digitalWrite(pin, !state);      // 设置pin脚为反
  237. }[/color][/font][/align][align=left][font=等线][color=#000000]void wifi_conn() {//进行WiFi连接
  238.   NTPtime = 8*3600;  //给NTP时间赋初值
  239.   savetime = millis();
  240.   NTP_got = 0;
  241.   udp.begin(localPort);//连接UDP,获取NTP时间需要
  242.       
  243.   // 开启 LLMNR responder
  244.   LLMNR.begin(host);                      //开启LLMNR域名解析
  245.   httpServer.on("/", handleRoot);         //调用主页面
  246.   httpServer.onNotFound(handleNotFound);  //出错调用
  247.    
  248.   // 开启 Web Update server.
  249.   httpUpdater.setup(&httpServer);
  250.   // 开启 HTTP server
  251.   httpServer.begin();
  252.   Serial.printf("HTTPUpdateServer ready! Open h t t p://%s.local/update in your browser\n", host);[/color][/font][/align][align=left][font=等线][color=#000000]  Serial.println("Wait for WiFi connection.");
  253.    
  254.   // ... 给ESP10秒时间连接wifi.
  255.   unsigned long startTime = millis();
  256.   while (wifiMulti.run() != WL_CONNECTED && millis() - startTime < 10000)
  257.   {
  258.         Serial.print(".");//如果没有连通向串口发送.....            
  259.         delay(250);
  260.   }
  261.   
  262.   // 检查连接状态
  263.   if(WiFi.status() == WL_CONNECTED)
  264.   {//如果WiFi连接成功
  265.       Serial.print("IP address: ");
  266.       Serial.println(WiFi.localIP());
  267.       slow_ticker.attach(0.8, led_blink, board_led);//WiFi连接正常,板载灯闪烁
  268.       fetchNTPtime();       //获取NTP时间
  269.   }
  270.   else
  271.   {//WiFi连接不成功
  272.       Serial.println("wifi connect fail!");
  273.       digitalWrite(board_led,HIGH);//WiFi连接失败,板载灯灭
  274.   }
  275. }
复制代码


模块启动时,板载灯点亮。WiFi连接成功后,板载灯闪烁;WiFi连接失败后,板载灯熄灭。




发表于 2020-12-10 21:44 | 显示全部楼层
哪复制的代码,中间多了很多多余的,影响下载
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|Archiver|手机版|Arduino中文社区

GMT+8, 2024-11-28 10:32 , Processed in 0.081613 second(s), 19 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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