Потребление тока в спящем режиме ATmega328PB

Я использую ATmega328PB для работы радиочастотного модуля. При тестировании потребления тока в спящем режиме я заметил, что оно значительно выше ожидаемого. Я удалил все ненужные компоненты. В схеме остались только: микросхема ATmega328PB, подтягивающий резистор между выводами VCC и RESET, конденсаторы ёмкостью 10 мкФ и 0,1 мкФ между VCC и GND; схема сводится к следующей схеме. эквивалентная схема со всем удалённым

Я работаю с микросхемой на внутренней частоте 8 МГц и напряжении 3,3 В. Я пробовал использовать функцию power_all_disable(), устанавливая все выводы в режим подтяжки входов, устанавливая предделитель тактовой частоты на clock_div_4, вызывая sleep_bod_disable() и устанавливая спящий режим в режим пониженного энергопотребления. В техническом описании (раздел 33.3 страница 352) указано, что микросхема должна потреблять 3,2 мкА в этом режиме, но я измеряю 110 мкА. Поскольку моя тактовая частота выше рекомендуемых 4 МГц при напряжении 3,3 В, я ожидаю, что потребление тока будет больше, но не настолько. Вот весь код, который я запускаю.

void setup(){
    delay(2000) //просто чтобы я мог сравнить текущие уровни (4,8 мА перед сном)
    power_all_disable();
    power_adc_disable();
    power_spi1_disable();
    power_spi_disable();
    power_timer0_disable();
    power_timer1_disable();
    power_timer2_disable();
    power_twi_disable();
    power_usart0_disable();
    for(uint8_t i = 0; i < 27; i++){
      pinMode(i, INPUT_PULLUP);
    }

    ADCSRA &= ~(1 << ADEN);
    ADCSRB &= ~(1 << ADEN);
    clock_prescale_set(clock_div_4);
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
    sleep_enable();
    sleep_bod_disable();
    sleep_mode();
 
    while(true);
}

loop(){

}

Я измеряю, подключая мультиметр последовательно между источником питания и схемой. Я знаю, что это может увеличить нагрузку на цепь и, следовательно, увеличить ток, но схема, которую я использую в качестве эталона, представляет собой другую версию этого модуля с микросхемой ATmega324P, которая измеряет около 40 мкА в спящем режиме с помощью той же схемы мультиметра. Если бы мне удалось снизить потребление тока примерно до 50 мкА с помощью этой схемы, этого было бы достаточно.

РЕДАКТИРОВАТЬ:

Я скомпилировал тот же код, что и выше, для ATmega324PB и загрузил его на плату, которую использовал в качестве образца. Потребление тока у него такое же, как у ATmega328PB (110 мкА). Когда я загружаю старый код, который был на нём, потребление падает до 14 мкА. Это очень убедительно указывает на то, что проблема программная, а не аппаратная. К сожалению, код длинный, старый и не очень хорошо организован. К тому же, он написан в Atmel Studio, а значит, я не могу просто перенести его на Arduino или перенести свой скетч с Arduino на Atmel.

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

//enable SPI, set as Master, set clock rate fck/8 = 500kHz
SPCR1 = (1 << SPE) | (1 << MSTR) | (1 << SPR0);

Похоже, устройство больше не переходит в спящий режим. Однако в данном случае потребляемый ток остаётся около 2,8 мА, а не 110 мкА, как выдаёт моя программа.

Еще одна вещь, которую я заметил и которая, как я теперь думаю, может быть причиной проблемы, заключается в том, что пока чип активен (т.е. не спит), в моей программе он работает при 2,9 мА, в то время как в старом коде он работал при 2,8 мА. Эта разница в 0,1 мА - это та же разница в режимах сна, из чего я делаю вывод, что в моем коде по какой-то причине что-то всегда включено, тогда как в старом коде это не так или оно отключено, но я понятия не имею, что именно.

, 👍4

Обсуждение

1. Обратите внимание, что бит ADEN принадлежит ADCSRA, а не ADCSRB. 2. Можете ли вы попробовать [рекомендуемую практику для сна с отключенным BOD](https://www.nongnu.org/avr-libc/user-manual/group__avr__sleep.html)?, @Edgar Bonet

@EdgarBonet 1. Я изменил его на ACME, хотя это не имело значения. 2. Единственное отличие в том, что у меня был дополнительный вызов sleep_enable() после sleep_bod_disable(), что не должно иметь значения, но я все равно это сделал (текущее состояние без изменений)., @user98055

Это не тот код, который вы запускаете, потому что он не компилируется. В строке sleep должна быть точка с запятой, а перед loopvoid., @Nick Gammon

Где вы приобрели ATMEGA328PB? Ходят слухи о «клонах» ATMEGA328P, которые потребляют больше энергии, чем обычно, в спящем режиме. Иногда их устанавливают на такие платы, как Pro Mini. Возможно, в продаже также встречаются «клоны» версии «PB»., @6v6gt


1 ответ


Лучший ответ:

1

Запустив ваш код в качестве теста на моем Atmega328P, я получил следующее:

15 мА, затем упал до 141 мкА.

Однако следующий код:

#include <avr/sleep.h>
void setup() {
  delay(2000); //просто чтобы я мог сравнить текущие уровни (4,8 мА перед сном)

  for (uint8_t i = 0; i < 27; i++) {
    pinMode (i, OUTPUT);
    digitalWrite(i, LOW);
  }
  
  // отключить АЦП
  ADCSRA = 0;

  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  noInterrupts ();           // следует временная последовательность
  sleep_enable();
  // отключить функцию отключения питания в программном обеспечении
  MCUCR = bit (BODS) | bit (BODSE);
  MCUCR = bit (BODS); 
  interrupts ();
  sleep_cpu();

  while (true);
}

void loop() {

}

.. дал мне 15,6 мА, затем упал до 0,128 мкА (128 нА).

,

Оказывается, power_all_disable() и power_adc_disable() на самом деле не отключают АЦП, потому что как только я сам отключил его через регистр (вместо этого я сделал ADCSRA &= ~(1<<ADEN);), мощность упала полностью!, @user98055