Энергосбережение и сон


У вас наверняка есть настольные часы-будильник с датчиком температуры и влажности, которые работают на двух пальчиковых батарейках уже не первый год и даже не планируют разряжаться. В то же время, если подключить плату Ардуино к “паурбанку” на 10 Ампер*часов, она высосет его за две недели. Как же так вышло?!

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

  • Правильно подобрать источник питания по напряжению.
  • Минимизировать и оптимизировать потребление пассивных компонентов (стабилизаторы напряжения, светодиоды индикации, делители напряжения и т.д.).
  • Задать оптимальный режим работы устройства и отдельных его частей: максимальное энергосбережение бОльшую часть времени работы, пробуждение по внешним событиям или таймеру, работа различных компонентов по расписанию и т.д. Например: опрос датчика и отправка данных по радио раз в минуту, всё остальное время – максимальный сон МК и отключение датчика и радио от питания.
  • Что касается сна самого МК – спать можно при помощи встроенных команд (например ассемблерной asm("sleep") или sleep_mode() из avr/sleep.h), а можно использовать библиотеки. Например есть стандартная avr/sleep.h, которая идёт в комплекте со средой разработки. Из нестандартных есть весьма популярные Narcoleptic и Low-Power, имеющие гораздо бОльшие возможности по настройке сна. Мы сделали свою библиотеку для управления энергосбережением МК – GyverPower, которая включает в себя удобное управление сном и энергопотреблением МК на всех уровнях (сон, управление частотой и периферией), а также встроенный калибровщик сторожевого таймера и несколько уникальных фишек, которых нет ни в каких других библиотеках. В данном уроке я буду ссылаться именно на неё, с полной документацией можно ознакомиться здесь.
  • Также потребление МК сильно зависит от частоты. Можно понижать частоту между периодами активной работы (вычислений, работы с датчиками), об этом читай ниже.

Вольты, амперы, ёмкость


Начнем с базовых понятий мира электричества: Вольты и Амперы (более подробно про это читай в этом уроке). Вольты – напряжение, оно же разность потенциалов. Напряжение задаёт источник питания, например батарейка или блок питания. Амперы – сила тока в цепи, показывает с какой силой “расходуется” электрическая энергия. Ток в цепи задаёт потребитель. (Примечание: описанное выше справедливо для источника напряжения, коим является любая батарейка/аккумулятор или обычный блок питания. Источником тока может быть специальное зарядное устройство или светодиодный драйвер, от них питать предназначенную для источника напряжения схему нельзя – сразу сгорит).

Потребляемую и запасаемую энергию принято считать в Ампер*часах, работает это следующим образом: допустим, ёмкость аккумулятора составляет 1 А*ч (Ампер*час). Это означает, что такой аккумулятор сможет отдавать ток с силой 1 Ампер в течение одного часа, полностью при этом разрядившись. Если ток в цепи будет 0.5 А – аккумулятора хватит на 1 А*ч / 0.5 А == 2 часа. Плата Ардуино потребляет в районе 24 мА, то есть тот же условный аккумулятор сможет питать её в течение 1000 мА*ч /24 мА ~ 42 часов. При параллельном подключении потребителей, как это обычно бывает в схеме, ток потребления суммируется. Если добавить в “схему” из предыдущего расчёта дисплей с подсветкой, который будет потреблять условно ещё 30 мА, то такая схема проработает от того же аккумулятора 1000 мА*ч / (24+30 мА) ~ 18.5 часов. 

Потребление компонентов схемы


Если в устройстве помимо МК есть какие-то другие модули/датчики/дисплеи/микросхемы, то больший вклад в потребление энергии будут вносить именно они, потому что МК можно погрузить в сон, а их – не всегда. Логично, что для максимальной экономии энергии нужно держать все компоненты в полностью отключенном состоянии и включать только на период активной работы: датчики – на время опроса, дисплеи и подсветки – на время взаимодействия с человеком, и тому подобное.

  • Некоторые железки имеют очень удобный пин EN – enable, позволяющий логическим уровнем с МК полностью включать и выключать компонент, что позволяет очень просто управлять его состоянием.
  • Некоторые микросхемы имеют встроенный режим энергосбережения, который можно активировать из программы (например, передав нужную команду по интерфейсу связи). Информацию нужно искать в даташите или библиотеке на конкретную железку.
  • Если таких возможностей у железки нет – всегда можно просто разорвать ей питание при помощи транзистора или оптопары. Электромеханическое реле использовать не рекомендуется, т.к. оно само потребляет приличный ток.
  • Маломощные (до 20 мА) компоненты можно питать напрямую от пинов МК, что ещё больше упрощает задачу по управлению питанием. Примечание: у “Ардуиновских” AVR весьма приличный запас по току – в районе 40 мА на пин, но на таком токе напряжение просаживается и работа “железки” может стать нестабильной, поэтому не рекомендуется подключать на пин нагрузку выше 20 мА. К слову, у других процессоров (STM32, esp8266) максимальный ток с пинов на порядок ниже (2-5 мА) и что-то от них питать в принципе невозможно.
  • Большинство “интерфейсных” микросхем при сбросе питания будут требовать повторной инициализации. У того же например lcd дисплея после отключения и включения питания нужно вызвать метод .init(), чтобы дисплей начал реагировать на остальные команды.

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

