Снизить энергопотребление в "0"

Vitaly
Offline
Зарегистрирован: 12.09.2011

 Снизить энергопотребление в "0".

Возможно ли  на atmega снизить энергопотребление до микроампер? дело в том, что нужно получить ОДИН импульс в СУТКИ. а контроллер питается от батарей и в обычном режиме потребляет 5-7 милиампер. Батарейки быстро разрядятся.

Какие есть варианты решения этой задачи? Может быть есть специальные экономичные микросхемы для этих целей?

step962
Offline
Зарегистрирован: 23.05.2011

Vitaly пишет:

 Возможно ли  на atmega снизить энергопотребление до микроампер?

Режимы работы микроконтроллера, позволяющие снижать потребление до 1-2 мкА (?), жертвуя его различными возможностями, имеются на любой вкус:

Idle mode

ADC noise reduction mode

Power-down mode

Power-save mode

Standby mode

Почитать о них можно в 10-й главе даташита или на многих-многих тематических сайтах, первый попавшийся: http://physlab.pomorsu.ru/FreeResources/Users/files/Electroradio_Engineering/2/ATmega128,%20ATmega128L/4.htm

Еще один вариант снижения потребления - снижение тактовой частоты. Тот же самый даташит утверждает:

Low power consumption
– Active mode:
250μA at 1MHz, 1.8V
15μA at 32kHz, 1.8V (including oscillator)
– Power-down mode:
0.1μA at 1.8V
 

Vitaly
Offline
Зарегистрирован: 12.09.2011

 step962, спасибо. Попробовал. Оказалось, что сторожевой таймер жутко нестабильная вешь. За 12 часов уход времени составил около часа. Делал на атмеге 168, таймер ставил на 8 секунд. Зато токопотребление порадовало - всего около 0.033 милиампер.

Наверное мне нужно было чётче сформулировать задачу) Устройство должно выдавать стабильно сигнал один раз сутки и один раз в неделю, при этом работая от батарейки. уход времени может быть максимум 10-20 минут в месяц. Похоже, что стандартными средставими атмеги тут не обойтись. Сегодня обнаружил, что существует удивительная микросхема DS1307. Думаю именно на ней можно реализовать моё устройство. Нашёл уже варианты часов с использованием этой микросхемы, но во всех примерах атмега работает постоянно, то есть не переходит в спящий режим. Сейчас ломаю голову как добавить такую функцию.

step962
Offline
Зарегистрирован: 23.05.2011

Vitaly пишет:

 Оказалось, что сторожевой таймер жутко нестабильная вешь.

В каком режиме тестировали?

Цитата:

уход времени может быть максимум 10-20 минут в месяц. Похоже, что стандартными средставими атмеги тут не обойтись. Сегодня обнаружил, что существует удивительная микросхема DS1307.

DS1307 на стандартном кварце дает уход в несколько секунд за месяц.

Цитата:

Думаю именно на ней можно реализовать моё устройство. Нашёл уже варианты часов с использованием этой микросхемы, но во всех примерах атмега работает постоянно, то есть не переходит в спящий режим. Сейчас ломаю голову как добавить такую функцию.

1. Подберите спящий режим с побудкой не от сторожевой собаки, а от внешнего прерывания (INT0/INT1)

2. Найдите у DS1307 ногу, на которую выдаются секундные импульсы (а еще учше минутные). Соедините эту ногу с выводом D2 или D3 Arduin'ы (они отвечают за прерывания INT0/INT1 - подробности смотрите в даташите).

3. Засыпайте спокойно - DS-ка обеспечит побудку в нужный момент.

Vitaly
Offline
Зарегистрирован: 12.09.2011

Дело в том, что по инструкции,  DS1307 может выдавать только секундные импульсы или чаще. А включатся каждую секунду, это будет уже неэкономно.

Пока я попробовал так: 

