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

Arduino:Примеры/wifi101UdpNTPClient

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

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

Контакты:

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


Получение времени от NTP-сервера при помощи WiFi Shield 101[1]

Этот пример показывает, как при помощи платы MKR1000 или модуля WiFi Shield 101 и платы Arduino/Genuino сделать запрос к серверу Network Time Protocol (NTP). Благодаря этому ваша плата сможет узнавать время через интернет.

Необходимое оборудование

  • Модуль Arduino WiFi Shield 101
  • Плата Arduino или Genuino Zero (или MKR1000)

Цепь

7-ой цифровой контакт используется в качестве контакта для «рукопожатия» между WiFi Shield 101 и платой, т.е. ни для каких других целей его использовать не следует.

Кроме того, для этого скетча нужен доступ к беспроводной сети типа 802.11b/g, подключенной к интернету. Также в скетче нужно будет поменять сетевые настройки, чтобы они соответствовали настройкам вашей SSID.

ArduinoWiFi101.png

На картинке выше модуль WiFi Shield 101 установлен поверх платы Arduino/Genuino Zero.

Код

  1. /*
  2.  
  3.  Клиент, запрашивающий время через NTP с помощью WiFi
  4.  
  5.  Получает информацию о времени через время-сервер Network Time
  6.  Protocol (NTP). Показывает, как получать и отправлять пакеты через
  7.  UDP. Более подробно о время-серверах NTP и сообщениях для
  8.  коммуникации с ними читайте на https://ru.wikipedia.org/wiki/NTP.
  9.  
  10.  Создан 4 сентября 2010 года Майклом Маргулисом (Michael Margolis),
  11.  модифицирован 9 апреля 2012 года Томом Иго (Tom Igoe).
  12.  
  13.  Этот код не защищен авторским правом.
  14.  
  15.  */
  16.  
  17. #include <SPI.h>
  18. #include <WiFi101.h>
  19. #include <WiFiUdp.h>
  20.  
  21. int status = WL_IDLE_STATUS;
  22. char ssid[] = "mynetwork";  //  ваш SSID (название точки доступа)
  23. char pass[] = "mypassword";       // пароль к точке доступа
  24. int keyIndex = 0;            // номер ключа (нужно только для WEP)
  25.  
  26. unsigned int localPort = 2390;      // локальный порт, который нужно прослушивать на предмет прихода UDP-пакетов
  27.  
  28. IPAddress timeServer(129, 6, 15, 28); // NTP-сервер time.nist.gov
  29.  
  30. const int NTP_PACKET_SIZE = 48; // временная отметка NTP находится в первых 48 байтах сообщения
  31.  
  32. byte packetBuffer[ NTP_PACKET_SIZE]; // буфер для хранения входящих и исходящих пакетов
  33.  
  34. // экземпляр класса UDP, который позволит отправлять и получать пакеты через UDP:
  35. WiFiUDP Udp;
  36.  
  37. void setup() {
  38.   // запускаем последовательную коммуникацию и ждем открытия порта:
  39.   Serial.begin(9600);
  40.   while (!Serial) {
  41.     ; // ждем подключения последовательного порта (нужно только для плат со штатным USB-портом)
  42.   }
  43.  
  44.   // проверяем наличие WiFi-модуля:
  45.   if (WiFi.status() == WL_NO_SHIELD) {
  46.     Serial.println("WiFi shield not present");  // "WiFi-модуль не подключен"
  47.     // дальше не продолжаем:
  48.     while (true);
  49.   }
  50.  
  51. // пробуем подключиться к WiFi-сети:
  52.   while ( status != WL_CONNECTED) {
  53.     Serial.print("Attempting to connect to SSID: ");  // "Пытаемся потключиться к SSID: "
  54.     Serial.println(ssid);
  55.     // подключаемся к WPA/WPA2 сети (при подключении к открытой сети и WEP-сети эту строчку нужно поменять):
  56.     status = WiFi.begin(ssid, pass);
  57.  
  58.     // 10 секунд ждем подключения:
  59.     delay(10000);
  60.   }
  61.  
  62.   Serial.println("Connected to wifi");  // "Подключились к WiFi"
  63.   printWifiStatus();
  64.  
  65.   Serial.println("\nStarting connection to server...");   // "\n Начинаем подключаться к серверу..."
  66.   Udp.begin(localPort);
  67. }
  68.  
  69. void loop() {
  70.   sendNTPpacket(timeServer); // отправляем NTP-пакет на время-сервер
  71.   // ждем, пока придет ответ:
  72.   delay(1000);
  73.   if (Udp.parsePacket()) {
  74.     Serial.println("packet received");   // "Пакет получен"
  75.     // Пакет получен, считываем данные из него:
  76.     Udp.read(packetBuffer, NTP_PACKET_SIZE); // считываем пакет в буфер
  77.  
  78.     // временная отметка начинается на 40-ом байте полученного пакета, и это 4 байта
  79.     // или 2 слова (тип данных – long). Сначала извлекаем 2 слова:
  80.  
  81.     unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
  82.     unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
  83.     // совмещаем 4 байта (2 слова) в long integer;
  84.     // это будет NTP-время (секунды, прошедшие с 1 января 1900 года):
  85.     unsigned long secsSince1900 = highWord << 16 | lowWord;
  86.     Serial.print("Seconds since Jan 1 1900 = ");   // "Секунды, прошедшие с 1 января 1900 года = "
  87.     Serial.println(secsSince1900);
  88.  
  89.     // теперь конвертируем NTP-время в обычное время:
  90.     Serial.print("Unix time = ");  // "Unix-время = "
  91.     // Unix-время стартует с 1 января 1970 года. В секундах это «2208988800»:
  92.     const unsigned long seventyYears = 2208988800UL;
  93.     // вычитаем 70 лет:
  94.     unsigned long epoch = secsSince1900 - seventyYears;
  95.     // показываем Unix-время:
  96.     Serial.println(epoch);
  97.  
  98.  
  99.     // показываем час, минуту и секунду:
  100.     Serial.print("The UTC time is ");       // "UTC-время: " UTC – это время по Гринвичу (GMT)
  101.     Serial.print((epoch  % 86400L) / 3600); // показываем час (86400  - это количество секунд в сутках)
  102.     Serial.print(':');
  103.     if (((epoch % 3600) / 60) < 10) {
  104.       // у первых 10 минут каждого часа впереди должна стоять цифра «0»:
  105.       Serial.print('0');
  106.     }
  107.     Serial.print((epoch  % 3600) / 60); // показываем минуту (3600 – это количество секунд в минуту)
  108.     Serial.print(':');
  109.     if ((epoch % 60) < 10) {
  110.       // у первых 10 секунд каждой минуты впереди должна стоять цифра «0»:
  111.       Serial.print('0');
  112.     }
  113.     Serial.println(epoch % 60); // показываем секунду
  114.   }
  115.   // перед тем, как спрашивать время еще раз, ждем 10 секунд:
  116.   delay(10000);
  117. }
  118.  
  119. // отправляем NTP-запрос на время-сервер по указанному адресу:
  120. unsigned long sendNTPpacket(IPAddress& address) {
  121.   //Serial.println("1");
  122.   // делаем все байты в буфере нулями:
  123.   memset(packetBuffer, 0, NTP_PACKET_SIZE);
  124.   // инициализируем значения, необходимые для NTP-запроса:
  125.   // (более подробно о пакетах читайте по ссылке выше)
  126.   //Serial.println("2");
  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.   //Serial.println("3");
  138.  
  139.   // после заполнения всех указанных полей
  140.   // вы сможете отправлять пакет с запросом о временной метке:
  141.   Udp.beginPacket(address, 123); // NTP-запросы на порт 123
  142.   //Serial.println("4");
  143.   Udp.write(packetBuffer, NTP_PACKET_SIZE);
  144.   //Serial.println("5");
  145.   Udp.endPacket();
  146.   //Serial.println("6");
  147. }
  148.  
  149.  
  150. void printWifiStatus() {
  151.   // показываем SSID сети, к которой подключились:
  152.   Serial.print("SSID: ");
  153.   Serial.println(WiFi.SSID());
  154.  
  155.   // показываем IP-адрес WiFi-модуля:
  156.   IPAddress ip = WiFi.localIP();
  157.   Serial.print("IP Address: ");  // "IP-адрес: "
  158.   Serial.println(ip);
  159.  
  160.   // показываем мощность приемного сигнала:
  161.   long rssi = WiFi.RSSI();
  162.   Serial.print("signal strength (RSSI):");   // "Мощность сигнала (RSSI):"
  163.   Serial.print(rssi);
  164.   Serial.println(" dBm");  // "дБм"
  165. }

См.также

  1. WiFi library – Your reference for the WiFi101 Library.
  2. WiFi Shield – Product details for the WiFi 101 Shield.
  3. MKR1000 – Product details for the MKR1000 board.
  4. Connect No Encryption - Demonstrates how to connect to an open network.
  5. Connect With WEP - Demonstrates how to connect to a network that is encrypted with WEP.
  6. Connect With WPA - Demonstrates how to connect to a network that is encrypted with WPA2 Personal.
  7. Scan Networks - Displays all WiFi networks in range.
  8. Simple Web Server WiFi – Turn on and off an LED accessing this simple Web Server.
  9. WiFi Chat Server - Set up a simple chat server.
  10. WiFi Web Client - Connect to a remote webserver.
  11. WiFi Web Client Repeating - Repeatedly make HTTP calls to a server.
  12. WiFi Web Server - Serve a webpage from the WiFi shield with Analog Input values.
  13. WiFi Send Receive UDP String - Send and receive a UDP string.

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

  1. Arduino.cc - Wifi101UdpNTPClient