Про Ардуино и не только

Для того чтобы перевести Ардуино в один из перечисленных режимов достаточно выполнить 2 функции: set_sleep_mode(mode) для задания конкретного режима и sleep_mode(). Они объявлены в файле sleep.h, поэтому он должен быть добавлен в секцию include вашего скетча.

Для указания режима используются константы:

  • SLEEP_MODE_IDLE
  • SLEEP_MODE_ADC
  • SLEEP_MODE_PWR_DOWN
  • SLEEP_MODE_PWR_SAVE
  • SLEEP_MODE_STANDBY
  • SLEEP_MODE_EXT_STANDBY

Пробуждение по сторожевому таймеру

В основе сторожевого таймера (WatchDog Timer) лежит многоразрядный счетчик, снабженный собственным тактовым генератором. Если таймер включен, то значение счетчика будет постоянно увеличиваться и при его переполнении будет сгенерирован сигнал сброса МК. Чтобы избежать сброса по переполнению программа должна постоянно обнулять счетчик специальной командой. Если программа зависла и счетчик не был вовремя сброшен, то сигнал сброса выведет МК из зависшего состояния, таким образом повышается стабильность системы на основе МК.

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

Здесь задается интервал сторожевого таймера и режим его работы для генерации прерываний через 2 секунды. После выполнения функции sleep_mode() Ардуино переходит в спящий режим. При генерации прерывания от сторожевого таймера и пробуждении МК, управление передается соответствующему обработчику (ISR (WDT_vect)). После его выполнения продолжится работа основной программы, т.е. выполнится следующая после sleep_mode() команда. Для задания значения предделителя сторожевого таймера можно использовать одну из следующих констант:

  • WDTO_15MS
  • WDTO_30MS
  • WDTO_60MS
  • WDTO_120MS
  • WDTO_250MS
  • WDTO_500MS
  • WDTO_1S
  • WDTO_2S
  • WDTO_4S
  • WDTO_8S

Пробуждение при нажатии кнопки

Пробуждение микроконтроллера при замыкании/размыкании контактов, будь то кнопка, геркон, энкодер и т.п. — это пробуждение по внешнему прерыванию (INT) или по прерыванию изменения уровня (PCINT). Для работы с первыми в IDE Arduino предусмотрены удобные функции. Для вторых ничего подобного в IDE нет, поэтому придется работать с регистрами микроконтроллера, отвечающими за настройку PCINT (хотя, наверняка, существуют библиотеки для работы с ними, я не искал). Для тех и других у меня есть подробные публикации с примерами использования: Прерывания в Ардуино. Часть 1, и Часть 2.

Предположим, что микроконтроллер в нашем устройстве должен всегда спать, просыпаться при нажатии кнопки, подключенной к входу запроса прерывания INT0, что-то делать и снова засыпать. Вход запроса прерывания (для INT0 — это вывод D2 Ардуино) должен быть подтянут к питанию или земле. Публикация про подтяжку в тему. Мы воспользуемся внутренними подтягивающими резисторами микроконтроллера. Кнопку установим между выводами D2 и Gnd. Простой скетч для ухода в сон и пробуждения при нажатии может быть таким:

Скетч содержит достаточно комментариев, я поясню лишь назначение цикла while. Все электромеханические коммутирующие устройства подвержены дребезгу контактов. В нашем случае дребезг на входе запроса прерывания будет воспринят микроконтроллером как многократное нажатие кнопки, в результате чего он будет выходить из спящего режима, выполнять заданный код и уходить в сон несколько раз подряд. Чтобы этого не происходило мы откладываем уход в сон до момента отпускания кнопки и возвращения сигнала на входе D2 к высокому уровню. Если сигнал остается высоким в течение 5 выборок с интервалом в 1мс, то считаем, что он стабилизировался и можно снова переводить микроконтроллер в режим энергосбережения.

Если добавить в схему аппаратное подавление дребезга, то можно обойтись без описанного цикла.

Пробуждение при нажатии кнопки, уход в сон по таймауту

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

Здесь уход микроконтроллера в сон возможен только при выполнении условия: разница между текущим значением millis() и значением переменной tm должно быть больше 10 секунд. Для того чтобы отложить сон, достаточно записать в tm значение millis(), что и делается при пробуждении и при нажатии на кнопку.

Также в данном примере отключается подсветка дисплея (текстовый дисплей типа 20*4 или 16*2) при переходе микроконтроллера в режим энергосбережения и включается при выходе из него. Сделано это в большей степени для демонстрации. В реальном же устройстве лучше отключать питание дисплея, поскольку он не имеет режима энергосбережения, а отключение подсветки уменьшит ток недостаточно — экономия должна быть экономной.

  • Аналого-цифровой преобразователь;
  • Аналоговый компаратор;
  • Детектор пониженного напряжения питания (Brown-Out Detector);
  • Внутренний источник опорного напряжения;
  • Сторожевой таймер;
  • Порты ввода-вывода;
  • Модуль внутрисхемной отладки.

В режиме Power Down продолжают работать АЦП и схема контроля питания. В приведенном скетче есть команды для их отключения. АЦП при необходимости потом можно будет включить установкой бита ADEN. Потребляемый Arduino Pro Mini ток с данным скетчем составил 136мкА.

Arduino Pro Mini режим энергосбережения

Я считаю, это неплохой результат по сравнению с начальными 15мА.

Чтобы уменьшить потребление еще больше, придется отказаться от использования плат Ардуино и перейти на использование "голых" микроконтроллеров. Оцените, например, потребление ATmega328P при тактировании от внутреннего RC генератора в этой статье.

Советую также посмотреть следующую мою статью об управлении режимами энергосбережения Ардуино — Библиотека Low-Power.


Источник: tsibrov.blogspot.com