Программируем Arduino. Основы работы со скетчами
Шрифт:
Отключает таймер 2
power_all_disable
Отключает все компоненты, перечисленные выше
Энергосберегающий режим
Самый действенный способ экономии электроэнергии — перевести плату Arduino в спящий режим на время, пока она не совершает полезной работы.
Narcoleptic
Питер Кнайт создал простую в использовании библиотеку с названием Narcoleptic, которую можно получить по адресу https://code.google.com/p/narcoleptic/.
Очевидно,
Библиотека Narcoleptic предоставляет альтернативную функцию delay, которая переводит Arduino в энергосберегающий режим на время, указанное в вызове delay. Поскольку в ходе задержки все равно ничего не происходит, этот метод действует блестяще.
Например, вернемся к старому доброму скетчу Blink. Следующий скетч включает светодиод на 1 с, затем выключает его на 10 с и повторяет эту последовательность до бесконечности:
// sketch_05_03_blink_standard
void setup
{
pinMode(13, OUTPUT);
}
void loop
{
digitalWrite(13, HIGH);
delay(1000);
digitalWrite(13, LOW);
delay(10000);
}
Ниже показана версия того же скетча, использующая библиотеку Narcoleptic:
// sketch_05_04_narcoleptic_blink
#include <Narcoleptic.h>
void setup
{
pinMode(13, OUTPUT);
}
void loop
{
digitalWrite(13, HIGH);
Narcoleptic.delay(1000);
digitalWrite(13, LOW);
Narcoleptic.delay(10000);
}
Единственное отличие этой версии в том, что она импортирует библиотеку Narcoleptic и использует ее версию функции delay вместо стандартной.
Запустив оба скетча на плате Mini Pro, питающейся напряжением 5 В и действующей на частоте 16 МГц, я выяснил, что для первого скетча в момент, когда светодиод выключен, потребляемый ток составил 17,2 мА. Для версии с библиотекой Narcoleptic потребляемый ток уменьшился до 3,2 мА, из которых большую часть потребляет светодиод On (около 3 мА), то есть, если его выпаять, средний потребляемый ток должен упасть ниже 1 мА.
Микроконтроллер очень быстро переходит в энергосберегающий режим, поэтому, если в вашем проекте имеется кнопка, нажатие на которую вызывает некоторые действия, нет необходимости использовать внешнее прерывание, чтобы вывести микроконтроллер из энергосберегающего режима. Можно написать код (что, возможно, проще), который будет переводить плату Arduino в энергосберегающий режим и выводить ее обратно 10 раз в секунду, проверять нажатие кнопки, сравнивая цифровой вход со значением HIGH, и затем выполнять какие-то операции вместо возврата в энергосберегающий режим. Следующий скетч демонстрирует, как это можно реализовать:
// sketch_05_05_narcoleptic_input
#include <Narcoleptic.h>
const int ledPin = 13;
const int inputPin = 2;
void setup
{
pinMode(ledPin, OUTPUT);
pinMode(inputPin, INPUT_PULLUP);
}
void loop
{
if (digitalRead(inputPin) == LOW)
{
doSomething;
}
Narcoleptic.delay(100);
}
void doSomething
{
for (int i = 0; i < 20; i++)
{
digitalWrite(ledPin, HIGH);
Narcoleptic.delay(200);
digitalWrite(ledPin, LOW);
Narcoleptic.delay(200);
}
}
Во время выполнения этого скетча плата Mini Pro, питающаяся напряжением 5 В и действующая на частоте 16 МГц, потребляла мизерные 3,25 мА, ожидая, пока что-то произойдет. После замыкания контакта 2 на «землю» светодиод L мигнул 20 раз, но, так как для задержки между включением и выключением светодиода скетч использует все ту же версию delay из библиотеки Narcoleptic, потребляемый ток увеличился в среднем всего лишь до 4–5 мА.
Если изменить вызов delay внутри функции loop, чтобы выводить Arduino из энергосберегающего режима, скажем, 100 раз в секунду, потребляемый ток увеличится, потому что для перевода Arduino в энергосберегающий режим действительно требуется некоторое время. Однако задержка на 50 мс (20 раз в секунду) дает довольно хорошие результаты.
Вывод из энергосберегающего режима внешними прерываниями
Только что описанный подход можно с успехом использовать в разных ситуациях, однако если требуется получить более быстрый отклик на внешнее событие, можно реализовать вывод микроконтроллера из энергосберегающего режима с помощью внешнего прерывания.
Чтобы переделать предыдущий пример и использовать контакт D2 как приемник внешних прерываний, требуется приложить дополнительные усилия, но результаты получаются немного лучше, так как отпадает необходимость периодически проверять состояние контакта. Код скетча получился сложным, поэтому сначала я покажу сам код, а потом расскажу, как он работает. Если вы пропустили главу 3 о прерываниях, то вам стоит прочитать ее перед изучением примера.
// sketch_05_06_sleep_external_wake
#include <avr/sleep.h>
const int ledPin = 13;
const int inputPin = 2;
volatile boolean flag;
void setup
{
pinMode(ledPin, OUTPUT);
pinMode(inputPin, INPUT_PULLUP);
goToSleep;
}
void loop
{
if (flag)
{
doSomething;
flag = false;
goToSleep;
}
}
void setFlag
{
flag = true;
}
void goToSleep
{
set_sleep_mode(SLEEP_MODE_PWR_DOWN);