Cat hungry.png
Здравствуйте! Собираем деньги на перевод материалов по электронике(https://www.allaboutcircuits.com/education/). Реквизиты указаны здесь.

Arduino:Примеры/TimeNTP ESP8266WiFi

Материал из Онлайн справочника
Перейти к: навигация, поиск

Перевод: Максим Кузьмин (Cubewriter)
Перевел 2686 статей для сайта.

Контакты:

Проверка/Оформление/Редактирование: Мякишев Е.А.


Синхронизация времени с помощью NTP-сервера и WiFi[1]

Это скетч для библиотеки Time и платы Arduino, который демонстрирует, как синхронизировать время при помощи NTP-сервера. Для связи используется WiFi.

Код

  1. /*
  2.  
  3. Синхронизация времени с помощью NTP-сервера и WiFi
  4.  
  5. Этот пример показывает, как синхронизировать время
  6. с помощью NTP-сервера.
  7.  
  8. */
  9.  
  10. #include <TimeLib.h>
  11. #include <ESP8266WiFi.h>
  12. #include <WiFiUdp.h>
  13.  
  14. const char ssid[] = "*************";  //  SSID (название) вашей сети
  15. const char pass[] = "********";       // пароль к вашей сети
  16.  
  17. // NTP-серверы:
  18. static const char ntpServerName[] = "us.pool.ntp.org";
  19. //static const char ntpServerName[] = "time.nist.gov";
  20. //static const char ntpServerName[] = "time-a.timefreq.bldrdoc.gov";
  21. //static const char ntpServerName[] = "time-b.timefreq.bldrdoc.gov";
  22. //static const char ntpServerName[] = "time-c.timefreq.bldrdoc.gov";
  23.  
  24. const int timeZone = 1;     // центрально-европейское время
  25. //const int timeZone = -5;  // восточное время (США)
  26. //const int timeZone = -4;  // восточное дневное время (США)
  27. //const int timeZone = -8;  // тихоокеанское время (США)
  28. //const int timeZone = -7;  // тихоокеанское дневное время (США) 
  29.  
  30.  
  31. WiFiUDP Udp;
  32. unsigned int localPort = 8888;  // локальный порт для прослушивания UDP-пакетов
  33.  
  34. time_t getNtpTime();
  35. void digitalClockDisplay();
  36. void printDigits(int digits);
  37. void sendNTPpacket(IPAddress &address);
  38.  
  39. void setup()
  40. {
  41.   Serial.begin(9600);
  42.   while (!Serial) ; // нужно только для Leonardo
  43.   delay(250);
  44.   Serial.println("TimeNTP Example");  //  "Синхронизация с помощью NTP"
  45.   Serial.print("Connecting to ");  //  "Подключаемся к "
  46.   Serial.println(ssid);
  47.   WiFi.begin(ssid, pass);
  48.  
  49.   while (WiFi.status() != WL_CONNECTED) {
  50.     delay(500);
  51.     Serial.print(".");
  52.   }
  53.  
  54.   Serial.print("IP number assigned by DHCP is ");  //  "IP, присвоенный DHCP: "
  55.   Serial.println(WiFi.localIP());
  56.   Serial.println("Starting UDP");  //  "Начинаем UDP"
  57.   Udp.begin(localPort);
  58.   Serial.print("Local port: ");  //  "Локальный порт: "
  59.   Serial.println(Udp.localPort());
  60.   Serial.println("waiting for sync");  //  "ждем синхронизации"
  61.   setSyncProvider(getNtpTime);
  62.   setSyncInterval(300);
  63. }
  64.  
  65. time_t prevDisplay = 0; // когда будут показаны цифровые часы
  66.  
  67. void loop()
  68. {
  69.   if (timeStatus() != timeNotSet) {
  70.     if (now() != prevDisplay) {  // обновляем дисплей только если время поменялось
  71.       prevDisplay = now();
  72.       digitalClockDisplay();
  73.     }
  74.   }
  75. }
  76.  
  77. void digitalClockDisplay()
  78. {
  79.   // показываем цифровые часы: 
  80.   Serial.print(hour());
  81.   printDigits(minute());
  82.   printDigits(second());
  83.   Serial.print(" ");
  84.   Serial.print(day());
  85.   Serial.print(".");
  86.   Serial.print(month());
  87.   Serial.print(".");
  88.   Serial.print(year());
  89.   Serial.println();
  90. }
  91.  
  92. void printDigits(int digits)
  93. {
  94.   // вспомогательная функция для печати данных о времени 
  95.   // на монитор порта; добавляет в начале двоеточие и ноль:
  96.   Serial.print(":");
  97.   if (digits < 10)
  98.     Serial.print('0');
  99.   Serial.print(digits);
  100. }
  101.  
  102. /*-------- Код для NTP ----------*/
  103.  
  104. const int NTP_PACKET_SIZE = 48;  //  NTP-время – в первых 48 байтах сообщения
  105. byte packetBuffer[NTP_PACKET_SIZE];  //  буфер для хранения входящих и исходящих пакетов 
  106.  
  107. time_t getNtpTime()
  108. {
  109.   IPAddress ntpServerIP; // IP-адрес NTP-сервера
  110.  
  111.   while (Udp.parsePacket() > 0) ; // отбраковываем все пакеты, полученные ранее 
  112.   Serial.println("Transmit NTP Request");  //  "Передача NTP-запроса" 
  113.   // подключаемся к случайному серверу из списка:
  114.   WiFi.hostByName(ntpServerName, ntpServerIP);
  115.   Serial.print(ntpServerName);
  116.   Serial.print(": ");
  117.   Serial.println(ntpServerIP);
  118.   sendNTPpacket(ntpServerIP);
  119.   uint32_t beginWait = millis();
  120.   while (millis() - beginWait < 1500) {
  121.     int size = Udp.parsePacket();
  122.     if (size >= NTP_PACKET_SIZE) {
  123.       Serial.println("Receive NTP Response");  //  "Получение NTP-ответа"
  124.       Udp.read(packetBuffer, NTP_PACKET_SIZE);  // считываем пакет в буфер 
  125.       unsigned long secsSince1900;
  126.       // конвертируем 4 байта (начиная с позиции 40) в длинное целое число: 
  127.       secsSince1900 =  (unsigned long)packetBuffer[40] << 24;
  128.       secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
  129.       secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
  130.       secsSince1900 |= (unsigned long)packetBuffer[43];
  131.       return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
  132.     }
  133.   }
  134.   Serial.println("No NTP Response :-(");  //  "Нет NTP-ответа :(" 
  135.   return 0; // если время получить не удалось, возвращаем «0» 
  136. }
  137.  
  138. // отправляем NTP-запрос серверу времени по указанному адресу: 
  139. void sendNTPpacket(IPAddress &address)
  140. {
  141.   // задаем все байты в буфере на «0»: 
  142.   memset(packetBuffer, 0, NTP_PACKET_SIZE);
  143.   // инициализируем значения для создания NTP-запроса
  144.   // (подробнее о пакетах смотрите по ссылке выше) 
  145.   packetBuffer[0] = 0b11100011;   // LI (от «leap indicator», т.е. «индикатор перехода»), версия, режим работы 
  146.   packetBuffer[1] = 0;     // слой (или тип часов) 
  147.   packetBuffer[2] = 6;     // интервал запросов 
  148.   packetBuffer[3] = 0xEC;  // точность 
  149.   // 8 байтов с нулями, обозначающие базовую задержку и базовую дисперсию: 
  150.   packetBuffer[12] = 49;
  151.   packetBuffer[13] = 0x4E;
  152.   packetBuffer[14] = 49;
  153.   packetBuffer[15] = 52;
  154.   // После заполнения всех указанных полей
  155.   // вы сможете отправлять пакет с запросом о временной метке:      
  156.   Udp.beginPacket(address, 123); // NTP-запросы к порту 123
  157.   Udp.write(packetBuffer, NTP_PACKET_SIZE);
  158.   Udp.endPacket();
  159. }

См.также

Внешние ссылки

  1. github.com - TimeNTP_ESP8266WiFi.ino