Как использовать память RTC в NodeMCU для подсчета пробуждений от глубокого сна?
Проблема: мне нужно повторить попытку по крайней мере 3 раза (прежде чем сдаться), чтобы повторно подключить NodeMCU, если он не подключается к Wi-Fi, через циклы глубокого сна, чтобы сэкономить батареи. Я думал использовать RTC-память для сохранения счетчика, но это не работает, потому что содержимое RTC-ОЗУ непредсказуемо при первом включении питания.
Ниже приведен НЕ РАБОЧИЙ код, но он дает представление о том, чего мне нужно достичь. Проблема в том, что переменная kounter постоянна в циклах, но ее самое первое значение непредсказуемо.
#define DONEPIN 5
uint32_t kounter;
void setup() {
digitalWrite(DONEPIN, HIGH);
// Функции настройки Wi-Fi...
// .....
if (WiFi.status() != WL_CONNECTED) {
ESP.rtcUserMemoryRead(0, &kounter, sizeof(kounter));
kounter++
if (kounter > 3) {
digitalWrite(DONEPIN, LOW);
}
ESP.rtcUserMemoryWrite(0, &kounter, sizeof(kounter));
ESP.deepSleep(60e6);
}
}
@Fabio Marzocca, 👍1
Обсуждение2 ответа
Лучший ответ:
Самый простой трюк - использовать более одной ячейки памяти. Имейте один, как и сейчас, в качестве счетчика, а затем один или несколько в качестве флага "Это было настроено".
В идеале вы хотите, чтобы флаг имел очень низкую вероятность случайного появления, поэтому использование комбинации нескольких ячеек памяти улучшило бы это.
Например, если вы читаете ячейки памяти 1-4 и ищете четыре конкретных байта, это дает вам примерно 1 шанс из 4 миллиардов, что это произойдет случайным образом.
Если вы не видите этих четырех байтов, вы устанавливаете байт счетчика равным 0 (или как бы вы ни хотели, чтобы ваше начальное значение было), а остальные 4 ячейки памяти содержат ваши 4 байта флага.
Использование 8 байтов для вашего флага даст вам вероятность случайного появления 1 в 1.8x1019.
Эти "комбинации флаговых байтов" часто называются "магическими числами" и используются повсюду, чтобы определить, что это такое, или если что-то действительно.
Итак, могу ли я использовать struct {счетчик байтов; проверка байтов [7]}
?, @Fabio Marzocca
Конечно, вы могли бы это сделать. Я не знаю, какие функции позволяют вам легко передавать, поэтому, возможно, проще просто напрямую обращаться к байтам памяти., @Majenko
Я понимаю, что это действительно старый, но он все еще находится в верхней части списка, когда вы ищете RTCmem read / write. Хотя это, возможно, не так "по книге", как "правильный" ответ выше, есть действительно простой способ справиться с проблемой "значение rtcmem - это что-то смешное при первом чтении". Когда вы впервые включите esp8266 или после сброса на основе кнопок, значение rtcmem БУДЕТ чем-то безумным. Вы можете объяснить это в коде, игнорируя все, что находится за пределами нужного вам количества. Поскольку мое приложение "спит" в течение 4 часов, что в esp8266 означает 4, 1 час цикла, я просто говорю, что если значение rtcMem находится за пределами этого диапазона, то оно явно фиктивное, установите его на то, что я хочу, и занимайтесь своими делами:
void writeToRTCMemory() {
if (rtcMem.count == MAXHOUR) {
rtcMem.count = 1;
} else {
if (rtcMem.count < 1) {
rtcMem.count = 1;
}
if (rtcMem.count > 4) {
rtcMem.count = 1;
}
rtcMem.count++;
}
До тех пор, пока ваше устройство не потеряло питание или вы не нажали кнопку сброса, оно будет работать так, как вы хотите, до тех пор, пока у него будет достаточно сока для глубокого сна. (Мои датчики на солнечных батареях с этой петлей работают около 2/2,5 недель в середине зимы и намного дольше летом)
- Как получить текущую дату
- Как заставить 5-вольтовое реле работать с NodeMCU
- ESP8266 не подключается к Wi-Fi
- Разница между этими двумя платами NodeMCU?
- NodeMCU - использовать кнопку flash в качестве входного сигнала в loop()
- Как определить размер Flash?
- Как изменить имя модуля ESP8266-12E по умолчанию
- Простой запрос GET с ESP8266HTTPClient
@Majenko интересно! Я этого не знал. Я удалил свой комментарий., @Gerben
@Gerben Я тоже так сделал: P, @Majenko
Вы можете различать первое включение и сброс (после глубокого сна), используя
rtc_get_reset_reason (0)
. Если я не ошибаюсь, это должно возвращать значение 1 при включении питания. Поэтому, когда это возвращает 1, перезапишите память RTC нулем. В противном случае считайте память., @Gerben