Режим энергосбережения

To
Offline
Зарегистрирован: 21.02.2015

Добый всем день!

Проясните, пожалуйста такую тему. Я пользуюсь Arduino IDE для компиляции. Сразу предвижу ответ "не пользуйтесь им", но всетаки по сути дела. Есть известный, наверное, всем скеч:

#include <avr/io.h>
#include <avr/sleep.h>
#include <avr/interrupt.h>
#include <util/delay.h>

int main(void)

{
 
   DDRC |= (1 << PC2) | (1 << PC1);     // leds for testing

   DDRD &= ~(1 << PD2);    // INT0: input...
   PORTD |= (1 << PD2);    // ...with pullup.

   // level interrupt INT0 (low level)
   MCUCR &= ~((1 << ISC01) | (1 << ISC00));

   // infinite main loop
   while (1)
   {
      // trigger leds for testing
      PORTC ^= (1 << PC1);
      _delay_ms(500);
      PORTC ^= (1 << PC1);

      // enable external interrupt
      GICR |= (1 << INT0);

      // set sleep mode
      set_sleep_mode(SLEEP_MODE_PWR_DOWN);

      // sleep_mode() has a possible race condition
      sleep_enable();
      sei();
      sleep_mode();
      //sleep_cpu();
      sleep_disable();

      // waking up...
      // disable external interrupt here, in case the external low pulse is too long
      GICR &= ~(1 << INT0);

      // disable all interrupts
      cli();
   }
}


ISR(INT0_vect)
{
   // ISR might be empty, but is necessary nonetheless
   PORTC ^= (1 << PC2);    // debugging
}

Решил проверить, на сколько все верно. Использую Atmega8L для эксперимента. Все ожидания подтвердились!!! Ток меньше 1 микроАмпера

Попробовал изменить скеч заменив int main(void) на void setup() и void loop() соответственно. В самом скече больше ничего не менял. После компиляции ток в режиме сна стал 129 микроАмпер!!!

Кто нибудь может сие объяснить?

To
Offline
Зарегистрирован: 21.02.2015

Даже не так.

Этот потребляет в режиме сна 110 мкА:


#include <avr/sleep.h>

void setup () 
{
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);  
  sleep_enable();
  sleep_cpu ();  
}  
void loop () { }

А вот этот 0.7 мкА:

include <avr/sleep.h>

int main(void)
{
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);  
  sleep_enable();
  sleep_cpu (); 
}  

 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Всё довольно логично, просто сказать что именно не выключено сходу сложно. При использовании конструкции setup и loop подгружается масса ардуиновских библиотек. Они включают таймеры, ацп, и прочее, и никто не считал сколько всего меняется.  Где то пролетала ссылка на детальные исследования зарубежного товарища Nic Gammon, где скорее всего можно найти информацию на этот счёт.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Так Вы посмотрите что делает ардуиновский main (исходники же доступны). Он там заводит таймеры, включает ADC и делает много чего другого. Повыключайте всё это и будет значительно лучше.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013
To
Offline
Зарегистрирован: 21.02.2015

dimax пишет:

Нашёл http://www.gammon.com.au/power

Спасибо за ответы!

Прикольно, скетчи ведь от туда ( скечь B) :-)

А что main их не грузит?

 

To
Offline
Зарегистрирован: 21.02.2015

Еще. Подключил INT0 для пробуждения, но вот кушает во время сна 270 мкА. Как снизить?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

To пишет:

А что main их не грузит?

Ну, Вы грузите из в main? А кроме Вас этого никто не сделает. Там делается только то, что Вы напишете.

Другое дело Ардуиновская среда. У них ведь основная фишка - "Всё просто и доступно любому чайнику". Вот они всё и делают, чтобы чайник мог просто пользоваться analogRead и millis, и чтобы у него не болела голова о том. что для всего этого нужно ещё кучу всяких битов в разные места засунуть. По-моему, нормальный подход. Именно он и обеспечил популярность Ардуино. Скажите людям, что для того чтобы запустить blink им надо правильно настроить таймер - желающих помигать диодами сразу же поубавится. Никто ведь не рекламирует Ардуино как среду для профессиональной разработки промышленных изделий. Это макетная среда, где всё упрощено, а за упрощения нужно платить :)

To
Offline
Зарегистрирован: 21.02.2015

 Я просто думал, что если среда одна и та же, то стандартные библиотеки подтягиваются в любом случае.

