Логотип sheen.bot

← Идеи и опыт

Почему ваша метеостанция на ESP32 зависает через 24 часа (и как это исправить)

6 окт. 2026 г.·Sheen Robotics
Почему ваша метеостанция на ESP32 зависает через 24 часа (и как это исправить)

Школьные IoT-проекты на ESP32 редко выходят из строя из-за дефектов микросхем. Они зависают из-за фрагментации динамической кучи, блокирующих циклов переподключения к Wi-Fi и отсутствия аппаратных сторожевых таймеров.

Если учебная метеостанция на базе ESP32 идеально работает на лабораторном столе во время четвертого урока, но к следующему утру полностью «гаснет», дело вовсе не в бракованном чипе. Микроконтроллеры не деградируют за сутки. Как правило, длительно работающее встраиваемое ПО сбоит из-за двух скрытых накопительных проблем: фрагментации динамической памяти (кучи) из-за операций с текстом и некорректно обработанных обрывов сети, загоняющих процессор в бесконечный блокирующий цикл.

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

Причина 1: динамические строки и фрагментация кучи

ESP32 имеет около 320 КБ доступной внутренней памяти SRAM. В метеостанции, опрашивающей датчики каждые десять секунд, код с использованием стандартного класса String в Arduino выделяет, перераспределяет и освобождает небольшие блоки памяти тысячи раз в день:

// Шаблон, который незаметно ломает ваш проект:
String payload = "{\"temp\": ";
payload += String(temperature);
payload += ", \"humidity\": ";
payload += String(humidity);
payload += "}";
http.POST(payload);

Каждый раз при создании и конкатенации динамических строк внутри loop() среда выполнения C++ выделяет память в куче. Поскольку системные фоновые задачи (например, стеки Wi-Fi и Bluetooth) параллельно запрашивают память, это непрерывное выделение и освобождение превращает кучу в швейцарский сыр. Общий объем свободной памяти может по-прежнему составлять 150 КБ, но размер наибольшего непрерывного свободного блока уменьшается до нескольких сотен байтов. Когда стеку Wi-Fi или сериализатору JSON внезапно требуется цельный блок размером 2 КБ для формирования TCP-пакета, выделение памяти завершается ошибкой, возвращая нулевой указатель (null pointer), что приводит к скрытой панике ядра или аварийному завершению работы.

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

// Надежная альтернатива без выделения памяти в куче:
char payload[128];
snprintf(payload, sizeof(payload), 
         "{\"temp\":%.2f,\"humidity\":%.2f}", 
         temperature, humidity);
http.POST((uint8_t*)payload, strlen(payload));

Причина 2: цикл переподключения к школьному Wi-Fi

В условиях школы работа Wi-Fi редко бывает полностью стабильной. Точки доступа обновляют ключи безопасности, срок аренды DHCP истекает, а локальные отключения электроэнергии или веерные отключения (load-shedding) временно выводят из строя маршрутизаторы, даже если сама IoT-станция работает от аккумулятора. Во многих вводных руководствах предлагают переподключаться к Wi-Fi следующим образом:

if (WiFi.status() != WL_CONNECTED) {
  WiFi.reconnect();
  while (WiFi.status() != WL_CONNECTED) {
    delay(500); // Фатально: блокирует процессор на неопределенный срок
  }
}

Если маршрутизатор перезагружается и ему требуется две минуты для поднятия локальной подсети, этот цикл while полностью замораживает выполнение программы. Поскольку FreeRTOS распределяет стек Wi-Fi и задачи управления системой между двумя ядрами, остановка основного цикла может лишить ресурсов фоновые задачи сторожевого таймера, что приведет к немедленной аппаратной перезагрузке или полной блокировке задач.

Решение: реализуйте подключение как неблокирующий конечный автомат. Никогда не останавливайте выполнение программы в ожидании соединения. Если Wi-Fi недоступен, сохраняйте данные локально во флеш-память или на SD-карту и повторяйте попытки подключения через заданные интервалы времени, не прерывая опрос датчиков.

