Есть ли у ардуино режим глубокого сна?

Во многих передатчиках можно включить режим глубокого сна, где плата ничего не делает, и не потребляет электричество. Есть ли подобный режим у ардуино уно, и как его включить, если он есть?

В самом фреймворке Arduino уход в сон реализован с помощью различных библиотек. Я же здесь рассмотрю "низкоуровневый" вариант, который может быть применен к абсолютно любому МК AVR.

МК AVR поддерживает различные режимы сна. Режимы сна реализуются с помощью отключения тактирования различных модулей входящих в состав МК. Самый легкий режим сна это:

IDLE

в этом режиме остановлено тактирование CPU и памяти FLASH. Вся остальная периферия тактируется.

Следующий режим сна связан с АЦП и называется:

 ADC\_NOISE\_REDUCTION

в этом режиме остановлено всё, кроме тактирования АЦП и таймеров. Это сделано для того, чтобы минимизировать шумы, которые могут ухудшить результат оцифровки.

Режим, который останавливает абсолютно всё:

POWER\_DOWN

Остановлено всё, кроме таймеров с внешним тактированием. К таким относятся RTC и WDT.

В различных моделях МК добавлены ещё режимы, но они являются вариациями вышеприведенных.

Как выводить МК из режима сна? По различным событиям, которые генерируют прерывания. Из абсолютно всех режимов сна можно выйти:

по таймерам WDT и RTC

по изменению логического уровня на любом пине, обозначенном PCINT. Сюда же входят пины INT0 и INT1 (в режиме POWER\_DOWN rising и falling на этих пинах не работает, т.к. остановлено тактирование!!!).

по получению байта с адресом МК по шине I2C.

Из режима  ADC\_NOISE\_REDUCTION дополнительно можно выйти по готовности результат оцифровки сигнала АЦП, по прерыванию от таймера, по флагу готовности EEPROM.

Из режима IDLE выйти можно по любому прерыванию.

Ниже я покажу, как уйти в сон и проснуться от WDT. Можно пожонглировать регистрами МК, но в каждом МК уход в сон реализован по-своему, поэтому проще воспользоваться библиотекой от Atmel. Подключим ее:

```
#include <avr/sleep.h>
```
Для ухода в сон воспользуемся следующими макросами:

```

	 set_sleep_mode(Sleep_mode);		// Выбираем режим сна

	 sleep_cpu();			// Уходим в сон здесь

```
Первый макрос определяет режим сна, второй макрос разрешает сон.  Если режим сна меняться не будет, то первый макрос достаточно написать один раз, второй макрос пишем в том участке кода, где необходимо уйти в сон.

Просыпаться мы будем по вачдогу. Но прежде нам надо его подготовить. В ATMega328 вачдог работает в одном из двух режимов - либо он отслеживает исполнение программы и ресетит МК, если очередной сброс счетчика вачдога пропущен (что приводит к его переполнению), либо он работает как обычный таймер и его переполнение может сгенерировать прерывание. Есть ещё комбинированный режим, который есть и в  ATTiny: первое переполнение счетчика поднимает флаг переполнения и, если разрешено, генерирует прерывание. Последующее переполнение счетчика (если не последовало сброса) генерирует нулевое прерывание - сброс МК.

Итак, первое - выбираем режим работы вачдога - обычный таймер. Для этого я запишу такой макрос:

```
#define WDT_int_on()     WDTCSR = bit (WDCE) | bit (WDE);
```
Установки данных битов - табличные значения.

Затем сразу необходимо "взвести" таймер. У меня это будут максимальные 8 секунд:

```
			WDT_int_on();
			WDTCSR = bit (WDIE) | bit (WDP3) | bit (WDP0);
```
бит WDIE разрешает прерывания от вачдога, иначе не проснемся никогда. Ну  и теперь осталось оформить обработчик прерывания (он должен быть обязателен хотя бы пустой):

```
ISR (WDT_vect)
{
	wdt_disable(); 
} 
```
Здесь я выключаю таймер вачдога, но можно его и сбросить:

```
wdt_reset();
```
Также счетчик таймера вачдога сбрасывает любое изменение периода. Например, 64 мс:

```
WDTCSR = bit (WDIE) | bit (WDP1) | bit (WDP0); 
```
Если таймер не выключается, а только лишь сбрасывается или меняется уставка периода, то макрос 

```
WDT_int_on();
```
необходимо вызвать только лишь один раз.

Перед глубоким сном обязательно все "лапки" МК необходимо сконфигурировать либо на выход, либо на вход с подтяжкой ( в зависимости от подключенной периферии). Но ни в коем случае не оставлять их как не подключенными входами - любая помеха на входе заставит переключаться входной триггер Шмитта, что отразится повышенным энергопотреблением. Если всё сделали правильно, то типовое энергопотребление AVR в режиме сна bc включенным вачдогом будет составлять порядка 3-4 мкА, без вачдога - 200-300 нА. Также обязательно выключать модуль BOD с помощью фьюзов - он отъест свои законные микроамперы.



Если за глубокий сон принять полное отключение перефирии и работу только таймера , отсчитывающего, когда МК проснётся то это 

 SLEEP\_MODE\_PWR\_DOWN :  0.36 mA.

Потребление указано с учётом только МК , с **обвязкой** **как** **на** **Ардуино** **Уно** **такой** **сон** **бессмысленен**.

Данного кода достаточно , чтобы МК ушел в сон сразу после включения:

```
#include <avr/sleep.h>
void setup ()
{
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_mode();
}
void loop()
{
}
```
Как же его выключить это отдельный вопрос , ответ на который  есть [здесь.](http://inet-deal.mpa.ru/articles/arduino-003.html)

Также если хочется сильно в этом разбираться то у Alex Gyverе естьбиблиотека <https://alexgyver.ru/gyverpower/>.



Да, в ардуино уно есть режим энергосбережения. И не один, а целых 6. Более подробно о этих режимах и методе их включения можно прочитать в [этой статье](https://tsibrov.blogspot.com/2018/02/arduino-power-down.html)