Счётчик воды на входе в квартиру я годами держал на глубоком сне: плата просыпалась по таймеру раз в минуту, читала импульсный выход и уходила обратно. Схема работала, но дышала тяжело: каждое пробуждение — полная загрузка, три секунды на поднятие WiFi, пересборка счётчиков из RTC-памяти. А когда поставил задачу считать импульсы честно (водомер щёлкает и ночью), глубоко засыпать стало нельзя вовсе: плату выключаешь на минуту — и импульс, пришедший во сне, пропал навсегда. Мой вывод после недели переделок: между «выключиться наглухо» и «жечь 40-120 мА постоянно» нужна третья ступень.
Эта ступень — light sleep, лёгкий сон. В этом уроке разберём esp_light_sleep_start() и его главное отличие от глубокого: код продолжается со строки, следующей за вызовом сна, а не с setup(); millis() не сбрасывается и продолжает тикать сквозь сон. Посмотрим, какие будильники его будят (те же таймер и RTC-пины, что у deep sleep), во сколько обходится такая дрёма — 0,8-1 мА у чипа против 10-150 мкА у глубокого, — и почему WiFi с долгим лёгким сном дружит плохо. Скетч в конце — готовый цикл «три секунды работы, пять секунд сна» с доказательством в Serial, что контекст пережил сон.
Сон, который не выключает плату
esp_light_sleep_start() останавливает ядра и основной тактовый генератор, но питание RAM и периферии не снимает: обычные переменные, счётчики, открытые драйверы — всё остаётся на месте. Будильники заводятся заранее, тем же API, что и у глубокого сна: esp_sleep_enable_timer_wakeup() принимает длительность в микросекундах, esp_sleep_enable_ext0_wakeup() будит по уровню на RTC-пине — я разбирал оба в уроке про кнопку-будильник. Разница в том, что происходит после: глубокий сон просыпается перезагрузкой — setup() с нуля, RAM пуста, а лёгкий возвращает управление на строку сразу за вызовом сна, как будто delay() был подлиннее.
Счёт времени во сне тоже не рвётся: медленный генератор RTC-домена продолжает тикать, и esp_timer подводит millis() по пробуждении — доказательство этого в скетче ниже станет вашим любимым тестом «а какой у меня вообще сон». Цена вопроса: 0,8-1 мА у чипа во сне против 40-120 мА в активной работе без радио — экономия в десятки раз при полной сохранности контекста. Но против глубокого сна с его 10-150 мкА лёгкая ступень проигрывает ещё в десять, поэтому ряд токов стоит держать в голове целиком: активный 40-120 мА, modem sleep 18-30 мА, light sleep 1 мА, deep sleep 10-150 мкА. Пауза на секунды-минуты, где контекст и счёт импульсов дороже микроамперов, — лёгкий; засыпание на часы, где всё равно стартуешь с нуля, — глубокий.
// Лёгкий сон: ядра спят, RAM жива, millis() не обнуляется.// После esp_light_sleep_start() скетч продолжается со следующей строки.const int PIN_LED = 2; // встроенный LED DevKit V1int cycles = 0; void setup() { Serial.begin(115200); delay(500); pinMode(PIN_LED, OUTPUT); Serial.println("start: rabota 3 s, potom light sleep 5 s");} void loop() { // фаза работы Serial.print("cikl #"); Serial.println(cycles); digitalWrite(PIN_LED, HIGH); delay(3000); digitalWrite(PIN_LED, LOW); // будильник на 5 секунд: тот же API, что у глубокого сна esp_sleep_enable_timer_wakeup(5ULL * 1000000ULL); Serial.println("uhozhu v light sleep..."); Serial.flush(); esp_light_sleep_start(); // сюда приходим ПОСЛЕ сна - строкой ниже, а не в setup() Serial.print("prosnyalis: millis()="); Serial.print(millis()); Serial.print(" prichina="); Serial.println(esp_sleep_get_wakeup_cause()); // 3 - таймер cycles++;}Разбор по выводу в мониторе. Первый цикл напечатает millis() около 8000: три секунды работы плюс пять секунд сна — счётчик времени шёл и во сне, что невозможно после глубокого (там millis() каждый раз стартует с нуля). Переменная cycles росла без всякой RTC_DATA_ATTR: обычная RAM, обычный инкремент. Причина пробуждения из esp_sleep_get_wakeup_cause() вернёт 3 — таймер; 1 и 2 означают ext0/ext1, 0 — питание или ресет. Если в журнале millis() вдруг с нуля — плату реально перезагрузило, и это удобный самотест на столе: не перепутать ступени сна.
WiFi — слабое место этой ступени. Радио во сне молчит, и роутер перестаёт видеть узел: паузы до одной-двух секунд WiFi переживает незаметно (modem sleep и так дремлет между кадрами), а минуты сна с активным соединением — лотерея. Я либо держу лёгкий сон коротким, либо расстаюсь с сетью честно и reconnect'юсь после пробуждения по лестнице пауз из урока про автопереподключение. И не забывайте про плату целиком: чип спит в миллиампере, а мост CP2102, стабилизатор и LED питания держат DevKit на 1-6 мА — энергобюджет батарейного проекта считается по всей плате, а не по даташиту кристалла.
| Режим | Ток чипа | Контекст после сна | Когда выбирать |
|---|---|---|---|
| Активный без радио | 40-120 мА | всё живёт | рабочая фаза: опрос датчика, передача |
| Modem sleep | 18-30 мА | всё живёт, WiFi держится | постоянная связь при редкой активности кода |
| Light sleep | 0,8-1 мА (DevKit 1-6 мА) | всё живёт, код продолжается со строки сна | паузы секунды-минуты, счёт импульсов и контекст важны |
| Deep sleep | 10-150 мкА | только RTC_DATA_ATTR, старт с setup() | сон минутами-часами, контекст не нужен |
- 1. Что происходит после пробуждения из light sleep?
- 2. Сколько ест ESP32 в light sleep?
- 3. Что станет с активным WiFi-соединением при минуте light sleep?
- esp_light_sleep_start(): после пробуждения код идёт дальше по строке, а не с setup()
- millis() и обычные переменные переживают лёгкий сон — счёт времени ведёт RTC-домен
- ток 0,8-1 мА у чипа и 1-6 мА у DevKit: между modem sleep (18-30 мА) и deep sleep (10-150 мкА)
- будильники те же, что у глубокого сна: таймер в микросекундах и RTC-пины ext0/ext1
- WiFi на время сна молчит: паузы до пары секунд — можно, минуты — с переподключением
Частые вопросы по теме урока
- Что происходит после пробуждения из light sleep?
- Лёгкий сон не обесточивает RAM и не перезагружает плату: управление возвращается на строку за вызовом сна, millis() подводится по RTC-домену. Перезагрузкой просыпается глубокий сон. код продолжается со строки после esp_light_sleep_start(), millis() не сбрасывается
- Сколько ест ESP32 в light sleep?
- Лёгкий сон на порядок дороже глубокого (10-150 мкА) и на порядок дешевле modem sleep (18-30 мА). На DevKit к этой цифре добавляются мост USB и стабилизатор — плата целиком 1-6 мА. 0,8-1 мА у чипа и 1-6 мА вся плата DevKit
- Что станет с активным WiFi-соединением при минуте light sleep?
- Радиомодуль во сне не слушает маяки роутера, и долгий сон с активной сетью заканчивается разрывом. Короткие паузы WiFi прощает; минутные — держите с честным reconnect после пробуждения. радио во сне молчит: роутер перестаёт видеть узел, соединение может отвалиться