Как использовать память 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); 
    }
}

, 👍1

Обсуждение

@Majenko интересно! Я этого не знал. Я удалил свой комментарий., @Gerben

@Gerben Я тоже так сделал: P, @Majenko

Вы можете различать первое включение и сброс (после глубокого сна), используя rtc_get_reset_reason (0). Если я не ошибаюсь, это должно возвращать значение 1 при включении питания. Поэтому, когда это возвращает 1, перезапишите память RTC нулем. В противном случае считайте память., @Gerben


2 ответа


Лучший ответ:

2

Самый простой трюк - использовать более одной ячейки памяти. Имейте один, как и сейчас, в качестве счетчика, а затем один или несколько в качестве флага "Это было настроено".

В идеале вы хотите, чтобы флаг имел очень низкую вероятность случайного появления, поэтому использование комбинации нескольких ячеек памяти улучшило бы это.

Например, если вы читаете ячейки памяти 1-4 и ищете четыре конкретных байта, это дает вам примерно 1 шанс из 4 миллиардов, что это произойдет случайным образом.

Если вы не видите этих четырех байтов, вы устанавливаете байт счетчика равным 0 (или как бы вы ни хотели, чтобы ваше начальное значение было), а остальные 4 ячейки памяти содержат ваши 4 байта флага.

Использование 8 байтов для вашего флага даст вам вероятность случайного появления 1 в 1.8x1019.

Эти "комбинации флаговых байтов" часто называются "магическими числами" и используются повсюду, чтобы определить, что это такое, или если что-то действительно.

,

Итак, могу ли я использовать struct {счетчик байтов; проверка байтов [7]}?, @Fabio Marzocca

Конечно, вы могли бы это сделать. Я не знаю, какие функции позволяют вам легко передавать, поэтому, возможно, проще просто напрямую обращаться к байтам памяти., @Majenko


2

Я понимаю, что это действительно старый, но он все еще находится в верхней части списка, когда вы ищете 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 недель в середине зимы и намного дольше летом)

,