Подписаться YouTube

Режим глубокого сна в ESP8266, WeMos, NodeMCU, ESP-01

Текст видео

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

В качестве примера в этом видео я буду использовать модуль WeMos d1 mini, потому что, на мой взгляд, это самая удобная реализация микроконтроллера ESP8266, и я обычно пользуюсь именно этим модулем. Материал в этом видео так же применим к другим модулям на базе микроконтроллера ESP8266. Таким как NodeMCU, ESP-01 и др.

Начну с теории. Микроконтроллер ESP8266, содержит в себе все необходимое для работы с Wi-Fi протоколом. Но Wi-Fi устройства по сравнению с другими беспроводными устройствами потребляют довольно много энергии. Если их подключить к литиево-ионному аккумулятору, например к 18650 с емкостью 3000 миллиампер*час, то они смогут работать непрерывно только несколько дней. Этого часто бывает недостаточно.

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

Другой задачей может быть датчик открытия двери, который должен что-то делать каждый раз, когда дверь открывается.

В этих случаях два дня автономной работы беспроводного устройства недостаточно. Конечно, хотелось бы, чтобы такие устройства работали дольше, чем несколько дней. Для этого и был придуман режим глубокого сна. Он позволяет периодически погружать устройство в режим пониженного энергопотребления.

В документации про этот режим написано, что переход в него осуществляется программно. С помощью вызова функции.

ESP.deepSleep(unsigned long sleepTime);

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

Выход из него осуществляется подачей LOW сигнала на контакт reset микроконтроллера. LOW сигнал это другими словами подключение RESET контакта к минусу питания.

Этот сигнал должен поступить с контакта D0. Поэтому контакт D0 и reset нужно соединить. По истечении заданного промежутка времени на контакт D0 будет подан сигнал LOW и микроконтроллер будет перезапущен.

В той же документации сказано, что в режиме глубокого сна все функции микроконтроллера будут выключены, за исключением RTC, т.е. часов реального времени. Часами реального времени они на самом деле называют тот таймер, что вызовет подачу LOW сигнала, а после и пробуждение микроконтроллера от глубокого сна. При этом в режиме глубокого сна Wi-Fi и процессор будут полностью выключены. Т.е. в режиме глубокого сна микроконтроллер ESP8266 ничего не делает и ни на что не реагирует, он может только ждать пробуждения.

Такое пробуждение аналогично нажатию на кнопку reset или кратковременному отключению питания. Оно начинается с вызова метода setup, а после выполнения цикла loop как при обычном включении микроконтроллера. Данные, которые хранятся в памяти, при этом, теряются. Если вам нужно сохранить какое-то состояние между циклами сна, то данные нужно будет сохранить в EEPROM память. Она энергонезависимая и естественно, что ее содержимое сохраняется. Если вам нужно будет получать точное время, то нужно будет использовать внешний модуль RTC с независимым питанием, либо при каждом пробуждении получать точное время из интернета. Счетчик миллисекунд millis сбрасывается при каждом пробуждении.

Реализация термометра при этом выглядит довольно просто. Нужно соединить D0 и reset проводом. В программе нужно каждый раз выполнять подключение к Wi-Fi и прочие настройки, затем, выполнять основную логику работы, а после отключаться от Wi-Fi и погружать микроконтроллер в сон снова. И так далее по кругу. Таким образом, энергопотребление можно будет существенно снизить, и на одной батареи устройство будет работать существенно дольше.

Схема термометра

В этой схеме мне бы хотелось проверить две вещи. Какой ток на самом деле будет потреблять устройство. И насколько точно работает таймер сна.

Для проверки тока потребления я включу амперметр в цепь питания на 5 вольт. И в цепь питания на 3,3 вольта. Модуль WeMos можно подключать к источнику питания как через контакты 5 вольт, так и через 3,3 вольта. Рабочее напряжение самого микроконтроллера ESP8266 составляет 3,3 вольта. И этот микроконтроллер очень требователен к этому напряжению. Его легко сжечь, если подать напряжение чуть выше. На входе в 5 вольт есть встроенный преобразователь напряжения ME6211. Про этот стабилизатор напряжения в документации сказано, что на вход он принимает напряжение от 2 до 6 вольт, а на выходе выдает 3.3 вольта, 0.5 А. А так же, что он имеет низкий ток энергопотребления, всего 40 мкА.

В качестве источника питания я буду использовать DC-DC преобразователь. Он позволяет получить стабильное напряжение с точностью до десятых долей вольта. Как раз то, что нужно.

Но вначале проверю, насколько точно работает мой цифровой амперметр. Буду использовать резистор на 10 кОм, и источник питания 3.3 Вольта. По закону Ома ток при этом должен быть 0.33 мА.

Все сошлось, значит мой мультиметр работает достаточно точно.

Ток в режиме глубокого сна по линии 3.3 вольта получился: 0.17 мА

Ток в режиме глубокого сна по линии 5 вольт у меня получился: 0.19 мА

Эти значения намного выше, чем обещанные в документации. Но все равно, в таком режиме одного аккумулятора 18650 хватит примерно на 2 года.

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

void setup() {  Serial.begin(74880);}void loop() {  Serial.println("WAKE UP!");  ESP.deepSleep(600e6);}

И включу отображение времени в консоли Arduino IDE. Питание будет происходить через micro USB порт.

Вот так выглядит лог работы этой нехитрой программы.