Ок. Спасибо. А поповоду тока, потребляемого при использовании прерыванием?

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

To пишет:

 

Ок. Спасибо. А поповоду тока, потребляемого при использовании прерыванием?

ну сделайте внешнюю подтяжку, скажем мегаомным резюком.

axill
Offline
Зарегистрирован: 05.09.2011

To пишет:

Еще. Подключил INT0 для пробуждения, но вот кушает во время сна 270 мкА. Как снизить?

INT0 ничего не потребляет, дело не в нем

на момент ухода в сон все ноги мк включая не использованные должны быть в одном из состояний:

- настроены на выход

- настроены на вход и включена внешняя подтяжка

- настроены на вход и присоеденена внешняя подтяжка

- настроены на вход и закорочены на GND - это вариант длянеиспользованных пинов, но можно и с внутренней подтяжкой

еще важно определиться с тем нужно ли просыпаться от таймеров. Таймеры много жрут

ждет ацп

жрет watch dog

жрет детектор напряжения который фьюзами включается

 

To
Offline
Зарегистрирован: 21.02.2015

Опыты продолжаются......

Atmega8L + nRF24L01+.

Перечитал кучу статей но так и не заработало энергосбережение.

Это работает хорошо - 1 мкА:


  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  sleep_mode();
  sleep_disable(); /* First thing to do is disable sleep. */

Но  стоит сделать

  radio.begin();
  radio.powerDown();

  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  sleep_mode();
  sleep_disable(); /* First thing to do is disable sleep. */
  radio.powerUp();

и  radio.powerDown(); не помогает, ток становится 7 мА. Причем с модулем или без все равно.

Посмотрел исходники - PWR_UP меняется с 1 на 0 , но толку чуть. Что делать не понимаю.

parovoZZ
Offline
Зарегистрирован: 15.02.2016

