КОРЗИНА
магазина
8 (499) 500-14-56 | ПН. - ПТ. 12:00-18:00
ЛЕСНОРЯДСКИЙ ПЕРЕУЛОК, 18С2, БЦ "ДМ-ПРЕСС"

Настенные часы с синхронизацией через интернет

Общие сведения

В этом проекте мы соберём часы с таймером и будильником на четырех модулях 7-сегментный дисплей 86*65мм с синхронизацией времени через интернет и объясним как работать с Network Time Protocol на ESP32.

Видео

Нам понадобится

Аппаратная часть

Программная часть

  • 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 СДВИГ - сдвиг с миллисекундах относительно UTC
    • int ЛЕТНЕЕ ВРЕМЯ - сдвиг с миллисекундах при переходе на летнее время
    • 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);

Ссылки




Обсуждение

Гарантии и возврат Используя сайт Вы соглашаетесь с условями