风筝
发表于: 2022-11-5 12:11:03 | 显示全部楼层

时不时地,您会发现跟踪时间是重中之重的想法。例如,考虑必须在特定时间激活继电器或必须以精确时间间隔存储值的数据记录器。


想到的第一件事是使用RTC(实时时钟)芯片。但是,由于这些芯片不是完全准确的,因此您必须定期执行手动调整以保持它们同步。


相反,最好采用网络时间协议(NTP)。如果您的ESP8266项目可以访问互联网,则可以免费获得日期和时间(精度为几毫秒的UTC)。另外,您不需要任何其他硬件。


什么是NTP?

NTP是网络时间协议(Network Time Protocol)的缩写。这是一种标准的Internet协议(IP),用于通过网络同步计算机时钟。


该协议将所有网络设备同步以在几毫秒内协调通用时间(UTC)(公共互联网上的50毫秒和LAN环境中的5毫秒以下)。


协调的通用时间(UTC)是类似于GMT(格林威治平均时间)的全球时间标准。 UTC不会改变;全世界都是一样的。


这里的想法是使用NTP将计算机时钟设置为UTC,然后应用任何本地时区偏移量或节省时间偏移。这使我们能够同步计算机时钟,无论位置或时区差异如何。


NTP体系结构

NTP采用层次结构。层次结构中的每个级别都称为层。

NTP-Hierarchical-Architecture-With-Stratums.jpg


在顶部是高精度计时设备,例如原子钟、GPS或无线电时钟,称为Stratum 0硬件时钟。Stratum 1服务器直接连接到Stratum 0硬件时钟,因此提供了最准确的时间。


层次结构中的每个阶层都与上面的层同步,并充当较低层中计算机的服务器。


NTP如何工作?

NTP可以以多种方式运行。最常见的配置是在客户端服务器模式下操作。


基本操作原则如下:

1.  客户端设备(例如ESP8266)通过端口123上的用户数据报协议(UDP)连接到NTP服务器。

2.  然后,客户端将请求数据包发送到NTP服务器。

3.  为了响应此请求,NTP服务器发送了一个时间戳记包。时间戳记包包含各种数据,例如UNIX时间戳、精度、延迟或时区。

4.  然后,客户可以从中提取当前日期和时间。

NTP-Server-Working-Request-And-Timestamp-Packet-Transfer.jpg


安装NTP Client库

NTP Client简化了从NTP服务器检索时间和日期的过程。请按照下面的步骤在您的Arduino IDE中安装此库。


导航到Sketch > Include Library > Manage Libraries… 等待Library Manager下载库索引并更新已安装的库列表。输入ntpclient筛选搜索结果。查找Fabrice Weinberg提供的NTPClient。单击该条目,然后选择Install。

Installing-NTP-Client-Library-In-Arduino-IDE.jpg


从NTP服务器获取日期和时间

下面的草图将向您显示如何从NTP服务器获得日期和时间。

  1. #include <NTPClient.h>
  2. #include <ESP8266WiFi.h>
  3. #include <WiFiUdp.h>

  4. const char *ssid     = "YOUR_SSID";
  5. const char *password = "YOUR_PASS";

  6. const long utcOffsetInSeconds = 3600;

  7. char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

  8. // Define NTP Client to get time
  9. WiFiUDP ntpUDP;
  10. NTPClient timeClient(ntpUDP, "pool.ntp.org", utcOffsetInSeconds);

  11. void setup(){
  12.   Serial.begin(115200);

  13.   WiFi.begin(ssid, password);

  14.   while ( WiFi.status() != WL_CONNECTED ) {
  15.     delay ( 500 );
  16.     Serial.print ( "." );
  17.   }

  18.   timeClient.begin();
  19. }

  20. void loop() {
  21.   timeClient.update();

  22.   Serial.print(daysOfTheWeek[timeClient.getDay()]);
  23.   Serial.print(", ");
  24.   Serial.print(timeClient.getHours());
  25.   Serial.print(":");
  26.   Serial.print(timeClient.getMinutes());
  27.   Serial.print(":");
  28.   Serial.println(timeClient.getSeconds());
  29.   //Serial.println(timeClient.getFormattedTime());

  30.   delay(1000);
  31. }
