Получение даты и времени от NTP сервера с помощью ESP8266 NodeMCU
Время от времени вы сталкиваетесь с идеей, в которой основным значением является время. Например, представьте реле, которое должно быть активировано в определенное время, или регистратор данных, который должен сохранять значения через определенные промежутки времени.
Первое, что приходит в голову, – это использовать микросхему RTC (часы реального времени). Но эти микросхемы не совсем точны, поэтому вам нужно снова и снова выполнять ручную подстройку, чтобы синхронизировать их с реальным временем.
Решение в этом случае – использовать протокол сетевого времени (NTP). Если у вашего проекта на ESP8266 есть доступ к Интернету, вы можете бесплатно получить дату и время (с точностью до нескольких миллисекунд от UTC). Дополнительное оборудование не требуется.
Что такое NTP?
NTP означает Network Time Protocol (протокол сетевого времени). Это стандартный интернет-протокол для синхронизации часов компьютера с неким эталоном в сети.
Данный протокол может использоваться для синхронизации всех сетевых устройств с всемирным координированным временем (UTC) с точностью до нескольких миллисекунд (50 миллисекунд в общедоступном Интернете и менее 5 миллисекунд в среде LAN).
Всемирное координированное время (UTC) – это всемирный стандарт времени, тесно связанный с GMT (средним временем по Гринвичу). UTC не меняется, оно одинаково во всем мире.
NTP устанавливает часы компьютеров в формате UTC, любое смещение местного часового пояса или смещение летнего времени применяется уже клиентом. Таким образом, клиенты могут синхронизироваться с серверами независимо от местоположения и разницы часовых поясов.
Архитектура NTP
NTP использует иерархическую архитектуру. Каждый уровень иерархии известен как слой (англ. stratum).
На самом верху находятся высокоточные устройства для измерения времени, известные как аппаратные часы уровня 0; это, например, атомные часы, GPS или радиочасы.
Серверы слоя 1 имеют прямое соединение с аппаратными часами слоя 0 и поэтому имеют наиболее точное время.
Каждый слой в иерархии синхронизируется с уровнем выше и действует как серверы для компьютеров нижнего слоя.
Как работает NTP?
NTP может работать разными способами. Наиболее распространенная конфигурация – работа в режиме клиент-сервер. Основной принцип работы следующий:
- клиентское устройство, такое как ESP8266, подключается к серверу с помощью протокола пользовательских датаграмм (UDP) через порт 123;
- затем клиент передает пакет запроса на сервер NTP;
- в ответ на этот запрос сервер NTP отправляет пакет с меткой времени;
- пакет с меткой времени содержит множество информации, такой как метка времени UNIX, точность, задержка или часовой пояс;
- затем клиент может проанализировать текущие значения даты и времени.
Подготовка IDE Arduino
Хватит теории, приступим к практике!
Но прежде чем углубляться в данное руководство, вы должны установить в вашу Arduino IDE дополнение для ESP8266. Чтобы подготовить Arduino IDE к работе с ESP8266 (если вы еще этого не сделали) следуйте инструкциям из статьи по ссылке ниже:
Установка библиотеки NTP-клиента
Самый простой способ получить дату и время с сервера NTP – это использовать клиент NTP из библиотек Arduino. Выполните следующие шаги, чтобы установить эту библиотеку в свою Arduino IDE.
Перейдите в раздел Скетч → Подключить библиотеку → Управлять библиотеками…. Подождите, пока менеджер библиотек загрузит индекс библиотек и обновит список установленных библиотек.
Отфильтруйте результаты поиска, набрав «ntpclient». Должна остаться пара записей. Ищите NTPClient by Fabrice Weinberg. Щелкните на эту запись и выберите «Установить».
Получение текущих дня недели и времени от NTP-сервера
Следующий скетч даст вам полное представление о том, как получить текущие день недели и время с NTP-сервера.
Прежде чем вы отправитесь загружать скетч, вам нужно внести пару изменений, чтобы он у вас заработал.
- Чтобы ESP8266 мог установить соединение с существующей сетью WiFi, вам необходимо изменить следующие две переменные в соответствии с учетными данными вашей сети.
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;
Как только вы закончите, загрузите скетч в ESP8266.
#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"};
// Определение NTP-клиента для получения времени
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);
}
После загрузки скетча нажмите кнопку 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
.
Теперь, прежде чем инициализировать объект NTP-клиента, нам нужно указать адрес 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 подключится к сети, мы инициализируем NTP-клиент с помощью функции begin()
.
timeClient.begin();
Теперь мы можем просто вызывать функцию update()
всякий раз, когда нам нужны текущие день недели и время. Эта функция передает пакет с запросом на NTP-сервер, используя протокол UDP, и преобразует полученный пакет с меткой времени в читаемый формат.
timeClient.update();
Вы можете получить доступ к информации о дне и времени, воспользовавшись функциями библиотеки NTP-клиента.
Serial.print(daysOfTheWeek[timeClient.getDay()]);
Serial.print(", ");
Serial.print(timeClient.getHours());
Serial.print(":");
Serial.print(timeClient.getMinutes());
Serial.print(":");
Serial.println(timeClient.getSeconds());