Arduino:Примеры/UdpNTPClient

Материал из Онлайн справочника
Версия от 12:38, 8 июля 2023; EducationBot (обсуждение | вклад)
(разн.) ← Предыдущая версия | Текущая версия (разн.) | Следующая версия → (разн.)
Перейти к навигацииПерейти к поиску

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


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

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

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

  • WiFi-модуль Arduino
  • Плата Arduino/Genuino, совместимая с WiFi-модулем

Цепь

Чтобы выполнить SPI-соединение с модулем HDG104, WiFi-модуль использует 10-ый, 11-ый, 12-ый и 13-ый контакты. Для управления SS-контактом SD-карты используется 4-ый цифровой контакт.

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

На картинке выше плата Arduino находится под WiFi-модулем Arduino.

Код

/*

 Клиент, запрашивающий время через NTP с помощью WiFi 

 Получает информацию о времени через время-сервер Network Time
 Protocol (NTP). Показывает, как получать и отправлять пакеты через
 UDP. Более подробно о время-серверах NTP и сообщениях для 
 коммуникации с ними читайте на https://ru.wikipedia.org/wiki/NTP.

 Создан 4 сентября 2010 года Майклом Маргулисом (Michael Margolis),
 модифицирован 9 апреля 2012 года Томом Иго (Tom Igoe).

 Этот код не защищен авторским правом.

 */

#include <SPI.h>
#include <WiFi.h>
#include <WiFiUdp.h>

int status = WL_IDLE_STATUS;
char ssid[] = "mynetwork";  //  ваш SSID (название точки доступа)
char pass[] = "mypassword";       // пароль к точке доступа
int keyIndex = 0;            // номер ключа (нужно только для WEP)

unsigned int localPort = 2390;      // локальный порт, который нужно прослушивать на предмет прихода UDP-пакетов

IPAddress timeServer(129, 6, 15, 28); // NTP-сервер time.nist.gov

const int NTP_PACKET_SIZE = 48; // временная отметка NTP находится в первых 48 байтах сообщения 

byte packetBuffer[ NTP_PACKET_SIZE]; // буфер для хранения входящих и исходящих пакетов

// экземпляр класса UDP, который позволит отправлять и получать пакеты через UDP:
WiFiUDP Udp;

void setup() {
  // запускаем последовательную коммуникацию и ждем открытия порта:
  Serial.begin(9600);
  while (!Serial) {
    ; // ждем подключения последовательного порта (нужно только для плат со штатным USB-портом)
  }

  // проверяем наличие WiFi-модуля:
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi shield not present");  // "WiFi-модуль не подключен"
    // дальше не продолжаем:
    while (true);
  }

  String fv = WiFi.firmwareVersion();
  if (fv != "1.1.0") {
    Serial.println("Please upgrade the firmware");  // "Пожалуйста, обновите прошивку"
  }

  // пытаемся подключиться к WiFi-сети:
  while (status != WL_CONNECTED) {
    Serial.print("Attempting to connect to SSID: ");  // "Пытаемся подключиться к SSID: "
    Serial.println(ssid);
    // подключаемся к сети с шифрованием WPA/WPA2. Если используете открытую сеть или WEP, поменяйте эту строчку:
    status = WiFi.begin(ssid, pass);

    // 10 секунд ждем подключения:
    delay(10000);
  }

  Serial.println("Connected to wifi");  // "Подключение к WiFi-точке установлено"
  printWifiStatus();

  Serial.println("\nStarting connection to server...");   // "\nНачинаем подключаться к серверу..." 
  Udp.begin(localPort);
}

