ESP32 - неточность NTP после глубокого сна
Я пытаюсь создать проект выборки датчиков с использованием ESP32 (аккумулятор, солнечная панель и влияние температуры не являются частью теста прямо сейчас, чтобы уменьшить внешние эффекты, которые могут вызвать/усилить такое поведение).
На текущем этапе я только тестирую функцию sleep & процесс пробуждения.
Краткое описание: система просыпается после цикла глубокого сна, подключается к Wi-Fi, MQTT, NTP и проверяет время пробуждения (значение пробуждения хранится в переменной ׳RTC_DATA_ATTR long calc_waketime׳ из предыдущего цикла), публикуя IFTTT, уходит в глубокий сон еще на 10 мин. цикл.
Феномен, которым я хотел бы поделиться: Чем дольше глубокий сон, NTP имеет дрейф в несколько секунд, который становится длиннее (опять же - синхронизация NTP имеет дрейф, а не часы RTC).
Я знаю, что время пробуждения/RTC дрейфует во время глубокого сна (особенно в чипах ESP8266, которые пробуждения могут быть неточными с точки зрения минут - я использую ESP32). Поскольку ESP32 использует RTC, пробуждение происходит очень точно (секунды). Чтобы проснуться в точное время (18:00, 18:10, 18:20... каждый час) код подключается к Wifi& NTP и убедитесь, что время пробуждения соответствовало назначению (сравните значение эпохи, которое было сохранено в конце предыдущего цикла, и текущее время эпохи).
Но - Что меня озадачивает, так это то, почему обновленное время NTP (которое никак не связано с дрейфами RTC) смещается по мере того, как длится сон (для сравнения: когда меньше минуты - почти нет дрейфа, когда сон длится 10 минут, 3 секунды дрейфа, 20 минут до 5 секунд дрейфа ).
Пожалуйста, см. ПРИМЕЧАНИЕ(1), чтобы увидеть дрейф в 10-минутном сне.
Публикация вывода терминала: некоторые пояснения: ПРИМЕЧАНИЕ (1) отображает 3-секундный дрейф, ПРИМЕЧАНИЕ (2) расчетное время, которое было сохранено в предыдущем цикле пробуждения, ПРИМЕЧАНИЕ (3) показывает, что этот дрейф синхронизируется во время выполнения кода - 594 сек для следующего пробуждения в 18:50:00.
18:39:58.032 -> 09B⸮⸮L⸮1U1V(⸮⸮⸮1m1m1F⸮Connecting to Xiaomi_D6C8 .... // ПРОСЫПАЕМСЯ
18:39:58.595 -> 192.168.3.186
18:39:59.013 -> now is: 1580575203 **// ПРИМЕЧАНИЕ (1)**
18:39:59.013 -> sleep time was: 1580574611
18:39:59.048 -> expected wake time: 1580575200 // ПРИМЕЧАНИЕ (2)
18:39:59.085 -> total time delta: 3
18:39:59.122 -> OK - WOKE UP after due time:
18:39:59.419 -> Attempting MQTT connection...connected
18:40:04.544 -> Connecting to maker.ifttt.com
18:40:04.855 -> Request resource: /trigger/send_reading/with/key/cFLymB4JT9tlODsKLFn9TA
18:40:05.376 -> HTTP/1.1 200 OK
18:40:05.376 -> Date: Sat, 01 Feb 2020 16:40:05 GMT
18:40:05.414 -> Content-Type: text/html; charset=utf-8
18:40:05.447 -> Content-Length: 52
18:40:05.480 -> Connection: close
18:40:05.515 -> X-Top-SecreTTT: VG9vIGVhc3k/IElmIHlvdSBjYW4gcmVhZCB0aGlzLCBFbWFpbCB1cyBhdCBqb2JzK3NlY3JldEBpZnR0dC5jb20uIFdlIHdhbnQgTWFrZXJzLg==
18:40:05.619 -> Server: web_server
18:40:05.619 ->
18:40:05.619 -> Congratulations! You've fired the send_reading event
18:40:05.689 -> closing connection
18:40:07.007 -> Last Sleep: 1580574611
18:40:07.007 -> Time left: 594 // ПРИМЕЧАНИЕ (3)
18:40:07.041 -> Going to DeepSleep for [594] sec
Соответствующий код:
void sleepNOW(int sec2sleep = 2700)
{
char tmsg[30];
sprintf(tmsg, "Going to DeepSleep for [%d] sec", sec2sleep);
Serial.println(tmsg);
// mqtt_pubmsg(tmsg);
Serial.flush();
esp_sleep_enable_timer_wakeup(sec2sleep * uS_TO_S_FACTOR);
esp_deep_sleep_start();
}
bool getTime()
{
delay(200);
if (getLocalTime(&timeinfo))
{
time(&now1);
delay(200);
return 1;
}
else
{
return 0;
}
}
bool check_awake_ontime()
{
getTime();
if (timeinfo.tm_year >= 120) // 2020 год
{
if (lastsleeptime != 0)
{ // не первая загрузка
long current_boottime = now1;
int t_delta = now1 - calc_waketime;
// int t_delta1 = TIME_TO_SLEEP * 60 - (t_delta + TIME_AWAKE);
Serial.print("now is: ");
Serial.println(now1);
Serial.print("sleep time was: ");
Serial.println(lastsleeptime);
Serial.print("expected wake time: ");
Serial.println(calc_waketime);
Serial.print("total time delta: ");
Serial.println(t_delta);
if (t_delta >= 0)
{
Serial.println("OK - WOKE UP after due time: ");
return 1;
}
else
{
Serial.println("FAIL- woke up before time: ");
sleepNOW(-1 * t_delta);
return 0;
}
}
else
{
return 1;
}
}
else
{
return 0;
}
}
внутри setup()
#if USE_WIFI
if (startWifi())
{
mqttConnect();
startNTP();
#if USE_SLEEP
check_awake_ontime(); // ОБРАЩАЙТЕСЬ ТОЛЬКО НА ЭТУ ЛИНИЮ
#endif
}
внутри loop()
#if USE_SLEEP
if (millis() >= TIME_AWAKE * 1000)
{
getTime();
Serial.print("Last Sleep: ");
Serial.println(lastsleeptime);
long clockCount = TIME_TO_SLEEP * 60 - (timeinfo.tm_min * 60 + timeinfo.tm_sec) % (TIME_TO_SLEEP * 60);
// Serial.print(timeinfo.tm_hour);
// Serial.print(":");
// Serial.print(timeinfo.tm_min);
// Serial.print(":");
// Serial.print(timeinfo.tm_sec);
// Serial.println("");
Serial.print("Time left: ");
Serial.println(clockCount);
lastsleeptime = now1;
calc_waketime = now1 + clockCount;
sleepNOW(clockCount);
}
Я публикую не весь код, а только соответствующие части. Будем признательны за любую помощь,
@Guy . D, 👍0
Обсуждение1 ответ
Лучший ответ:
Как прокомментировал Юрай, задержка в 2,5 [сек.] решила проблему, и обновление NTP было правильным.
Можно принять свой собственный ответ как решение проблемы., @VE7JRO
- ESP32 не может спать дольше 35 минут.
- ESP32 — петля DeepSleep или нет?
- Невозможно создать переменную RTC_DATA_ATTR внутри класса
- целочисленное переполнение в выражении типа 'int' приводит к
- Детектор браунаута ESP32-S2 Случайно срабатывает в глубоком сне
- Как узнать, просыпается ESP32 самостоятельно или вручную
- Монитор напряжения батареи сразу после глубокого сна
- Почему ESP32 не остается в глубоком сне дольше 35 минут?
NTP устанавливает только RTC. и NTP не сразу, @Juraj
@Juraj вы бы порекомендовали отсрочку? так как
getTime()
имеет 2 задержки по 200 миллисекунд, @Guy . DОбычно достаточно 5 секунд. Вы можете сделать трюк. сбросьте время RTC на 0, а затем вы можете проверить, установлено ли оно уже NTP, @Juraj
@Juraj, не могли бы вы объяснить, как?, @Guy . D
извините, я забыл, что нет API для установки времени RTC на esp32. https://arduinoprosto.ru/q/72010/set-the-wall-clock-time-or-change-gmt-offset-without-ntp-server/72019#72019, @Juraj