ESP32做一个电子手表(二) WIFI+NTP对时

ESP32做一个电子手表(二) WIFI+NTP对时

前期准备

ESP32开发板 * 1
串口助手/arduino自带的串口监视器

一、WIFI配置

由于ESP32自带WIFI模块,所以我们只需要使用代码初始化WiFi即可

示例代码

//用到了WIFI.h库
#include <WiFi.h>
const char* id="要连接wifi名字";   //定义两个字符串指针常量
const char* psw="wifi密码";

void setup() {
  Serial.begin(115200);
  WiFi.begin(id,psw);
  while(WiFi.status()!=WL_CONNECTED){			//未连接上
    delay(500);
    Serial.println("正在连接...");
  }
  Serial.println("连接成功!");				//连接上
}
void loop(){							//空循环
}

其中id为所需连接的wifi名称,psw为wifi的密码,需要手动修改一下。成功烧录代码后就可以连接wifi啦~

串口验证

arduino编译器的右上角有一个长得像放大镜的东西请添加图片描述
这就是串口监视器了,连接上我们的开发板,记得要在底部右下方修改串口波特率(一般第一次打开默认好像是9600)。因为我们程序设置的波特率为115200,所以下方波特率也要修改为115200。
请添加图片描述

二、NTP对时

NTP对时原理

连接网络, 从网络中请求NTP对时数据。我使用的是阿里云的NTP服务器 ntp1.aliyun.com,还有很多其他的服务器可以选择,这里就不多赘述了。另外由于我们地理位置处于东八区,因此应该偏移8个小时。

初始化一个NTP服务客户端

time.h 是 ESP32 本机时间库,用于执行正常的 NTP 服务器同步。

#include "time.h"

然后,我们还需要指定要使用的NTP服务器的地址。pool.ntp.org 是一个开放的NTP项目,非常适合做这样的事情。

const char* ntpServer = "pool.ntp.org";
const long  gmtOffset_sec = 28800;
const int   daylightOffset_sec = 0;

pool.ntp.org 会自动选择地理位置接近您的时间服务器。但是,如果要显式选择,请使用 pool.ntp.org 子区域之一。
面积 主机名
全球 pool.ntp.org
亚洲 asia.pool.ntp.org
欧洲 europe.pool.ntp.org
北美洲 north-america.pool.ntp.org
大洋洲 oceania.pool.ntp.org
南美洲 south-america.pool.ntp.org

ESP32 连接到网络后,我们使用函数初始化 NTP 客户端,以从 NTP 服务器获取日期和时间。

configTime()
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);

现在,只要我们想要打印当前日期和时间,我们就可以简单地调用自定义函数printLocalTime()

getLocalTime()函数用于将请求数据包传输到NTP服务器,并将接收到的时间戳数据包解析为可读格式。它采用时间结构作为参数。

然后我们就可以通过访问此时间结构的成员来访问日期和时间信息。

/*
%A	返回星期几
%B	返回年份月份
%d	返回月份中的某一天
%Y	回报年份
%H	返回时间
%M	返回分钟数
%S	返回秒数
*/
void printLocalTime()
{
  struct tm timeinfo;
  if(!getLocalTime(&timeinfo)){
    Serial.println("Failed to obtain time");
    return;
  }
  Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
}

有几个系统提供的函数,
链接: https://github.com/espressif/ard … 2/esp32-hal-timer.h

可以设置系统时间,也可以获取到系统时间tm info结构,可以取到当前的年月日时分秒

这是tm的结构体

struct tm
{
  int        tm_sec;
  int        tm_min;
  int        tm_hour;
  int        tm_mday;
  int        tm_mon;
  int        tm_year;
  int        tm_wday;
  int        tm_yday;
  int        tm_isdst;
#ifdef __TM_GMTOFF
  long        __TM_GMTOFF;
#endif
#ifdef __TM_ZONE
  const char *__TM_ZONE;
#endif
};

