Предыдущая статья.

Ардуино. Энергосбережение.


Навеяно (вольный перевод) статьёй Nick Gammon:
This page can be quickly reached from the link: http://gammon.com.au/power

В первой части статьи говорится, что сам по себе процессор, без обвязки (макетной платы, ардуино) за счет отсутствия светодиодных индикаторов, линейного стабилизатора питания и т.п., потребляет ощутимо меньше. Тут - не поспоришь...

Уровни энергосбережения.


Различные режимы "сна" могут быть включены инструкцией:
 set_sleep_mode (SLEEP_MODE_PWR_DOWN);  
По энергопотреблению режимы "сна" делятся на:

Power-save mode оставляет работающим Timer 2 (providing clocked from an external source).
Stand-by mode похожа power-down mode, за исключением того, что продолжает работать генератор. Это позволяет микросхеме быстрее выходить из режима "сна".
Note: В IDLE mode внутренний тактовый генератор продолжает работать. Это означает, что (если мы не запретим) будет работать timer0, используемый для обеспечения счетчика millis(), и таким образом микросхема будет просыпаться примерно каждую миллисекунду.

Запрет Brown-out.


В режиме SLEEP_MODE_PWR_DOWN с отключенным brown-out, потребление снижается с 360 uA to 335 uA, что позволяет сэкономить 25 uA (микро-ампер).

Brown-out Detector (BOD) - встроенная в ATmega подсистема, следящая за уровнем питания чипа, и выключенная по-умолчанию в Arduino. В момент подачи питания на схему происходит масса переходных процессов: возрастает напряжение питания, разгоняется резонатор. Необходимо дождаться их стабилизации, прежде чем начинать выполнение инструкций, иначе поведение МК может быть непредсказуемым. Для нейтрализации этого эффекта применяют стандартные схемы - т.н. "супервизоры" питания, которые следят за уровнем входного напряжения и удерживают (или подают) сигнал сброса контроллера до тех пор, пока оно не достигнет нормального уровня.
В промышленных разработках, особенно при работе со встроенной в AVR eeprom, Brown-out Detector должен быть включен.

BOD может быть выключен постоянно программированием соответствующих фьюзов в AVRdude:
avrdude -c usbtiny -p m328p -U efuse:w:0x07:m
или временно (до перезагрузки) - из кода программы:

Sketch C

Команда sleep_cpu() должна следовать сразу за вышеприведенными битовыми инструкциями, иначе Brown-out Detector снова включится.
#include  <avr/sleep.h>

void setup () 
 {
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);  
  sleep_enable();

  // turn off brown-out enable in software
  MCUCR = bit (BODS) | bit (BODSE);  // turn on brown-out enable select
  MCUCR = bit (BODS);        // this must be done within 4 clock cycles of above
  sleep_cpu ();              // sleep within 3 clock cycles of above
 }  // end of setup

void loop () { }

Выключение ADC (analog to digital conversion)


Отключение подсистемы аналого-цифрового преобразования (в SLEEP_MODE_PWR_DOWN) приводит к тому, что потребляемая мощность падает с 335 uA до 0.355 uA!
 // disable ADC
 ADCSRA = 0;

Конфигурация портов ввода-вывода


В зависимости от конфигурации портов ввода-вывода потребление в режиме сна тоже может быть разным.

Sketch D


#include <avr/sleep.h>

void setup () 
{

  for (byte i = 0; i <= A5; i++)
      {
       pinMode (i, OUTPUT);    // changed as per below
       digitalWrite (i, LOW);  //     ditto
      }

      // disable ADC
      ADCSRA = 0;  

      set_sleep_mode (SLEEP_MODE_PWR_DOWN);  
      sleep_enable();

      // turn off brown-out enable in software
      MCUCR = bit (BODS) | bit (BODSE);
      MCUCR = bit (BODS); 
      sleep_cpu ();  

}  // end of setup

void loop () { }


Результаты тестирования в режиме SLEEP_MODE_PWR_DOWN:
Note: При этом к портам ничего не было подключено. Если у Вас имеется работающий LED или что-то еще - потребление будет выше.


Power Reduction Register (PRR)



Using the internal clock



Пробуждение из режима "сна" по WatchDog таймеру.


Note:Прежде, чем начать эксперименты, полезно проверить: правильно ли обрабатывает bootloader ардуины перезагрузку. Хорошая статья на эту тему: http://habrahabr.ru/post/189744/

Тестирование на watchdog
#include <avr/wdt.h>

