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

Arduino:Примеры/TimeNTP

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

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

Контакты:

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


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

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

Код

  1. /*
  2.  
  3. Синхронизация времени с помощью NTP-сервера
  4.  
  5. Этот пример показывает, как синхронизировать время 
  6. с помощью NTP-сервера.
  7.  
  8. В скетче используется библиотека Ethernet.
  9.  
  10. */
  11.  
  12. #include <TimeLib.h>
  13. #include <Ethernet.h>
  14. #include <EthernetUdp.h>
  15. #include <SPI.h>
  16.  
  17. byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; 
  18. // NTP-серверы:
  19. IPAddress timeServer(132, 163, 4, 101); // time-a.timefreq.bldrdoc.gov
  20. // IPAddress timeServer(132, 163, 4, 102); // time-b.timefreq.bldrdoc.gov
  21. // IPAddress timeServer(132, 163, 4, 103); // time-c.timefreq.bldrdoc.gov
  22.  
  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. EthernetUDP Udp;
  32. unsigned int localPort = 8888;  // локальный порт для прослушивания UDP-пакетов
  33.  
  34. void setup() 
  35. {
  36.   Serial.begin(9600);
  37.   while (!Serial) ; // нужно только для Leonardo
  38.   delay(250);
  39.   Serial.println("TimeNTP Example");  //  "Синхронизация с помощью NTP"
  40.   if (Ethernet.begin(mac) == 0) {
  41.     // продолжать смысла нет, поэтому дальше ничего не делаем:
  42.     while (1) {
  43.       Serial.println("Failed to configure Ethernet using DHCP");  //  "Не удалось сконфигурировать Ethernet при помощи UDP"
  44.       delay(10000);
  45.     }
  46.   }
  47.   Serial.print("IP number assigned by DHCP is ");  //  "IP, присвоенный DHCP: "
  48.  
  49.   Serial.println(Ethernet.localIP());
  50.   Udp.begin(localPort);
  51.   Serial.println("waiting for sync");  //  "ждем синхронизации"
  52.  
  53.   setSyncProvider(getNtpTime);
  54. }
  55.  
  56. time_t prevDisplay = 0; // когда будут показаны цифровые часы
  57.  
  58. void loop()
  59. {  
  60.   if (timeStatus() != timeNotSet) {
  61.     if (now() != prevDisplay) { // обновляем дисплей только если время поменялось
  62.       prevDisplay = now();
  63.       digitalClockDisplay();  
  64.     }
  65.   }
  66. }
  67.  
  68. void digitalClockDisplay(){
  69.   // показываем цифровые часы:
  70.   Serial.print(hour());
  71.   printDigits(minute());
  72.   printDigits(second());
  73.   Serial.print(" ");
  74.   Serial.print(day());
  75.   Serial.print(" ");
  76.   Serial.print(month());
  77.   Serial.print(" ");
  78.   Serial.print(year()); 
  79.   Serial.println(); 
  80. }
  81.  
  82. void printDigits(int digits){
  83.   // вспомогательная функция для печати данных о времени 
  84.   // на монитор порта; добавляет в начале двоеточие и ноль:
  85.   Serial.print(":");
  86.   if(digits < 10)
  87.     Serial.print('0');
  88.   Serial.print(digits);
  89. }
  90.  
  91. /*-------- Код для NTP ----------*/
  92.  
  93. const int NTP_PACKET_SIZE = 48; // NTP-время – в первых 48 байтах сообщения
  94. byte packetBuffer[NTP_PACKET_SIZE]; // буфер для хранения входящих и исходящих пакетов
  95.  
  96. time_t getNtpTime()
  97. {
  98.   while (Udp.parsePacket() > 0) ; // отбраковываем все пакеты, полученные ранее
  99.   Serial.println("Transmit NTP Request");  //  "Передача NTP-запроса"
  100.   sendNTPpacket(timeServer);
  101.   uint32_t beginWait = millis();
  102.   while (millis() - beginWait < 1500) {
  103.     int size = Udp.parsePacket();
  104.     if (size >= NTP_PACKET_SIZE) {
  105.       Serial.println("Receive NTP Response");  //  "Получение NTP-ответа"
  106.       Udp.read(packetBuffer, NTP_PACKET_SIZE);  // считываем пакет в буфер
  107.       unsigned long secsSince1900;
  108.       // конвертируем 4 байта (начиная с позиции 40) в длинное целое число:
  109.       secsSince1900 =  (unsigned long)packetBuffer[40] << 24;
  110.       secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
  111.       secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
  112.       secsSince1900 |= (unsigned long)packetBuffer[43];
  113.       return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
  114.     }
  115.   }
  116.   Serial.println("No NTP Response :-(");  //  "Нет NTP-ответа :("
  117.   return 0; // если время получить не удалось, возвращаема «0»
  118. }
  119.  
  120. // отправляем NTP-запрос серверу времени по указанному адресу:
  121. void sendNTPpacket(IPAddress &address)
  122. {
  123.   // задаем все байты в буфере на «0»:
  124.   memset(packetBuffer, 0, NTP_PACKET_SIZE);
  125.   // инициализируем значения для создания NTP-запроса
  126.   // (подробнее о пакетах смотрите по ссылке выше)
  127.   packetBuffer[0] = 0b11100011;   // LI (от «leap indicator», т.е. «индикатор перехода»), версия, режим работы
  128.   packetBuffer[1] = 0;     // слой (или тип часов)
  129.   packetBuffer[2] = 6;     // интервал запросов
  130.   packetBuffer[3] = 0xEC;  // точность
  131.   // 8 байтов с нулями, обозначающие базовую задержку и базовую дисперсию:
  132.   packetBuffer[12]  = 49;
  133.   packetBuffer[13]  = 0x4E;
  134.   packetBuffer[14]  = 49;
  135.   packetBuffer[15]  = 52;
  136.   // После заполнения всех указанных полей
  137.   // вы сможете отправлять пакет с запросом о временной метке:    
  138.   Udp.beginPacket(address, 123); //NTP requests are to port 123
  139.   Udp.write(packetBuffer, NTP_PACKET_SIZE);
  140.   Udp.endPacket();
  141. }

См.также

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

  1. github.com - TimeNTP.ino