复制代码

在开始上传草图之前,您需要进行一些更改,以确保它对您有用。

使用网络凭据修改以下两个变量,以便ESP8266可以连接到现有网络。

  1. const char* ssid       = "YOUR_SSID";
  2. const char* password   = "YOUR_PASS";
复制代码

调整UTC偏移的时区(以秒为单位)。请参阅UTC时间偏移列表。以下是各个时区的一些示例:

●    UTC -5.00 : -5 * 60 * 60 : -18000

●    UTC +1.00 : 1 * 60 * 60 : 3600

●    UTC +0.00 : 0 * 60 * 60 : 0

  1. const long utcOffsetInSeconds = 3600;
复制代码

上传草图后,按下NodeMCU上的复位按钮。串口显示器应每秒显示日期和时间。

ESP8266-Reads-Date-Time-From-NTP-Server-Output-On-Serial-monitor.jpg


代码说明

让我们快速查看代码以查看其工作原理。首先,我们包括此项目所需的库。

●    NTPClient.h 是一个时间库,可以处理NTP服务器同步。

●    ESP8266WiFi.h 是一个包含ESP8266特定WiFi函数的库,我们将使用将其连接到网络。

●    WiFiUdp.h 库处理UDP协议任务,例如打开UDP端口,发送和接收UDP数据包等。

  1. #include <NTPClient.h>
  2. #include <ESP8266WiFi.h>
  3. #include <WiFiUdp.h>
复制代码

定义了一些常量,例如SSID、WiFi密码和UTC偏移。还定义了Daysoftheweek二维数组。

  1. const char *ssid     = "YOUR_SSID";
  2. const char *password = "YOUR_PASS";
  3. const long utcOffsetInSeconds = 3600;
  4. char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
复制代码

此外,指定了NTP服务器的地址。 pool.ntp.org是这类事情的绝佳开放NTP项目。

  1. WiFiUDP ntpUDP;
  2. NTPClient timeClient(ntpUDP, "pool.ntp.org", utcOffsetInSeconds);
复制代码

pool.ntp.org自动选择物理上靠近您的时间服务器。但是,如果要选择特定的服务器,请使用pool.ntp.org子区域之一。


setup()函数中,我们首先与PC建立串口通信,然后通过调用WiFi.begin()函数连接到WiFi网络。

  1. Serial.begin(115200);

  2. WiFi.begin(ssid, password);

  3. while ( WiFi.status() != WL_CONNECTED ) {
  4.   delay ( 500 );
  5.   Serial.print ( "." );
  6. }
复制代码

ESP8266连接到网络后,我们使用begin()函数来初始化NTP客户端。

  1. timeClient.begin();
复制代码

现在,我们只需调用update()函数即可获得当前日期和时间。此函数将请求数据包发送到NTP服务器,并将接收到的时间戳数据包解析为可读格式。

  1. timeClient.update();
复制代码

您可以通过调用NTP客户端对象的方法来检索当前日期和时间。

  1. Serial.print(daysOfTheWeek[timeClient.getDay()]);
  2. Serial.print(", ");
  3. Serial.print(timeClient.getHours());
  4. Serial.print(":");
  5. Serial.print(timeClient.getMinutes());
  6. Serial.print(":");
  7. Serial.println(timeClient.getSeconds());
复制代码

跳转到指定楼层
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题 54 | 回复: 107



手机版|

GMT+8, 2024-11-21 16:32 , Processed in 0.090299 second(s), 8 queries , Gzip On, MemCache On. Powered by Discuz! X3.5

YiBoard一板网 © 2015-2022 地址:河北省石家庄市长安区高营大街 ( 冀ICP备18020117号 )

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