Во, интересная тема! Я радиомодуль планирую через полевик включать. С ноги низзя - на передаче жрет много((

To
Offline
Зарегистрирован: 21.02.2015

axill пишет:

To пишет:

Еще. Подключил INT0 для пробуждения, но вот кушает во время сна 270 мкА. Как снизить?

INT0 ничего не потребляет, дело не в нем

на момент ухода в сон все ноги мк включая не использованные должны быть в одном из состояний:

- настроены на выход

- настроены на вход и включена внешняя подтяжка

- настроены на вход и присоеденена внешняя подтяжка

- настроены на вход и закорочены на GND - это вариант длянеиспользованных пинов, но можно и с внутренней подтяжкой

еще важно определиться с тем нужно ли просыпаться от таймеров. Таймеры много жрут

ждет ацп

жрет watch dog

жрет детектор напряжения который фьюзами включается

 

Уважаемый, axill!

Не могли бы подробнее разяснить как сделать то что Вы описали?

Действительно, у меня есть такие  строки кода

......
pinMode(A0, INPUT);
pinMode(A1, INPUT);

.......
int a=analogRead(A0);
int b=analogRead(A1);

После них режим спячки в котором он потребляет 270 мкА. Если две последние строки закоментировать, то ток в спячке падает до 100 мкА. Пробовал подтягивать все входы А0-А5 digitalWrite(А0, HIGH); и LOW - непомогает. Вобще HIGH плохо, т.к. на входе резистор на землю (делителя). Возможно ли перевести их в начальное состояние?

 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

To, так вы читали статью того дядьки из ссылки? Он же там всё отключает что б добиться полного минимума..

To
Offline
Зарегистрирован: 21.02.2015

dimax пишет:

To, так вы читали статью того дядьки из ссылки? Он же там всё отключает что б добиться полного минимума..

A я и спрашиваю: "как?"

и потом везде пишут - режим  powerDown отключает все!!!

  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  sleep_mode();
  sleep_disable(); /* First thing to do is disable sleep. */

 Или не так?

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

To, ну судя по дядькиным эксперементам само ничего не отключается. Скопируйте в свой скетч все его команды, да и проверьте.. делов то.

To
Offline
Зарегистрирован: 21.02.2015

Да, признатся, Вы были правы. У меня это первый опыт с энергосбережением.  В общем удалось добиться в режиме сна 1 мкА.

Но! У меня в схеме задействовано INT1 по LOW уровню. Источником служит RC цепочка, заряжаемая импульсом. Поскольку напряжение на ноге INT1 меняется плавно, то потребление при "среднем уровне" оказывается весьма велико. Отказаться от внешнего прерывания нельзя, поскольку atmega8L пробуждается из состояния Power Down только INT. Буду думать дальше. Весьма признателен. Спасибо.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

To пишет:

У меня в схеме задействовано INT1 по LOW уровню. Источником служит RC цепочка, заряжаемая импульсом. Поскольку напряжение на ноге INT1 меняется плавно, то потребление при "среднем уровне" оказывается весьма велико.

Несколько раз перечитал, много думал. Но так и не понял как такое может быть. Ну импульс, и что? . Из статьи дяди Ника возьмём например скетч J ,  я на нём лично измерял - МК потребляет в режиме сна 0,3-0,4 мка. Т.е. практически ничего не потребляет.  Что нужно сделать, что-бы потребление стало велико, как часто дёргать это прерывание, каждую миллисекунду? Тогда зачем спать..

a5021
Offline
Зарегистрирован: 07.07.2013

parovoZZ пишет:

Во, интересная тема! Я радиомодуль планирую через полевик включать. С ноги низзя - на передаче жрет много((

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

To
Offline
Зарегистрирован: 21.02.2015

dimax!

Наверно  я неверно обьяснил. К ножке INT1 подкючены параллельно R=2MOm и C=500мкФ. Через диод с другой ноги на эту цепочку подается короткий импульс, который заряжает кондер. Теперь на INT1 лог.1. Во время действия импульса происходит считывание информации (импульс является еще и запиткой датчиков). После окончания импульса кондер начинает разряжаться с лог. 1 до лог.0. Происходит срабатывание INT1 по LOW. Дальше процесс повторяется. Вот во время разрядки (RC определяет время разрядки, "некое реле времени" ~ нескольно минут) пока уровень плавно меняется на INT1 и возрастает ток. Это сделано потому, что разбудить из PowerDown только через внешний INT. Если бы это был скачкообразный переход, то все было бы нормально.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

To, как то извратно.. А что мешает по-обычному сделать? Импульс включает МК, он даёт питание датчикам, делает свои дела и уходит спать..

To
Offline
Зарегистрирован: 21.02.2015

dimax пишет:

To, как то извратно.. А что мешает по-обычному сделать? Импульс включает МК, он даёт питание датчикам, делает свои дела и уходит спать..

Чей импульс? Кроме МК и nrf21L01+, который то же спит, никого нет!

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

To, ну вот только сейчас всё понял :) да..задачка.  Я б наверно часики rtc прикрутил, типа ds3231. Тогда всё будет по-человечески :)

To
Offline
Зарегистрирован: 21.02.2015

dimax пишет:

To, ну вот только сейчас всё понял :) да..задачка.  Я б наверно часики rtc прикрутил, типа ds3231. Тогда всё будет по-человечески :)

Ха! Ну ладно. Забей!  Я решил проще, положил в краватку вмеcто atmega8L - atmega328P. У нее все нормально - просыпается от WDT. Железка уже работает. Конечно замена не равноценная, но что делать.

Спасибо за участие!

parovoZZ
Offline
Зарегистрирован: 15.02.2016

a5021 пишет:

parovoZZ пишет:

Во, интересная тема! Я радиомодуль планирую через полевик включать. С ноги низзя - на передаче жрет много((

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

Написал же - на передаче много жрет.

kvaDrug
Offline
Зарегистрирован: 02.01.2016

Автор, открой исходники ардуины, там найдешь файл hardware/arduino/avr/cores/arduino/main.cpp. Как видно, setup() и loop() это лишь упрощение, на деле все происходит в main:

/*
  main.cpp - Main loop for Arduino sketches
  Copyright (c) 2005-2013 Arduino Team.  All right reserved.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include <Arduino.h>

// Declared weak in Arduino.h to allow user redefinitions.
int atexit(void (* /*func*/ )()) { return 0; }

// Weak empty variant initialization function.
// May be redefined by variant files.
void initVariant() __attribute__((weak));
void initVariant() { }

void setupUSB() __attribute__((weak));
void setupUSB() { }

int main(void)
{
	init();

	initVariant();

#if defined(USBCON)
	USBDevice.attach();
#endif
	
	setup();
    
	for (;;) {
		loop();
		if (serialEventRun) serialEventRun();
	}
        
	return 0;
}

 

a5021
Offline
Зарегистрирован: 07.07.2013

parovoZZ пишет:
Написал же - на передаче много жрет.

