Потребление тока в спящем режиме 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 мА - это та же разница в режимах сна, из чего я делаю вывод, что в моем коде по какой-то причине что-то всегда включено, тогда как в старом коде это не так или оно отключено, но я понятия не имею, что именно.
@user98055, 👍4
Обсуждение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
- Самая низкая мощность, возможная в Arduino
- Как перевести ATtiny/ATmega в режим глубокого сна (чтобы годами работать от батарей), но при этом обнаруживать нажатие кнопки?
- Датчик DHT11: режим ожидания или выключение?
- Энергосберегающая конфигурация несоединенных контактов
- Случайно закоротил 5 В на GND на Arduino Nano. Могу ли я повторно использовать ATmega328p?
- Настройка таймера ATMega328p (Arduino)
- Измерение литий-ионого аккумулятора, от которого работает Arduino
- Откуда берется выходная мощность 5 В на Arduino uno?
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должна быть точка с запятой, а передloop—void., @Nick GammonГде вы приобрели ATMEGA328PB? Ходят слухи о «клонах» ATMEGA328P, которые потребляют больше энергии, чем обычно, в спящем режиме. Иногда их устанавливают на такие платы, как Pro Mini. Возможно, в продаже также встречаются «клоны» версии «PB»., @6v6gt