ESP32 Deep Sleep: как сделать датчик на батарейках, работающий месяцами

Используем Deep Sleep на ESP32, чтобы снизить энергопотребление и продлить работу автономного датчика от батареи.
Приветствую всех любителей умного дома и DIY-электроники! Сегодня мы разберём одну из самых крутых фич микроконтроллера ESP32 — режим глубокого сна (Deep Sleep). Если вы, как и я, сталкивались с тем, что ваши беспроводные датчики требуют постоянной подзарядки или замены батареек каждые пару недель, то этот материал станет для вас настоящим откровением. Мы создадим энергоэффективный датчик, который на двух пальчиковых батарейках типа АА сможет работать не месяцы, а до года и более, периодически просыпаясь, чтобы отправить данные. Идеально для удалённых датчиков температуры, влажности, контроля открытия дверей или окон.
Зачем это нужно? Проблема энергопотребления
Когда я только начинал строить свою систему умного дома, я поставил несколько датчиков температуры в разных комнатах на базе ESP32. Они работали в режиме постоянного подключения к Wi-Fi и отправляли данные каждые 10 секунд. Результат? Powerbank на 10000 мАч садился за 1.5-2 дня. Это было совершенно неприемлемо для автономных устройств.
Суть решения в том, что ESP32 умеет практически полностью отключать себя, потребляя в режиме глубокого сна всего 10-150 мкА (микроампер!), оставляя «включённым» лишь небольшой участок памяти (RTC) и таймер, который может его разбудить. Для сравнения: в активном режиме с работающим Wi-Fi потребление составляет 60-80 мА — в тысячи раз больше!
Что можно сделать с Deep Sleep:
- Батарейные датчики температуры/влажности (DHT22, BME280) для погреба, гаража, улицы.
- Датчики открытия дверей/окон (герконы).
- Счётчики импульсов (например, для учёта расхода воды).
- Датчики протечки.
- Любые устройства, где данные не нужны каждую секунду, а достаточно обновления раз в 5, 10, 30 минут или даже час.
Как работает Deep Sleep на ESP32
Представьте медведя в спячке. Его метаболизм замедлен до минимума, но он может проснуться от внешнего стимула (шум, приход весны). Так и ESP32. В Deep Sleep отключается основное ядро, ОЗУ, Wi-Fi/Bluetooth радио. Работает только: 1. RTC (Real Time Clock) — часы реального времени. 2. ULP (Ultra Low Power) сопроцессор — может очень медленно опрашивать аналоговые датчики или GPIO. 3. RTC память (8 КБ) — небольшой участок памяти, где можно сохранить данные между циклами сна. 4. Таймеры RTC — могут разбудить микроконтроллер по истечении заданного времени.
Проснуться ESP32 может по нескольким «будильникам»: * Таймер RTC (самый частый вариант — просыпаться каждые N секунд). * Внешнее прерывание (EXT0, EXT1) — изменение уровня на определённых GPIO-пинах (идеально для кнопки или геркона). * Сенсорный прерывание (Touch) — прикосновение к сенсорному контакту. * Прерывание от ULP-сопроцессора.
Сегодня мы сосредоточимся на самом популярном сценарии — пробуждение по таймеру.
Практика: Собираем батарейный датчик температуры
Необходимые компоненты
- Плата ESP32 (любая, например, ESP32 DevKit V1). Важно: на некоторых платах (как у меня в первый раз) не распаян токоограничительный резистор на линии EN, что мешает глубокому сну. Ищите платы с маркировкой «EN» или проверяйте схему.
- Датчик температуры BME280 (I2C). Он лучше DHT22 по точности и также измеряет влажность и атмосферное давление.
- Макетная плата и провода.
- Источник питания: 2 батарейки АА (3В) в держателе или литиевый аккумулятор 18650 (3.7В). ESP32 работает от 3.3В, поэтому прямое подключение 2хАА (≈3В) допустимо, но для 18650 понадобится понижающий преобразователь (LDO) до 3.3В.
- (Опционально) Конденсатор 100-470 мкФ для сглаживания скачков потребления при включении Wi-Fi.
Схема подключения
Подключим BME280 по I2C. Это просто и требует всего 4 провода.
ESP32 (DevKit) BME280 (модуль)
3.3V (3V3) ---> VCC
GND ---> GND
GPIO 22 ---> SCL
GPIO 21 ---> SDA
- 3.3V / GND: Питание датчика.
- GPIO 22 (SCL): Тактовый сигнал I2C.
- GPIO 21 (SDA): Линия данных I2C.
Важный момент для Deep Sleep: Чтобы ESP32 могла уйти в сон, контакты GPIO16 (U2RX) и RST (Reset) должны быть соединены перемычкой. Это необходимо для работы таймера RTC. На многих платах это уже сделано, но лучше проверить.
Программная часть (Прошивка)
Мы будем использовать Arduino IDE. Убедитесь, что у вас установлена поддержка плат ESP32 через Board Manager.
-
Установите необходимые библиотеки:
Adafruit BME280 Library(для работы с датчиком)Adafruit Unified Sensor(зависимость для BME280)
-
Код прошивки (скетча):
// Библиотеки
#include <WiFi.h>
#include <PubSubClient.h> // Для MQTT
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include "esp_sleep.h" // Библиотека для управления сном
// Настройки Wi-Fi
const char* ssid = "ВАШ_SSID";
const char* password = "ВАШ_ПАРОЛЬ";
// Настройки MQTT
const char* mqtt_server = "192.168.1.100"; // IP вашего MQTT-брокера
const char* mqtt_topic_temp = "home/sensor/bedroom/temperature";
const char* mqtt_topic_hum = "home/sensor/bedroom/humidity";
const char* mqtt_topic_press = "home/sensor/bedroom/pressure";
WiFiClient espClient;
PubSubClient client(espClient);
// Объект датчика
Adafruit_BME280 bme;
// Константы для Deep Sleep
#define uS_TO_S_FACTOR 1000000ULL // Коэффициент перевода микросекунд в секунды
#define TIME_TO_SLEEP 300 // Время сна в секундах (5 минут = 300 сек)
// Пины I2C
#define I2C_SDA 21
#define I2C_SCL 22
// RTC_DATA_ATTR сохраняет переменную в RTC-памяти между циклами сна
RTC_DATA_ATTR int bootCount = 0;
void setup() {
Serial.begin(115200);
delay(1000); // Небольшая задержка для стабилизации
// Увеличиваем счётчик пробуждений
bootCount++;
Serial.println("Пробуждение №" + String(bootCount));
// Инициализация I2C с указанием пинов
Wire.begin(I2C_SDA, I2C_SCL);
// Инициализация датчика
bool bme_status = bme.begin(0x76); // Адрес 0x76 или 0x77
if (!bme_status) {
Serial.println("Ошибка! Не найден датчик BME280. Проверьте подключение.");
// Если датчик не найден, всё равно уходим в сон, чтобы не разряжать батарею
goToDeepSleep();
}
// Подключение к Wi-Fi
setup_wifi();
// Подключение к MQTT-брокеру
if (!client.connected()) {
reconnect_mqtt();
}
client.loop();
// Чтение данных с датчика
float temperature = bme.readTemperature();
float humidity = bme.readHumidity();
float pressure = bme.readPressure() / 100.0F; // Переводим в гПа
// Проверка на ошибки чтения (возвращает NAN)
if (isnan(temperature) || isnan(humidity) || isnan(pressure)) {
Serial.println("Ошибка чтения данных с BME280!");
} else {
// Вывод в Serial-монитор
Serial.print("Температура: ");
Serial.print(temperature);
Serial.println(" °C");
Serial.print("Влажность: ");
Serial.print(humidity);
Serial.println(" %");
Serial.print("Давление: ");
Serial.print(pressure);
Serial.println(" гПа");
// Публикация данных в MQTT
char msg_temp[10];
char msg_hum[10];
char msg_press[10];
dtostrf(temperature, 4, 2, msg_temp);
dtostrf(humidity, 4, 2, msg_hum);
dtostrf(pressure, 6, 2, msg_press);
client.publish(mqtt_topic_temp, msg_temp);
client.publish(mqtt_topic_hum, msg_hum);
client.publish(mqtt_topic_press, msg_press);
Serial.println("Данные отправлены в MQTT.");
}
// Небольшая задержка перед сном, чтобы убедиться, что данные ушли
delay(100);
// Отключение Wi-Fi (важно для снижения потребления перед сном)
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
// Уходим в глубокий сон
goToDeepSleep();
}
void loop() {
// Пустой, так как весь код в setup(). После сна контроллер перезагружается.
}
// Функция подключения к Wi-Fi
void setup_wifi() {
delay(10);
Serial.print("Подключение к ");
Serial.println(ssid);
WiFi.begin(ssid, password);
// Ограничиваем время попытки подключения (например, 10 секунд)
int wifi_retry = 0;
while (WiFi.status() != WL_CONNECTED && wifi_retry < 20) {
delay(500);
Serial.print(".");
wifi_retry++;
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("");
Serial.println("Wi-Fi подключен");
Serial.print("IP адрес: ");
Serial.println(WiFi.localIP());
} else {
Serial.println("Не удалось подключиться к Wi-Fi!");
}
}
// Функция переподключения к MQTT-брокеру
void reconnect_mqtt() {
while (!client.connected()) {
Serial.print("Попытка подключения к MQTT...");
String clientId = "ESP32-DeepSleep-";
clientId += String(random(0xffff), HEX);
if (client.connect(clientId.c_str())) {
Serial.println("успешно!");
} else {
Serial.print("ошибка, rc=");
Serial.print(client.state());
Serial.println(" пробуем снова через 5 секунд");
delay(5000);
}
}
}
// Функция перехода в глубокий сон
void goToDeepSleep() {
Serial.println("Настройка таймера пробуждения...");
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
Serial.println("Переход в режим Deep Sleep на " + String(TIME_TO_SLEEP) + " секунд");
Serial.flush(); // Важно! Ожидаем завершения передачи всех данных в Serial
esp_deep_sleep_start(); // Отправляем ESP32 спать
// Код после этой строки не выполнится до перезагрузки
}
Пояснения к коду и типичные ошибки
RTC_DATA_ATTR int bootCount = 0;— эта переменная сохраняется в специальной RTC-памяти между циклами сна и перезагрузками. Отлично подходит для счётчиков.esp_sleep_enable_timer_wakeup()— ключевая функция, настраивающая «будильник».Serial.flush()передesp_deep_sleep_start()— ОЧЕНЬ важно! Без этой команды последние Serial-сообщения могут не успеть отправиться, и вы не увидите их в мониторе порта.- Wi-Fi и MQTT отключение: Мы явно отключаем Wi-Fi (
WiFi.mode(WIFI_OFF)) перед сном. Иногда библиотеки делают это не полностью, что ведёт к повышенному потреблению. - Ошибка «Guru Meditation Error» при пробуждении: Часто связана с неправильной инициализацией периферии после сна. Помните, что после глубокого сна ESP32 перезагружается, и весь код выполняется с начала
setup(). Не пытайтесь использовать объекты, созданные до сна. - Питание датчика от GPIO: Некоторые пытаются сэкономить ещё больше, отключая питание датчика через GPIO перед сном. Это хорошая практика, но не все датчики это любят (BME280 — нормально). Добавьте
pinMode(PIN_POWER, OUTPUT); digitalWrite(PIN_POWER, LOW);перед сном иHIGHв началеsetup().
Проверка результата и тестирование
- Загрузите скетч в ESP32. Подключите её по USB к компьютеру.
- Откройте Serial Monitor (115200 baud). Вы увидите процесс пробуждения, подключения, отправки данных и ухода в сон с указанием времени.
- Отсоедините USB и подключите к батарейкам. Используйте мультиметр в режиме амперметра, включённого последовательно в цепь питания, чтобы измерить потребление.
- В активной фазе (измерение, Wi-Fi) вы увидите пики до 70-80 мА.
- В режиме глубокого сна потребление должно упасть до 10-150 мкА (0.01 - 0.15 мА). Если оно выше (например, 2-5 мА), значит что-то не даёт ESP32 уснуть (возможно, неправильно подключённый датчик, который тянет линию).
- Проверьте данные в MQTT. Подключитесь к вашему брокеру, например, Mosquitto, с помощью MQTT-клиента (MQTT Explorer, MQTT.fx) и убедитесь, что в топики
home/sensor/bedroom/...приходят новые значения каждые 5 минут. - Долгосрочный тест. Оставьте датчик на батарейках на сутки. Посчитайте среднее потребление:
(Время_активности * 70мА + Время_сна * 0.1мА) / Общее_время. Для цикла 5 минут (10 сек активность, 290 сек сон) средний ток будет около 0.25 мА. Две батарейки АА (емкость ~2000 мАч каждая, итого 4000 мАч при 3В) должны проработать 4000 мАч / 0.25 мА ≈ 16000 часов или более 1.5 лет! На практике срок будет меньше из-за саморазряда батареек и КПД преобразователя, но год работы — вполне достижимая цель.
Заключение
Режим Deep Sleep — это мощнейший инструмент в арсенале создателя автономных IoT-устройств на ESP32. Как показала наша практика, переделав обычный датчик в «ленивый», просыпающийся лишь на несколько секунд, мы увеличиваем время его работы от батарей в сотни раз.
Следующими шагами вы можете: * Добавить больше датчиков (например, контроль качества воздуха на том же ESP32). * Реализовать пробуждение не по таймеру, а по прерыванию от геркона (для датчика открытия двери). * Настроить визуализацию данных из MQTT в домашней метеостанции с графиками или в Home Assistant.
Экспериментируйте, считайте ампер-часы и создавайте по-настоящему автономные устройства для своего умного дома! Если есть вопросы или интересные кейсы использования Deep Sleep — делитесь в комментариях.
Удачи в проектах!
===SEO_JSON_START=== { "meta_title": "ESP32 Deep Sleep: датчик на батарейках на год работы", "meta_description": "Пошаговое руководство по созданию автономного датчика на ESP32 с Deep Sleep. Увеличьте время работы от батареек с дней до месяцев и лет. Код, схема, расчёты.", "keywords": ["ESP32 Deep Sleep", "батарейный датчик ESP32", "энергосбережение ESP32", "автономный датчик температуры", "IoT на батарейках", "режи
Понравилась статья?
Поставьте лайк и сохраните полезный материал в закладки.
Посетители, находящиеся в группе Гости, не могут оставлять комментарии к данной публикации.
ESP: как Espressif переписала правила DIY-электроники
ESP32-P4 vs ESP32-S3: в чём разница и для каких проектов нужен P4
Что можно сделать на LILYGO T-Dongle S3: 10 практических проектов
WiFi на ESP32: как устроен стек и где он раскрывается лучше всего
ESP32 Marauder: что это такое, как выбрать плату и где скачать прошивку
ESP32 vs ESP8266: Что выбрать для своего DIY-проекта в 2024 году