Обсуждаем контроллеры компании Atmel.
Ответить

Проблемы с режимом Power-Save Atmega16A

Чт янв 03, 2019 14:26:18

Здравствуйте, уважаемые форумчане!
Отзовитесь, кто работал с режимом Power-Save в Atmega16A.
В устройстве есть резервное батарейное питание от CR2032 и внешнее 5в. Развязано двумя диодами Шоттки. Все внешние линии запитаны от 5в, от резервного питается только контроллер.
Раз в секунду по асинхронному таймеру включаю компаратор с внутренним ИОН. Если напряжение ниже, ухожу в спячку, предварительно повесив все порты в hi-z.
В симуляции все работает, да и в железе судя по всему в спячку контроллер уходит - проверял вставкой короткой вспышки светодиода. Очень тускло, через обратный диод развязки питания, но он моргает. Следом идет команда sleep, значит по идее контроллер должен засыпать.

Беда в том, что даже в этом режиме схема жрет 2,5мА, что для 2032 много, долго она не проживет.
Как еще проверить уходит ли реально контроллер в спячку? И вообще, сколько должен потреблять контроллер в режиме Power-Save?

Re: Проблемы с режимом Power-Save Atmega16A

Чт янв 03, 2019 15:44:01

ATmega16 Здесь есть всё. И то, что периферию (JTAG, к примеру) нужно отключать и то, что порты нужно держать хотя бы с встроенной подтяжкой и то, в режиме POWER SAVE ток потребления <10...12мкА. :)

Re: Проблемы с режимом Power-Save Atmega16A

Чт янв 03, 2019 16:49:26

А "Монитор питания выключен"? СКОРТ то же выключен?

Re: Проблемы с режимом Power-Save Atmega16A

Чт янв 03, 2019 18:13:14

BOD, JTAG, WDT выключены, порты в hi-z. Плата выверенная, заводская, утечек быть не должно.
А что такое СКОРТ? Простите за глупый вопрос.
У меня небезосновательное подозрение, что он просто не засыпает. Уже проверил, если убрать sleep_cpu(), все те же 2,5мА...

Re: Проблемы с режимом Power-Save Atmega16A

Чт янв 03, 2019 19:24:52

СКОРТ страница 25 выше приведенного даташита.
От какой частоты тактируется контроллер?
Укажите последовательность команд перехода в слееп режим?

Re: Проблемы с режимом Power-Save Atmega16A

Чт янв 03, 2019 20:37:34

//инициализация power save
MCUCR = (1<<SE)|(0<<SM2)|(1<<SM1)|(1<<SM0);
...

while()
{
переводим порты в hi-z, затем
sleep_cpu();
}


частота 8, внутренний RC.
fuse CKOPT=0

Re: Проблемы с режимом Power-Save Atmega16A

Чт янв 03, 2019 20:47:37

внутренний rc 8МГц
active > 2000mkA
powerdown - 6mkA - Асинхронный тамер

внутренний rc 128кГц
active - 56mkA
powerdown - 5mkA - Асинхронный тамер
Eric_88 писал(а):Раз в секунду по асинхронному таймеру включаю компаратор с внутренним ИОН.
Асинхронный таймер от чего тактируется? От низкого кварца, допустим 32768кГц, или как?

Re: Проблемы с режимом Power-Save Atmega16A

Чт янв 03, 2019 21:14:48

