ESP8266系列模块初始化成可以OTA,通过Web页进行升级(1)
本帖最后由 wherestheway 于 2018-10-16 20:11 编辑大家好,下面分享一下本人的一些经验。ESP8266系列模块(有ESP-01、ESP-12)具有WiFi功能,Arduino常常与之相连实现无线上网。其实,ESP8266系列模块不但具有WiFi功能,还具有MCU功能,可以对IO脚进行输入输出控制,完全可以替代Arduino模块。还可以通过域名直接访问(局域网内),实现Web页无线升级。升级界面:下面是代码:
/*
日期:2018.8.12
Arduino IDE 版本:1.8.6
ESP8266 for Arduino 版本:2.4.2
芯片:WeMos D1 mini功能:初始化芯片,使其具有Web Browser OTA升级功能,NTP时间获取
通过h t t p://D1-mini.local/可以访问状态
通过h t t p://D1-mini.local/update可以进行OTA升级
*/#include <ESP8266WiFiMulti.h>
#include <WiFiUdp.h>
#include <ESP8266WebServer.h>
#include <ESP8266LLMNR.h>
#include <ESP8266HTTPUpdateServer.h>
#include<time.h>
#include <Ticker.h>
ADC_MODE(ADC_VCC);const char *host = "D1-mini"; //节点名,web update server hostname//数字输出管脚定义
byte board_led = 2; //D1-mini板载灯脚,D4
//byte board_led = 1; //ESP-01板载灯脚// 获取NTP时间相关配置
unsigned int localPort = 2390; // 本地端口,侦听UDP packets
IPAddress timeServerIP; //时间服务器动态IP地址
//const char* ntpServerName = "time.nist.gov";//时间服务器域名
const char* ntpServerName = "cn.pool.ntp.org";//国内时间服务器域名
const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message
byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets
unsigned long NTPtime; //获取的NTP时间(秒)
unsigned long nowtime; //实时时间(毫秒)
unsigned long savetime; //获取NTP时间时,对应的系统时间(millis)
bool NTP_got = 0; //成功获取NTP时间,1为成功,0为失败
#define Detect_Interval 3000 // 检测周期,3秒
unsigned int next_Detect_Time; //下次检测时间//创建对象Ticker slow_ticker; //用于板载灯慢闪烁控制
WiFiUDP udp; //获取NTP时间需要
ESP8266WebServer httpServer(80); //用于web服务器
ESP8266HTTPUpdateServer httpUpdater; //用于代码OTA更新
ESP8266WiFiMulti wifiMulti; //多WiFi名称登陆void setup() {
Serial.begin(115200);
delay(10);
Serial.println();
Serial.println("D1 Initialize");
//Serial.setDebugOutput(true);
pinMode(board_led,OUTPUT); //设置板载灯脚为输出状态
digitalWrite(board_led,LOW); //点亮板载灯(低电平有效),开始连接WiFi //预置WiFi名称和密码,这样模块在家和单位就都可以使用了
wifiMulti.addAP("WiFi名称", "密码");//家
wifiMulti.addAP("WiFi名称", "密码");//单位
//还可以再加,好像最多为6个
wifi_conn();//连接WiFi
//WiFi.printDiag(Serial);
}
void loop() { nowtime = (millis()-savetime)/1000 + NTPtime; //现在时间计算赋值
// Handle http server.
httpServer.handleClient(); //再次获得时间
if( (millis() > next_Detect_Time && !NTP_got) || millis() < 250){
//如果获取NTP时间失败,并累计超过3秒,再或模块系统时间清零,重新获取
Serial.print("begin fetch NTP time again\r\n");
fetchNTPtime();
next_Detect_Time = millis() + Detect_Interval;//设置下次检测时间
}
//在下面输入你的代码
Serial.print("ESP.getVcc(): ");
Serial.println(ESP.getVcc()); delay(2500);
}void fetchNTPtime(){//获取NTP时间//通过域名获取IP地址
WiFi.hostByName(ntpServerName, timeServerIP); sendNTPpacket(timeServerIP); // 调用这个函数,向时间服务器发请求
// wait to see if a reply is available
delay(1000);
int cb = udp.parsePacket();
if (!cb) {//没有接收到数据
//Serial.println("no packet yet");
NTP_got = 0;
}
else {//接收到数据 udp.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer //从接收包第40个字节开始的4个字为节时间戳,先分别赋值到2 word
unsigned long highWord = word(packetBuffer, packetBuffer);
unsigned long lowWord = word(packetBuffer, packetBuffer);
//合并4字节成长整型,这就是NTP时间(从1900.1.1开始的秒数)
// this is NTP time (seconds since Jan 1 1900):
unsigned long secsSince1900 = highWord << 16 | lowWord;
//Serial.print("Seconds since Jan 1 1900 = " );
//Serial.println(secsSince1900); // now convert NTP time into everyday time:
//Serial.print("Unix time = ");
// Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
const unsigned long seventyYears = 2208988800UL;
// subtract seventy years:
NTPtime = secsSince1900 - seventyYears;
NTPtime += 8 * 3600;//北京时间,东八区修正
NTP_got = 1;
//Serial.print("got NTP time\r\n");
savetime = millis();//获得NTP时间的系统时刻
} nowtime = (millis()-savetime)/1000 + NTPtime; //打印小时、分钟和秒:
Serial.print("The Beijing time is ");
Serial.println(displaytime(nowtime));
}//发送NTP请求到指定IP地址的时间服务器
unsigned long sendNTPpacket(IPAddress& address)
{
//Serial.println("sending NTP packet...");
//将缓冲区里所有字节清零
memset(packetBuffer, 0, NTP_PACKET_SIZE);
// 准备NTP请求数据
packetBuffer = 0b11100011; // LI, Version, Mode
packetBuffer = 0; // Stratum, or type of clock
packetBuffer = 6; // Polling Interval
packetBuffer = 0xEC;// Peer Clock Precision
// 8 bytes of zero for Root Delay & Root Dispersion
packetBuffer= 49;
packetBuffer= 0x4E;
packetBuffer= 49;
packetBuffer= 52;// all NTP fields have been given values, now
// you can send a packet requesting a timestamp:
udp.beginPacket(address, 123); //NTP requests are to port 123
udp.write(packetBuffer, NTP_PACKET_SIZE);
udp.endPacket();
}void handleRoot() {
IPAddress local_ip;String message = "<!DOCTYPE HTML>";
message += "<html><head><meta charset=\"UTF-8\"><title>初始化芯片</title>";
message += "</head><body><div align=\"center\">";
message += "<div id=\"container\" style=\"width:600px\">";
message += "<div id=\"header\" style=\"background-color:#FFB3B3;\">";
message += "<h2 style=\"margin-bottom:0;\">D1-mini芯片连接成功!</h2></div>";
message += "<div id=\"hoststatus\" style=\"background-color:#FFE5E5;height:160px;width:600px;float:left;\"><form><br>";
message += "模块时间:";
message += displaytime(nowtime);
message += " 星期";
switch (weekday(nowtime)){
case 0 :
message += "一";
break;
case 1 :
message += "二";
break;
case 2 :
message += "三";
break;
case 3 :
message += "四";
break;
case 4 :
message += "五";
break;
case 5 :
message += "六";
break;
case 6 :
message += "日";
}
message += "<br><br><div id=\"SSID\">SSID:";
message += WiFi.SSID();
message += "</div><div id=\"IP_Address\">IP 地址:";
local_ip = WiFi.localIP();
for (uint8_t i=0; i<3; i++){
message += local_ip;
message += ".";
}
message += local_ip;
message += "<br><br><a href=\"/update\">点击这里</a> 进入OTA升级界面";
message += "</div></div></body></html>";
httpServer.send ( 200, "text/html", message );
}void handleNotFound(){
//digitalWrite(board_led, 1);
String message = "File Not Found\n\n";
message += "URI: ";
message += httpServer.uri();
message += "\nMethod: ";
message += (httpServer.method() == HTTP_GET)?"GET":"POST";
message += "\nArguments: ";
message += httpServer.args();
message += "\n";
for (uint8_t i=0; i<httpServer.args(); i++){
message += " " + httpServer.argName(i) + ": " + httpServer.arg(i) + "\n";
}
httpServer.send(404, "text/plain", message);
//digitalWrite(board_led, 0);
}String displaytime(unsigned long nt)
{
//显示日期,小时、分钟和秒:
String dt;
time_t nowtm;
struct tm *timeinfo;
//time( &nowtime );
//timeinfo = localtime( &nowtime );
nowtm = nt;
timeinfo = localtime(&nowtm);
int xtn = timeinfo->tm_year + 1900;
int xty = timeinfo->tm_mon + 1;
int xtr = timeinfo->tm_mday;
int xts = timeinfo->tm_hour;
int xtf = timeinfo->tm_min;
int xtm = timeinfo->tm_sec; dt += xtn;
dt += "-";
dt += xty;
dt += "-";
dt += xtr;
dt += " ";
if (xts < 10 ) {
// 前10小时加“ ”
dt += ' ';
}
dt += xts;
dt += ":";
if (xtf < 10 ) {
// 前10分加“0”
dt += '0';
}
dt += xtf;
dt += ":";
if (xtm < 10 ) {
// 前10秒加“0”
dt += '0';
}
dt += xtm; return dt;
}byte weekday(unsigned long nt)
{
//显示星期数:周一为0,周二为1,周三为2,周四为3,周五为4,周六为5,周日为6
byte wd;
time_t nowtm;
struct tm *timeinfo;
//time( &nowtime );
//timeinfo = localtime( &nowtime );
nowtm = nt;
timeinfo = localtime(&nowtm);
int xtn = timeinfo->tm_year + 1900; //年份
int xty = timeinfo->tm_mon + 1; //月份
int xtr = timeinfo->tm_mday; //日
int xtc = xtn / 100; //世纪
xtn = xtn % 100; //年数 if (xty < 3){ //如果是一月或二月,需要修正
xtn --;
xty += 12;
}
wd = (xtn + int(xtn * 0.25) + int(xtc * 0.25) - xtc * 2 + int((xty + 1) * 2.6) + xtr - 2) % 7;
return wd;
}void led_blink(byte pin)
{ //指定pin脚改变其状态
bool state = digitalRead(pin);// 获得pin脚当前状态
digitalWrite(pin, !state); // 设置pin脚为反
}void wifi_conn() {//进行WiFi连接
NTPtime = 8*3600;//给NTP时间赋初值
savetime = millis();
NTP_got = 0;
udp.begin(localPort);//连接UDP,获取NTP时间需要
// 开启 LLMNR responder
LLMNR.begin(host); //开启LLMNR域名解析
httpServer.on("/", handleRoot); //调用主页面
httpServer.onNotFound(handleNotFound);//出错调用
// 开启 Web Update server.
httpUpdater.setup(&httpServer);
// 开启 HTTP server
httpServer.begin();
Serial.printf("HTTPUpdateServer ready! Open h t t p://%s.local/update in your browser\n", host);Serial.println("Wait for WiFi connection.");
// ... 给ESP10秒时间连接wifi.
unsigned long startTime = millis();
while (wifiMulti.run() != WL_CONNECTED && millis() - startTime < 10000)
{
Serial.print(".");//如果没有连通向串口发送.....
delay(250);
}
// 检查连接状态
if(WiFi.status() == WL_CONNECTED)
{//如果WiFi连接成功
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
slow_ticker.attach(0.8, led_blink, board_led);//WiFi连接正常,板载灯闪烁
fetchNTPtime(); //获取NTP时间
}
else
{//WiFi连接不成功
Serial.println("wifi connect fail!");
digitalWrite(board_led,HIGH);//WiFi连接失败,板载灯灭
}
}
模块启动时,板载灯点亮。WiFi连接成功后,板载灯闪烁;WiFi连接失败后,板载灯熄灭。
哪复制的代码,中间多了很多多余的,影响下载
页:
[1]