|
本帖最后由 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[/color][/font][/align][align=left][font=等线][color=#000000]功能:初始化芯片,使其具有Web Browser OTA升级功能,NTP时间获取
- 通过h t t p://D1-mini.local/可以访问状态
- 通过h t t p://D1-mini.local/update可以进行OTA升级
- */[/color][/font][/align][align=left][font=等线][color=#000000]#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);[/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]//数字输出管脚定义
- byte board_led = 2; //D1-mini板载灯脚,D4
- //byte board_led = 1; //ESP-01板载灯脚[/color][/font][/align][align=left][font=等线][color=#000000]// 获取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; //下次检测时间[/color][/font][/align][align=left][font=等线][color=#000000]//创建对象[/color][/font][/align][align=left][font=等线][color=#000000]Ticker slow_ticker; //用于板载灯慢闪烁控制
- WiFiUDP udp; //获取NTP时间需要
- ESP8266WebServer httpServer(80); //用于web服务器
- ESP8266HTTPUpdateServer httpUpdater; //用于代码OTA更新
- ESP8266WiFiMulti wifiMulti; //多WiFi名称登陆[/color][/font][/align][align=left][font=等线][color=#000000]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[/color][/font][/align][align=left][font=等线][color=#000000] //预置WiFi名称和密码,这样模块在家和单位就都可以使用了
- wifiMulti.addAP("WiFi名称", "密码");//家
- wifiMulti.addAP("WiFi名称", "密码");//单位
- //还可以再加,好像最多为6个
-
- wifi_conn();//连接WiFi
- //WiFi.printDiag(Serial);
- }
-
- void loop() {[/color][/font][/align][align=left][font=等线][color=#000000] nowtime = (millis()-savetime)/1000 + NTPtime; //现在时间计算赋值
-
- // Handle http server.
- httpServer.handleClient();[/color][/font][/align][align=left][font=等线][color=#000000] //再次获得时间
- 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());[/color][/font][/align][align=left][font=等线][color=#000000] delay(2500);
- }[/color][/font][/align][align=left][font=等线][color=#000000]void fetchNTPtime(){//获取NTP时间[/color][/font][/align][align=left][font=等线][color=#000000] //通过域名获取IP地址
- WiFi.hostByName(ntpServerName, timeServerIP); [/color][/font][/align][align=left][font=等线][color=#000000] 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 {//接收到数据[/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
- unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
- unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
- //合并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);[/color][/font][/align][align=left][font=等线][color=#000000] // 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时间的系统时刻
- }[/color][/font][/align][align=left][font=等线][color=#000000] nowtime = (millis()-savetime)/1000 + NTPtime;[/color][/font][/align][align=left][font=等线][color=#000000] //打印小时、分钟和秒:
- Serial.print("The Beijing time is ");
- Serial.println(displaytime(nowtime));
- }[/color][/font][/align][align=left][font=等线][color=#000000]//发送NTP请求到指定IP地址的时间服务器
- unsigned long sendNTPpacket(IPAddress& address)
- {
- //Serial.println("sending NTP packet...");
- //将缓冲区里所有字节清零
- memset(packetBuffer, 0, NTP_PACKET_SIZE);
- // 准备NTP请求数据
- packetBuffer[0] = 0b11100011; // LI, Version, Mode
- packetBuffer[1] = 0; // Stratum, or type of clock
- packetBuffer[2] = 6; // Polling Interval
- packetBuffer[3] = 0xEC; // Peer Clock Precision
- // 8 bytes of zero for Root Delay & Root Dispersion
- packetBuffer[12] = 49;
- packetBuffer[13] = 0x4E;
- packetBuffer[14] = 49;
- packetBuffer[15] = 52;[/color][/font][/align][align=left][font=等线][color=#000000] // 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();
-
- }[/color][/font][/align][align=left][font=等线][color=#000000]void handleRoot() {
- IPAddress local_ip;[/color][/font][/align][align=left][font=等线][color=#000000] 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[i];
- message += ".";
- }
- message += local_ip[3];
- message += "<br><br><a href="/update">点击这里</a> 进入OTA升级界面";
- message += "</div></div></body></html>";
- httpServer.send ( 200, "text/html", message );
- }[/color][/font][/align][align=left][font=等线][color=#000000]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);
- }[/color][/font][/align][align=left][font=等线][color=#000000]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;[/color][/font][/align][align=left][font=等线][color=#000000] 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;[/color][/font][/align][align=left][font=等线][color=#000000] return dt;
- }[/color][/font][/align][align=left][font=等线][color=#000000]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; //年数[/color][/font][/align][align=left][font=等线][color=#000000] 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;
- }[/color][/font][/align][align=left][font=等线][color=#000000]void led_blink(byte pin)
- { //指定pin脚改变其状态
- bool state = digitalRead(pin); // 获得pin脚当前状态
- digitalWrite(pin, !state); // 设置pin脚为反
- }[/color][/font][/align][align=left][font=等线][color=#000000]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);[/color][/font][/align][align=left][font=等线][color=#000000] 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连接失败后,板载灯熄灭。
|
|