获取时间函数是

bool getLocalTime(struct tm * info, uint32_t ms = 5000);

时间的处理:
由于获取的数据我们后面需要放到OLED上去显示,所以需要对小于10的数据补0处理。对于年的处理则是加上1900。

void printLocalTime()//打印本地时间函数
{
  struct tm timeinfo;
  if(!getLocalTime(&timeinfo)){
    Serial.println("Failed to obtain time");
    return;
  }
  s=timeinfo.tm_sec;//获取时间参数
  m=timeinfo.tm_min;
  h=timeinfo.tm_hour;
  d=timeinfo.tm_mday;
  mon=timeinfo.tm_mon;
  int ss=int(timeinfo.tm_sec);
  int mm=int(timeinfo.tm_min);
  int hh=int(timeinfo.tm_hour);
  int dayd=int(timeinfo.tm_mday);
  int monm=int(timeinfo.tm_mon);//转换成int类型,用于判断是否需要补0
  if(ss<10){s=Zero[0]+s;}//如果小于10的数字在前面补0
  if(mm<10){m=Zero[0]+m;}
  if(hh<10){h=Zero[0]+h;}
  if(dayd<10){d=Zero[0]+d;}
  montrue=monm+1;//月份为0~11所以要加1
  if(monm<10){montrue=Zero[0]+montrue;}
  y=int(timeinfo.tm_year)+1900;//2022年的y值为122,所以加上1900后再显示
  w=int(timeinfo.tm_wday);//星期一
  Serial.println(&timeinfo, "%A, %Y-%m-%d %H:%M:%S");
}

完整代码

为了避免代码冗长,这里我把WIFI和OLED的初始化程序放到我的自定义库里面去了,如果对自定义库不理解的可以翻阅我的其他博客。

#include "SSD1306Wire.h"
#include <Wire.h>
#include <WiFi.h>
#include "MYWIFI.h"
#include "OLED.h"
#include "time.h"

void printLocalTime();

const char* ntpServer = "pool.ntp.org";
const long  gmtOffset_sec = 28800;
const int   daylightOffset_sec = 0;

String s;
String m;
String h;
String d;
String mon;
String montrue;
String T;
int y;
int w;
String Zero[1]={"0"};
String week[8]={"Sun","Mon","Tues","Wednes","Thur","Fri","Sat"};

void setup() 
{
  wifi_init();
  oled_init(); 
  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);//初始化NTP客户端
  printLocalTime();//获取本地时间 
}

void loop() 
{
  
}

void printLocalTime()//打印本地时间函数
{
  struct tm timeinfo;
  if(!getLocalTime(&timeinfo)){
    Serial.println("Failed to obtain time");
    return;
  }
  s=timeinfo.tm_sec;//获取时间参数
  m=timeinfo.tm_min;
  h=timeinfo.tm_hour;
  d=timeinfo.tm_mday;
  mon=timeinfo.tm_mon;
  int ss=int(timeinfo.tm_sec);
  int mm=int(timeinfo.tm_min);
  int hh=int(timeinfo.tm_hour);
  int dayd=int(timeinfo.tm_mday);
  int monm=int(timeinfo.tm_mon);//转换成int类型,用于判断是否需要补0
  if(ss<10){s=Zero[0]+s;}//如果小于10的数字在前面补0
  if(mm<10){m=Zero[0]+m;}
  if(hh<10){h=Zero[0]+h;}
  if(dayd<10){d=Zero[0]+d;}
  montrue=monm+1;//月份为0~11所以要加1
  if(monm<10){montrue=Zero[0]+montrue;}
  y=int(timeinfo.tm_year)+1900;//2022年的y值为122,所以加上1900后再显示
  w=int(timeinfo.tm_wday);//星期一
  Serial.println(&timeinfo, "%A, %Y-%m-%d %H:%M:%S");
}

串口打印出来看一下
请添加图片描述
时间正确。

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值