ATMEGA328P power down mode not working as expected

Status
Not open for further replies.

vinodstanur

Advanced Member level 3
Joined
Oct 31, 2009
Messages
751
Helped
114
Reputation
234
Reaction score
114
Trophy points
1,333
Location
Kerala (INDIA)
Activity points
7,054
Hi,
I am trying powerdown mode in avr atmega328p.
I am using internal 1MHz clock, brown out detection disabled in fuse.

My problem is, I am not able to get a current less than 55uA at power down mode...

Here is my code:

Code:
#include <avr/io.h>
#define F_CPU 1000000UL
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <avr/wdt.h>
#include "uart.h"

void deepsleep(void);
void extint_enable(void);

ISR(INT0_vect)
{
}

//main routine
void main(void)
{
		DDRB |= 1<<PB0;
		extint_enable();
		sei();
		deep_sleep();
                 //after wakeup blink led
		while(1) {
			PORTB ^= 1<<PB0;
			_delay_ms(1000);
		}

}

void deep_sleep(void) {
		set_sleep_mode(SLEEP_MODE_PWR_DOWN);
		sleep_mode();
}

void extint_enable(void) {
   	 	EICRA |= (1<<ISC01)|(1<<ISC00);
      	    EIMSK |= 1<<INT0;
}


Circuit is simple, pulled up reset using 10k resistor, pulled down interrupt 0 pin using 10k resistor, connected a .1uf cap between Vdd and gnd close to mcu, connected an LED with 100 E at PB0 to ground.... Thats all....

Removed the ISP programmer after programming still the current is 55uA .... Measuring using M890G UNITY multimeter...

Also one more thing, since it is ATMEGA328(P) I tried to reduce the voltage to 1.8V but at that time the powerdown mode current becomes 215uA..

BUT according to datasheet it is written as
Low Power Consumption at 1 MHz, 1.8V, 25°C for ATmega48PA/88PA/168PA/328P:
– Active Mode: 0.2 mA
– Power-down Mode: 0.1 μA
– Power-save Mode: 0.75 μA (Including 32 kHz RTC)


So what will be the problem ?
 

Most likely reason for excessive current consumption is floating input state of unconnected pins, possibly activation of additional poecessor resources,

Generally speaking, it's necessary to think a little bit when designing a low power application. Consider the intended state of each processor pin. If not connected to an external driver,pins should be either driven as output or by internal pull-up resistor.
 

Hi, thanks for this info.. I got an improvement after connecting the AVCC to VCC pin...
Now the current is 20uA at power down mode. earlier it was 55uA.

Then I pulled up all the unused port pins internally by writing 1 to those bits. But couldn't find further improvement... Also I tried to write 1 and 0 after making all unused pins output but still 20uA..
Still I am far away from the datasheet values ie 0.1uA..
 

I must confess that i didn't implement low power ATmega applications, but the problems are basically the same as with other processors e.g. PIC.

I can just suggest to read the datasheet chapter "Minimizing Power Consumption" line by line and check every detail.
 
Another common source of unwanted power consumption are peripheral modules which can remain unintentionally active even after the device is put into a Power Down Sleep Mode.

Common culprits are the ADC and BOD peripheral modules, both of which remain in an active state in various Power Saving/Sleep Modes.

From personal experience, I've noted the Brown Out Detection (BOD) Module alone can consume over 15uA if active during Power Down Sleep Mode.

Check your fuse configuration and ensure all unneeded peripheral modules configurable by fuses are disabled at powerup by default.

The Power Reduction Register(s) (PRR), in devices with offer them, and the MCU Control Register (MCUCR) can be modified during runtime to disable any unneeded peripheral modules before the device is put into a particular Sleep Mode.

For devices which do provide a Power Reduction Register(s) (PRR) these runtime modifications can be made by using the routines found in:

Code:
#include <avr/power.h>

// Example
power_adc_disable() 
power_spi_disable()
power_timer0_disable()
power_timer1_disable()
power_twi_disable()

Example:

Code:
#include<avr/io.h>
#include<avr/interrupt.h>
#include<stdlib.h>
[COLOR="#FF0000"]#include<avr/power.h>[/COLOR]

#define DATABUFSIZE     42
#define NUMBER_OFSET    34

char demoBuff[DATABUFSIZE] = {'M','o','r','e',' ','o','o','m','f',' ','t','o',' ','y','o','u','r',' ','a','m','p','s',',',' ','p','i','c','o','P','o','w','e','r','!',0,0,0,0,  0,'\r','\n'};
uint16_t iteration=1;

void init_adc()
{
    ADMUX = (1<<MUX3);   //Set mux to internal temp sens. 
    ADCSRA = (1<<ADEN);  //ADC enable 
}