С полевиком он меньше жрать не станет. На свой вопрос я ответа не получил.

std
Offline
Зарегистрирован: 05.01.2012

To пишет:
во время разрядки (RC определяет время разрядки, "некое реле времени" ~ нескольно минут) пока уровень плавно меняется на INT1 и возрастает ток

Не совсем понятно, но речь видимо о том, что МК всё равно не спит всё то время, пока на плюсе конденсатора (на выводе INT1) "где то ещё не ноль, но уже не единица". Если это так, то проблема лечится инвертором на полевом транзисторе, ну только тогда надо конденсатор не заряжать а разряжать, т. к. логика будет наоборот.

 

parovoZZ
Offline
Зарегистрирован: 15.02.2016

a5021 пишет:

parovoZZ пишет:
Написал же - на передаче много жрет.

С полевиком он меньше жрать не станет. На свой вопрос я ответа не получил.

если цеплять на лапу ардуино - спалит лапу.

a5021
Offline
Зарегистрирован: 07.07.2013

Какие полевеки? Какие лапы? Вы не пятую ли ногу пытаетесь собаке пришить?

Будучи предоставленным самому себе, NRF24L01+ находится в состоянии глубокого сна с суб-микроамперным потреблением (900нА). В процессе инициализации и подотовки приема/передачи, он сам выбирает оптимальное энергопотребление, чередуя режимы Standby-I (25 мкА) и Standby-II (320 мкА). Максимальное потребление (~14 мА) возникает непосредственно в момент работы радио-передатчика, время работы которого ограничено аппаратно и не может превышать четырех миллисекунд.

Теперь вопрос: зачем весь этот цирк с конями, полевиками и лапами, если единственное, чего можно добиться прикручивая внешнюю кустарную коммутанцию -- это усложнение схемы и увеличение потребления ? Я уж не спрашиваю, как четырнадцатью миллиамперами можно сжечь ногу ардуине.

Ardfun
Offline
Зарегистрирован: 22.05.2016

А каким образом понизить частоту процессора, есть ли функция чтобы задавать частоту? Так как это позволит в состоянии бодрствования снизить энергопотребление.

a5021
Offline
Зарегистрирован: 07.07.2013

Одним из способов может быть запись соответствующего значения в прескалер (регистр CLKPR). Частоту можно понизить в 2, 4, 8 ... 128 и 256 раз. Этой фишкой удобно пользоваться для динамического изменения скорости работы МК. Например, если МК ждет некоего события и более ничем не занят, то частоту можно понизить, а когда событие происходит, то поднять частоту обратно и обработать его на максимальной скорости.

Ardfun
Offline
Зарегистрирован: 22.05.2016

a5021 пишет:

Одним из способов может быть запись соответствующего значения в прескалер (регистр CLKPR). Частоту можно понизить в 2, 4, 8 ... 128 и 256 раз. 

а поподробней где можно почитать как это с рабочим кодом увязывать

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ardfun пишет:

а поподробней где можно почитать 

В даташите.

Ardfun
Offline
Зарегистрирован: 22.05.2016

к сожалению я неумею в даташитах разбираться, я безнадежный новичек :)

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ardfun пишет:

к сожалению я неумею в даташитах разбираться, я безнадежный новичек :)

Самое время научиться.

Ну, если в даташитах не умеете, так смотрите классическую статью Гэммона, там про экономию энергии всё написано. В частности про уменьшение частоты с примером и обсуждением (начиная со слов "Altering the processor frequency")

Слава Богу, это в одну строчку делается, если power.h включить

#include <avr/power.h>

void setup(void) {
   clock_prescale_set (clock_div_256); // уменьшаем частоту в 256 раз
   ...
}

 

Ardfun
Offline
Зарегистрирован: 22.05.2016

Теперь  не могу найти данную библиотеку, и еще вопрос так как слышал что не на всех платах ардуино можна реализовать спящий и подобный режим типа дело в загружчике???

a5021
Offline
Зарегистрирован: 07.07.2013

Ardfun пишет:

Теперь  не могу найти данную библиотеку,

\Program Files\Arduino\hardware\tools\avr\avr\include\avr\power.h

parovoZZ
Offline
Зарегистрирован: 15.02.2016

А частота работы SPI зависит от значения делителя прескалера?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

parovoZZ пишет:

А частота работы SPI зависит от значения делителя прескалера?

А сами-то как думаете? Конечно, зависит. У SPI нет собственного осциллятора.

