Энергопотребление Arduino

Как известно, микроконтроллеры ATmega (а соответственно и Arduino) имеют различные режимы энергосбережения. Некоторые из них отключают только некоторые неиспользуемые компоненты микроконтроллера (ADC, SPI, TWI, USART и т.д.). Некоторые — полностью вводят процессор в режим сна, из которого его можно вывести либо по таймеру, либо по внешнему прерыванию. Применение этим режимам можно найти в устройствах, питающихся автономно от батарей (возможно напишу об этом более подробно в одной из статей). А пока я решил просто измерить энергопотребление Arduino в каждом из режимов.

Для экспериментов использовалась Freeduino Through-Hole — аналог Arduino Diecimila. Напряжение подавалось от стабилизированного источника питания 5 вольт.

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

void setup()
{
  while (1) {}
}
 
void loop()
{
 
}

Теперь загрузим микроконтроллер работой, а именно — заставим его вычислять простые числа.

long i = 1000000; //начинаем с миллиона
 
void setup()
{
 
}
 
long found = 0;
 
void loop()
{
  is_prime(i);
  i++;
}
 
int is_prime(long num) {
  int upper = sqrt(num);
 
  for (long cnum = 2; cnum <= upper; cnum++)
  {
    long mod = num % cnum;
 
    if (mod == 0)
    {
      //not simple
      return 0;
    }
  }
  //simple
  return 1;
}

Сила тока немного возрасла:

Теперь переходим собственно к режимам энергосбережения. Итак, первый режим — понижение тактовой частоты. Данный скетч демонстрирует перевод микроконтроллера на пониженную частоту работы = 62.5 КГц (штатная = 16 МГц). При этом скорость работы резко замедляется, а потребление энергии уменьшается, что видно по графику.

void setup() 
{
	delay(10000);
	pinMode(13, OUTPUT);
	noInterrupts();
	CLKPR = 1<<CLKPCE;
	CLKPR = 8;
	interrupts();
}
 
void loop() 
{
	digitalWrite(13, HIGH);
	delay(50);
	digitalWrite(13, LOW);
	delay(50);
}

Замерим ток, когда светодиод на 13 выводе погашен:

Теперь код, который не изменяет скорости работы, но может полностью приостановить любую деятельность процессора, до наступления определённого события:

/*
5 режимов энергосбережения:
SLEEP_MODE_IDLE
SLEEP_MODE_ADC
SLEEP_MODE_PWR_SAVE
SLEEP_MODE_STANDBY
SLEEP_MODE_PWR_DOWN
*/
 
#include <avr/sleep.h>
extern volatile unsigned long timer0_millis;
void setup() 
{
	pinMode(13, OUTPUT);
	interrupts();
}
void loop() 
{
	while(timer0_millis < 5000) {
		set_sleep_mode(SLEEP_MODE_IDLE); // выбор режима
		sleep_mode(); // уходим в спячку
	}
	timer0_millis = 0; // сброс счётчика
	bitSet(PINB, 5);   // переключение светодиода
}

SLEEP_MODE_IDLE:

SLEEP_MODE_ADC:

SLEEP_MODE_PWR_SAVE:

SLEEP_MODE_STANDBY:

SLEEP_MODE_PWR_DOWN:

И теперь график этих 5 режимов:

Сводная таблица:

РежимСила тока, миллиампер
Пустой цикл22.68
Простые числа23.81
Снижение частоты14.45
SLEEP_MODE_IDLE17.52
SLEEP_MODE_ADC15.29
SLEEP_MODE_PWR_SAVE12.82
SLEEP_MODE_STANDBY12.79
SLEEP_MODE_PWR_DOWN11.69

Как мы видим, энергопотребление Arduino в различных режимах может различаться более чем в два раза, что в некоторых случаях позволяет экономить заряд батарей в автономных устройствах. К сожалению не все режимы возможно применить в большинстве устройств, так как некоторые из них переводят микропроцессор в «глубокий сон» из которого его можно вывести лишь внешними «раздражителями» — прерываниями. Для создания электронных часов вполне можно использовать понижение частоты, иногда повышая её для чтения данных из RTC и обновления показаний.