Лог работы программы

Перед сообщением WAKE UP! Есть несколько других строчек. Это какая-то информация о прошивке, которую сообщает ESP8266 каждый раз при пробуждении. Ее можно увидеть, если правильно выставить частоту обмена. В моем случае это 74880 бод. После идет сообщение “WAKE UP!” которое выводит программа, перед тем как заснуть.

Обработанные результаты этого лога выглядят вот так.

ВремяРазность, сек.Погрешность, %
16:33:38.385
16:42:49.804551,4198,10%
16:52:41.483591,6791,39%
17:02:33.946592,4631,26%
17:12:26.786592,841,19%
17:22:19.422592,6361,23%
17:32:11.986592,5641,24%
17:42:04.489592,5031,25%
17:51:57.444592,9551,17%
18:01:50.190592,7461,21%
18:11:43.227593,0371,16%
18:21:35.834592,6071,23%
18:31:28.473592,6391,23%
18:41:21.439592,9661,17%
18:51:14.042592,6031,23%
19:01:06.340592,2981,28%
19:10:59.021592,6811,22%
19:20:51.774592,7531,21%
19:30:44.475592,7011,22%
19:40:37.313592,8381,19%
19:50:30.082592,7691,21%
20:00:22.695592,6131,23%
20:10:15.315592,621,23%

Первый столбец это время вывода сообщения “WAKE UP!”. Второй разность между двумя ближайшими значениями. Третий погрешность в процентах. За 100% я принял 600 секунд. Видно, что вначале Микроконтроллер проспал на 8% меньше, а затем погрешность стала постоянной. Контроллер спал меньше на 1.2% чем надо.

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

Если вам нужно будет что-то делать строго через заданный промежуток времени, то это может стать настоящей проблемой. Одним из выходов может быть заранее, пробуждать контроллер получать точное время из внешних источников и делать паузу с помощью delay(), держа при этом микроконтроллер в состоянии бодрствования. Либо использовать какой-то более точный внешний таймер.

Об этой проблеме я знал давно. Мне попадались модули, купленные в разных магазинах на Aliexpress, и такая проблема была них во всех. Возможно, есть какие-то модули на базе ESP8266 в которых таймер глубокого сна работает точно, но мне такие не попадались.

Следующий пример, который я хочу рассмотреть это датчик открытия двери. В этом случае микроконтроллер должен просыпаться, когда дверь открывается, отправлять сообщение о том, что дверь открылась и вновь засыпать. В качестве датчика открытия двери я буду использовать переключатель. Когда дверь открывается, он будет подключать reset , к минусу питания, а когда закрывается, отключать. Микроконтроллер при этом будет отправлять некий отчет, а после бессрочно засыпать, до следующего открытия двери. Раз так, то reset подключать к D0 уже не обязательно.

Схема датчика открытия двери (неправильная)

На первый взгляд все просто, но такая схема будет работать не так, как это можно ожидать. Дело в том, что пока reset подключен к земле, микроконтроллер не работает. Об этом почему-то обычно забывают сказать. В таком состоянии ни одна из его функций не работает. Ток потребления при этом равен 24 мА.

Программа начнет выполняться только тогда, когда дверь закроют. Если ее конечно закроют.

В такой ситуации может возникнуть желание подключить переключатель наоборот. Чтобы reset был всегда замкнут, когда дверь закрыта и размыкался, как только дверь откроется. Но тогда никакого энергосбережения не получается. С закрытой дверью микроконтроллер будет потреблять все время 24 мА.

Что же делать? На самом деле есть несколько решений. Одно из них выглядит вот так.

Схема датчика открытия двери (неправильная)

Это схема инвертирующая работа переключателя, про которую я рассказывал в видео про умную шкатулку. Она подключена к переключателю очень странным образом. Такого подключения наверняка никто не поймет, если не объяснить. Дело в том, что в момент переключения есть очень короткий промежуток времени в течение которого средний контакт ни к чему не подключен. В этот момент база транзистора не будет подключена к земле, транзистор откроется и подаст короткий импульс, благодаря которому ESP8266 выйдет из глубокого сна.

Ток, который течет через резистор в 100 кОм, в этой схеме очень мал. Через такой резистор аккумулятор 18650 будет разряжаться больше 5 лет.

Но эту схему нужно проверить. Для проверки буду использовать вот такой код.

#define WEMOS_D4_LED 2void setup() {  Serial.begin(74880);}void loop() {  for (int i = 0; i <= 5; i++) {    digitalWrite(WEMOS_D4_LED, LOW);    delay(500);    digitalWrite(WEMOS_D4_LED, HIGH);    delay(500);  }  ESP.deepSleep(0);}

Во время пробуждения микроконтроллер будет мигать индикатором 6 раз, а после бессрочно засыпать.

В качестве транзистора я буду использовать IRFZ44N. Потому, что я давно закупился такими транзисторами как наиболее универсальными, и они у меня до сих пор не закончились.

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

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

Пора подводить итоги. Как видите с глубоким сном в WeMos не все так просто и безоблачно, как обычно об этом пишут. По-моему, режим глубокого сна в микроконтроллерах ESP8266 реализован кривовато и с ним часто приходится бороться, чтобы добиться желаемого эффекта. Теперь у вас должны сложиться более точные представления о нем. Возможно, это видео наведет вас на какие-то мысли, или новые идеи для своих самоделок.