Получение даты и времени с NTP-сервера с помощью ESP8266 NodeMCU
Время от времени вы сталкиваетесь с идеей, где поддержание точного времени является главным приоритетом. Например, рассмотрим реле, которое должно быть активировано в определённое время, или регистратор данных, который должен сохранять значения через точные интервалы.
Первое, что приходит на ум — использовать микросхему RTC (часы реального времени). Однако, поскольку эти микросхемы не являются идеально точными, вам придётся регулярно выполнять ручную корректировку, чтобы поддерживать их синхронизацию.
Вместо этого предпочтительнее использовать Network Time Protocol (NTP) — протокол сетевого времени. Если ваш проект на ESP8266 имеет доступ к Интернету, вы можете получать дату и время (с точностью до нескольких миллисекунд от UTC) БЕСПЛАТНО. Кроме того, вам не потребуется никакое дополнительное оборудование.
Что такое NTP?
NTP — это аббревиатура от Network Time Protocol. Это стандартный интернет-протокол (IP) для синхронизации часов компьютеров по сети.
Этот протокол синхронизирует все сетевые устройства с координированным всемирным временем (UTC) с точностью до нескольких миллисекунд (50 миллисекунд через публичный Интернет и менее 5 миллисекунд в среде LAN).
Координированное всемирное время (UTC) — это глобальный стандарт времени, аналогичный GMT (среднее время по Гринвичу). UTC не меняется; оно одинаково во всём мире.
Идея состоит в том, чтобы использовать NTP для установки часов компьютера на UTC, а затем применить любое смещение местного часового пояса или смещение летнего времени. Это позволяет нам синхронизировать часы наших компьютеров независимо от местоположения или различий в часовых поясах.
Архитектура NTP
NTP использует иерархическую архитектуру. Каждый уровень в иерархии называется стратой (stratum).
На самом верху находятся высокоточные устройства хранения времени, такие как атомные часы, GPS или радиочасы, известные как аппаратные часы страты 0.
Серверы страты 1 имеют прямое подключение к аппаратным часам страты 0 и поэтому обеспечивают наиболее точное время.
Каждая страта в иерархии синхронизируется со стратой выше и выступает в качестве сервера для компьютеров в нижних стратах.
Как работает NTP?
NTP может работать несколькими способами. Наиболее распространённая конфигурация — работа в режиме клиент-сервер.
Основной принцип работы заключается в следующем:
Клиентское устройство, такое как ESP8266, подключается к NTP-серверу через протокол пользовательских датаграмм (UDP) на порту 123.
Затем клиент отправляет пакет запроса на NTP-сервер.
В ответ на этот запрос NTP-сервер отправляет пакет с меткой времени. Пакет с меткой времени содержит различные данные, такие как временная метка UNIX, точность, задержка или часовой пояс.
Затем клиент может извлечь из него текущую дату и время.
Подготовка Arduino IDE
Перед тем как приступить к этому руководству, у вас должно быть установлено дополнение ESP8266 в вашей Arduino IDE. Если вы ещё не установили его, следуйте руководству ниже.
Установка платы ESP8266 в Arduino IDE — Существует несколько платформ разработки, доступных для программирования ESP8266. Вы можете выбрать Arduino IDE — предназначенную для тех, кто знаком с Arduino, Espruino…
Установка библиотеки NTP Client
Библиотека NTP Client упрощает процесс получения времени и даты с NTP-сервера. Выполните приведённые ниже шаги, чтобы установить эту библиотеку в вашей Arduino IDE.
Перейдите в Sketch > Include Library > Manage Libraries… Подождите, пока менеджер библиотек загрузит индекс библиотек и обновит список установленных библиотек.
Отфильтруйте поиск, введя „ntpclient“. Найдите NTPClient от Fabrice Weinberg. Нажмите на эту запись, а затем выберите Install.
Получение даты и времени с NTP-сервера
Приведённый ниже скетч покажет вам, как именно получить дату и время с NTP-сервера.
#include <NTPClient.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
const char *ssid = "YOUR_SSID";
const char *password = "YOUR_PASS";
const long utcOffsetInSeconds = 3600;
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
// Define NTP Client to get time
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", utcOffsetInSeconds);
void setup(){
Serial.begin(115200);
WiFi.begin(ssid, password);
while ( WiFi.status() != WL_CONNECTED ) {
delay ( 500 );
Serial.print ( "." );
}
timeClient.begin();
}
void loop() {
timeClient.update();
Serial.print(daysOfTheWeek[timeClient.getDay()]);
Serial.print(", ");
Serial.print(timeClient.getHours());
Serial.print(":");
Serial.print(timeClient.getMinutes());
Serial.print(":");
Serial.println(timeClient.getSeconds());
//Serial.println(timeClient.getFormattedTime());
delay(1000);
}
Перед тем как начать загрузку скетча, вам нужно внести несколько изменений, чтобы убедиться, что он будет работать для вас.
Измените следующие две переменные, указав ваши сетевые учётные данные, чтобы ESP8266 мог подключиться к существующей сети.
const char* ssid = "YOUR_SSID";
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
const long utcOffsetInSeconds = 3600;
После загрузки скетча нажмите кнопку RST на вашем NodeMCU. Монитор последовательного порта должен отображать дату и время каждую секунду.
Объяснение кода
Давайте кратко рассмотрим код, чтобы понять, как он работает. Для начала мы подключаем библиотеки, необходимые для этого проекта.
NTPClient.h — это библиотека времени, которая корректно обрабатывает синхронизацию с NTP-сервером.
ESP8266WiFi.h — это библиотека, содержащая специфичные для ESP8266 методы WiFi, которые мы будем использовать для подключения к сети.
WiFiUdp.h — библиотека, обрабатывающая задачи протокола UDP, такие как открытие UDP-порта, отправка и получение UDP-пакетов и так далее.
#include <NTPClient.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
Определяется несколько констант, таких как SSID, пароль WiFi и смещение UTC. Также определяется двумерный массив daysOfTheWeek.
const char *ssid = "YOUR_SSID";
const char *password = "YOUR_PASS";
const long utcOffsetInSeconds = 3600;
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
Кроме того, указывается адрес NTP-сервера. pool.ntp.org — это отличный открытый NTP-проект для подобных задач.
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", utcOffsetInSeconds);
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 |
В секции setup мы сначала устанавливаем последовательную связь с ПК, а затем подключаемся к WiFi-сети, вызывая функцию WiFi.begin().
Serial.begin(115200);
WiFi.begin(ssid, password);
while ( WiFi.status() != WL_CONNECTED ) {
delay ( 500 );
Serial.print ( "." );
}
Как только ESP8266 подключён к сети, мы используем функцию begin() для инициализации NTP-клиента.
timeClient.begin();
Теперь мы просто вызываем функцию update() для получения текущей даты и времени. Эта функция отправляет пакет запроса на NTP-сервер и разбирает полученный пакет с меткой времени в читаемый формат.
timeClient.update();
Вы можете получить текущую дату и время, вызывая методы объекта NTP Client.
Serial.print(daysOfTheWeek[timeClient.getDay()]);
Serial.print(", ");
Serial.print(timeClient.getHours());
Serial.print(":");
Serial.print(timeClient.getMinutes());
Serial.print(":");
Serial.println(timeClient.getSeconds());