Потребление платы Ардуино


Честно говоря, сам микроконтроллер может работать абсолютно самостоятельно просто при наличии питания, а смена режима сна или частоты будет влиять на потребление ровно так, как написано в даташите. Если в основе проекта лежит плата ардуино – начинаем загибать пальцы: светодиоды индикации, стабилизатор питания и usb-ttl преобразователь – все они потребляют ток в холостом режиме, просто потому что они сидят на общем питании. Плата Nano в активном режиме потребляет около 24 мА, а если погрузить МК в максимальный сон – в районе 5 мА. В то же время по даташиту МК в таком режиме должен потреблять в районе 1 мкА, то есть в 5000 (пять тысяч) раз больше!!! Эти самые 5 мА потребляют перечисленные выше компоненты на плате ардуино, поэтому для создания действительно энергоэффективного проекта нужно делать свою плату и паять на неё МК, либо брать скальпель/паяльник и убирать лишнее с платы Ардуино.

Потребление МК

Частота тактирования


Вычислительное ядро потребляет энергию всегда, когда находится в активном режиме: вычисляет ли программа арккосинус, ожидает ли окончание задержки delay(), висит ли в бесконечном пустом for(;;) – неважно. Потребление будет одинаковым во всех случаях, пока ядро тактируется. Более того, от частоты тактирования зависит напряжение, при котором МК гарантированно стабильно работает. Вот картинки из даташита на ATmega328:

 

На самом деле всё как обычно слегка “завышено”, потому что на 16 МГц клоке Ардуино прекрасно работает начиная от 3.3V, а на 8 МГц (внутреннем) – от 1.8V (при отключенном BOD). Есть четыре уровня управления тактовой частотой:

  • Подключение внешнего кварца с нужной частотой (на плате Ардуино стоит 16 МГц, сам МК поддерживает вплоть до 20 МГц без разгона).
  • Выбор источника тактирования при помощи фьюзов: внешний (частота соответствует установленному генератору) и внутренний (8 МГц).
  • Изменение системной частоты прямо из программы: большинство МК avr позволяют понизить приходящую с источника тактирования частоту, а именно – поделить (реализовано в GyverPower). Таким образом можно замедлить работу всего МК для уменьшения потребления энергии или увеличения стабильности работы от пониженного напряжения. Можно выполнить необходимые действия на высокой частоте, а затем понизить её до минимума до наступления внешних событий по прерываниям или по таймеру. На некоторых МК есть PLL – умножитель частоты (например на Attiny85), позволяющий тактироваться на частоте 36 МГц от внутреннего источника! Для такого разгона придется поднять напряжение и обеспечить теплоотвод, но об этом не в этом уроке =).
  • Фьюз CKDIV8: системный делитель из предыдущего пункта автоматически устанавливается на 8 перед запуском МК. Это нужно для более надёжного старта при низком напряжении. Обычно используют так: МК стартует с CKDIV8 на пониженной частоте, измеряет напряжение питания, если оно достаточно высокое (аккумулятор не разряжен) частота выставляется на необходимую и работа продолжается. Иначе например можно всё вырубить и уйти в сон.

Также прилагаю картинку с графиками тока потребления МК в активном режиме (не во сне) в зависимости от частоты и напряжения питания:

Режимы энергосбережения


У микроконтроллера есть несколько режимов энергосбережения, в каждом из которых остаются в активном режиме только некоторые из аппаратных блоков (таймеры, интерфейсы, АЦП, и т.д.). Также у мк есть блок BOD, отвечающий за постоянный мониторинг напряжения и перезагрузку в случае его падения ниже настроенного порога. Во всех режимах сна остаётся активен АЦП, его нужно отключать отдельно (всё реализовано в GyverPower). Режимы энергосбережения МК (AVR):

  • IDLE – Легкий сон, отключается только клок CPU и Flash, пробуждается мгновенно от любых прерываний
  • POWERDOWN – Наиболее глубокий сон, отключается всё кроме WDT и внешних прерываний, просыпается от аппаратных (обычных + PCINT) или WDT, пробуждение за 1000 тактов (62 мкс)
  • STANDBY – Глубокий сон, идентичен POWERDOWN + system clock активен, пробуждение за 6 тактов (0.4 мкс)
  • POWERSAVE – Глубокий сон, идентичен POWERDOWN + timer 2 активен (+ можно проснуться от его прерываний), можно использовать для счета времени
  • EXTSTANDBY – Глубокий сон, идентичен POWERSAVE + system clock активен, пробуждение за 6 тактов (0.4 мкс)