void setup() {
  wdt_disable(); // бесполезная строка до которой не доходит выполнение при bootloop
  Serial.begin(9600);
  Serial.println("Setup..");

  Serial.println("Wait 5 sec..");
  delay(5000); // Задержка, чтобы было время перепрошить устройство в случае bootloop
  wdt_enable (WDTO_8S); // Для тестов не рекомендуется устанавливать значение менее 8 сек.
  Serial.println("Watchdog enabled.");
 }

int timer = 0;

void loop(){
  // Каждую секунду мигаем светодиодом и значение счетчика пишем в Serial
  if(!(millis()%1000)){
  timer++;
  Serial.println(timer);
  digitalWrite(13, digitalRead(13)==1?0:1); delay(1);
  }
  //  wdt_reset();
}
/*
Если после перезагрузки светодиод на 13-м пине начинает бесконечно мигать, то значит 
загрузчик не поддерживает watchdog. Здесь даже кнопка сброса не поможет. Для последующей 
прошивки нужно плату отключать от питания и после включения успеть прошить до первой перезагрузки.
*/


Судя по даташиту, у процессора есть два состояния WDT:
System Reset - ресет при первом же удобном случае (по-умолчанию),
Interrupt and System Reset - при первом срабатывании WatchDog таймер формирует и отрабатывает прерывание, после чего бит WDIE сбрасывается в ноль, и (если бит WDIE не был повторно взведен скетчем) на второй раз - ресет. С точки зрения безопасности - не рекомендуется (повторно) взводить бит WDIE в процедуре обработки прерывания.

Sketch H


#include  <avr/sleep.h>
#include  <avr/wdt.h>

const byte LED = 9;

void flash ()
  {
  pinMode (LED, OUTPUT);
  for (byte i = 0; i < 10; i++)
    {
    digitalWrite (LED, HIGH);
    delay (50);
    digitalWrite (LED, LOW);
    delay (50);
    }
    
  pinMode (LED, INPUT);
    
  }  // end of flash
  
// watchdog interrupt
ISR (WDT_vect) 
{
   wdt_disable();  // disable watchdog
}  // end of WDT_vect
 
void setup () { }

void loop () 
{
 
  flash ();
  
  // disable ADC
  ADCSRA = 0;  

  // clear various "reset" flags
  MCUSR = 0;     
  // allow changes, disable reset
  WDTCSR = bit (WDCE) | bit (WDE);
  // set interrupt mode and an interval 
  WDTCSR = bit (WDIE) | bit (WDP3) | bit (WDP0);    // set WDIE, and 8 seconds delay
  wdt_reset();  // pat the dog
  
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);  
  sleep_enable();
 
  // turn off brown-out enable in software
  MCUCR = bit (BODS) | bit (BODSE);
  MCUCR = bit (BODS); 
  sleep_cpu ();  
  
  // cancel sleep as a precaution
  sleep_disable();
  
  } // end of loop

Немного модифицированный пример показывает, как Вы можете проснуться, мигнуть на секунду светодиодом (approximately), после чего погрузиться в сон до следующего раза. Здесь используется свойство "WDTCSR Bit 6 - WDIE: Watchdog Interrupt Enable", т.е. при установке этого бита в "единицу" первое срабатывание WatchDog будет просто вызывать прерывание а не ресетить процессор: разница в точке, с которой продолжается работа скетча.

Sketch I


#include  <avr/sleep.h>
#include  <avr/wdt.h>

const byte LED = 9;
  
// watchdog interrupt
ISR (WDT_vect) 
{
   wdt_disable();  // disable watchdog
}  // end of WDT_vect
 
void setup () { }

void loop () 
{
 
  pinMode (LED, OUTPUT);
  digitalWrite (LED, HIGH);
  delay (50);
  digitalWrite (LED, LOW);
  pinMode (LED, INPUT);
  
  // disable ADC
  ADCSRA = 0;  

  // clear various "reset" flags
  MCUSR = 0;     
  // allow changes, disable reset
  WDTCSR = bit (WDCE) | bit (WDE);
  // set interrupt mode and an interval 
  WDTCSR = bit (WDIE) | bit (WDP2) | bit (WDP1);    // set WDIE, and 1 second delay
  wdt_reset();  // pat the dog
  
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);  
  sleep_enable();
 
  // turn off brown-out enable in software
  MCUCR = bit (BODS) | bit (BODSE);
  MCUCR = bit (BODS); 
  sleep_cpu ();  
  
  // cancel sleep as a precaution
  sleep_disable();
  
  } // end of loop

PR-CY.ru
Еще статьи.