void loop() {
  sendNTPpacket(timeServer); // отправляем NTP-пакет на время-сервер
  // ждем, пока придет ответ:
  delay(1000);
  if (Udp.parsePacket()) {
    Serial.println("packet received");   // "Пакет получен"
    // Пакет получен, считываем данные из него:
    Udp.read(packetBuffer, NTP_PACKET_SIZE); // считываем пакет в буфер 

    // временная отметка начинается на 40-ом байте полученного пакета, и это 4 байта
    // или 2 слова (тип данных – long). Сначала извлекаем 2 слова:

    unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
    unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
    // совмещаем 4 байта (2 слова) в long integer;
    // это будет NTP-время (секунды, прошедшие с 1 января 1900 года): 
    unsigned long secsSince1900 = highWord << 16 | lowWord;
    Serial.print("Seconds since Jan 1 1900 = ");   // "Секунды, прошедшие с 1 января 1900 года = "
    Serial.println(secsSince1900);

    // теперь конвертируем NTP-время в обычное время:
    Serial.print("Unix time = ");  // "Unix-время = "
    // Unix-время стартует с 1 января 1970 года. В секундах это «2208988800»:
    const unsigned long seventyYears = 2208988800UL;
    // вычитаем 70 лет:
    unsigned long epoch = secsSince1900 - seventyYears;
    // показываем Unix-время:
    Serial.println(epoch);


    // показываем час, минуту и секунду:
    Serial.print("The UTC time is ");       // "UTC-время: " UTC – это время по Гринвичу (GMT)
    Serial.print((epoch  % 86400L) / 3600); // показываем час (86400  - это количество секунд в сутках)
    Serial.print(':');
    if (((epoch % 3600) / 60) < 10) {
      // у первых 10 минут каждого часа впереди должна стоять цифра «0»:
      Serial.print('0');
    }
    Serial.print((epoch  % 3600) / 60); // показываем минуту (3600 – это количество секунд в минуту)
    Serial.print(':');
    if ((epoch % 60) < 10) {
      // у первых 10 секунд каждой минуты впереди должна стоять цифра «0»:
      Serial.print('0');
    }
    Serial.println(epoch % 60); // показываем секунду
  }
  // перед тем, как спрашивать время еще раз, ждем 10 секунд:
  delay(10000);
}

// отправляем NTP-запрос на время-сервер по указанному адресу:
unsigned long sendNTPpacket(IPAddress& address) {
  //Serial.println("1");
  // делаем все байты в буфере нулями:
  memset(packetBuffer, 0, NTP_PACKET_SIZE);
  // инициализируем значения, необходимые для NTP-запроса:
  // (более подробно о пакетах читайте по ссылке выше)
  //Serial.println("2");
  packetBuffer[0] = 0b11100011;   // LI (leap indicator, т.е. «индикатор перехода»), версия, режим работы
  packetBuffer[1] = 0;     // слой (или тип часов)
  packetBuffer[2] = 6;     // интервал запросов
  packetBuffer[3] = 0xEC;  // точность
  // 8 байт с нулями, обозначающие базовую задержку и базовую дисперсию
  packetBuffer[12]  = 49;
  packetBuffer[13]  = 0x4E;
  packetBuffer[14]  = 49;
  packetBuffer[15]  = 52;

  //Serial.println("3");

  // после заполнения всех указанных полей 
  // вы сможете отправлять пакет с запросом о временной метке:
  Udp.beginPacket(address, 123); // NTP-запросы на порт 123
  //Serial.println("4");
  Udp.write(packetBuffer, NTP_PACKET_SIZE);
  //Serial.println("5");
  Udp.endPacket();
  //Serial.println("6");
}


void printWifiStatus() {
  // показываем SSID сети, к которой подключились:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // показываем IP-адрес WiFi-модуля:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");  // "IP-адрес: "
  Serial.println(ip);

  // показываем мощность приемного сигнала:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");   // "Мощность сигнала (RSSI):"
  Serial.print(rssi);
  Serial.println(" dBm");  // "дБм"
}

См.также

  1. WiFi library – Your reference for the WiFi Library.
  2. WiFi Shield – Product details for the retired WiFi Shield.
  3. Getting started – Getting started with the retired WiFi Shield.
  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.

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