ESP32 — петля DeepSleep или нет?

Я пытаюсь создать батарею & ESP32 на солнечной энергии для будущего использования с датчиками. Он подключается к Wi-Fi, MQTT, публикует некоторые показания и сообщения о состоянии и снова уходит в сон. Время от времени (может произойти после нескольких циклов сна, а иногда и после нескольких сотен циклов) я получаю 2 необъяснимых поведения: 1) не удается подключиться к MQTT при загрузке, 2) не удается заснуть.

Иногда эти действия происходят одновременно.

Есть ли известная проблема с deepsleep и MQTT (с использованием PubSubClient)? Самый большой пример глубокого сна, который я видел в Интернете, весь код находится за пределами секции loop() — обязательно ли быть таким?

Я не делюсь кодом, так как это более общий вопрос.

Парень

ОБНОВЛЕНО 1

  1. большая часть обратного вызова была закомментирована, осталась только печать входящего сообщения.

  2. Светодиод был подключен к GPIO, вызывая мигание в loop() — при успешном переходе в спящий режим он гаснет, при сбое — остается включенным. Этот тест показывает, что когда эта "ошибка" происходит, код на самом деле перестает работать, но не переходит в глубокий сон (в зависимости от мощности)

, 👍0

Обсуждение

пропустите вызов публикации MQTT, чтобы увидеть, не переходит ли устройство в спящий режим... пропустите вызов, выполнив вычисление, такое как if (a+1 == 2) {, а не комментируя строку, потому что комментирование строка приведет к тому, что компилятор сгенерирует другой код ........ сделайте то же самое с кодом сна, @jsotola

@jsotola просто для понимания - «a + 1» должно создавать логическое состояние, которое не будет входить в цикл «if», чтобы аннулировать «публикацию»? а другая часть в esp_deep_sleep_start();? Я не понимаю, почему так... кстати - см. редактирование 1/, @Guy . D

если вы используете знак комментария //, чтобы предотвратить запуск команды публикации MQTT, тогда компилятор создаст другой код, который может не иметь проблемы со сном .... использование оператора if гарантирует, что компилятор не пропустит un -исполняемый код ..... проведите такой же тест для спящего кода, чтобы увидеть, влияет ли он на код MQTT ...... проведите тесты отдельно, @jsotola

@jsotola - я понял, почему это нужно сделать, я попросил только часть сна. кстати - обходной путь publish не сработал, даже когда я увеличил MQTT_MAX_PACKET_SIZE до 512, чтобы быть уверенным, @Guy . D

@jsotola для второй проверки («маскировка» фазы сна) - все прошло, как и ожидалось. Чтобы вызвать «перезагрузку», в «loop()» каждые 30 секунд добавлялся ESP.restart()., @Guy . D


2 ответа


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

1

Есть ли известная проблема с глубоким сном и MQTT?

Нет. Может быть конкретная проблема с конкретной библиотекой, которую вы используете, но концепция проблемы с MQTT в целом — чепуха.

В большинстве примеров глубокого сна, которые я видел в Интернете, весь код находится за пределами секции loop() - обязательно ли быть таким?

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

,

Я не знаю насчет ерунды, но аналогичный вопрос был задан в https://github.com/knolleary/pubsubclient/issues/634 (такое же поведение, но дело все еще открыто...), @Guy . D

MQTT — это просто протокол. Концепция наличия проблемы не имеет логического смысла. Если есть проблема, связанная с использованием MQTT, то это проблема с pubsubclient, а не с MQTT., @Majenko

Хорошо, я согласен, я обращаюсь к pubsubClient, @Guy . D


2

Проблема с вызовом ESP.deepSleep(xx) внутри loop() заключается в том, что там уже активирован сторожевой таймер, а затем во время спящего режима происходит сброс.< /п>

Чтобы исправить это, я использовал собственную технику сброса ESP.restart() программного обеспечения после записи подписи для файла «not init». переменная следующим образом:

Область переменной:

uint16_t SleepSign __attribute__((section(".noinit"))); // Горячий сброс/подпись глубокого сна.

Затем в начале setup() мы пишем код, который проверяет содержимое этой неинициализированной переменной и, если она содержит подпись, ESP.deepSleep(xx) называется. В моем случае я использую ESP.deepSleep(0), потому что я хочу, чтобы устройство перезагружалось только при новой загрузке:

void setup()
{
     if (SleepSign == 0xdd11) ESP.deepSleep(0);
     Rest of the initialization:
     ...

Inside loop():
     ...
     if ((millis() - timeconnect) > 300*1000) {
       SleepSign = 0xdd11; // глубокий сон при перезапуске
       ESP.restart();
     }
     ...

Эта система протестирована и работает корректно, сокращая потребление до минимума, указанного espressif. Раньше я пытался заблокировать просмотр перед выходом из setup(), но это, конечно, не сработало:

*((volatile uint32_t*) 0x60000900) &= ~(1); // Аппаратное WDT ВЫКЛ.

Очевидно, что если мы заинтересованы в использовании DeepSleep по времени и чтобы устройство делало что-либо перед тем, как снова перейти в спящий режим, мы можем присвоить несколько значений переменной SleepSign для управления перезапуском, а также сбросить ее значение перед вызовом ESP.deepSleep. (0):

 void setup()
 {
 if (SleepSign == 0xdd11) {
    SleepSign = 0xffff;
    ESP.deepSleep(xx);
  }
  Rest of the initialization:
  ...

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

,