Самый часто используемый на практике режим – power down, самый глубокий сон. В нём отключается всё, кроме watchdog и аппаратных прерываний (обычные external и PCINT). В данном режиме МК потребляет минимальный ток (ATmega328 – чуть меньше 1 мкА), а проснуться можно только по прерыванию Watchdog таймера или по аппаратному прерыванию (по кнопке). Очевидно, что в глубоком сне не работают таймеры и прерывания по ним, поэтому счёт времени становится отдельной задачей (в GyverPower эта задача решена максимально удобно).

Периферия


Помимо главного “ядра” у микроконтроллера есть куча периферийных блоков (АЦП, компаратор, таймеры, интерфейсы связи), которые по сути работают отдельно и могут общаться с МК на аппаратном уровне. Каждый блок потребляет некоторый ток, и при желании некоторые блоки можно отключить. В режиме глубокого сна они отключаются автоматически, а вот в активной работе нужно отключить их вручную. Большую таблицу с потреблением МК в разных режимах и с разным набором активной периферии можно посмотреть на официальной странице библиотеки Low Power, на всякий случай приложу её ниже. Управление периферией также реализовано в GyverPower.

Измерения проводились на 8 МГц плате Pro Mini при питании от Li-Ion аккумулятора (3.7V):

Питание

Источник питания


Выбор источника питания очень важен для эффективного энергосбережения: максимально желательно питать МК напрямую от батарейки/аккумулятора:

  • Трёх-четырёх АА/ААА батареек или аккумуляторов достаточно для работы на стандартной частоте 16 МГц (с 4-мя батарейками нужно быть аккуратнее по суммарному напряжению, а 4 никелевых аккумулятора подходят идеально).
  • От одного литиевого аккумулятора (3.7-4.2V) можно работать на 16 МГц, но при разряде ниже 3.5V работа на такой частоте уже может быть не очень стабильной (частоту можно чуть понизить, об этом ниже).
  • От литиевой 3V таблетки (CR2025, CR2032 и прочие) микроконтроллер отлично будет работать на внутреннем 8 МГц клоке.
  • Плохим вариантом можно считать ситуации, когда приходится использовать понижающие преобразователи и стабилизаторы: они все будут тратить несколько миллиампер “в тепло”, и даже режим сна МК может оказаться абсолютно бессмысленным. Но в любой ситуации нужно считать потребление и прикидывать время работы, для каких-то задач и работа от “Кроны” через стабилизатор будет приемлемой во имя упрощения схемы и стабильных 5 Вольт (китайский транзистор-тестер, например, включается на несколько секунд, поэтому заморочек по питанию нет).
  • Если в устройстве используется аккумуляторная батарея, то можно схитрить: высоковольтный потребитель (мотор к примеру) может питаться от общего напряжения с батареи через драйвер, а микроконтроллер может работать от одной его “банки”, соединяясь общим проводом с минусом. Микроконтроллер, особенно в режиме сна, потребляет ничтожно мало по сравнению с тем же мотором, поэтому о разбалансировке банок можно не беспокоиться. Таким образом МК также может мониторить напряжение батареи и отключать её при разряде, выполняя роль BMS. Про измерение напряжения мы говорили в уроке про аналоговые входы.
  • Также напомню, что питать всякие железки напрямую от МК можно только в некоторых пределах, подробнее о них и вообще питании проекта мы говорили в уроке о питании Ардуино и схемы в целом.

Самоблокировка питания


Самый надёжный и аппаратно простой способ сэкономить энергию – самоблокировка питания. Он подходит для устройств, которые включаются тактовой кнопкой (без фиксации) и через некоторое время должны сами отключиться до следующего клика по кнопке. Самоблокировка работает следующим образом: нажатие на кнопку подаёт ток на МК, он запускается, подаёт сигнал на “ключ”, который запараллеливает линию питания. Мы отпускаем кнопку, а МК продолжает работать, потому что сам удерживает ключ, через который идёт питание. Отсюда и название: самоблокировка питания. По тайм-ауту или другому алгоритму работы МК может отпустить ключ и отключиться. Через этот же ключ могут питаться и остальные железки, и точно так же быть отключены от питания при самовыключении.

Проблема в том, что МК от AVR могут питаться от любого GPIO пина (при наличии общей GND), поэтому практически все старые схемы из интернета не работают. Пока что удалось найти две схемы на форуме arduino, но лично я их не тестировал. В будущем дополню урок.

Но есть шикарный, простой и рабочий вариант: использовать стабилизатор напряжения с пином Enable, за который МК может “заблокировать” себе питание (за идею спасибо Дмитрию Карманову). Вот пример со стабилизатором me6212c33m5g на 3.3V (стоит в районе 15 руб). На схеме PWR_EN ведёт на физическую кнопку, подключенную второй ногой к питанию (батарейке), BUT_MK идёт на пин МК, который будет подавать высокий сигнал при запуске. 3V3 соответственно линия 3.3 (от неё питается сам МК и опционально что-то ещё), и BAT – батарейка.

Важные страницы