├── .gitattributes ├── .github └── workflows │ └── tg-send.yml ├── LICENSE ├── README.md ├── README_EN.md ├── examples ├── GyverPower_example │ └── GyverPower_example.ino ├── WDT_calibration │ └── WDT_calibration.ino ├── customSleepMillis │ └── customSleepMillis.ino ├── hardwareControl │ └── hardwareControl.ino ├── interruptWakeSleep │ └── interruptWakeSleep.ino ├── interruptWakeSleepDelay │ └── interruptWakeSleepDelay.ino ├── lowClock │ └── lowClock.ino ├── lowClockTimeCorrect │ └── lowClockTimeCorrect.ino ├── power_mode │ └── power_mode.ino ├── powersaveMillis │ ├── powersaveMillis.ino │ └── uptime2.h ├── simpleWakePeriodic │ └── simpleWakePeriodic.ino ├── sleepDelayMillis │ └── sleepDelayMillis.ino ├── sleepDelayTest │ └── sleepDelayTest.ino ├── sleepMillis │ └── sleepMillis.ino └── sleeptime │ └── sleeptime.ino ├── keywords.txt ├── library.properties └── src ├── GyverPower.cpp ├── GyverPower.h └── powerConstants.h /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.github/workflows/tg-send.yml: -------------------------------------------------------------------------------- 1 | 2 | name: Telegram Message 3 | on: 4 | release: 5 | types: [published] 6 | jobs: 7 | build: 8 | name: Send Message 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: send telegram message on push 12 | uses: appleboy/telegram-action@master 13 | with: 14 | to: ${{ secrets.TELEGRAM_TO }} 15 | token: ${{ secrets.TELEGRAM_TOKEN }} 16 | disable_web_page_preview: true 17 | message: | 18 | ${{ github.event.repository.name }} v${{ github.event.release.tag_name }} 19 | ${{ github.event.release.body }} 20 | https://github.com/${{ github.repository }} 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 AlexGyver 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Foo](https://img.shields.io/badge/Version-2.2-brightgreen.svg?style=flat-square)](#versions) 2 | [![Foo](https://img.shields.io/badge/Website-AlexGyver.ru-blue.svg?style=flat-square)](https://alexgyver.ru/) 3 | [![Foo](https://img.shields.io/badge/%E2%82%BD$%E2%82%AC%20%D0%9D%D0%B0%20%D0%BF%D0%B8%D0%B2%D0%BE-%D1%81%20%D1%80%D1%8B%D0%B1%D0%BA%D0%BE%D0%B9-orange.svg?style=flat-square)](https://alexgyver.ru/support_alex/) 4 | 5 | [![Foo](https://img.shields.io/badge/README-ENGLISH-brightgreen.svg?style=for-the-badge)](https://github-com.translate.goog/GyverLibs/GyverPower?_x_tr_sl=ru&_x_tr_tl=en) 6 | 7 | # GyverPower 8 | GyverPower - библиотека для управления энергопотреблением МК AVR 9 | - Управление системным клоком 10 | - Включение/выключение периферии: 11 | - BOD 12 | - Таймеры 13 | - I2C/UART/SPI 14 | - USB 15 | - ADC 16 | - Сон в разных режимах (список ниже) 17 | - Сон на любой период 18 | - Калибровка таймера для точного времени сна 19 | - Корректировка millis() 20 | 21 | ### Совместимость 22 | - Atmega2560/32u4/328 23 | - Attiny85/84/167 24 | 25 | ### Документация 26 | К библиотеке есть [расширенная документация](https://alexgyver.ru/GyverPower/) 27 | 28 | ## Содержание 29 | - [Использование](#usage) 30 | - [Пример](#example) 31 | - [Установка](#install) 32 | - [Версии](#versions) 33 | - [Баги и обратная связь](#feedback) 34 | 35 | 36 | 37 | ## Использование 38 | ```cpp 39 | void hardwareEnable(uint16_t data); // включение указанной периферии (см. ниже "Константы периферии") 40 | void hardwareDisable(uint16_t data); // выключение указанной периферии (см. ниже "Константы периферии") 41 | void setSystemPrescaler(prescalers_t prescaler); // установка делителя системной частоты 42 | void adjustInternalClock(int8_t adj); // подстройка частоты внутреннего генератора (число -120...+120) 43 | void bodInSleep(bool en); // Brown-out detector в режиме сна (true вкл - false выкл) [умолч. false] 44 | 45 | void setSleepMode(sleepmodes_t mode); // установка текущего режима сна [умолч. POWERDOWN_SLEEP] 46 | void sleep(sleepprds_t period); // сон на стандартный период 47 | bool inSleep(); // вернёт true, если МК спит для проверки в прерывании 48 | 49 | uint16_t sleepDelay(uint32_t ms); // сон на произвольный период в миллисекундах, возвращает остаток времени для коррекции таймеров 50 | uint16_t sleepDelay(uint32_t ms, uint32_t sec, uint16_t min = 0, uint16_t hour = 0, uint16_t day = 0); 51 | void setSleepResolution(sleepprds_t period); // установить разрешение сна sleepDelay() [умолч. SLEEP_128MS] 52 | void correctMillis(bool state); // корректировать миллис на время сна sleepDelay() [умолч. true] 53 | void calibrate(); // автоматическая калибровка таймера сна sleepDelay(), выполняется 16 мс 54 | void wakeUp(); // помогает выйти из sleepDelay() прерыванием (вызывать в будящем прерывании) 55 | ``` 56 | 57 | ```cpp 58 | ===== РЕЖИМЫ СНА для setSleepMode() ===== 59 | IDLE_SLEEP - Легкий сон, отключается только клок CPU и Flash, просыпается мгновенно от любых прерываний 60 | ADC_SLEEP - Легкий сон, отключается CPU и system clock, АЦП начинает преобразование при уходе в сон (см. пример ADCinSleep) 61 | EXTSTANDBY_SLEEP - Глубокий сон, идентичен POWERSAVE_SLEEP + system clock активен 62 | STANDBY_SLEEP - Глубокий сон, идентичен POWERDOWN_SLEEP + system clock активен 63 | POWERSAVE_SLEEP - Глубокий сон, идентичен POWERDOWN_SLEEP + timer 2 активен (+ можно проснуться от его прерываний), можно использовать для счета времени (см. пример powersaveMillis) 64 | POWERDOWN_SLEEP - Наиболее глубокий сон, отключается всё кроме WDT и внешних прерываний, просыпается от аппаратных (обычных + PCINT) или WDT 65 | 66 | ===== ПЕРИОДЫ СНА для sleep() и setSleepResolution() ===== 67 | SLEEP_16MS 68 | SLEEP_32MS 69 | SLEEP_64MS 70 | SLEEP_128MS 71 | SLEEP_256MS 72 | SLEEP_512MS 73 | SLEEP_1024MS 74 | SLEEP_2048MS 75 | SLEEP_4096MS 76 | SLEEP_8192MS 77 | SLEEP_FOREVER - вечный сон 78 | 79 | ===== КОНСТАНТЫ ДЕЛИТЕЛЯ для setSystemPrescaler() ===== 80 | PRESCALER_1 81 | PRESCALER_2 82 | PRESCALER_4 83 | PRESCALER_8 84 | PRESCALER_16 85 | PRESCALER_32 86 | PRESCALER_64 87 | PRESCALER_128 88 | PRESCALER_256 89 | 90 | ===== КОНСТАНТЫ ПЕРИФЕРИИ для hardwareDisable() и hardwareEnable() ===== 91 | PWR_ALL - всё железо 92 | PWR_ADC - АЦП и компаратор 93 | PWR_TIMER1 - Таймер 0 94 | PWR_TIMER0 - Таймер 1 95 | PWR_TIMER2 - Таймер 2 96 | PWR_TIMER3 - Таймер 3 97 | PWR_TIMER4 - Таймер 4 98 | PWR_TIMER5 - Таймер 5 99 | PWR_UART0 - Serial 0 100 | PWR_UART1 - Serial 1 101 | PWR_UART2 - Serial 2 102 | PWR_UART3 - Serial 3 103 | PWR_I2C - Wire 104 | PWR_SPI - SPI 105 | PWR_USB - USB 106 | PWR_USI - Wire + Spi (ATtinyXX) 107 | PWR_LIN - USART LIN (ATtinyXX) 108 | ``` 109 | 110 | ### Простой сон 111 | - Режим сна настраивается в `power.setSleepMode()`, по умолчанию активен `POWERDOWN_SLEEP` (остальные см. выше). 112 | - Чтобы уснуть - вызываем `power.sleep()` с указанием одного из стандартных периодов (см. выше). 113 | - Реальное время сна будет слегка отличаться, так как "таймер сна" не очень точный. 114 | 115 | ### Сон на любой период 116 | - Режим сна настраивается в `power.setSleepMode()`, по умолчанию активен `POWERDOWN_SLEEP` (остальные см. выше). 117 | - Чтобы уснуть - вызываем `power.sleepDelay()` с указанием периода в миллисекундах (`uint32_t`, до ~50 суток). 118 | *Как это работает? Просто цикл со стандартными периодами сна внутри этой функции.* 119 | - По умолчанию данная функция "спит" периодами по 128 миллисекунд. Время бодрствования между периодами сна составляет около 2.2 мкс (при 16 Мгц), 120 | что составляет 0.0017% от времени сна. Соответственно точность времени сна кратна одному периоду сна. Этот период можно настроить в 121 | `power.setSleepResolution()`, которая принимает те же константы, что и `sleep()`. Если нужен более точный сон - можно поставить 16 мс (`SLEEP_16MS`), 122 | если максимальное энергосбережение - 8 секунд (`SLEEP_8192MS`). 123 | - Для преждевременного пробуждения по прерыванию нужно обязательно вызвать `power.wakeUp()` внутри обработчика прерывания. 124 | - Сон `sleepDelay()` имеет две очень полезные возможности: 125 | - Сон на очень точный период при откалиброванном таймере (см. ниже) 126 | - Сохранение счёта времени `millis()` на время сна (см. пример sleeptime) 127 | 128 | ### Калибровка таймера 129 | В версии 2.0 библиотеки калибровка была упрощена: достаточно вызвать `power.autoCalibrate()` при запуске микроконтроллера. Функция выполняется ~16 мс. 130 | **Внимание! power.setSleepResolution() нужно вызывать после калибровки таймера.** 131 | 132 | 133 | 134 | ## Пример 135 | Остальные примеры смотри в **examples**! 136 | ```cpp 137 | // демо возможностей библиотеки 138 | #include 139 | 140 | void setup() { 141 | pinMode(13, OUTPUT); // настраиваем вывод со светодиодом на выход 142 | Serial.begin(9600); 143 | 144 | power.autoCalibrate(); // автоматическая калибровка 145 | 146 | // отключение ненужной периферии 147 | power.hardwareDisable(PWR_ADC | PWR_TIMER1); // см раздел константы в GyverPower.h, разделяющий знак " | " 148 | 149 | // управление системной частотой 150 | power.setSystemPrescaler(PRESCALER_2); // см константы в GyverPower.h 151 | 152 | // настройка параметров сна 153 | power.setSleepMode(STANDBY_SLEEP); // если нужен другой режим сна, см константы в GyverPower.h (по умолчанию POWERDOWN_SLEEP) 154 | //power.bodInSleep(false); // рекомендуется выключить bod во сне для сохранения энергии (по умолчанию false - уже выключен!!) 155 | 156 | // пример однократного ухода в сон 157 | Serial.println("go to sleep"); 158 | delay(100); // даем время на отправку 159 | 160 | power.sleep(SLEEP_2048MS); // спим ~ 2 секунды 161 | 162 | Serial.println("wake up!"); 163 | delay(100); // даем время на отправку 164 | } 165 | 166 | void loop() { 167 | // пример циклического сна 168 | power.sleepDelay(1500); // спим 1.5 секунды 169 | digitalWrite(13, !digitalRead(13)); // инвертируем состояние на пине 170 | } 171 | ``` 172 | 173 | 174 | 175 | ## Установка 176 | - Библиотеку можно найти по названию **GyverPower** и установить через менеджер библиотек в: 177 | - Arduino IDE 178 | - Arduino IDE v2 179 | - PlatformIO 180 | - [Скачать библиотеку](https://github.com/GyverLibs/GyverPower/archive/refs/heads/main.zip) .zip архивом для ручной установки: 181 | - Распаковать и положить в *C:\Program Files (x86)\Arduino\libraries* (Windows x64) 182 | - Распаковать и положить в *C:\Program Files\Arduino\libraries* (Windows x32) 183 | - Распаковать и положить в *Документы/Arduino/libraries/* 184 | - (Arduino IDE) автоматическая установка из .zip: *Скетч/Подключить библиотеку/Добавить .ZIP библиотеку…* и указать скачанный архив 185 | - Читай более подробную инструкцию по установке библиотек [здесь](https://alexgyver.ru/arduino-first/#%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D0%B1%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA) 186 | 187 | 188 | 189 | ## Версии 190 | - v1.2 - фикс калибровки 191 | - v1.3 - фикс для 32U4 192 | - v1.4 - добавлен adjustInternalClock 193 | - v1.5 - совместимость с аттини 194 | - v1.6 - ещё совместимость с аттини 195 | - v1.7 - оптимизация, совместимость с ATtiny13 196 | - v1.8 - совместимость с ATmega32U4 197 | - v2.0 - оптимизация памяти, переделан sleepDelay, можно точно узнать фактическое время сна 198 | - v2.0.1 - fix compiler warnings 199 | - v2.0.2 - исправлена ошибка компиляции ATtiny85 200 | - v2.1 - добавлена bool inSleep(), для проверки спит ли МК 201 | - v2.2 - улучшена стабильность 202 | 203 | 204 | ## Баги и обратная связь 205 | При нахождении багов создавайте **Issue**, а лучше сразу пишите на почту [alex@alexgyver.ru](mailto:alex@alexgyver.ru) 206 | Библиотека открыта для доработки и ваших **Pull Request**'ов! 207 | -------------------------------------------------------------------------------- /README_EN.md: -------------------------------------------------------------------------------- 1 | This is an automatic translation, may be incorrect in some places. See sources and examples! 2 | 3 | # Gyverpower 4 | Gyverpower - Library for Energy Executive Management MK AVR 5 | - System shock management 6 | - Turning on/off the periphery: 7 | - Bod 8 | - Tiemers 9 | - i2c/uart/spi 10 | - USB 11 | - ADC 12 | - sleep in different modes (list below) 13 | - sleep for any period 14 | - Tiemer calibration for the exact time of sleep 15 | - adjustment Millis () 16 | 17 | ## compatibility 18 | - Atmega2560/32U4/328 19 | - Attiny85/84/167 20 | 21 | ### Documentation 22 | There is [expanded documentation] to the library (https://alexgyver.ru/gyverpower/) 23 | 24 | ## Content 25 | - [installation] (# Install) 26 | - [initialization] (#init) 27 | - [use] (#usage) 28 | - [Example] (# Example) 29 | - [versions] (#varsions) 30 | - [bugs and feedback] (#fedback) 31 | 32 | 33 | ## Installation 34 | - The library can be found by the name ** gyverpower ** and installed through the library manager in: 35 | - Arduino ide 36 | - Arduino ide v2 37 | - Platformio 38 | - [download the library] (https://github.com/gyverlibs/gyverpower/archive/refs/heads/main.zip) .Zip archive for manual installation: 39 | - unpack and put in * C: \ Program Files (X86) \ Arduino \ Libraries * (Windows X64) 40 | - unpack and put in * C: \ Program Files \ Arduino \ Libraries * (Windows X32) 41 | - unpack and put in *documents/arduino/libraries/ * 42 | - (Arduino id) Automatic installation from. Zip: * sketch/connect the library/add .Zip library ... * and specify downloaded archive 43 | - Read more detailed instructions for installing libraries [here] (https://alexgyver.ru/arduino-first/#%D0%A3%D1%81%D1%82%D0%B0%BD%D0%BE%BE%BE%BED0%B2%D0%BA%D0%B0_%D0%B1%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA) 44 | ### Update 45 | - I recommend always updating the library: errors and bugs are corrected in the new versions, as well as optimization and new features are added 46 | - through the IDE library manager: find the library how to install and click "update" 47 | - Manually: ** remove the folder with the old version **, and then put a new one in its place.“Replacement” cannot be done: sometimes in new versions, files that remain when replacing are deleted and can lead to errors! 48 | 49 | 50 | 51 | ## initialization 52 | No 53 | 54 | 55 | ## Usage 56 | `` `CPP 57 | VOID Hardwareenable (Uint16_T DATA);// inclusion of the specified periphery (see below the "peripheral constants") 58 | VOID HardwareDisable (Uint16_T DATA);// Turning off the specified periphery (see below the "Constant of the Periphery") 59 | VOID SetSystemprescaler (Prescalers_t PressCaler); // Installation of a system frequency divider (see below "Delichela Constant) 60 | VOID Adjustinternalclock (Int8_T Adj);// adjustment of the frequency of the internal generator (number -120 ...+120) 61 | 62 | VOID BODINSLEP (BOOL EN);// Brown -out Detector in sleep mode (True vkl - False cap) by the silence.Disconnected! 63 | VOID setsleepmode (Sleepmodes_t Mode);// Installation of the current sleep regime (see below "Sleep modes") 64 | VOID setsleepResolution (Uint8_t Period);// Set a resolution of sleep (see below the "periods of sleep") 65 | 66 | VOID autocalibrate (VOID);// Automatic calibration of sleep timer, 16 ms is performed 67 | VOID Sleep (Uint8_t Period);// sleep for a fixed period (see below "periods of sleep") 68 | Uint8_t SleepDelay (Uint32_T MS);// Sleep to arbitrary peRiodes in milliseconds (up to 52 days), returns the rest of the time to correct timers 69 | VOID Correctmillis (Bool State);// Correct millis for sleep time SleepDelay () (by default on) 70 | VOID Wakeup (VOID);// Helps to leave SleepDelay an interruption (call in a waking interruption) 71 | Bool Insleep (Void);// will return True if MK sleeps (for verification in interruption) 72 | `` ` 73 | 74 | `` `CPP 75 | ===== Sleep modes for setsleepmode () ======= 76 | Idle_sleep - light sleep, only a CPU and Flash clock is turned off, it wakes up instantly from any interruption 77 | ADC_SLEP is a light dream, CPU and System Clock are disconnected, ADC begins to transform it when leaving (see Adcinsleep example) 78 | Extstandby_sleep - deep sleep, identical to PowerSave_Sleep + System Clock is active 79 | Standby_sleep - deep sleep, identical to PowerDown_Sleep + System Clock is active 80 | PowerSave_Sleep - deep sleep, identical to powerdown_sleep + timer 2 is active ( + you can wake up from its interruptions), you can use time (see example of powerSavemillis) 81 | PowerDown_Sleep - the deepest sleep, everything is turned off except WDT and external interruptions, wakes up from hardware (ordinary + PCINT) or WDT 82 | 83 | ===== Sleep periods for Sleep () and setsleepresolution () =========== 84 | Sleep_16ms 85 | Sleep_32MS 86 | Sleep_64ms 87 | Sleep_128MS 88 | Sleep_256MS 89 | Sleep_512MS 90 | Sleep_1024ms 91 | Sleep_2048MS 92 | Sleep_4096ms 93 | Sleep_8192MS 94 | Sleep_Forever - Eternal Dream 95 | 96 | ===== The divider constant for setsyStemprescaler () =========== 97 | PressCaler_1 98 | PressCaler_2 99 | PressCaler_4 100 | PressCaler_8 101 | PressCaler_16 102 | PressCaler_32 103 | PressCaler_64 104 | PressCaler_128 105 | PressCaler_256 106 | 107 | ===== The periphery constants for Hardwareedisable () and Hardwareenable () ========== 108 | Pwr_all - all iron 109 | PWR_ADC - ACP and comparator 110 | PWR_Timer1 - timer 0 111 | PWR_Timer0 - TIMER 1 112 | PWR_Timer2 - TIMER 2 113 | PWR_Timer3 - TIMER 3 114 | PWR_Timer4 - TIMER 4 115 | PWR_Timer5 - TIMER 5 116 | PWR_UART0 - Serial 0 117 | PWR_UART1 - Serial 1 118 | PWR_UART2 - Serial 2 119 | PWR_UART3 - Serial 3 120 | PWR_I2C - Wire 121 | PWR_SPI - SPI 122 | PWR_USB - USB 123 | PWR_USI - Wire + SPI (Attinyxx) 124 | PWR_LIN - USART LIN (Attinyxx) 125 | `` ` 126 | 127 | ### simple sleep 128 | - Sleep mode is tuned in `Power.setsleepmode ()`, by default, `PowerDown_Sleep` is active (the rest see above). 129 | - To fall asleep, we call `Power.sleep ()` with one of the standard periods (see above). 130 | - The real time of sleep will be slightly different, since the "sleep timer" is not very accurate. 131 | 132 | ### sleep for any period 133 | - Sleep mode is tuned in `Power.setsleepmode ()`, by default, `PowerDown_Sleep` is active (the rest see above). 134 | - To fall asleep, we call `Power.sleepDelay ()` with a period in milliseconds (`uint32_t`, up to ~ 50 days). 135 | *How it works?Just a cycle with standard periods of sleep inside this function.* 136 | - By default, this function “sleeps” with periods of 128 milliseconds.The wakefulness between the periods of sleep is about 2.2 μs (at 16 MHz), 137 | which is 0.0017% of the time of sleep.Accordingly, the accuracy of the time of sleep is multiple of one period of sleep.This period can be configured in 138 | `Power.SetSleepResolution ()`, which accepts the same constants as `Sleep ()`.If you need a more accurate dream, you can put 16 ms (`Sleep_16MS`), 139 | If the maximum energy conservation is 8 seconds (`Sleep_8192MS`). 140 | - For premature awakening for interruption, it is necessary to call `Power.wakeup ()` inside the interruption processor. 141 | - Sleep `SleepDelay ()` has two very useful opportunities: 142 | - sleep for a very accurate period with a calibrated timer (see below) 143 | - Preservation of the time account `millis ()` during sleep (see example of Sleeptime) 144 | 145 | ### Tymer Calibration 146 | In version 2.0 of the library, the calibration was simplified: it is enough to call `Power.autocalibrate ()` when the microcontroller is launched.The function is performed ~ 16 ms. 147 | **Attention!Power.SetsleepResolution () should be called after calibration of the timer. ** 148 | 149 | 150 | ## Example 151 | The rest of the examples look at ** Examples **! 152 | `` `CPP 153 | // Demo of the library capabilities 154 | #include 155 | 156 | VOID setup () { 157 | Pinmode (13, output);// set up inCranberries with LED output 158 | Serial.Begin (9600); 159 | 160 | Power.autocalibrate ();// Automatic calibration 161 | 162 | // Disconnecting unnecessary periphery 163 | Power.hardwardedisable (pwr_adc | pwr_timer1);// see Constant section in gyverpower.h, separating the sign "| 164 | 165 | // System frequency management 166 | Power.SetSySteMprescaler (Prescaler_2);// cm constants in gyverpower.h 167 | 168 | // Sleep settings 169 | Power.Setsleepmode (Standby_Sleep);// If you need another sleep mode, cm constants in gyverpower.h (by default PowerDown_Sleep) 170 | //power.BodinSleep (False);// It is recommended to turn off BOD in a dream to preserve energy (by default FALSE - already turned off !!) 171 | 172 | // Example of single care of sleep 173 | Serial.println ("Go to Sleep"); 174 | DELAY (100);// Give the time to send 175 | 176 | Power.sleep (Sleep_2048MS);// Sleep ~ 2 seconds 177 | 178 | Serial.println ("Wake Up!"); 179 | DELAY (100);// Give the time to send 180 | } 181 | 182 | VOID loop () { 183 | // example of cyclic sleep 184 | Power.SleepDelay (1500);// Sleep 1.5 seconds 185 | DigitalWrite (13,! DigitalRead (13));// Inverting the condition on the pin 186 | } 187 | `` ` 188 | 189 | 190 | ## versions 191 | - V1.2 - Calibration Fix 192 | - V1.3 - Fix for 32U4 193 | - v1.4 - Adjustinternalclock added 194 | - V1.5 - compatibility with Attini 195 | - V1.6 - more compatibility with Attini 196 | - V1.7 - optimization, compatibility with Attiny13 197 | - V1.8 - Compatibility with atmega32u4 198 | - V2.0 - memory optimization, redepdlavia remoded, you can definitely find out the actual sleep time 199 | - V2.0.1 - FIX Compiler Warnings 200 | - v2.0.2 - Fixed compilation error attiny85 201 | - V2.1 - Added Bool Insleep (), whether MK sleeps for verification 202 | - V2.2 - Improved stability 203 | 204 | 205 | ## bugs and feedback 206 | Create ** Issue ** when you find the bugs, and better immediately write to the mail [alex@alexgyver.ru] (mailto: alex@alexgyver.ru) 207 | The library is open for refinement and your ** pull Request ** 'ow! 208 | 209 | 210 | When reporting about bugs or incorrect work of the library, it is necessary to indicate: 211 | - The version of the library 212 | - What is MK used 213 | - SDK version (for ESP) 214 | - version of Arduino ide 215 | - whether the built -in examples work correctly, in which the functions and designs are used, leading to a bug in your code 216 | - what code has been loaded, what work was expected from it and how it works in reality 217 | - Ideally, attach the minimum code in which the bug is observed.Not a canvas of a thousand lines, but a minimum code -------------------------------------------------------------------------------- /examples/GyverPower_example/GyverPower_example.ino: -------------------------------------------------------------------------------- 1 | // демо возможностей библиотеки 2 | #include 3 | 4 | void setup() { 5 | pinMode(13, OUTPUT); // настраиваем вывод со светодиодом на выход 6 | Serial.begin(9600); 7 | 8 | power.autoCalibrate(); // автоматическая калибровка 9 | 10 | // отключение ненужной периферии 11 | power.hardwareDisable(PWR_ADC | PWR_TIMER1); // см раздел константы в GyverPower.h, разделяющий знак " | " 12 | 13 | // управление системной частотой 14 | power.setSystemPrescaler(PRESCALER_2); // см константы в GyverPower.h 15 | 16 | // настройка параметров сна 17 | power.setSleepMode(STANDBY_SLEEP); // если нужен другой режим сна, см константы в GyverPower.h (по умолчанию POWERDOWN_SLEEP) 18 | //power.bodInSleep(false); // рекомендуется выключить bod во сне для сохранения энергии (по умолчанию false - уже выключен!!) 19 | 20 | // пример однократного ухода в сон 21 | Serial.println("go to sleep"); 22 | delay(100); // даем время на отправку 23 | 24 | power.sleep(SLEEP_2048MS); // спим ~ 2 секунды 25 | 26 | Serial.println("wake up!"); 27 | delay(100); // даем время на отправку 28 | } 29 | 30 | void loop() { 31 | // пример циклического сна 32 | power.sleepDelay(1500); // спим 1.5 секунды 33 | digitalWrite(13, !digitalRead(13)); // инвертируем состояние на пине 34 | } -------------------------------------------------------------------------------- /examples/WDT_calibration/WDT_calibration.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void setup() { 4 | Serial.begin(9600); 5 | pinMode(13, OUTPUT); // шоб мигать 6 | 7 | // WDT будит МК ото сна, его таймер не очень точный (с завода) и нуждается в калибровке 8 | power.autoCalibrate(); // автоматическая калибровка, выполняется ~16 миллисекунд 9 | } 10 | 11 | void loop() { 12 | // пример циклического сна 13 | power.sleepDelay(1500); // спим ровно 1.5 секунды (мы откалиброваны!) 14 | digitalWrite(13, !digitalRead(13)); // инвертируем состояние на пине 15 | } -------------------------------------------------------------------------------- /examples/customSleepMillis/customSleepMillis.ino: -------------------------------------------------------------------------------- 1 | // Делаем свой счётчик времени сна 2 | // допустим таймер 0 у нас используется для других целей, но нам 3 | // нужно хотя бы приблизительно считать время и выполнять по нему действия 4 | 5 | #include 6 | 7 | uint32_t myMillis = 0; // наш миллис 8 | 9 | void setup() { 10 | power.autoCalibrate(); // автоматическая калибровка 11 | } 12 | 13 | void loop() { 14 | static uint32_t tmr1, tmr2; 15 | 16 | // "таймер" на 2 секунды 17 | if (myMillis - tmr1 > 2000) { 18 | tmr1 += 2000; 19 | // действие 1 20 | } 21 | 22 | // "таймер" на 10 секунд 23 | if (myMillis - tmr2 > 10000) { 24 | tmr2 += 10000; 25 | // действие 2 26 | } 27 | 28 | // спим 1 секунду (1000 мс) 29 | // sleepDelay возвращает остаток сна в мс, если он есть 30 | byte left = power.sleepDelay(1000); 31 | 32 | // прибавляем и корректируем наш миллис 33 | myMillis += 1000 - left; 34 | } 35 | -------------------------------------------------------------------------------- /examples/hardwareControl/hardwareControl.ino: -------------------------------------------------------------------------------- 1 | // управление периферией МК 2 | #include 3 | 4 | void setup() { 5 | Serial.begin(9600); 6 | // можно выборочно включать-выключать периферийные блоки МК, разделитель - | 7 | // список констант смотри в GyverPower.h / Константы периферии 8 | 9 | // отключили АЦП, таймеры 1 и 0 10 | power.hardwareDisable(PWR_ADC | PWR_TIMER1 | PWR_TIMER0); 11 | 12 | // включили ADC обратно 13 | power.hardwareEnable(PWR_ADC); 14 | } 15 | 16 | void loop() { 17 | Serial.println(millis()); 18 | // отключили таймер 0 - миллис не тикает... 19 | } 20 | -------------------------------------------------------------------------------- /examples/interruptWakeSleep/interruptWakeSleep.ino: -------------------------------------------------------------------------------- 1 | // просыпаемся по аппаратному прерыванию из sleep 2 | #include 3 | 4 | void setup() { 5 | Serial.begin(9600); 6 | 7 | // кнопка подключена к GND и D3 8 | pinMode(3, INPUT_PULLUP); 9 | 10 | // подключаем прерывание на пин D3 (Arduino NANO) 11 | attachInterrupt(1, isr, FALLING); 12 | 13 | // глубокий сон 14 | power.setSleepMode(POWERDOWN_SLEEP); 15 | } 16 | 17 | // обработчик аппаратного прерывания 18 | void isr() { 19 | // в отличие от sleepDelay, ничего вызывать не нужно! 20 | } 21 | 22 | void loop() { 23 | Serial.println("go sleep"); 24 | delay(300); 25 | 26 | // правильно будет вот тут включать прерывание 27 | // attachInterrupt(1, isr, FALLING); 28 | 29 | // спим ~8 секунд, но можем проснуться по кнопке 30 | power.sleep(SLEEP_8192MS); 31 | // тут проснулись, по кнопке или через указанный период 32 | 33 | // а вот тут сразу отключать 34 | // detachInterrupt(1); 35 | 36 | Serial.println("wake up!"); 37 | delay(300); 38 | } 39 | -------------------------------------------------------------------------------- /examples/interruptWakeSleepDelay/interruptWakeSleepDelay.ino: -------------------------------------------------------------------------------- 1 | // просыпаемся по аппаратному прерыванию из sleepDelay 2 | 3 | #include 4 | 5 | // sleepDelay состоит из нескольких sleep, и команда wakeUp() 6 | // позволяет окончательно проснуться по прерыванию. 7 | // Без неё мы будем "досыпать" некоторое время 8 | 9 | void setup() { 10 | Serial.begin(9600); 11 | 12 | // кнопка подключена к GND и D3 13 | pinMode(3, INPUT_PULLUP); 14 | 15 | // подключаем прерывание на пин D3 (Arduino NANO) 16 | attachInterrupt(1, isr, FALLING); 17 | 18 | // глубокий сон 19 | power.setSleepMode(POWERDOWN_SLEEP); 20 | } 21 | 22 | // обработчик аппаратного прерывания 23 | void isr() { 24 | // дёргаем за функцию "проснуться" 25 | // без неё проснёмся чуть позже (через 0-8 секунд) 26 | power.wakeUp(); 27 | } 28 | 29 | void loop() { 30 | Serial.println("go sleep"); 31 | delay(300); 32 | 33 | // правильно будет вот тут включать прерывание 34 | // attachInterrupt(1, isr, FALLING); 35 | 36 | // спим 12 секунд, но можем проснуться по кнопке 37 | power.sleepDelay(12000); 38 | // тут проснулись по кнопке или через указанный период 39 | 40 | // а вот тут сразу отключать 41 | // detachInterrupt(1); 42 | 43 | Serial.println("wake up!"); 44 | delay(300); 45 | } 46 | -------------------------------------------------------------------------------- /examples/lowClock/lowClock.ino: -------------------------------------------------------------------------------- 1 | // пример управления системной частотой 2 | // мы можем только уменьшить (разделить) системную частоту (на платах ардуино 16 МГц) 3 | // Пониженная частота позволяет чуть снизить потребление или питать МК от пониженного напряжения! 4 | 5 | #include 6 | 7 | void setup() { 8 | power.setSystemPrescaler(PRESCALER_16); // замедляем в 16 раз 9 | 10 | // с понижением системной частоты "уйдут" все завязанные на частоте блоки периферии! 11 | // чтобы сериал завёлся (если нужен), умножаем скорость на замедление 12 | // иначе не заведётся на указанной скорости 13 | Serial.begin(9600 * 16L); 14 | 15 | Serial.println("serial test"); 16 | } 17 | 18 | void loop() { 19 | } 20 | -------------------------------------------------------------------------------- /examples/lowClockTimeCorrect/lowClockTimeCorrect.ino: -------------------------------------------------------------------------------- 1 | // пример управления системной частотой 2 | // мы можем только уменьшить (разделить) системную частоту (на платах ардуино 16 МГц) 3 | // Пониженная частота позволяет чуть снизить потребление или питать МК от пониженного напряжения! 4 | #include 5 | 6 | // с понижением частоты "уйдут" функции времени 7 | // для их коррекции можно сделать так: 8 | #define millis() (millis() << (CLKPR & 0xF)) 9 | #define micros() (micros() << (CLKPR & 0xF)) 10 | #define delay(x) delay((x) >> (CLKPR & 0xf)) 11 | #define delayMicroseconds(x) delayMicroseconds((x) >> (CLKPR & 0xf)) 12 | 13 | // данные дефайны нужно прописать ПЕРЕД подключением остальных библиотек. 14 | // Таким образом дефайн сможет "проникнуть" в библиотеку и скорректировать 15 | // работу используемых там функций времени 16 | 17 | void setup() { 18 | power.setSystemPrescaler(PRESCALER_16); // замедляем в 16 раз 19 | pinMode(13, OUTPUT); 20 | } 21 | 22 | void loop() { 23 | digitalWrite(13, !digitalRead(13)); // мигаем 24 | delay(1000); // держит 1 секунду, несмотря на пониженный клок! 25 | } 26 | -------------------------------------------------------------------------------- /examples/power_mode/power_mode.ino: -------------------------------------------------------------------------------- 1 | // пример настроек сна 2 | #include 3 | 4 | void setup() { 5 | pinMode(13, OUTPUT); // шоб мигать 6 | 7 | // отключение ненужной периферии 8 | power.hardwareDisable(PWR_ADC | PWR_TIMER1); // см. константы, разделяющий знак " | " 9 | // можно отключить всё 10 | // hardwareDisable(PWR_ALL); 11 | 12 | power.setSleepMode(STANDBY_SLEEP); // режим сна (по умолчанию POWERDOWN_SLEEP) 13 | //bodInSleep(false); // отключение BOD (по у молчанию и так выключен) - экономит энергию 14 | } 15 | 16 | void loop() { 17 | power.sleep(SLEEP_2048MS); // спим ~ 2 секунды (некалиброванный таймаут. Смотри пример с калибрвокой!) 18 | digitalWrite(13, !digitalRead(13)); // инвертируем состояние на пине 19 | } 20 | -------------------------------------------------------------------------------- /examples/powersaveMillis/powersaveMillis.ino: -------------------------------------------------------------------------------- 1 | // спим в EXTSTANDBY_SLEEP, считаем время таймером 2 2 | // используется uptime2.h (лежит в папке с примером) 3 | // НЕ РЕКОМЕНДУЕТСЯ К ИСПОЛЬЗОВАНИЮ, смотрите пример sleepDelayMillis 4 | 5 | #include "uptime2.h" 6 | #include 7 | 8 | void setup() { 9 | Serial.begin(9600); 10 | uptime2Init(); // запуск миллиса на 2 таймере 11 | power.setSleepMode(EXTSTANDBY_SLEEP); 12 | 13 | // ВНИМАНИЕ! 14 | // миллис2 сделан на прерываниях таймера 2 15 | // прерывания настроены на частоту ~976.56 Гц 16 | // с этой частотой МК будет просыпаться вне зависимости от указанного периода сна!! 17 | // можно даже SLEEP_FOREVER поставить 18 | } 19 | 20 | void loop() { 21 | static uint32_t tmr; 22 | // наш таймер на миллис2 23 | if (millis2() - tmr >= 1000) { 24 | tmr += 1000; 25 | Serial.print("time: "); 26 | Serial.println(millis2()); 27 | delay2(50); 28 | } 29 | 30 | // спим 31 | power.sleep(SLEEP_FOREVER); 32 | // тут проснулись в любом случае по прерыванию и код продолжает выполняться 33 | } 34 | -------------------------------------------------------------------------------- /examples/powersaveMillis/uptime2.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #define MICROSECONDS_PER_TIMER2_OVERFLOW (clockCyclesToMicroseconds(64 * 256)) 3 | #define MILLIS2_INC (MICROSECONDS_PER_TIMER2_OVERFLOW / 1000) 4 | #define FRACT2_INC ((MICROSECONDS_PER_TIMER2_OVERFLOW % 1000) >> 3) 5 | #define FRACT2_MAX (1000 >> 3) 6 | #define MICROS2_MULT (64 / clockCyclesPerMicrosecond()) 7 | 8 | void uptime2Init(); 9 | unsigned long millis2(); 10 | unsigned long micros2(); 11 | void delay2(unsigned long ms); 12 | void delayMicroseconds2(unsigned int us); 13 | 14 | volatile unsigned long timer2_overflow_count = 0; 15 | volatile unsigned long timer2_millis = 0; 16 | static unsigned char timer2_fract = 0; 17 | 18 | void uptime2Init() { 19 | sei(); 20 | TCCR2A = (1 << WGM20) | (1 << WGM21); 21 | TCCR2B = 1 << CS22; 22 | TIMSK2 = 1 << TOIE2; 23 | } 24 | 25 | ISR(TIMER2_OVF_vect) { 26 | timer2_millis += MILLIS2_INC; 27 | timer2_fract += FRACT2_INC; 28 | if (timer2_fract >= FRACT2_MAX) { 29 | timer2_fract -= FRACT2_MAX; 30 | timer2_millis++; 31 | } 32 | timer2_overflow_count++; 33 | } 34 | 35 | unsigned long millis2() { 36 | uint8_t oldSREG = SREG; // запомнинаем были ли включены прерывания 37 | cli(); // выключаем прерывания 38 | unsigned long m = timer2_millis; // перехватить значение 39 | SREG = oldSREG; // если прерывания не были включены - не включаем и наоборот 40 | return m; // вернуть миллисекунды 41 | } 42 | 43 | unsigned long micros2() { 44 | uint8_t oldSREG = SREG; // запомнинаем были ли включены прерывания 45 | cli(); // выключаем прерывания 46 | unsigned long m = timer2_overflow_count; // счет переполнений 47 | uint8_t t = TCNT2; // считать содержимое счетного регистра 48 | if ((TIFR2 & _BV(TOV2)) && (t < 255)) // инкремент по переполнению 49 | m++; 50 | SREG = oldSREG; // если прерывания не были включены - не включаем и наоборот 51 | return (long)(((m << 8) + t) * MICROS2_MULT); // вернуть микросекунды 52 | } 53 | 54 | void delay2(unsigned long ms) { 55 | uint32_t start = micros(); 56 | while (ms > 0) { // ведем отсчет 57 | while ( ms > 0 && (micros() - start) >= 1000) { 58 | ms--; 59 | start += 1000; 60 | } 61 | } 62 | } 63 | 64 | void delayMicroseconds2(unsigned int us) { 65 | #if F_CPU >= 24000000L 66 | us *= 6; // x6 us, = 7 cycles 67 | us -= 5; //=2 cycles 68 | 69 | #elif F_CPU >= 20000000L 70 | __asm__ __volatile__ ( 71 | "nop" "\n\t" 72 | "nop" "\n\t" 73 | "nop" "\n\t" 74 | "nop"); //just waiting 4 cycles 75 | if (us <= 1) return; // = 3 cycles, (4 when true) 76 | us = (us << 2) + us; // x5 us, = 7 cycles 77 | us -= 7; // 2 cycles 78 | 79 | #elif F_CPU >= 16000000L 80 | if (us <= 1) return; // = 3 cycles, (4 when true) 81 | us <<= 2; // x4 us, = 4 cycles 82 | us -= 5; // = 2 cycles, 83 | 84 | #elif F_CPU >= 12000000L 85 | if (us <= 1) return; // = 3 cycles, (4 when true) 86 | us = (us << 1) + us; // x3 us, = 5 cycles 87 | us -= 5; //2 cycles 88 | 89 | #elif F_CPU >= 8000000L 90 | if (us <= 2) return; // = 3 cycles, (4 when true) 91 | us <<= 1; //x2 us, = 2 cycles 92 | us -= 4; // = 2 cycles 93 | 94 | #else 95 | if (us <= 16) return; //= 3 cycles, (4 when true) 96 | if (us <= 25) return; //= 3 cycles, (4 when true), (must be at least 25 if we want to substract 22) 97 | us -= 22; // = 2 cycles 98 | us >>= 2; // us div 4, = 4 cycles 99 | 100 | #endif 101 | __asm__ __volatile__ ( 102 | "1: sbiw %0,1" "\n\t" // 2 cycles 103 | "brne 1b" : "=w" (us) : "0" (us) // 2 cycles 104 | ); 105 | } 106 | -------------------------------------------------------------------------------- /examples/simpleWakePeriodic/simpleWakePeriodic.ino: -------------------------------------------------------------------------------- 1 | // самый простой пример, для слабонервных =) 2 | #include 3 | 4 | void setup() { 5 | //Serial.begin(9600); 6 | // сериал для демонстрации! 7 | // по умолчанию стоит самый экономный режим сна POWER DOWN 8 | } 9 | 10 | void loop() { 11 | // опрашиваем датчики, мигаем светодиодами, etc 12 | // ... 13 | // ... 14 | 15 | //Serial.println("go sleep"); 16 | //delay(300); 17 | 18 | // спим 5 секунд (5000 мс) 19 | // в POWER DOWN вся периферия отключается, по умолчанию также отключается BOD и ADC 20 | power.sleepDelay(5000); 21 | // тут проснулись и код продолжает выполняться 22 | 23 | //Serial.println("wake up!"); 24 | //delay(300); 25 | } 26 | -------------------------------------------------------------------------------- /examples/sleepDelayMillis/sleepDelayMillis.ino: -------------------------------------------------------------------------------- 1 | // помогаем миллису сохранить свой счёт на время сна sleepDelay 2 | #include 3 | 4 | // На время сна в большинстве режимов millis() останавливается, 5 | // но сон при помощи функции sleepDelay автоматически корректирует millis()! 6 | 7 | void setup() { 8 | Serial.begin(9600); 9 | power.calibrate(); // автоматическая калибровка таймера сна 10 | 11 | // по умолчанию стоит самый экономный режим сна POWER DOWN 12 | // power.correctMillis(false); // можно отключить коррекцию миллис (по умолч. включена) 13 | } 14 | 15 | void loop() { 16 | // опрашиваем датчики, мигаем светодиодами, etc 17 | // таймер на миллис на 3 секунды для теста 18 | static uint32_t tmr; 19 | if (millis() - tmr >= 3000) { 20 | tmr += 3000; 21 | Serial.println("kek"); 22 | delay(50); 23 | } 24 | 25 | // спим 1.5 секунды (1500 мс) 26 | power.sleepDelay(1500); 27 | // проснулись 28 | // миллис корректируется автоматически! 29 | } 30 | -------------------------------------------------------------------------------- /examples/sleepDelayTest/sleepDelayTest.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void setup() { 4 | Serial.begin(115200); 5 | Serial.println("hello"); 6 | delay(10); 7 | 8 | power.calibrate(); 9 | } 10 | 11 | void loop() { 12 | power.sleepDelay(300000); 13 | 14 | delay(10); 15 | Serial.begin(115200); 16 | Serial.println("hello"); 17 | delay(10); 18 | } -------------------------------------------------------------------------------- /examples/sleepMillis/sleepMillis.ino: -------------------------------------------------------------------------------- 1 | // помогаем миллису сохранить свой счёт на время сна sleep 2 | #include 3 | 4 | // КОРРЕКЦИЯ МИЛЛИС РЕАЛИЗОВАНА В САМОЙ БИБЛИОТЕКЕ, ЭТО ПРОСТО ПРИМЕР ДЛЯ ДРУГИХ ПЛАТФОРМ 5 | // На время сна в большинстве режимов millis() останавливается, скорректировать можно вручную. 6 | // Функция sleep спит не ровно указанное время, так как WDT таймер имеет заводскую неточность. 7 | // Данный пример показан чисто для примера, не рекомендуется его использовать. 8 | // Для точных периодов сна используйте sleedDelay и калибровку WDT 9 | // см. пример sleepDelayMillis 10 | 11 | // "вытягиваем" переменную, отвечающую за счётчик миллис 12 | extern volatile unsigned long timer0_millis; 13 | 14 | void setup() { 15 | Serial.begin(9600); 16 | // по умолчанию стоит самый экономный режим сна POWER DOWN 17 | } 18 | 19 | void loop() { 20 | // опрашиваем датчики, мигаем светодиодами, etc 21 | // таймер на миллис на 3 секунды для теста 22 | static uint32_t tmr; 23 | if (millis() - tmr >= 3000) { 24 | tmr += 3000; 25 | Serial.println("kek"); 26 | delay(50); 27 | } 28 | 29 | // спим ~512 мс 30 | power.sleep(SLEEP_512MS); 31 | 32 | // скорректировали миллис: прибавили время сна к счётчику миллис 33 | timer0_millis += 512; 34 | } 35 | -------------------------------------------------------------------------------- /examples/sleeptime/sleeptime.ino: -------------------------------------------------------------------------------- 1 | // измеряем время, проведённое во сне 2 | // кнопка на D3 и GND 3 | #include 4 | 5 | // здесь просыпаемся 6 | void wake() { 7 | power.wakeUp(); 8 | } 9 | 10 | void setup() { 11 | Serial.begin(9600); 12 | power.autoCalibrate(); // калибруем таймер сна 13 | // можно установить разрешение 14 | //power.setSleepResolution(SLEEP_1024MS); 15 | 16 | pinMode(3, INPUT_PULLUP); 17 | // будильник по кнопке 18 | attachInterrupt(1, wake, FALLING); 19 | } 20 | 21 | uint32_t tmr; 22 | void loop() { 23 | tmr = millis(); 24 | power.sleepDelay(50000); 25 | 26 | // выводим время сна 27 | Serial.println(millis() - tmr); 28 | delay(300); 29 | } 30 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For GyverPower 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | power KEYWORD1 9 | GyverPower KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | hardwareEnable KEYWORD2 15 | hardwareDisable KEYWORD2 16 | setSystemPrescaler KEYWORD2 17 | adjustInternalClock KEYWORD2 18 | 19 | bodInSleep KEYWORD2 20 | setSleepMode KEYWORD2 21 | setSleepResolution KEYWORD2 22 | autoCalibrate KEYWORD2 23 | correctMillis KEYWORD2 24 | 25 | sleep KEYWORD2 26 | sleepDelay KEYWORD2 27 | wakeUp KEYWORD2 28 | inSleep KEYWORD2 29 | 30 | getMaxTimeout KEYWORD2 31 | calibrate KEYWORD2 32 | 33 | ####################################### 34 | # Constants (LITERAL1) 35 | ####################################### 36 | PRESCALER_1 LITERAL1 37 | PRESCALER_2 LITERAL1 38 | PRESCALER_4 LITERAL1 39 | PRESCALER_8 LITERAL1 40 | PRESCALER_16 LITERAL1 41 | PRESCALER_32 LITERAL1 42 | PRESCALER_64 LITERAL1 43 | PRESCALER_128 LITERAL1 44 | PRESCALER_256 LITERAL1 45 | 46 | PWR_ALL LITERAL1 47 | PWR_USB LITERAL1 48 | PWR_TIMER5 LITERAL1 49 | PWR_TIMER4 LITERAL1 50 | PWR_TIMER3 LITERAL1 51 | PWR_UART3 LITERAL1 52 | PWR_UART2 LITERAL1 53 | PWR_UART1 LITERAL1 54 | PWR_I2C LITERAL1 55 | PWR_TIMER2 LITERAL1 56 | PWR_TIMER0 LITERAL1 57 | PWR_TIMER1 LITERAL1 58 | PWR_SPI LITERAL1 59 | PWR_UART0 LITERAL1 60 | PWR_ADC LITERAL1 61 | PWR_USI LITERAL1 62 | PWR_LIN LITERAL1 63 | 64 | SLEEP_16MS LITERAL1 65 | SLEEP_32MS LITERAL1 66 | SLEEP_64MS LITERAL1 67 | SLEEP_128MS LITERAL1 68 | SLEEP_256MS LITERAL1 69 | SLEEP_512MS LITERAL1 70 | SLEEP_1024MS LITERAL1 71 | SLEEP_2048MS LITERAL1 72 | SLEEP_4096MS LITERAL1 73 | SLEEP_8192MS LITERAL1 74 | SLEEP_FOREVER LITERAL1 75 | 76 | IDLE_SLEEP LITERAL1 77 | ADC_SLEEP LITERAL1 78 | POWERDOWN_SLEEP LITERAL1 79 | POWERSAVE_SLEEP LITERAL1 80 | EXTSTANDBY_SLEEP LITERAL1 81 | STANDBY_SLEEP LITERAL1 -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=GyverPower 2 | version=2.2.1 3 | author=AlexGyver 4 | maintainer=AlexGyver 5 | sentence=Library for power management of AVR 6 | paragraph=Library for power management of AVR 7 | category=Other 8 | url=https://github.com/GyverLibs/GyverPower 9 | architectures=avr -------------------------------------------------------------------------------- /src/GyverPower.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef MILLIS_CORRECT_IS_SUPPURT 4 | extern volatile unsigned long timer0_millis; 5 | #endif 6 | static volatile bool _wdtFlag = false; 7 | 8 | // ===================== ЖЕЛЕЗО ===================== 9 | void GyverPower::hardwareEnable(uint16_t data) { 10 | #if defined(PRR1) 11 | PRR1 &= ~highByte(data); // загрузили данные в регистр 12 | PRR0 &= ~lowByte(data); 13 | #else 14 | PRR &= ~lowByte(data); 15 | #endif 16 | if (data & PWR_ADC) { // если что то сказали про ацп 17 | ADCSRA |= (1 << ADEN); // вкл ацп 18 | ACSR &= ~(1 << ACD); // вкл компаратор 19 | } 20 | } 21 | 22 | void GyverPower::hardwareDisable(uint16_t data) { 23 | if (data & PWR_ADC) { // если что то сказали про ацп 24 | ADCSRA &= ~(1 << ADEN); // выкл ацп 25 | ACSR |= (1 << ACD); // выкл компаратор 26 | } 27 | #if defined(PRR1) 28 | PRR1 |= highByte(data); // загрузили данные в регистр 29 | PRR0 |= lowByte(data); 30 | #else 31 | PRR |= lowByte(data); 32 | #endif 33 | } 34 | 35 | // ===================== КЛОК ===================== 36 | void GyverPower::setSystemPrescaler(prescalers_t prescaler) { 37 | CLKPR = (1 << CLKPCE); // разрешили менять делитель 38 | CLKPR = prescaler; // загрузили новый 39 | } 40 | 41 | void GyverPower::adjustInternalClock(int8_t adj) { 42 | static uint8_t currentCal; 43 | static bool startup = false; 44 | if (!startup) { 45 | startup = true; 46 | currentCal = OSCCAL; 47 | } 48 | uint8_t oldSreg = SREG; 49 | currentCal = constrain(currentCal + adj, 0, 255); 50 | cli(); 51 | OSCCAL = currentCal; 52 | SREG = oldSreg; 53 | } 54 | 55 | // ===================== НАСТРОЙКИ СНА ===================== 56 | void GyverPower::bodInSleep(bool state) { 57 | _bodEnable = state; 58 | } 59 | 60 | void GyverPower::setSleepMode(sleepmodes_t mode) { 61 | _sleepMode = mode; 62 | } 63 | 64 | void GyverPower::correctMillis(bool state) { 65 | _correctF = state; 66 | } 67 | 68 | // ===================== КАЛИБРОВКА ===================== 69 | void GyverPower::calibrate() { 70 | _wdtFlag = false; 71 | uint32_t us = micros(); 72 | _wdt_start(SLEEP_16MS); 73 | while (!_wdtFlag); 74 | wdt_disable(); 75 | _us16 = micros() - us; 76 | setSleepResolution(_delayPrd); 77 | } 78 | 79 | // ===================== СОН ===================== 80 | void GyverPower::sleep(sleepprds_t prd) { 81 | _prepare(); 82 | _sleep(prd); 83 | _finish(); 84 | } 85 | 86 | void GyverPower::setSleepResolution(sleepprds_t prd) { 87 | uint32_t stepUs = (uint32_t)_us16 * (1 << prd); 88 | _step = stepUs / 1000ul; 89 | _fstep = (stepUs % 1000ul) >> 3; 90 | _delayPrd = prd; 91 | } 92 | 93 | uint16_t GyverPower::sleepDelay(uint32_t ms, uint32_t sec, uint16_t min, uint16_t hour, uint16_t day) { 94 | if (sec) ms += sec * 1000ul; 95 | if (min) ms += min * 60 * 1000ul; 96 | if (hour) ms += hour * 60 * 60 * 1000ul; 97 | if (day) ms += day * 24 * 60 * 60 * 1000ul; 98 | return sleepDelay(ms); 99 | } 100 | 101 | uint16_t GyverPower::sleepDelay(uint32_t ms) { 102 | #ifdef MILLIS_CORRECT_IS_SUPPURT 103 | uint32_t saveMs = ms; 104 | #endif 105 | uint8_t fcount = 0; 106 | _wakeF = false; 107 | _prepare(); 108 | while (ms > _step) { 109 | _sleep(_delayPrd); 110 | ms -= _step; 111 | fcount += _fstep; 112 | if (fcount >= (1000 >> 3)) { 113 | --ms; 114 | fcount -= (1000 >> 3); 115 | } 116 | if (_wakeF) { 117 | #ifdef MILLIS_CORRECT_IS_SUPPURT 118 | if (_correctF) { 119 | uint8_t oldSREG = SREG; 120 | cli(); 121 | timer0_millis += saveMs - ms; 122 | SREG = oldSREG; 123 | } 124 | #endif 125 | _finish(); 126 | return ms; 127 | } 128 | } 129 | #ifdef MILLIS_CORRECT_IS_SUPPURT 130 | if (_correctF) { 131 | uint8_t oldSREG = SREG; 132 | cli(); 133 | timer0_millis += saveMs - ms; 134 | SREG = oldSREG; 135 | } 136 | #endif 137 | _finish(); 138 | return ms; // вернуть остаток времени 139 | } 140 | 141 | void GyverPower::wakeUp() { 142 | _wakeF = true; 143 | } 144 | 145 | bool GyverPower::inSleep() { 146 | return _sleepF; 147 | } 148 | 149 | // ===================== PRIVATE ===================== 150 | void GyverPower::_prepare() { 151 | _sleepF = 1; 152 | // принудительно выкл АЦП и компаратор 153 | switch (_sleepMode) { 154 | case IDLE_SLEEP: 155 | case ADC_SLEEP: 156 | break; 157 | default: 158 | ADCSRA &= ~(1 << ADEN); // Выкл ацп 159 | ACSR |= (1 << ACD); // Выкл аналог компаратор 160 | } 161 | 162 | #if defined(__AVR_ATtiny85__) 163 | // Принудительное отключение PLL 164 | _pllCopy = PLLCSR; // Запомнили настройки 165 | PLLCSR &= ~(1 << PLLE); // Выключили 166 | #endif 167 | } 168 | 169 | void GyverPower::_sleep(sleepprds_t period) { 170 | if (period != SLEEP_FOREVER) _wdt_start(period); 171 | set_sleep_mode(_sleepMode); // Настраиваем нужный режим сна 172 | sleep_enable(); // Разрешаем сон 173 | if (_bodEnable) interrupts(); // для БОД, если он включен 174 | #if defined(sleep_bod_disable) 175 | else { 176 | noInterrupts(); // Запрет прерываний 177 | sleep_bod_disable(); // Выключаем BOD 178 | interrupts(); // Разрешаем прерывания 179 | } 180 | #endif 181 | sleep_cpu(); // <<< точка ухода в сон 182 | wdt_disable(); // выкл пса 183 | wdt_reset(); // сброс пса 184 | sleep_disable(); // Запрещаем сон 185 | } 186 | 187 | void GyverPower::_finish() { 188 | // Восстановление настроек АЦП 189 | #if defined(PRR0) 190 | if (!(PRR0 & (1 << PRADC))) { // если ацп не выключен принудительно 191 | ADCSRA |= (1 << ADEN); // вкл после сна 192 | ACSR &= ~(1 << ACD); 193 | } 194 | #else 195 | if (!(PRR & (1 << PRADC))) { // если ацп не выключен принудительно 196 | ADCSRA |= (1 << ADEN); // вкл после сна 197 | ACSR &= ~(1 << ACD); 198 | } 199 | #endif 200 | 201 | // Восстановление настроек PLL (для тини85) 202 | #if defined(__AVR_ATtiny85__) 203 | PLLCSR = _pllCopy; 204 | #endif 205 | _sleepF = 0; 206 | } 207 | 208 | void GyverPower::_wdt_start(uint8_t timeout) { 209 | wdt_enable(timeout); 210 | WDTCSR |= 1 << WDIE; // Режим ISR+RST 211 | wdt_reset(); // Сброс WDT 212 | } 213 | 214 | ISR(WDT_vect) { // просыпаемся тут 215 | _wdtFlag = true; // для калибровки 216 | } 217 | 218 | GyverPower power = GyverPower(); 219 | 220 | ////////////////////// 221 | uint16_t GyverPower::getMaxTimeout() { return 8000; } 222 | void GyverPower::calibrate(uint16_t ms) { calibrate(); } 223 | void GyverPower::autoCalibrate() { calibrate(); } -------------------------------------------------------------------------------- /src/GyverPower.h: -------------------------------------------------------------------------------- 1 | #ifndef _GyverPower_h 2 | #define _GyverPower_h 3 | #include 4 | #include 5 | #include 6 | 7 | #include "powerConstants.h" 8 | 9 | // =============== ФУНКЦИИ =============== 10 | class GyverPower { 11 | public: 12 | void hardwareEnable(uint16_t data); // включение указанной периферии (см. ниже "Константы периферии") 13 | void hardwareDisable(uint16_t data); // выключение указанной периферии (см. ниже "Константы периферии") 14 | void setSystemPrescaler(prescalers_t prescaler); // установка делителя системной частоты 15 | void adjustInternalClock(int8_t adj); // подстройка частоты внутреннего генератора (число -120...+120) 16 | void bodInSleep(bool en); // Brown-out detector в режиме сна (true вкл - false выкл) [умолч. false] 17 | void setSleepMode(sleepmodes_t mode); // установка текущего режима сна [умолч. POWERDOWN_SLEEP] 18 | void sleep(sleepprds_t period); // сон на стандартный период 19 | bool inSleep(); // вернёт true, если МК спит для проверки в прерывании 20 | 21 | uint16_t sleepDelay(uint32_t ms); // сон на произвольный период в миллисекундах, возвращает остаток времени для коррекции таймеров 22 | uint16_t sleepDelay(uint32_t ms, uint32_t sec, uint16_t min = 0, uint16_t hour = 0, uint16_t day = 0); 23 | void setSleepResolution(sleepprds_t period); // установить разрешение сна sleepDelay() [умолч. SLEEP_128MS] 24 | void correctMillis(bool state); // корректировать миллис на время сна sleepDelay() [умолч. true] 25 | void calibrate(); // автоматическая калибровка таймера сна sleepDelay(), выполняется 16 мс 26 | void wakeUp(); // помогает выйти из sleepDelay() прерыванием (вызывать в будящем прерывании) 27 | 28 | // устарело 29 | void autoCalibrate(); // автоматическая калибровка таймера сна, выполняется 16 мс 30 | void calibrate(uint16_t ms); // ручная калибровка тайм-аутов watchdog для sleepDelay (ввести макс период из getMaxTimeout) 31 | uint16_t getMaxTimeout(); // возвращает реальный период "8 секунд", выполняется ~8 секунд 32 | 33 | private: 34 | void _prepare(); 35 | void _sleep(sleepprds_t period); 36 | void _finish(); 37 | void _wdt_start(uint8_t timeout); 38 | 39 | uint16_t _step = 1 << (SLEEP_128MS + 4); 40 | uint16_t _us16 = 16000; 41 | uint8_t _fstep = 0; 42 | sleepprds_t _delayPrd = SLEEP_128MS; 43 | sleepmodes_t _sleepMode = POWERDOWN_SLEEP; 44 | 45 | volatile bool _wakeF = false; 46 | volatile bool _sleepF = 0; 47 | bool _correctF = true; 48 | bool _bodEnable = false; 49 | 50 | #if defined(__AVR_ATtiny85__) 51 | uint8_t _pllCopy = 0; 52 | #endif 53 | }; 54 | 55 | extern GyverPower power; 56 | 57 | // =============== КОНСТАНТЫ =============== 58 | /* 59 | ===== РЕЖИМЫ СНА для setSleepMode() ===== 60 | IDLE_SLEEP - Легкий сон, отключается только клок CPU и Flash, просыпается мгновенно от любых прерываний 61 | ADC_SLEEP - Легкий сон, отключается CPU и system clock, АЦП начинает преобразование при уходе в сон (см. пример ADCinSleep) 62 | EXTSTANDBY_SLEEP - Глубокий сон, идентичен POWERSAVE_SLEEP + system clock активен 63 | STANDBY_SLEEP - Глубокий сон, идентичен POWERDOWN_SLEEP + system clock активен 64 | POWERSAVE_SLEEP - Глубокий сон, идентичен POWERDOWN_SLEEP + timer 2 активен (+ можно проснуться от его прерываний), можно использовать для счета времени (см. пример powersaveMillis) 65 | POWERDOWN_SLEEP - Наиболее глубокий сон, отключается всё кроме WDT и внешних прерываний, просыпается от аппаратных (обычных + PCINT) или WDT 66 | 67 | ===== ПЕРИОДЫ СНА для sleep() и setSleepResolution() ===== 68 | SLEEP_16MS 69 | SLEEP_32MS 70 | SLEEP_64MS 71 | SLEEP_128MS 72 | SLEEP_256MS 73 | SLEEP_512MS 74 | SLEEP_1024MS 75 | SLEEP_2048MS 76 | SLEEP_4096MS 77 | SLEEP_8192MS 78 | SLEEP_FOREVER - вечный сон 79 | 80 | ===== КОНСТАНТЫ ДЕЛИТЕЛЯ для setSystemPrescaler() ===== 81 | PRESCALER_1 82 | PRESCALER_2 83 | PRESCALER_4 84 | PRESCALER_8 85 | PRESCALER_16 86 | PRESCALER_32 87 | PRESCALER_64 88 | PRESCALER_128 89 | PRESCALER_256 90 | 91 | ===== КОНСТАНТЫ ПЕРИФЕРИИ для hardwareDisable() и hardwareEnable() ===== 92 | PWR_ALL - всё железо 93 | PWR_ADC - АЦП и компаратор 94 | PWR_TIMER1 - Таймер 0 95 | PWR_TIMER0 - Таймер 1 96 | PWR_TIMER2 - Таймер 2 97 | PWR_TIMER3 - Таймер 3 98 | PWR_TIMER4 - Таймер 4 99 | PWR_TIMER5 - Таймер 5 100 | PWR_UART0 - Serial 0 101 | PWR_UART1 - Serial 1 102 | PWR_UART2 - Serial 2 103 | PWR_UART3 - Serial 3 104 | PWR_I2C - Wire 105 | PWR_SPI - SPI 106 | PWR_USB - USB 107 | PWR_USI - Wire + Spi (ATtinyXX) 108 | PWR_LIN - USART LIN (ATtinyXX) 109 | */ 110 | #endif -------------------------------------------------------------------------------- /src/powerConstants.h: -------------------------------------------------------------------------------- 1 | #ifndef powerConstants_h 2 | #define powerConstants_h 3 | 4 | /* --- system prescaler --- */ 5 | enum prescalers_t : uint8_t { 6 | PRESCALER_1, 7 | PRESCALER_2, 8 | PRESCALER_4, 9 | PRESCALER_8, 10 | PRESCALER_16, 11 | PRESCALER_32, 12 | PRESCALER_64, 13 | PRESCALER_128, 14 | PRESCALER_256, 15 | }; 16 | 17 | /* --- sleep periods --- */ 18 | enum sleepprds_t : uint8_t { 19 | SLEEP_16MS, 20 | SLEEP_32MS, 21 | SLEEP_64MS, 22 | SLEEP_128MS, 23 | SLEEP_256MS, 24 | SLEEP_512MS, 25 | SLEEP_1024MS, 26 | SLEEP_2048MS, 27 | SLEEP_4096MS, 28 | SLEEP_8192MS, 29 | SLEEP_FOREVER, 30 | }; 31 | 32 | /* --- sleep modes --- */ 33 | enum sleepmodes_t : uint8_t { 34 | IDLE_SLEEP = SLEEP_MODE_IDLE, 35 | ADC_SLEEP = SLEEP_MODE_ADC, 36 | POWERDOWN_SLEEP = SLEEP_MODE_PWR_DOWN, 37 | #if defined(SLEEP_MODE_EXT_STANDBY) 38 | EXTSTANDBY_SLEEP = SLEEP_MODE_EXT_STANDBY, 39 | #endif 40 | #if defined(SLEEP_MODE_PWR_SAVE) 41 | POWERSAVE_SLEEP = SLEEP_MODE_PWR_SAVE, 42 | #endif 43 | #if defined(SLEEP_MODE_STANDBY) 44 | STANDBY_SLEEP = SLEEP_MODE_STANDBY 45 | #endif 46 | }; 47 | 48 | /* --- periphery disable / enable --- */ 49 | #if defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny167__) || defined(__AVR_ATtiny84__) 50 | #define PWR_ALL 0xFFFF 51 | #define PWR_LIN _BV(5) 52 | #define PWR_SPI _BV(4) 53 | #define PWR_TIMER1 _BV(3) 54 | #define PWR_TIMER0 _BV(2) 55 | #define PWR_USI _BV(1) 56 | #define PWR_ADC _BV(0) 57 | #else 58 | #define PWR_ALL 0xFFFF 59 | #define PWR_USB _BV(15) 60 | #define PWR_TIMER5 _BV(13) 61 | #define PWR_TIMER4 _BV(12) 62 | #define PWR_TIMER3 _BV(11) 63 | #define PWR_UART3 _BV(10) 64 | #define PWR_UART2 _BV(9) 65 | #define PWR_UART1 _BV(8) 66 | #define PWR_I2C _BV(7) 67 | #define PWR_TIMER2 _BV(6) 68 | #define PWR_TIMER0 _BV(5) 69 | #define PWR_TIMER1 _BV(3) 70 | #define PWR_SPI _BV(2) 71 | #define PWR_UART0 _BV(1) 72 | #define PWR_ADC _BV(0) 73 | #endif 74 | 75 | /* Спец. переопределения */ 76 | #if defined(WDTIE) 77 | #define WDIE WDTIE 78 | #endif 79 | 80 | #if defined(WDTCR) 81 | #define WDTCSR WDTCR 82 | #endif 83 | 84 | /* Поддержка millis-correct */ 85 | #if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) 86 | #define MILLIS_CORRECT_IS_SUPPURT 87 | #endif 88 | 89 | #endif --------------------------------------------------------------------------------