Причина 3: отсутствие сторожевых таймеров

Насколько бы чистым ни был ваш код, внешние датчики, скачки напряжения от расположенных поблизости компрессоров или зависания шины I2C (особенно у популярных датчиков BME280 или DHT22) могут привести ESP32 к аппаратному зависанию. Если датчик не освобождает линию тактирования I2C, стандартная библиотека Wire может зависнуть навсегда.

Сторожевой таймер задач (Task Watchdog Timer, TWDT) отслеживает критические циклы программы. Если главный цикл не успевает «покормить» или сбросить сторожевой таймер в течение заданного окна (например, 8 секунд), ESP32 автоматически выполняет аппаратную перезагрузку и восстанавливает работу без вмешательства человека.

#include <esp_task_wdt.h>

#define WDT_TIMEOUT_SECONDS 8

void setup() {
  // Инициализация сторожевого таймера с таймаутом 8 секунд
  esp_task_wdt_init(WDT_TIMEOUT_SECONDS, true);
  esp_task_wdt_add(NULL); // Подключение текущего потока
}

void loop() {
  // Сброс сторожевого таймера на каждой итерации
  esp_task_wdt_reset();

  readSensors();
  sendTelemetry();
  
  // Избегайте длительных delay(); используйте неблокирующие проверки через millis()
}

Важное замечание о стабильности питания

Прежде чем списывать проблему исключительно на программное обеспечение, проверьте цепь питания. При кратковременных всплесках передачи по Wi-Fi (радиочастотная калибровка и передача пакетов) ESP32 потребляет импульсный ток до 350–500 мА. Если плата запитана через тонкий USB-кабель от ноутбука или от дешевого сетевого адаптера на 5 В, просадки напряжения ниже порогового значения 2,7 В активируют встроенный детектор просадки питания (brownout detector), вызывая внезапную перезагрузку.

  • Установите электролитический конденсатор емкостью от 100 мкФ до 470 мкФ между выводами VIN и GND для сглаживания переходных скачков тока.
  • Убедитесь, что детектор просадки питания включен в настройках вашей платформы, а не отключен программно, поскольку пониженное напряжение повреждает данные во встроенной флеш-памяти.

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

#esp32#iot#робототехника#устранение неполадок#программирование

Больше в категории «Идеи и опыт»

Почему датчик TDS сходит с ума при включении гидропонной помпы
Идеи и опыт· 5 окт. 2026 г.

Почему датчик TDS сходит с ума при включении гидропонной помпы

Погружные насосы создают блуждающие токи и электромагнитные помехи прямо в общем баке с питательным раствором. Объясняем, почему из-за этого искажаются аналоговые показания TDS и как устранить проблему программно или аппаратно.

Читать далее →
Почему линейные направляющие FTC заклинивает на середине подъема (и как правильно настроить тросовую систему)
Идеи и опыт· 4 окт. 2026 г.

Почему линейные направляющие FTC заклинивает на середине подъема (и как правильно настроить тросовую систему)

Заклинивание линейных направляющих на середине хода вызвано уменьшением площади перекрытия секций, увеличивающим трение в подшипниках, перекосом из-за непараллельных тросов или потерей натяжения в непрерывной схеме запасовки. Рассказываем, как это диагностировать и исправить.

Читать далее →
Почему плавятся отсеки для аккумуляторов 18650 в школьной робототехнике (и как это исправить)
Идеи и опыт· 3 окт. 2026 г.

Почему плавятся отсеки для аккумуляторов 18650 в школьной робототехнике (и как это исправить)

Безымянные батарейные отсеки со спиральными стальными пружинами создают сильное переходное сопротивление. При всплесках потребления Wi-Fi на ESP32 и блокировке моторов локальный джоулев нагрев быстро плавит пластиковый корпус.

Читать далее →