ЭНЕРГОПОТРЕБЛЕНИЕ МИКРОКОНТРОЛЛЕРА

Энергопотребление электронного устройства складывается из нескольких факторов:

  • Режим работы МК
  • Частота тактирования МК
  • Напряжение питания МК
  • Состояние периферии МК (вкл/выкл)
  • Состояние/потребление внешних устройств

Если управление внешними устройствами ложится на плечи разработчика железа (транзисторы по питанию и проч.), то управление энергопотреблением МК осуществляется прямо из программы!

БИБЛИОТЕКА GYVERPOWER

GyverPower – библиотека для расширенного управления энергопотреблением микроконтроллера

  • Управление системным клоком
    • Функции времени (millis/delay) корректируются под выбранный клок
  • Включение/выключение периферии:
    • BOD
    • Таймеры
    • I2C/UART/SPI
    • USB
    • ADC
  • Сон в разных режимах:
    • IDLE_SLEEP – отключается только CPU и Flash
    • ADC_SLEEP – автоматически начинает преобразование при уходе в сон, отключается CPU и system clock
    • POWERDOWN_SLEEP – отключается всё, кроме WDT и внешних прерываний, относительно долгий выход из сна
    • POWERSAVE_SLEEP – аналог power down, но timer 2 остается активным, можно использовать для счета времени
    • STANDBY_SLEEP – аналог power down, но system clock остается активен, быстрый выход из сна, большее потребление
    • EXTSTANDBY_SLEEP – аналог standby, но timer 2 остается активным, можно использовать для счета времени
  • Сон на любой период
    • Калибровка таймера для точных периодов сна
  • Разработано by Egor ‘Nich1con’ Zaharov

Поддерживаемые платформы: платы на основе ATmega2560/32u4/328 и ATtiny85/84/167

ДОКУМЕНТАЦИЯ


void hardwareEnable(uint16_t data);         // Включение указанной периферии (см. ниже "Константы периферии")
void hardwareDisable(uint16_t data);        // Выключение указанной периферии (см. ниже "Константы периферии")
void setSystemPrescaler(uint8_t prescaler); // Установка делителя системной частоты (см. ниже "Константы делителя")
void bodInSleep(bool en);                   // Brown-out detector в режиме сна [вкл-выкл] [true - false]
void setSleepMode(uint8_t mode);            // Установка текущего режима сна (см. ниже "Режимы сна")
void autoCalibrate(void);                   // автоматическая калибровка таймера сна, выполняется 2 секунды
uint16_t getMaxTimeout(void);               // возвращает реальный период 8с, выполняется 8 секунд
void calibrate(uint16_t ms);                // калибровка тайм-аутов watchdog для sleepDelay [ввести макс период из getMaxTimeout]
void sleep(uint8_t period);                 // Переход мк в режим сна (см. ниже "Периоды сна")
uint8_t sleepDelay(uint32_t ms);            // сон на произвольный период (до 52 суток)
/* ======== РЕЖИМЫ СНА ========
IDLE_SLEEP          - Легкий сон , отключается только CPU и Flash
ADC_SLEEP           - Легкий сон , автоматически начинает преобразование при уходе в сон, отключается CPU и system clock
POWERDOWN_SLEEP     - Наиболее глубокий сон, отключается все, кроме WDT и внешних прерываний,относительно долгий выход из сна
STANDBY_SLEEP       - Глубокий сон, аналог power down, но system clock остается активен, быстрый выход из сна , большее потребление
POWERSAVE_SLEEP     - Глубокий сон, аналог power down, но timer 2 остается активным, можно использовать для счета времени
EXTSTANDBY_SLEEP    - Глубокий сон, аналог standby, но timer 2 остается активным, можно использовать для счета времени
*/
/* ======= ПЕРИОДЫ СНА =======
SLEEP_16MS
SLEEP_32MS
SLEEP_64MS
SLEEP_128MS
SLEEP_256MS
SLEEP_512MS
SLEEP_1024MS
SLEEP_2048MS
SLEEP_4096MS
SLEEP_8192MS
SLEEP_FOREVER
*/
/* ==== КОНСТАНТЫ ДЕЛИТЕЛЯ ====
PRESCALER_1
PRESCALER_2
PRESCALER_4
PRESCALER_8
PRESCALER_16
PRESCALER_32
PRESCALER_64
PRESCALER_128
PRESCALER_256
*/
/* ==== КОНСТАНТЫ ПЕРИФЕРИИ ====
PWR_ALL     - всё
PWR_USB     - usb
PWR_TIMER5  - таймер 5
PWR_TIMER4  - таймер 4
PWR_TIMER3  - таймер 3
PWR_TIMER2  - таймер 2
PWR_TIMER0  - таймер 1
PWR_TIMER1  - таймер 0
PWR_UART3   - Serial3
PWR_UART2   - Serial2
PWR_UART1   - Serial1
PWR_UART0   - Serial
PWR_I2C     - Wire
PWR_SPI     - Spi
PWR_ADC     - АЦП
PWR_USI     - Wire + Spi (ATtinyXX)
PWR_LIN     - USART LIN (ATtinyXX)
*/