атмега кажые 8 секунд просыпается и "смотрит" время по DS1307. Для пробы вывожу в ком порт. Работает. Подожду сутки. Чтобы получить суточные импульсы, думаю сравнивать текущее время, с заранее указанным и в случае совпадения давать сигнал. Фактически это тупо будильник получается. Жаль, что будильник не реализован непосредственно в DSке, это бы сильно упростило задачу и код.

step962
Offline
Зарегистрирован: 23.05.2011

Vitaly пишет:

Дело в том, что по инструкции,  DS1307 может выдавать только секундные импульсы или чаще. А включатся каждую секунду, это будет уже неэкономно.

Пока я попробовал так: 

атмега кажые 8 секунд просыпается

[...]

1. Какой режим засыпания используете?

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

 

Vitaly
Offline
Зарегистрирован: 12.09.2011

Я точно не могу сказать какой именно испольуется режим засыпания, но выгляди это вот так:
{
cbi( SMCR,SE ); 
cbi( SMCR,SM0 ); 
sbi( SMCR,SM1 ); 
cbi( SMCR,SM2 ); 

 

собственно момент засыпания 

cbi(ADCSRA,ADEN);
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();

} все выходы переключаются в режим входа, это точно. 

проверить, что будет экономнее, представляет некоторую сложность. Дело в том, что включение и опрос времени происходит настолько мгновенно, что засечь время не получается. А осциллограф недоступен. 

step962
Offline
Зарегистрирован: 23.05.2011

Vitaly пишет:

cbi( SMCR,SE ); 
cbi( SMCR,SM0 ); 
sbi( SMCR,SM1 ); 
cbi( SMCR,SM2 ); 

SM2..SM0: 010 - это режим Power Down, при котором пробуждение может происходить только от сторожевого таймера, схемы BOD или от внешнего прерывания (INT0/INT1).

если установить SM2..SM0 в "011" (т.е. sbi(SMCR,SM0);), то микроконтроллер будет входить в режим Power Save, идентичный предыдущему (чуть более прожорливый), но дополнительно появляется возможность пробуждения от таймера/счетчика TMR2. То есть появляется возможность настроить таймер/счетчик на генерацию прерывания при достижении значения 240 (TMR2 8-битный) и, подавая посекундный сигнал от микросхемы RTC на вход таймера/счетчика TMR2, пробуждать микроконтроллер каждые 4 минуты (240 сек).

 

Как-то так ...

step962
Offline
Зарегистрирован: 23.05.2011

Vitaly пишет:

проверить, что будет экономнее, представляет некоторую сложность. Дело в том, что включение и опрос времени происходит настолько мгновенно, что засечь время не получается. А осциллограф недоступен. 

Вопрос был в некоторой степени риторическим - опрос состояния микросхемы (по последовательному каналу!!!) в тактах может оказаться длиннее сэкономленных семи пробуждений/засыпаний. Или почти равен оному.

step962
Offline
Зарегистрирован: 23.05.2011

Vitaly пишет:

{
cbi( SMCR,SE ); 
cbi( SMCR,SM0 ); 
sbi( SMCR,SM1 ); 
cbi( SMCR,SM2 ); 

 

собственно момент засыпания 

cbi(ADCSRA,ADEN);
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();

}

Если в Вашей программе инструкции стоят именно в таком виде и порядке, то она несколько перегружена,

ведь три операции установки/сброса битов SM2...SM0 задают микроконтроллеру режим засыпания, но ведь то же самое, похоже происходит и в функции set_sleep_mode (о чем говорит параметр-константа SLEEP_MODE_PWR_DOWN).

Согласно даташиту, условием входа в любой из режимов сна является установка бита SE регистра SMCR в 1. То есть самая первая операция (установка SE в 0) не имеет смысла.

Ну и наконец cbi(ADCSRA,ADEN). Этот бит отвечает за работу АЦП. Сбросив его, Вы выключаете АЦП. Но в режимах Power Save, Power Down и Standby АЦП и так выключается. Операция имеет смысл только для режимов Idle и ADC Noise Reduction.

 

ustas
Offline
Зарегистрирован: 12.03.2012

