Общие сведения
В этом проекте мы соберём часы с таймером и будильником на четырех модулях 7-сегментный дисплей 86*65мм с синхронизацией времени через интернет и объясним как работать с Network Time Protocol на ESP32.
Видео
Нам понадобится
Аппаратная часть
- Микроконтроллер Piranha Set ESP32
- Set Expander
- Часы реального времени RTC RX-8025T (Trema-модуль)
- Зуммер (Trema-модуль)
- Две TREMA-кнопки
- Четыре модуля 7-сегментный дисплей 86*65мм
- Соединительные провода «папа-папа»
- Блок питания
- Коннектор power jack Мама с клемником
Программная часть
- Arduino IDE 1.8.19
- ESP32 core (устанавливается в Arduino IDE, пункт меню Инструменты->Плата->Менеджер плат)
- Библиотека iarduino RTC
- Библиотека iarudino_nLED
Про установку библиотек в Arduino IDE можно узнать по ссылке: https://wiki.iarduino.ru/page/Installing_libraries/
Подключение
Установите Set Expander на Piranha Set ESP32
Установите Часы реального времени, Кнопки и Зуммер на Piranha Set ESP32
Соедините четыре модуля 7-сегментный дисплей как показано на рисунке
Проводами подключите дисплей к колодке с цифровыми выводами на Piranha Set ESP32 согласно таблице:
Вывод дисплея | Вывод ESP32 |
---|---|
PWM | 26 |
SDI | 25 |
SCL | 32 |
+5V | V |
GND | G |
7-сегментные дисплеи могут потреблять до 1,5 А тока, поэтому рекомендуется подключить внешнее питание в колодку PWR.
Принцип работы
После подключения питания ESP32 подключается к точке доступа WiFi,
данные которой необходимо указать в скетче. Далее функцией
configTime()
запускается клиент NTP, который работает в
фоновом режиме и проверяет синхронизацию времени с сервером раз в час.
Для получения текущего времени используется функция
getLocalTime()
, если же сеть пропадает, то время берётся из
модуля часов реального времени.
Прибор управляется двумя кнопками, при первом нажатии на любую включается функция таймера. Левая кнопка в этом режиме добавляет по 30 секунд к таймеру при нажатии, правая - запускает таймер. По истечении таймера подаётся сигнал на модуль Зуммер.
Если зажать и подержать обе кнопки включается установка времени будильника. Повторное зажатие обоих кнопок возвращает в изначальное состояние - отображение текущего времени. Так же, если не запущен таймер, переход в последний режим будет произведёт по истечении SETTINGS_TIMEOUT миллисекунд.
Текущее время хранится в переменной g_current_time
и
преобразуется в структуру времени struct tm
при помощи
библиотечной функции языка Си localtime()
.
g_current_time
обновляется в зависимости от наличия
соединения с интернет, если подключен WiFi, то переменная обновляется
встроенной функцией ESP32 getLocalTime()
и стандартной
функцией Си mktime()
, если соединения нет, то переменная
обновляется функцией библиотеки iarduino_RTC
gettimeUnix()
.
Для более детальной работы со встроенной синхронизацией времени ESP32
необходимо подключить бибилотеку esp_sntp.h
. Так в скетче
используется функция sntp_get_sync_status()
, при помощи
которой можно узнать была ли проведена синхронизация времени с сервером.
Надо заметить что эта функция – триггер, если вызвать её после
завершения синхронизации времени, то она вернёт состояние
SNTP_SYNC_STATUS_COMPLETED
, но последующие её вызовы будут
возвращать SNTP_SYNC_STATUS_RESET
до следующей
синхронизации. Так же можно назначить функцию-callback при помощи
sntp_set_time_sync_notification_cb()
, которая будет
вызываться при каждой синхронизации.
Скетч проекта
#include <esp_sntp.h> #include <WiFi.h> #include <iarduino_RTC.h> // 2.0.1 #include <Button2.h> // 2.2.4 #include <SPIFFS.h> #include <iarduino_nLED.h> using namespace std; // сервер для получения точного времени #define NTP_SERVER "pool.ntp.org" // значение по умолчанию для таймера (сек) #define PRESET_TIMER 30 // часовой пояс int8_t gUTC = 3; // данные для подключения const char* ssid = "Имя Вашей точки доступа WiFi"; const char* password = "Пароль Вашей точки доступа WiFi"; // Определения констант дисплея #define DISP_SCL 32 #define DISP_SDI 25 #define DISP_PWM 26 #define HOURS_DISP_POS 1 #define MINUTES_DISP_POS 3 #define BLINK_SIZE 2 #define HIDE true #define SHOW false #define DISP_SIZE 4 #define DISP_PWM_FREQ 122 // X макрос возможных настроек #define SETTINGS\ X(HOURS_ALARM)\ X(MINUTES_ALARM)\ X(ALARM_SET)\ #define CLOCK_BRIGHTNESS 100 #define SETTINGS_BRIGHTNESS 64 #define TIMER_PRESET_CHANGE 30 #define TIMER_START_TIMEOUT 4 // вывода зуммера constexpr unsigned TONE_PIN = 18; // вывод левой кнопки constexpr unsigned BUTTON_LEFT = 33; // вывод правой кнопки constexpr unsigned BUTTON_RIGHT = 13; // через сколько миллисекунд сохранять настройки после последнего нажатия на кнопку constexpr unsigned USER_INTERACTED_DELAY = 2000; // выход из настроек через (миллисекунды) constexpr unsigned SETTINGS_TIMEOUT = 10000; // время зажатия для входа в настройки (миллисекунды) constexpr unsigned HOLD_TIME = 1000; // время повтора при зажатии кнопки constexpr unsigned REPEAT_TIME = 200; bool g_alarm_on = false; bool g_on_timer = false; bool g_forbid_timer = true; bool g_alarm_set = false; time_t g_current_time = 0; // определение типа указателя на функцию typedef void(*func_ptr)(); // глобальные переменные кнопок bool g_left_pressed = false; bool g_right_pressed = false; bool g_left_released = false; bool g_right_released = false; bool g_left_holding = false; bool g_right_holding = false; // пользовательский тип настроек typedef uint16_t setting_t; // объект дисплея iarduino_nLED disp(DISP_SIZE, DISP_SCL, DISP_SDI); // объект часов реального времени iarduino_RTC rtc(RTC_RX8025); // объект файла настроек fs::File g_file; // объекты кнопок Button2 leftButton; Button2 rightButton; // состояние меню typedef enum { MAIN, TIMER_MENU, ON_TIMER, SETTINGS_MENU, SETTINGS_MENU2 } state_t; state_t menu_state = MAIN; // возможные насройки (см. макрос SETTINGS) typedef enum { #define X(INDEX) INDEX, SETTINGS #undef X N_SETTING } settings_state_t; // переопределение оператора для смены текущей настройки settings_state_t& operator++(settings_state_t& s) { switch (s) { default: #define X(INDEX) \ case INDEX: s = static_cast<settings_state_t>(INDEX + 1); s == N_SETTING ? s = HOURS_ALARM: 0; return s; SETTINGS #undef X } } // первая настройка settings_state_t current_item = HOURS_ALARM; // массив настроек setting_t settings[N_SETTING]{0}; // название файла настроек const char* settings_file = "/settings.cfg"; void initButtons(void); void setup() { Serial.begin(115200); initDisplay(); initWiFi(); initFlashMemory(); initButtons(); initRTC(); initNTP(); handleSettingsFile(); } void loop() { handleInput(); handleDisplay(); handleClock(); handleMenu(); handleTimer(); handleAlarm(); handleSettingsSave(); } // инициализация синхронизации NTP void initNTP() { configTime(3600*gUTC, 0, NTP_SERVER); } unsigned long submenu_millis = 0; bool g_already_in_settings = false; // инициализация модуля часов void initRTC() { rtc.begin(); delay(1500); getI2Ctime(); } // обновить текущее время из модуля RTC void getI2Ctime() { g_current_time = rtc.gettimeUnix(); } // обновить время в модуле void setI2Ctime() { rtc.settimeUnix(g_current_time); } // обновить время в модуле после синхронизации void updateI2Ctime() { Serial.println("обноновляем время RTC"); struct tm timeinfo; if (getLocalTime(&timeinfo)) { g_current_time = mktime(&timeinfo); setI2Ctime(); } } // обновление часов void updateClock() { // Нет соединения - берём время из RTC if (WiFi.status() != WL_CONNECTED) g_current_time = rtc.gettimeUnix(); else { struct tm timeinfo; if (getLocalTime(&timeinfo)) g_current_time = mktime(&timeinfo); } } // обработка часов void handleClock() { // При успешной синхронизации с сервером обновляем время RTC if (sntp_get_sync_status() == SNTP_SYNC_STATUS_COMPLETED) { updateI2Ctime(); } // обновляем время раз в секунду static constexpr unsigned long time_check_interval = 1000; static unsigned long time_millis = 0; if (millis() - time_millis > time_check_interval) { time_millis = millis(); updateClock(); } } // обработка состояний меню void handleMenu() { if (menu_state == MAIN) { handleMainMenu(); } else if (menu_state == TIMER_MENU) { handleChangeTimerMenu(); exitOnTimeOut(); } else if (menu_state == SETTINGS_MENU || menu_state == SETTINGS_MENU2) { handleSettingsMenu(); exitOnTimeOut(); } } // обработка главного меню void handleMainMenu() { if (!isLeftReleased() && !isRightReleased() && g_already_in_settings) { return; } g_already_in_settings = false; if (isLeftPressed() || isRightPressed()) { menu_state = TIMER_MENU; g_forbid_timer = false; submenu_millis = millis(); } if (areBothHolding()) { menu_state = SETTINGS_MENU; submenu_millis = millis(); } } // обработка меню установки таймера void handleChangeTimerMenu() { if (isLeftPressed() || isLeftRepeating()) { submenu_millis = millis(); incrementTimer(); } if (isRightPressed() || isRightRepeating()) { submenu_millis = millis(); decrementTimer(); } if (millis() - submenu_millis > TIMER_START_TIMEOUT) startTimer(); if (areBothHolding()) { menu_state = SETTINGS_MENU; } } func_ptr g_item_func = changeAlarmHour; // обработка меню настроек void handleSettingsMenu() { if (!isLeftReleased() && !isRightReleased() && !g_already_in_settings) { return; } g_already_in_settings = true; if (isLeftPressed() || isLeftRepeating()) { submenu_millis = millis(); changeItem(); } if (isRightPressed() || isRightRepeating()) { submenu_millis = millis(); g_item_func(); } if (areBothHolding()) { backToMain(); } } // обработка таймера void handleTimer() { if (g_on_timer) countDown(); } bool g_blink_hour = true; // изменения настраиваемого пункта (часы будильника, минуты будильника, вкл/выкл будильника) void changeItem() { if (g_item_func == changeAlarmHour) { g_blink_hour = false; g_item_func = changeAlarmMinute; } else if (g_item_func == changeAlarmMinute) { g_item_func = changeAlarmSet; menu_state = SETTINGS_MENU2; } else if (g_item_func == changeAlarmSet) { g_blink_hour = true; g_item_func = changeAlarmHour; menu_state = SETTINGS_MENU; } } // изменение часа будильника void changeAlarmHour() { ++settings[HOURS_ALARM]; settings[HOURS_ALARM] %= 24; } // изменение минут будильника void changeAlarmMinute() { ++settings[MINUTES_ALARM]; settings[MINUTES_ALARM] %= 60; } // изменение работы будильника void changeAlarmSet() { settings[ALARM_SET] = !settings[ALARM_SET]; } // обработка будильника void handleAlarm() { static bool alerted = false; struct tm* timeinfo = localtime(&g_current_time); if (settings[HOURS_ALARM] == timeinfo->tm_hour && settings[MINUTES_ALARM] == timeinfo->tm_min) g_alarm_on = true; else { g_alarm_on = false; alerted = false; } if (settings[ALARM_SET] && g_alarm_on && !alerted && menu_state == MAIN) { alerted = true; alert(); } } // функции таймера time_t g_timer_seconds = PRESET_TIMER; void incrementTimer() { g_forbid_timer = false; g_on_timer = false; g_timer_seconds += TIMER_PRESET_CHANGE; } void decrementTimer() { g_on_timer = false; g_timer_seconds -= TIMER_PRESET_CHANGE; if (g_timer_seconds <= 0) { g_forbid_timer = true; g_timer_seconds = 0; } } void startTimer() { g_on_timer = true; } void showTimer() { int minutes = g_timer_seconds/60; int seconds = g_timer_seconds%60; char buf[12]{0}; sprintf(buf, "%02d.%02d", minutes, seconds); disp.print(buf); } void countDown() { if (!g_timer_seconds) { backToMain(); g_timer_seconds = PRESET_TIMER; g_on_timer = false; alert(); } static constexpr unsigned long one_second = 1000; static unsigned long timer_millis = 0; if (millis() - timer_millis > one_second) { timer_millis = millis(); g_timer_seconds--; } } // функция звонка будильника и таймера void alert() { tone(TONE_PIN, 1000, 5000); } // обработка дисплея void handleDisplay() { static unsigned long output_millis = 0; static constexpr unsigned long time_update_interval = 100; if (millis() - output_millis < time_update_interval) return; output_millis = millis(); static state_t last_state = menu_state; if (last_state != menu_state) { disp.clear(); last_state = menu_state; } if (menu_state == MAIN) { printLocalTime(); } else if (menu_state == TIMER_MENU) { printTimer(); } else if (menu_state == SETTINGS_MENU) { printAlarm(); } else if (menu_state == SETTINGS_MENU2) { printAlarmSet(); } else if (menu_state == ON_TIMER) { printTimer(); } } // вывод на дисплей текущего времени void printLocalTime() { bright(); static bool dot = false; static unsigned long dot_millis = 0; static constexpr unsigned long dot_interval = 1000; if (millis() - dot_millis > dot_interval) { dot = !dot; dot_millis = millis(); } struct tm* timeinfo = localtime(&g_current_time); int hour = timeinfo->tm_hour; int minute = timeinfo->tm_min; char buf[12]{0}; if (dot) sprintf(buf, "%02d.%02d", hour, minute); else sprintf(buf, "%02d%02d", hour, minute); disp.print(buf); } // вывод на дисплей таймера void printTimer() { dim(); showTimer(); } // вывод на дисплей будильника void printAlarm() { dim(); // мигаем выбранной позицией static unsigned long blinkMillis = millis(); static constexpr unsigned long BLINK_INTERVAL = 333; static bool blink = false; if (millis() - blinkMillis > BLINK_INTERVAL) { int pos = HOURS_DISP_POS; if (g_blink_hour) pos = HOURS_DISP_POS; else pos = MINUTES_DISP_POS; blinkMillis = millis(); disp.hide(pos, BLINK_SIZE, blink); blink = !blink; } // выводим время будильника char buf[12]{0}; sprintf(buf, "%02d.%02d", settings[HOURS_ALARM], settings[MINUTES_ALARM]); disp.print(buf); } void printAlarmSet() { disp.hide(SHOW); disp.print(settings[ALARM_SET]?"On ":"Off"); } // обработка ввода void handleInput() { leftButton.loop(); rightButton.loop(); } // инициализация памяти void initFlashMemory() { if (!SPIFFS.begin()) { Serial.println("Форматируем память, нужно подождать..."); disp.print("F "); SPIFFS.format(); } if (!SPIFFS.begin()) { Serial.println("Не получилось отформатировать, остановка."); disp.print("E 01"); while(true) ; } } // подключение void initWiFi() { WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); disp.print("."); } Serial.println(); } // парсинг файла настроек будильника void parseFile(fs::File& file) { static constexpr size_t bufsiz = 256; int b = 0; char buf[bufsiz]; String loaded_setting = ""; while (b != EOF) { static int i = 0; static settings_state_t index = HOURS_ALARM; b = file.read(); if (b == '\n') { loaded_setting = String(buf); settings[index] = static_cast<settings_state_t>(loaded_setting.toInt()); Serial.println(settings[index]); ++index; i = 0; memset(buf, '\0', bufsiz); continue; } buf[i++] = (byte)b; } } // обработка загрузки файла void handleSettingsFile() try { if (!SPIFFS.exists(settings_file)) { Serial.println("Нет файла настроек"); return; } g_file = SPIFFS.open(settings_file, "r"); if (!g_file) { Serial.println("Не получилось открыть файл"); return; } parseFile(g_file); g_file.close(); } catch (...) { g_file.close(); Serial.println("Проблемы парсинга файла"); } // инициализация кнопок void initButtons() { leftButton.begin(BUTTON_LEFT, INPUT, false); rightButton.begin(BUTTON_RIGHT, INPUT, false); leftButton.setReleasedHandler(released); leftButton.setLongClickTime(HOLD_TIME); leftButton.setLongClickDetectedHandler(longClickDetected); rightButton.setReleasedHandler(released); rightButton.setLongClickTime(HOLD_TIME); rightButton.setLongClickDetectedHandler(longClickDetected); } // функции обработки кнопок bool isLeftPressed() { bool tmp = g_left_pressed; g_left_pressed = false; return tmp; } bool isRightPressed() { bool tmp = g_right_pressed; g_right_pressed = false; return tmp; } bool isLeftRepeating() { if (digitalRead(BUTTON_LEFT) == LOW) { g_left_holding = false; } if (g_left_holding && repeatInterval()) return true; else return false; } bool isRightRepeating() { if (digitalRead(BUTTON_RIGHT) == LOW) { g_right_holding = false; } if (g_right_holding && repeatInterval()) return true; else return false; } bool isLeftHolding() { return g_left_holding; } bool isRightHolding() { return g_left_holding; } bool isLeftReleased() { return !leftButton.isPressed(); } bool isRightReleased() { return !rightButton.isPressed(); } bool areBothHolding() { if (g_right_holding && g_left_holding && digitalRead(BUTTON_LEFT) && digitalRead(BUTTON_RIGHT)) return true; else return false; } void longClickDetected(Button2& btn) { if (&btn == &leftButton) g_left_holding = true; if (&btn == &rightButton) g_right_holding = true; } void released(Button2& btn) { disp.hide(SHOW); if (&btn == &leftButton) { if (g_left_holding) g_left_holding = false; else g_left_pressed = true; } if (&btn == &rightButton) { if (g_right_holding) g_right_holding = false; else g_right_pressed = true; } } bool repeatInterval() { static unsigned long repeat_millis = 0; if (millis() - repeat_millis > REPEAT_TIME) { repeat_millis = millis(); return true; } else return false; } // обработка сохранения настроек void handleSettingsSave() { static bool saved = true; static unsigned long last_input_millis = 0; static state_t last_state = menu_state; if (last_state != menu_state) { last_input_millis = millis(); last_state = menu_state; saved = false; } if (saved) return; if (millis() - last_input_millis > USER_INTERACTED_DELAY) { saved = saveSettings(); } } // сохранение настроек bool saveSettings() { try { g_file = SPIFFS.open(settings_file, "w"); if (!g_file) { Serial.println("Ошибка открытия файла"); return false; } for (auto& s:settings) { g_file.print(s); g_file.print('\n'); } g_file.flush(); g_file.close(); Serial.println("Настройки сохранены"); return true; } catch (...) { Serial.println("Исключение при сохранении файла"); return false; } } // выход по истечении времени на главный экран void exitOnTimeOut() { if (g_on_timer && menu_state == TIMER_MENU) return; if (millis() - submenu_millis > SETTINGS_TIMEOUT) { backToMain(); } } void backToMain() { menu_state = MAIN; disp.hide(SHOW); bright(); } // инициализация дисплея void initDisplay() { pinMode(DISP_PWM, OUTPUT); analogWriteFrequency(DISP_PWM_FREQ); dim(); disp.clear(); delay(500); disp.print("Strt"); } void dim() { analogWrite(DISP_PWM, SETTINGS_BRIGHTNESS); } void bright() { analogWrite(DISP_PWM, CLOCK_BRIGHTNESS); }
Функции SNTP
Здесь перечисленны полезные функции, которые могут понадобиться для работы с NTP
configTime()
- Назначение: конфигурациф работы с NTP
- Синтаксис: configTime(СДВИГ, ЛЕТНЕЕ ВРЕМЯ, СЕРВЕР1, [СЕРВЕР2, СЕРВЕР3]);
- Параметры:
long
СДВИГ - сдвиг с миллисекундах относительно UTCint
ЛЕТНЕЕ ВРЕМЯ - сдвиг с миллисекундах при переходе на летнее времяconst char*
СЕРВЕР - строка адреса сервера
- Возвращаемые значения: нет
- Примечание:
- Функцию достаточно вызвать один раз в коде
setup
; - Функция запускает выполнение синхронизации, которая работает в отдельном потоке
- Синхронизация времени происходит раз в час, при желании интервал
можно изменить функцие
sntp_set_sync_interval()
. Интервал не может быть меньше 15000 миллисекунд.
- Функцию достаточно вызвать один раз в коде
- Пример:
int offset = 3; // сдвиг на +3 часа от UTC (Москва) long offset_ms = 3600*offset; // сдвиг в миллисекундах int summer_time = 0; // сдвиг летнего времени const char* ntp_server = "ntp0.ntp-servers.net"; // адрес сервера configTime(offset_ms, summer_time, ntp_server); // Запускаем NTP
getLocalTime()
- Назначение: получение точного локального времени
- Синтаксис: bool success = getLocalTime(УКАЗАТЕЛЬ НА СТРУКТУРУ ВРЕМЕНИ, ЗАДЕРЖКА);
- Параметры:
struct tm*
УКАЗАТЕЛЬ НА СТРУКТУРУ ВРЕМЕНИ - указатель на структуру времени для заполненияuint32_t
ЗАДЕРЖКА - время в миллисекундах, для попыток заполнения времени (по умолчанию 5000)
- Возвращаемые значения: bool - успех выполнения.
true
- успешное выполнение. - Примечание:
- Функция активно блокирует поток выполнения. Структура времени
заполняется в цикле
while
до тех пор пока текущий код структуры не станет больше 116 (2016 - 1900) или не пройдёт время ЗАДЕРЖКИ.
- Функция активно блокирует поток выполнения. Структура времени
заполняется в цикле
- Пример:
// создаём структуру времени struct tm timeinfo; if (getLocalTime(&timeinfo)) { Serial.println(timeinfo.tm_hour); // выводим текущий час в последовательный порт }
sntp_init()
- Назначение: инициализация SNTP
- Синтаксис:
sntp_init();
- Параметры: нет
- Возвращаемые значения: нет
- Примечание: необходимость вызвать эту функцию возникает только при
ручной конфигурации сервера при помощи
sntp_setservername()
. Если используетсяconfigTime()
, то использовать эту функцию нет необходимости. - Пример:
sntp_setservername(0, "ntp.pool.org"); sntp_init();
sntp_stop()
- Назначение: - остановка синхронизации времени NTP
- Синтаксис:
sntp_stop();
- Параметры: нет
- Возвращаемые значения: нет
- Примечание: для перезапуска синхронизации используйте
sntp_restart()
илиsntp_init()
- Пример:
sntp_stop();
sntp_restart()
- Назначение: перезапуск синхронизации времени
- Синтаксис:
bool success = sntp_restart();
- Параметры: нет
- Возвращаемые значения: bool - true - перезапущено, false - SNTP ещё не инициирован
- Пример:
sntp_restart();
sntp_get_sync_mode()
- Назначение:
- Синтаксис:
sntp_get_sync_mode();
- Параметры: нет
- Возвращаемые значения: sntp_sync_mode_t - режим синхронизации:
- SNTP_SYNC_MODE_IMMED - мгновенная синхронизация
- SNTP_SYNC_MODE_SMOOTH - постепенная синхронизация (часы спешат или отстают до тех пор пока не синхронизируются)
- Примечание:
- Пример:
switch (sntp_get_sync_mode()) { default: break; case SNTP_SYNC_MODE_IMMED: Serial.println("Моментальное изменение времени"); break; case SNTP_SYNC_MODE_SMOOTH: Serial.println("Постепенное изменение времени"); break; }
sntp_get_sync_status()
- Назначение: получение текущего статуса синхронизации времени
- Синтаксис:
sntp_sync_status_t status = sntp_get_sync_status();
- Параметры: нет
- Возвращаемые значения: sntp_sync_status_t - статус синхронизации:
- SNTP_SYNC_STATUS_RESET: статус уже был запрошен или синхронизация ещё не произошла
- SNTP_SYNC_STATUS_COMPLETED: время синхронизировано
- SNTP_SYNC_STATUS_IN_PROGRESS: время синхронизируется сейчас (если выбран режим SNTP_SYNC_MODE_SMOOTH)
- Примечание:
- Пример:
// если произошла синхронизация if (sntp_get_sync_status() == SNTP_SYNC_STATUS_COMPLETED) { struct tm timeinfo; getLocalTime(&timeinfo); // выводим текущие часы в последовательный порт Serial.println(timeinfo.tm_hour); }
sntp_get_sync_interval()
- Назначение: получение текущего интервала синхронизации
- Синтаксис:
uint32_t interval = sntp_get_sync_interval(void);
- Параметры: нет
- Возвращаемые значения: uint32_t - интервал синхронизации в миллисекундах
- Пример:
// выводим текущий интервал синхронизации в последовательный порт Serial.println(sntp_set_sync_interval());
sntp_set_sync_interval()
- Назначение: установка интервала синхронизации времени
- Синтаксис:
sntp_set_sync_interval(ИНТЕРВАЛ);
- Параметры: unit32_t ИНТЕРВАЛ - интервал синхронизации в миллисекундах
- Возвращаемые значения: нет
- Примечание: интервал не может быть установлен меньше 15000 миллисекунд, при попытке установить более короткий интервал будет установлен интервал в 15 секунд
- Пример:
// установливаем синхронизацию времени раз в час sntp_set_sync_interval(3600000);
Обсуждение