void init_timer2()
{
    TCCR2B = (1<<CS20) | (1<<CS22);     //Clock prescaler set to 5, overflow each sec
    TIMSK2 = (1<<TOIE2);                //Enable timer2 overflow interrupt
    ASSR = (1<<AS2);                    //Enable async operation
}

void init_uart()
{
    UCSR0A = (1<<U2X0);                 // Enable U2Xn to get a baud rate with less error margin
	UCSR0B = (1<<TXEN0);	            // Transmitter enable
	UCSR0C = (1<<UCSZ00) | (1<<UCSZ01); // Asynchronous USART | No parity | 1 stopbit | CH size 8-bit
	UBRR0 = 0x0C;	                    // 19200 Baudrate@8Mhz
}

void enable_pullups()
{
    PORTB = 0xFF;   // Enables internal pull-ups on the IO pins, direction bits are by default set to 0 (input)
    PORTC = 0xFF;   // The UART tx pin will still work
    PORTD = 0xFF;
}

void enable_prr()
{
[COLOR="#FF0000"]    power_spi_disable();
    power_timer0_disable();
    power_timer1_disable();
    power_twi_disable();[/COLOR]
}

void cal_clock()
{
    OSCCAL = 0x66;  // Calibrate oscillator to 8MHz
}

int main()
{
    int count=0;

    cal_clock();
    clock_prescale_set(clock_div_4);    // Prescale systemclock to 2 MHz

    enable_pullups();
    enable_prr();
  
    init_uart();
    init_timer2();
    init_adc();

    while(1)
    {
        ADMUX |= (1<<REFS1) | (1<<REFS0); // Enable internal 1.1V ref. 
        ADCSRA |= (1<< ADSC);             // Start conversion 
        while(!(ADCSRA & (1<<ADIF)));     // Wait for ready flag
        ADMUX &= (1<<MUX3);               // Disable internal 1.1V ref.

        utoa(iteration, &demoBuff[NUMBER_OFSET], 10);       // Generate desimal number string from itt

       	__asm__ volatile (                // Simulate 1000 cycles of processing
            "ldi r24, 25" "\n\t"          // Load 25 into register 24
    	    "1: sbiw r24,1" "\n\t"        // Subtract 1 for each iteration
            "brne 1b"                     // Branch if not equal (Z = 0), the loop takes 4 cycles
	    );

        for(count=0;count<DATABUFSIZE;++count)
        {
            while(!(UCSR0A & (1<<UDRE0)));  // Wait for the last byte to be shifted out of the data register in the UART module

            UDR0 = demoBuff[count];
        }


        while(!(TIFR2 & (1<<TOV2)));             // Wait for the timer to count a second 
        TIFR2 = (1<<TOV2);                       // Reset timer/counter 2 interrupt flag

        iteration++;                              // Increase the itterator counter
    }

    return 0;
}

A little outdated, but still useful reference:

AVR Power Routines

picoPower Labs - Basic power-saving techniques



BigDog
 
Reactions: vinodstanur and FvM

    FvM

    Points: 2
    Helpful Answer Positive Rating
    V

    Points: 2
    Helpful Answer Positive Rating

    vinodstanur

    Points: 2
    Helpful Answer Positive Rating
@vinodstanur

Out of curiosity, were you able to further reduce the power consumption of your design?

I happened upon the following discussion which details the steps in reducing the power consumption of an ATmega328.

I thought you might find it of interest.

Adventures in Low Power Land

BigDog
 


Hi sir sorry for late reply
Today I was working on it actually. I couldn't further reduce the current below 20uA in power down mode. But now that is not a problem because I realised I couldn't use power down mode any way because I need a timer to run in background to check if the external interrupt is not happening for a long time then I have to do some thing, so I need to go to power saver mode..

But I found some interesting things today, at first I thought external crystal will make problem for me in power saver mode coz I couldn't find much difference even I am prescaling (256 time) the 8MHz external clock before entering the power saver mode. But my fuse bits were in "ext-full swing external crystal" mode. Then I changed to "ext 8MHz crystal mode" and then after prescaling to ~31KHz before entering the power saver mode I could measure around 150uA (at 3.3v) current that is okay for me

Is it okay? Or is it too much current at this mode which I can further reduce by some tricks?
I am using external 8MHz just because I want to use 115200 baudrate UART and I don't want any failure on run time after long time because of some RC oscillator frequency drift and stuff like that........... But still I am thinking if I can use internal oscillator coz I set the osc calib register and set around 7.3MHz where UART baud error is 0% for 115200 and a drift of around +-300 KHz is okay coz I tested with ICE and HOT AIR PUMP over the IC :razz:
 

Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…