Хочу сделать "долгоиграющий" модуль (пока это датчик уличной температуры и влажности, построенный на базе DHT11). Коммуникация с основным блоком происходит по радиоканалу (nRF24L01)

Для снижения питания выбрасываю из схемы все лишнее - остается только сам "камень" (с кварцевым резонатором и парой конденсаторов), стабилизатор питания на 3.3В (L78L33 и пара конденсаторов по питанию) для питания RF-модуля, пара резисторов (один для подтягивания Reset к питанию и второй - для работы датчика).

У RF-модуля задействую вывод IRQ для пробуждения "камня", когда приходит запрос от "головного" блока. Когда устойство бездействует - загоняю его в режим SLEEP_MODE_PWR_DOWN.

Питаю всю конструкцию от 3 батареек ААА. 

Все функционирует отлично, только комплект батареек эта конструкция высасывает за 2 дня (батарейки обычные, не алкалийные).

Как-то совсем грустно от такой "продолжительности" жизни... (запросы к датчику идут раз в 4 минуты, все остальное время - "спим").

Сегодня попробовал вариант с "возобновляемой" энергией (солнечная панель на 0,5Вт, зарядник http://www.seeedstudio.com/wiki/Lipo_Rider_V1.1 и АКБ на 1000мАч 3.7В) - пока непонятно, понаблюдаю пару дней...

Может, у кого-то есть мысли, как можно продлить жизнь подобной конструкции? Как еще можно минимизировать потребление?

На всякий случай приведу скетч модуля:

#include <SPI.h>
#include <DHT.h>
#include <Mirf.h>
#include <ASLibrary1.h>
#include <MirfHardwareSpiDriver.h>
#include <avr/sleep.h>


#define NumSensors 2

AS_SensorStatus MySensors[NumSensors] = {
  0,0,"tmp(C)",
  0,0,"hdm(%)"};

DHT dht(6, DHT11);  //Создаем датчик DHT11 на 6 пине

float t, h;

void wakeupFunction(){
}

void toSleep(){
  attachInterrupt(0,wakeupFunction,LOW);
  sleep_mode();
  detachInterrupt(0);
}


void setup() {
  //Serial.begin(9600);
  dht.begin(); //Инициализируем датчик DHT

  for(int i=0; i<NumSensors; i++){
    MySensors[i].Status = 0;
  }
  
  Mirf.spi = &MirfHardwareSpi;
  Mirf.csnPin = 9;
  Mirf.cePin = 8;
  Mirf.init();
  Mirf.setRADDR((byte *)"TEST"); //Задаем адрес под которым будем принимать данные
  Mirf.setTADDR((byte *)"TEST");
    
  Mirf.payload = AS_NRF24L01_payload; //Задаем размер буфера данных
  Mirf.channel = AS_NRF24L01_channel; //Задаем канал
  Mirf.config(); //Инициализируем модуль NRF24L01
  //Serial.println("init");
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();//Переходим в спящий режим

}

//Вычисляет все данные и заполняет массив значений датчиков
byte CalculateAllData()
{
  t = dht.readTemperature();
  h = dht.readHumidity();
  
  //Serial.println(t);

  if (isnan(t) || isnan(h)) {
    MySensors[0].Status = 0;
    MySensors[0].Value = 0;
    MySensors[1].Status = 0;
    MySensors[1].Value = 0;
  }
  else {
    MySensors[0].Status = 1;
    MySensors[0].Value = t;
    MySensors[1].Status = 1;
    MySensors[1].Value = h;
  }
  return 1;
}

AS_Answer ExecuteCommand(AS_Command MyCommand){
  
  AS_Answer  MyAnswer;  // Ответ
  MyAnswer.Status = 0;
  MyAnswer.Value  = 0;
  
  switch (MyCommand.Command) {
    case 0: //Reset
      resetFunc();
      break;
    case 1: //Получиь количество датчиков
    //Serial.println("1");
      MyAnswer.Status = 1;
      MyAnswer.Value  = NumSensors;    
      break;
    case 2: //Рассчитать все значения датчиков
    //Serial.println("2");
      MyAnswer.Status = CalculateAllData();
      break;
    case 4: //Получиь значение датчика по номеру
    //Serial.println("4");
      if ((MyCommand.Parametr+1) > NumSensors){
        MyAnswer.Status = 0;
        MyAnswer.Value  = 0;
        memcpy(&MyAnswer.Comment,&"Too big num par.", CommentLen);
      }
      else{
        MyAnswer.Status = MySensors[MyCommand.Parametr].Status;
        MyAnswer.Value  = MySensors[MyCommand.Parametr].Value;    
        memcpy(&MyAnswer.Comment,&MySensors[MyCommand.Parametr].Comment, CommentLen);
      }
      break;
    }
  return MyAnswer;
}

void loop() {

  AS_Command MyCommand; // Команда
  AS_Answer  MyAnswer;  // Ответ

  if(!Mirf.isSending() && Mirf.dataReady()){
    Mirf.getData((byte *) &MyCommand);
    //Serial.println("command");
    MyAnswer = ExecuteCommand(MyCommand);
    Mirf.send((byte *) &MyAnswer);
    while(Mirf.isSending()){}
  }
  else{
    /* No data - night night. */
    toSleep();
  }

}

 

 

freearduino
Offline
Зарегистрирован: 21.04.2014

Я покупал вот такие вот солнечные ячейки:

http://www.ebay.com/itm/A-Grade-125x125-Monocrystalline-Solar-Cells-Mono...

Разрезал ячейку на несколько частей, что-бы добится повышения напряжения(т.к. одна ячейка дает 0.5В 6-7Ампер), получалось 10 кусочков и ставил батарейку(подключал через диод).

У меня в городе одна ячейка стоит 100р. Суммарно получалось 300р.

Практика показала что МК может работать круглосуточно. Зависит от емкости АКБ.

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

могу вам рекомендовать два варианта

1. делаем свою плату (важно, чтобы не было ничего лишнего). Ставим туда минимальный обвес МК без кварца - т.е. только МК + керамический конденсатор 0.1мкф по питанию. Для экономии батарейки лучше расчитать питание без стабилизатора, например от одной Lion можно питать напрямую. Если не получится, то поставить LDO с треблением не более 1мка.  Дальше читаем раздел даташита на atmega328p где описан асинхронным режим таймера. Согласно описанию подключаем внешний часовой кварц (32768Гц). В этом варианте самым критичным будет выбор кварца. От него будет зависеть точность хода. Дальше пишем правильную программу (только ардуино вам тут не большой помошник, таймеры надо будет самому настраивать) и используем где только можно режим Power_save, в этом режиме асинхронный таймер продолжает работать. Этот вариант лучше чем вариант с DS1307 так как кроме МК тут больше никто ничего не потребляет Да! МК тактируем от внутренней RC 1МГЦ (настраиваем фьюзы) и дополнительно снижаем частоту по максимуму используя предт\делитель на 1024.

2. В первом варианте будет проблема найти точный кварц (вариант с DS1307 страдает той же проблеммой). Так что во стором варианте используем RTC со встроенным кварцем - например DS3231. Этот RTC хорош тем, что на нем можно настроить будильник с точностью до минуты и пробуждать МК по будильнику отключив на МК се таймеры (даже WDT). Используем POWER_DOWN. Вариант хорош тем, что бет высокая точность кварца, это гарантируется производителем чипа

alecksis
alecksis аватар
Offline
Зарегистрирован: 13.10.2017

есче один способ , использоватьWatchDogT , с прерыванием. Каждые 8 секунт происходит разбудение контроллера. Можно проверить что надо, а потом в сон.

b707
Offline
Зарегистрирован: 26.05.2017

alecksis пишет:

есче один способ , использоватьWatchDogT , с прерыванием. Каждые 8 секунт происходит разбудение контроллера. Можно проверить что надо, а потом в сон.

дурной тон отвечать на сообщение 4х-летней давности... и даже не прочитав ветку целиком :)