Метео-датчик на балконе прожил от банки 18650 ровно двадцать восемь часов. Я вкрутил в него свежую 18650 на 3400 мА·ч и смотрел на корпус с уверенностью человека, который «поставил большую батарейку». Через сутки датчик молчал. Арифметика была честная — я просто не сделал её до сборки: ESP32 с поднятым WiFi ест около 120 миллиампер, 3400 делить на 120 — это 28,3 часа. Батарейка отработала паспортно. Подвёл не аккумулятор, а я.
К этому моменту в разделе стоит весь скелет: в уроке про таймер сна и бюджет мы глушили ядро и вылавливали микроамперы, а часы после сна научились жить своей жизнью. Не хватает одного шага: собрать всё в полный энергобюджет — сколько ест каждое состояние платы, как из duty cycle получается средний ток и сколько месяцев такой режим реально даёт от банки.
Пойдём по порядку: ток по режимам с числами и условиями, прогноз на салфетке, цикл «проснулся — померил — отправил — уснул» сначала скетчем для платы, потом в симуляторе. Там потенциометр на A0 задаёт период сна, а Serial печатает прогноз работы от 18650 при каждом пробуждении.
Сколько ест каждое состояние
Активный режим с поднятым радио — около 120 мА для типичного DevKit при умеренной передаче по 2.4 ГГц; в момент выхода модуля в эфир на полной мощности пики доходят до 240-350 мА. Выключенный WiFi (WiFi.mode(WIFI_OFF)) оставляет ядру 30-40 мА на своих 240 МГц — до сих пор много, но уже трое-четверо суток от нашей банки вместо одних. Между ними живёт modem sleep: скетч работает, радио дремлет между пакетами, потребление падает до 3-20 мА — вариант для платы, которая обязана слушать сеть постоянно.
Deep sleep здесь пересчитывать не буду — в уроке про бюджет сна мы уже разобрали 6-15 мкА на чипе и выяснили, куда эти микроамперы утекают на реальной плате. Запомните только вилку: голый чип спит на 10 мкА, DevKit с обвязкой — 10-150 мкА. Разница между этими цифрами — это годы работы, поэтому я не верю прогнозам «до десяти лет» без указания конкретной платы. Разницу я прочувствовал на собственном заказе — история ниже.
Средний ток цикла считается на салфетке за минуту. Мой датчик бодрствует 10 секунд по 120 мА и спит 590 секунд по 0,15 мА: I = (120×10 + 0,15×590) / 600 ≈ 2,1 мА. Делим 3000 честных мА·ч на 2,1 — получаем около 60 суток. Тот же датчик с периодом раз в час даёт 0,48 мА и около 260 суток. Без сна вообще — те самые 28 часов. Решает всё не ёмкость, а duty cycle. Формула одна для любого девайса — светильника, логгера, будильника: меняются только числа в скобках.
| Состояние | Ток | Время от 18650 на 3400 мА·ч |
|---|---|---|
| Активный, WiFi шлёт | 120 мА, пики до 350 мА | около 28 часов |
| Активный без радио | 30-40 мА | 3-4 суток |
| Deep sleep: голый чип | около 10 мкА | дольше саморазряда банки |
| Deep sleep: DevKit с обвязкой | 10-150 мкА | от двух с половиной лет |
Мой тупик в этом проекте длился две недели из-за слова low power в описании товара. Я заказал плату с пометкой ultra-low-power, подключил и увидел во сне 12 мА — в тысячу раз больше паспортных микроамперов. Виноват оказался не чип, а обвязка: USB-UART мост продолжал питаться, стабилизатор тратил свой миллиампер, красный светодиод питания горел даже во сне. Голый модуль со снятым LED показал 25 мкА — с тем же скетчем. С тех пор в моём заказе слова low power и ultra значат ровно ничего: смотрю не на описание, а на фото платы — есть ли на ней светодиод и какой стоит USB-мост.
С тех пор я не верю ни одному числу потребления без мультиметра: прибор в режиме микроампер встаёт в разрыв минусового провода, и первый замер я делаю до всякой логики — на спящем скетче. Если прибор показывает миллиамперы там, где ждёте микроамперы, ищите светодиоды и чипы обвязки, а не переписывайте код.
И про саму банку. 3400 мА·ч — паспорт при идеальном токе разряда; плата снимет 80-90 процентов, потому что защита BMS отсекает литий при 2,75-2,9 В, а на зимнем балконе при нуле отдача падает ещё на треть. Все мои прогнозы теперь считаются от 3000 мА·ч — и пока ни один не подвёл.
Цикл: проснулся, померил, отправил, уснул
Порядок бодрствования я держу жёсткий: сначала датчик, потом сеть. DHT22 не нужен роутер, чтобы выдать температуру — читаем его сразу после пробуждения, пока питание дежурное (в покое сенсор допивает десятки микроамперов, на замер уходит около миллиампера на полторы-две секунды; как подключать сам DHT — схема в уроке про DHT11, у DHT22 всё то же самое с точностью до подтяжки).
Потом радио. WiFi.begin после сна — всегда новое подключение, на моём роутере оно занимает 2-6 секунд. Отправка — один GET с параметрами в адресе, полсекунды. Всё бодрствование — около 10 секунд, и каждая лишняя секунда с поднятым радио стоит 120 миллиампер-секунд, то есть 0,033 мА·ч. Считать, сколько раз в час можно разбудить плату, теперь легко прямо в уме. Понадобилась вторая отправка в час — сначала посчитайте: она удвоит и радио-фазу, и весь средний ток вместе с прогнозом.
Если сеть умерла — роутер перезагружали, сосед выключил свет, — таймаут на подключение 8 секунд, дальше сон без отправки. Искать сеть до посинения — главный способ слить батарею за первые сутки: одну 18650 я так просадил за ночь, когда скетч честно крутил while бесконечно. Что будит плату кроме таймера — я разбирал в уроке про кнопку и причины пробуждения, а что память переживает сон — в уроке про RTC-память со счётчиком снов.
// Цикл раз в 10 минут. Порядок: датчик -> сеть -> отправка -> сон.#include <WiFi.h>#include <HTTPClient.h>#include <DHT.h>#include "esp_sleep.h" DHT dht(4, DHT22);RTC_DATA_ATTR int cikl = 0; void setup() { Serial.begin(115200); delay(300); // UART оживает не мгновенно cikl = cikl + 1; Serial.print("cikl="); Serial.println(cikl); // 1. датчик: сеть ему не нужна float t = dht.readTemperature(); float h = dht.readHumidity(); bool dhtOk = (t > -40.0) && (t < 100.0) && (h > 0.0) && (h <= 100.0); // 2. радио включаем ТОЛЬКО сейчас WiFi.mode(WIFI_STA); WiFi.begin("Dom", "parol123"); unsigned long t0 = millis(); while (WiFi.status() != WL_CONNECTED && millis() - t0 < 8000) { delay(100); // максимум 8 с: сеть может умереть } // 3. отправка: данные в параметрах адреса if (WiFi.status() == WL_CONNECTED) { HTTPClient http; String url = "http://192.168.1.10:8080/pogoda"; url += "?c="; url += cikl; if (dhtOk) { url += "&t="; url += t; url += "&h="; url += h; } http.begin(url); int code = http.GET(); http.end(); Serial.print("otvet="); Serial.println(code); } else { Serial.println("seti net: spim bez otpravki"); } // 4. спать WiFi.mode(WIFI_OFF); // радио гасим явно Serial.println("usnul na 10 minut"); delay(100); // дать UART дописать строку esp_sleep_enable_timer_wakeup(600ULL * 1000000ULL); esp_deep_sleep_start();} void loop() { } // сюда плата не доходитПо строкам. Радио включается последним: WiFi.mode(WIFI_STA) стоит после чтения датчика, и до этого момента ядро живёт без радиомодуля и его миллиамперов. Таймаут 8000 мс — страховка от бесконечного while: не подключились — не беда, спим, показания уйдут в следующем цикле. GET с данными в адресе — тот же приём из урока про HTTPClient и GET-запрос, только параметры теперь наши собственные.
WIFI_OFF перед сном обязателен: ядро во сне гаснет целиком, но радио честнее попросить выйти в оффлайн заранее, чем надеяться на питание домена сна. И суффикс ULL в enable_timer_wakeup: 600 миллиардов микросекунд в 32 бита не влезают, без ULL число усечётся и будильник прозвенит когда попало. Если сервер не нужен вовсе, тот же цикл пишет показания на SD-карту — логгер со сном и батарейкой мы собирали в разделе про SD, там же таблица, сколько живёт связка. Мой балконный датчик делал оба: днём писал на карту, раз в час отправлял в сеть — карта ничего не видит, а графики строятся сами.
- 1. Датчик бодрствует 10 секунд по 120 мА и спит 590 секунд по 150 мкА. Каков средний ток цикла?
- 2. 18650 на 3400 мА·ч питает ESP32 с постоянно поднятым WiFi — около 120 мА. На сколько хватит?
- 3. Голый чип ESP32 спит на 10 мкА, а DevKit с тем же скетчем — на 12 мА. Кто виноват?
- 4. Почему для питания ESP32 с WiFi не годится CR2032?
- 5. Период сна увеличили с 10 минут до часа, бодрствование те же 10 секунд по 120 мА. Что станет со средним током и прогнозом от 3000 мА·ч?
- Средний ток делает duty cycle, а не батарейка: (ток бодрствования × секунды + ток сна × секунды) / период
- 120 мА с радио против 10-150 мкА во сне; в момент передачи пики до 240-350 мА
- Паспортные 3400 мА·ч считайте как 3000: BMS отсекает банку при 2,75-2,9 В, зима съедает ещё треть
- Порядок цикла: датчик, сеть с таймаутом 8 с, отправка, WIFI_OFF, сон с суффиксом ULL
- CR2032 и другие кнопочные не годятся: импульсный ток радиомодуля они не тянут
Частые вопросы по теме урока
- Датчик бодрствует 10 секунд по 120 мА и спит 590 секунд по 150 мкА. Каков средний ток цикла?
- Средний ток — взвешенное по времени среднее: (120×10 + 0,15×590)/600 ≈ 2,1 мА. От 3000 честных мА·ч это около 60 суток. Около 2 мА: (120×10 + 0,15×590) / 600
- 18650 на 3400 мА·ч питает ESP32 с постоянно поднятым WiFi — около 120 мА. На сколько хватит?
- Активное потребление режет и самую большую банку: 3400 мА·ч / 120 мА ≈ 28 часов. Месяцы дают циклы со сном, а не ёмкость. На 28 часов: 3400 делим на 120, никакой магии
- Голый чип ESP32 спит на 10 мкА, а DevKit с тем же скетчем — на 12 мА. Кто виноват?
- Во сне ядро гаснет, но обвязка продолжает питаться от банки. Лечение — плата без лишних чипов и LED и замер мультиметром до всякой логики. Обвязка платы: USB-UART мост, стабилизатор, светодиод питания
- Почему для питания ESP32 с WiFi не годится CR2032?
- Ёмкость тут вторична: кнопочный элемент не умеет отдавать сотни миллиампер. Напряжение проседает в момент выхода в эфир — и плата перезагружается при каждой передаче. Она отдаёт единицы миллиампер, а передаче нужны пики 240-350 мА — плата уходит в коричневый сброс
- Период сна увеличили с 10 минут до часа, бодрствование те же 10 секунд по 120 мА. Что станет со средним током и прогнозом от 3000 мА·ч?
- (120×10 + 0,15×3590)/3600 ≈ 0,48 мА — сон занимает почти весь час. От 3000 мА·ч это 260 суток. Тот же скетч, одна строка периода. Около 0,5 мА и около 260 суток