Ardfun
Offline
Зарегистрирован: 22.05.2016

так power.h должен находится в папке libraries чтоб работала библиотека но я че то недоганяю че куда(

 

a5021
Offline
Зарегистрирован: 07.07.2013

parovoZZ пишет:
А частота работы SPI зависит от значения делителя прескалера?

Зависит. Только большинству устройство частота SPI не так уж и важна. В рамках разумного, конечно. Какой подается клок, с такой скоростью и идет обмен данными.

 

a5021
Offline
Зарегистрирован: 07.07.2013

parovoZZ пишет:
А частота работы SPI зависит от значения делителя прескалера?

Зависит. Только большинству устройство частота SPI не так уж и важна. В рамках разумного, конечно. Какой подается клок, с такой скоростью и идет обмен данными.

Ardfun пишет:

так power.h должен находится в папке libraries чтоб работала библиотека но я че то недоганяю че куда(

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

ptr
Offline
Зарегистрирован: 28.05.2016

a5021 пишет:

parovoZZ пишет:
А частота работы SPI зависит от значения делителя прескалера?

Зависит. Только большинству устройство частота SPI не так уж и важна. В рамках разумного, конечно. Какой подается клок, с такой скоростью и идет обмен данными.

Частота SPI важна slave-устройству. Если ардуина выступает мастером, то да, пониженная частота SPI будет влиять только на скорость обмена по SPI. А вот если ардуина выступает слейвом, то принимать данные по SPI на пониженной частоте она может и не успеть. Например, для ATmega328, при 16Мгц тактовой, гарантируется прием только на частоте SCK до 4МГц, хотя передавать она может и на 8МГц.

В итоге, если ардуина мастер на SPI, то тактовая частота не влияет на работоспособность SPI. Если slave - то может привести к неработоспособности SPI.

Ardfun
Offline
Зарегистрирован: 22.05.2016

вроди все без ошибки компилируется но если оставить значение 256 то в моем приборе экран даже не показывает ничего, максимум 4 ставил тогда работает но страшно тормозится включение в 2 самое оптимальное  ;)

кстати void setup(void) так же нельзя писать не будет работать

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ardfun пишет:

кстати void setup(void) так же нельзя писать не будет работать

Не понял, можно поподробнее, что нельзя писать и как надо?

Ardfun
Offline
Зарегистрирован: 22.05.2016

когда написал в то заработало

 void setup() {

   clock_prescale_set (clock_div_256); // уменьшаем частоту в 256 раз
   
}

иначе ошибку писало

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Т.е. Вы хотите сказать, что программа со строчкой 

void setup() {

работает, а если вместо этой строчки написать

void setup(void) {

и ничего больше не менять, то работать перестаёт? Так?

Боюсь, Вы в чём-то ошиблись. Так не бывает. Приведите пожалуйста программу целиком.

Ardfun
Offline
Зарегистрирован: 22.05.2016

извиняюсь вы правы, я не так все делал сначала, все работает) только вопрос в чем rfhlbyfkmyj отличие когда void setup(void) и когда просто стандартно void setup()?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ardfun пишет:

в чем отличие когда void setup(void) и когда просто стандартно void setup()?

Смотря в каком языке (это довольно тонкое отличие С от С++).

В С++ разницы нет никакой.

В С разница есть:

void f() {}   // Функция f может иметь любое (включая и 0) количество аргументов
void s(void) {}   // Функция s не имеет аргументов. Попытка передать аргумент вызовет ошибку

Разница в контроле, который осуществляет компилятор. Например, если у функции реально не должно быть аргументов, то лучше явно сказать про это компилятору (написать void). Тогда, если Вы по ошибке вызовете её с аргументом (ами) (ну, например, Вы ошибочно полагаете. что аргументы ей нужны), компилятор обругается. А если не писать void, то он это молча проглотит и ошибку можно будет обнаружить только при выполнении.

Это, конечно, "на скорость не влияет", но лучше так делать. Полная аналогия, например - заземление корпуса люстры. Пока всё хорошо - нет никакой разницы заземлена она или нет. Но если вдруг почему-то фаза закоротит на корпус, то при заземлённой люстре Вы об этом сразу же узнаете (автомат вышибет) и почините. А если у Вас корпус люстры не заземлён, то о том, что на нём фаза Вы узнаете только когда лапнете рукой за корпус при смене лампочки. Видите разницу?