Асинхронный таймер от часового кварца тактируется.
Я понимаю, что чем меньше частота, тем меньше потребление. Но я боюсь не успеть, много считать всего в промежутках. Плюс еще таймер индикатора настроен на 8 МГц, ставишь меньше - цифры мерцают, уменьшаешь делитель - засветка.
Странно себя ведет контроллер, когда уходит в спячку, ток падает до 80мкА, потом секунд за 7 растет до 2,3мА и уже не падает(( Если вывести из спячки и снова усыпить, все повторяется. Такое ощущение, что после того, как его будит асинхронный таймер, что-то ломается...

Re: Проблемы с режимом Power-Save Atmega16A

Пт янв 04, 2019 02:11:40

Eric_88 писал(а):переводим порты в hi-z, затем sleep_cpu();
The simplest method to ensure a defined level of an unused pin, is to enable the internal pull-up. In this case, the pull-up will be disabled during reset. If low power consumption during reset is important, it is recommended to use an external pull-up or pull-down.


Eric_88 писал(а):частота 8, внутренний RC. fuse CKOPT=0

The CKOPT Fuse should always be unprogrammed when using this clock option.

Re: Проблемы с режимом Power-Save Atmega16A

Пт янв 04, 2019 04:23:36

Eric_88 писал(а):Такое ощущение, что после того, как его будит асинхронный таймер, что-то ломается...
Все верно, сейчас бы я у вас спросил последовательность (код) работы с асинхронным таймером, но да ладно.

Вот примерный код:
Спойлер
Код:
#include <mega16a.h>
#include <sleep.h>

#define KN_PORT    PORTC     // порт
#define KN_DDR     DDRC
#define KN_PIN     PINC

#define KN_D         0        // пин кнопка

// Declare your global variables here
bit Power_detect=0;

// Timer2 overflow interrupt service routine
interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{
// Place your code here
   if(KN_PIN & (1<<KN_D)) {
    Power_detect=1;
   } else { Power_detect =0;
   }

}

void main(void)
{

// Input/Output Ports initialization
// Port A initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
DDRA=(0<<DDA7) | (0<<DDA6) | (0<<DDA5) | (0<<DDA4) | (0<<DDA3) | (0<<DDA2) | (0<<DDA1) | (0<<DDA0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
PORTA=(0<<PORTA7) | (0<<PORTA6) | (0<<PORTA5) | (0<<PORTA4) | (0<<PORTA3) | (0<<PORTA2) | (0<<PORTA1) | (0<<PORTA0);

// Port B initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
DDRB=(0<<DDB7) | (0<<DDB6) | (0<<DDB5) | (0<<DDB4) | (0<<DDB3) | (0<<DDB2) | (0<<DDB1) | (0<<DDB0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0);

// Port C initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
DDRC=(0<<DDC7) | (0<<DDC6) | (0<<DDC5) | (0<<DDC4) | (0<<DDC3) | (0<<DDC2) | (0<<DDC1) | (0<<DDC0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
PORTC=(0<<PORTC7) | (0<<PORTC6) | (0<<PORTC5) | (0<<PORTC4) | (0<<PORTC3) | (0<<PORTC2) | (0<<PORTC1) | (0<<PORTC0);

// Port D initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
DDRD=(0<<DDD7) | (0<<DDD6) | (0<<DDD5) | (0<<DDD4) | (0<<DDD3) | (0<<DDD2) | (0<<DDD1) | (0<<DDD0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
PORTD=(0<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (0<<PORTD0);

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=0xFF
// OC0 output: Disconnected
TCCR0=(0<<WGM00) | (0<<COM01) | (0<<COM00) | (0<<WGM01) | (0<<CS02) | (0<<CS01) | (0<<CS00);
TCNT0=0x00;
OCR0=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer1 Stopped
// Mode: Normal top=0xFFFF
// OC1A output: Disconnected
// OC1B output: Disconnected
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);
TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (0<<WGM12) | (0<<CS12) | (0<<CS11) | (0<<CS10);
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: TOSC1 pin
// Clock value: PCK2/128
// Mode: Normal top=0xFF
// OC2 output: Disconnected
ASSR=1<<AS2;
TCCR2=(0<<PWM2) | (0<<COM21) | (0<<COM20) | (0<<CTC2) | (1<<CS22) | (0<<CS21) | (1<<CS20);
TCNT2=0x00;
OCR2=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=(0<<OCIE2) | (1<<TOIE2) | (0<<TICIE1) | (0<<OCIE1A) | (0<<OCIE1B) | (0<<TOIE1) | (0<<OCIE0) | (0<<TOIE0);

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// INT2: Off
MCUCR=(0<<ISC11) | (0<<ISC10) | (0<<ISC01) | (0<<ISC00);
MCUCSR=(0<<ISC2);

// USART initialization
// USART disabled
UCSRB=(0<<RXCIE) | (0<<TXCIE) | (0<<UDRIE) | (0<<RXEN) | (0<<TXEN) | (0<<UCSZ2) | (0<<RXB8) | (0<<TXB8);

// Analog Comparator initialization
// Analog Comparator: Off
// The Analog Comparator's positive input is
// connected to the AIN0 pin
// The Analog Comparator's negative input is
// connected to the AIN1 pin
ACSR=(1<<ACD) | (0<<ACBG) | (0<<ACO) | (0<<ACI) | (0<<ACIE) | (0<<ACIC) | (0<<ACIS1) | (0<<ACIS0);
SFIOR=(0<<ACME);

// ADC initialization
// ADC disabled
ADCSRA=(0<<ADEN) | (0<<ADSC) | (0<<ADATE) | (0<<ADIF) | (0<<ADIE) | (0<<ADPS2) | (0<<ADPS1) | (0<<ADPS0);

// SPI initialization
// SPI disabled
SPCR=(0<<SPIE) | (0<<SPE) | (0<<DORD) | (0<<MSTR) | (0<<CPOL) | (0<<CPHA) | (0<<SPR1) | (0<<SPR0);

// TWI initialization
// TWI disabled
TWCR=(0<<TWEA) | (0<<TWSTA) | (0<<TWSTO) | (0<<TWEN) | (0<<TWIE);

// Global enable interrupts
#asm("sei")

while (1)
      {
      // Place your code here

       if (Power_detect==1) {
        sleep_disable();
       } else {
          //Вход в режим сна (пробуждение наступит после
         // возникновения прерывания timer overflow interrupt):

             //Разрешение входа в режим сна:                     
            sleep_enable();
            powersave();
           
          //Запись пустого значения в регистр управления:
         TCCR2=(0<<PWM2) | (0<<COM21) | (0<<COM20) | (0<<CTC2) | (1<<CS22) | (0<<CS21) | (1<<CS20);
         //Ожидание завершения обновления TC2:
          while(ASSR & ((1 << TCR2UB)|(1 << OCR2UB)|(1 << TCN2UB)));                       
       }
             
      }
}
Power detect
СпойлерИзображение

Re: Проблемы с режимом Power-Save Atmega16A

Пт янв 04, 2019 14:13:06

The simplest method to ensure a defined level of an unused pin, is to enable the internal pull-up...

The CKOPT Fuse should always be unprogrammed when using this clock option.

Хм, я всегда считал (и читал), что самое энергетически выгодное состояние - это hi-z. Спасибо, попробую pull-up.
а вот на счет CKOPT, бегло взглянул и без всяких сомнений считал, что 0 - это выключен... Спасибо.

Dimon, все у меня в точности, как вы написали. Плюс/минус.
За исключением ожидания падения флагов. Вчера поздно ночью дочитался до этого в статье DI HALTа про асинхронный таймер, но пробовать уже не вариант было) сейчас попробую, спасибо.

Еще вчера вспомнил, что не нашел хороших номиналов резисторов для делителя, поэтому впаял 15к и 30к, а это лишние 58мкА пассивной нагрузки. Заменю на высокие.

Добавлено after 1 hour 9 minutes 29 seconds:
Всем спасибо огромное, кажется заработало!
Во сне стабильно держит 66 мкА. Из них 58 - делитель. Поставлю резисторы в 10 раз больше и ток упадет соответственно.
Повесил свободные пины в pull-up, занятые оставил в hi-z. Если все повесить в pull-up, ток около 250 мкА.
Сейчас оставил на длительный тест точности часов во сне.
Еще раз спасибо!
Ответить