ПРИМЕРЫ


//#define FIX_TIME // Коррекция времени в случае изменения системной частоты
#include "GyverPower.h"
void setup() {
pinMode(13, OUTPUT); // настраиваем вывод со светодиодом на выход
Serial.begin(9600);
// калибровка таймаутов для максимальной точности sleepDelay
//Serial.println(getMaxTimeout()); // вывести реальный макс. период
//calibrate(8935); 			// ввести реальный макс. период
//calibrate(getMaxTimeout()); // автоматически посчитать и откалибровать
autoCalibrate(); // автоматическая калибровка ~ 2 секунды , средняя но достаточная точность
/* отключение ненужной периферии */
hardwareDisable(PWR_ADC | PWR_TIMER1); // см константы, разделяющий знак " | "
/* управление системной частотой */
setSystemPrescaler(PRESCALER_2); // см константы
/* настройка параметров сна */
//setSleepMode(STANDBY_SLEEP); // если нужен другой режим сна (по умолчанию POWERDOWN_SLEEP)
bodInSleep(false); // рекомендуется выключить bod во сне для сохранения энергии (по умолчанию true - включен)
/* пример однократного ухода в сон */
Serial.println("go to sleep");
delay(100); // даем время на отправку
sleep(SLEEP_2048MS); // спим ~ 2 секунды
Serial.println("wake up!");
delay(100); // даем время на отправку
}
void loop() {
/* пример циклического сна */
sleepDelay(1500); // спим 1.5 секунды
digitalWrite(13, !digitalRead(13)); // инвертируем состояние на пине
}
#define FIX_TIME // Коррекция времени в случае изменения системной частоты
// дефайнить до подключения библиотеки!!!
#include "GyverPower.h"
void setup() {
setSystemPrescaler(PRESCALER_16); // замедляем в 16 раз
// чтобы сериал завёлся (если нужен), умножаем скорость на замедление
Serial.begin(9600 * 16L);
// иначе не заведётся на указанной скорости
Serial.println("serial test");
pinMode(13, OUTPUT);
}
void loop() {
digitalWrite(13, !digitalRead(13)); // мигаем
delay(1000);    // держит 1 секунду, несмотря на пониженный клок!
}
// пример настроек сна
#include "GyverPower.h"
void setup() {
// отключение ненужной периферии
hardwareDisable(PWR_ADC | PWR_TIMER1); // см. константы, разделяющий знак " | "
// можно отключить всё
// hardwareDisable(PWR_ALL);
// ПОСЛЕ СНА НЕОБХОДИМО ВРУЧНУЮ ВКЛЮЧАТЬ НУЖНУЮ ПЕРИФЕРИЮ!
setSleepMode(STANDBY_SLEEP); // режим сна (по умолчанию POWERDOWN_SLEEP)
//bodInSleep(false); // отключение BOD (по у молчанию и так выключен) - экономит энергию
}
void loop() {
sleep(SLEEP_2048MS); // спим ~ 2 секунды (некалиброванный таймаут. Смотри пример с калибрвокой!)
digitalWrite(13, !digitalRead(13)); // инвертируем состояние на пине
}
#include "GyverPower.h"
void setup() {
Serial.begin(9600);
// WDT будит МК ото сна, его таймер не очень точный (с завода) и нуждается в калибровке.
// Калибровка таймаутов для максимальной точности sleepDelay
// === ВАРИАНТ 1 ===
Serial.println(getMaxTimeout()); // вывести реальный макс. период (выполняется ~8 секунд)
// допустим вывело 8321
calibrate(8321); 			// калибруем по реальному периоду
// можно жёстко задать в скетче (как выше) или пихнуть в EEPROM
// === ВАРИАНТ 2 ===
// автоматически посчитать и откалибровать (выполняется ~8 секунд)
// каждый раз при запуске скетча
calibrate(getMaxTimeout());
// === ВАРИАНТ 3 ===
autoCalibrate(); // автоматическая калибровка ~2 секунды
// калибрует менее точно, чем вариант с 8-ю секундами. Можно оставить "на каждый запуск"
pinMode(13, OUTPUT);
}
void loop() {
// пример циклического сна
sleepDelay(1500); // спим ровно 1.5 секунды (мы откалиброваны!)
digitalWrite(13, !digitalRead(13)); // инвертируем состояние на пине
}