ATmega Taking 1mA in power down need to reduce it further

Guys, sorry dident understand which catagory suits this thread so puting it here!
I am trying to make a code of arduino uno for NRF but as I am opperating it with 3.3 V battery I need to save current!
But when I check my following code my NRF is going in power down but my AtMega 328 is not!
I didnt connect anyhting other than crystal to arduino to check it and just execute my code and still its taking 1mA where as it should take 1uA in power down!
Here is my code!:-

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <avr/sleep.h>
#include <avr/power.h>
/*-----( Declare Constants and Pin Numbers )-----*/
#define CE_PIN   9
#define CSN_PIN 10
// NOTE: the "LL" at the end of the constant is "LongLong" type
const uint64_t pipe = 0xE8E8F0F0E1LL; // Define the transmit pipe


/*-----( Declare objects )-----*/
RF24 radio(CE_PIN, CSN_PIN); // Create a Radio
/*-----( Declare Variables )-----*/
int joystick[2];  // 2 element array holding Joystick readings
int cnt1=80,cnt2=90;
int sleepStatus = 0, swtch=3;             // variable to store a request for sleep
int flag;
void wakeUpNow()        // here the interrupt is handled after wakeup
{
 flag = 1; 
 
}


void setup()   /****** SETUP: RUNS ONCE ******/
{
  Serial.begin(9600);
  radio.begin();
  radio.setCRCLength(RF24_CRC_16);
  radio.setDataRate(RF24_250KBPS);
  radio.setChannel(10);
 radio.setPALevel(RF24_PA_LOW);
  radio.openWritingPipe(pipe);
   pinMode(swtch, INPUT);

  attachInterrupt(1, wakeUpNow,RISING); // use interrupt 1 (pin 3) and run function
                                      // wakeUpNow when pin 3 gets RISING edge 
}//--(end setup )---


void sleepNow()         // here we put the arduino to sleep
{
  
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);   // sleep mode is set here
    radio.powerDown();
    sleep_enable();          // enables the sleep bit in the mcucr register
                             // so sleep is possible. just a safety pin 

    

    attachInterrupt(1,wakeUpNow, RISING); // use interrupt 1 (pin 3) and run function
                                       // wakeUpNow when pin 3 gets rising edge 
sleep_mode();            // here the device is actually put to sleep!!
                             // THE PROGRAM CONTINUES FROM HERE AFTER WAKING UP

    sleep_disable();         // first thing after waking from sleep:
                             // disable sleep...
    detachInterrupt(0);      // disables interrupt 0 on pin 2 so the 
                             // wakeUpNow code will not be executed 
                             // during normal running time.

                                      
}


void loop()   /****** LOOP: RUNS CONSTANTLY ******/
{
  radio.powerUp();
  if((digitalRead(swtch)&&(flag==1)))  //// debounce check
    {if(digitalRead(swtch))
    delay(10);
    if(digitalRead(swtch))
    {
  joystick[0] = cnt1;
  joystick[1] = cnt2;
  delay(10);
  radio.write( joystick, sizeof(joystick) );
  flag=0;

   }
    else
    {
      flag=0;
    }
    }
    sleepNow();     // sleep function called here
    }//--(end main loop )---

/*-----( Declare User-written Functions )-----*/

//NONE
//*********( THE END )***********

Can any body who can tell me where i am doing wrong?

Where do you call:
sleep_cpu();

http://www.nongnu.org/avr-libc/user-manual/group__avr__sleep.html

I am not using it anywhere (I am using sleep_mode() insted as mentioned in below example!), as in the example in given link they didn't used it as well, though they mentioned it previously!
And I am using 16 MHZ crystal so it could take little more current but didn't expect it to take 1mA on power down!
and even i use sleep_cpu() before of sleep_mode(); still its taking same current!

And can I use 4Mhz crystal with this code without making any change or do i need to boot load or some process before changing crystal frequency?
I found out that my uC is going in sleep but it is still consuming (1mA) much more than he should!
I only have following connection to my atmega 328
3.3V battery to vcc and ground.
crystal(16Mhz) and 22pf cap to x1,x2.
and pin 5 (digital pin3) is pull down with 100k and it is defined as input
where am i doing wrong?

I forgot to mention that after putting above cod i am taking out my atmega 328 and just puttin it on general purpose board with 16 Mhz crystal and .22pF cap with it thats all!
So as per atmega data sheet it should consume max .6uA but it is still consuming .995mA so where I am doing wrong please any inputs?

I have only used sleep_cpu(); in my sketches so have no experience in your method, sorry.

.

sleep_mode() is a macro defined in sleep.h:

#define sleep_mode() \
do {                 \
    sleep_enable();  \
    sleep_cpu();     \
    sleep_disable(); \
} while (0)

Thank you jboyton.

But still my question is unanswered that do atmega will take 1 mA on 16Mhz 3.3V crystal even i power down mode?

You should disable the A/D to achieve minimum current. Try adding this to your sleep routine:

ADCSRA &= ~_BV(ADEN); // disable ADC

Also, there's no reason to use sleep_mode() if you're explicitly calling sleep_enable() and disable(). You could either replace sleep_mode() with sleep_cpu() or delete the calls to sleep_enable/disable since they are called by sleep_mode().

And it's not really clear to me that your interrupt won't be going off due to noise if it's not tied to anything. Although since you don't define it as an input maybe you're safe?

jboyton:
You should disable the A/D to achieve minimum current. Try adding this to your sleep routine:

ADCSRA &= ~_BV(ADEN); // disable ADC

And it's not really clear to me that your interrupt won't be going off due to noise if it's not tied to anything. Although since you don't define it as an input maybe you're safe?

I think the ADC is only a few hundred uA - you absolutely have to do it though, if you want low power.
ADCSRA &=127 before sleep, ADCSRA |= 128 after to turn it back on. Junk the first reading after turning it back on.

He said above it's pulled down w/100k.
All pins are inputs on poweron.

DrAzzy:
I think the ADC is only a few hundred uA - you absolutely have to do it though, if you want low power.

Yeah you're right but it's the only thing I could see to suggest.

I've fooled myself before by leaving the programmer attached when measuring the current.

DrAzzy:
He said above it's pulled down w/100k.
All pins are inputs on poweron.

Thanks for the corrections.

I got 20uA difference Thats all with this!
Right now I am on 965uA
How can I switch of BOD (Brown out detect)?
How can I change my crystal frequancy to 2Mhz or 1 Mhz?
As it should be below 200uA atleast with my current setting I am really dont no where I am doing wrong!

Keep everything of my code a side I am using a simple code as follows to determine my current in sleep only!
And in this current consumption I am getting is 960uA, Don’t no where I am doing wrong!
I modified my hardware as I read that INT0/1 should put on low to interrupt so I remove all and now I have following connection!

  1. 3.3V to vcc Avcc with ground
  2. button between pin no 5 (digital pin 3 (INT1 interrupt)) and ground.
    3.Crystal of 16Mhz and 2 22pf cap connected to XTAL 1&2
  3. led to digital pin 13 to show the power on and power down mode as in power down it gets 0( I tried without it too still current is same for power down!)
#include <avr/sleep.h>

#define LED 13

void setup()
{
Serial.begin(115200);
digitalWrite (3, HIGH);  // pull-up
pinMode (LED, OUTPUT);
digitalWrite (LED, HIGH);  // awake
//Serial.println ("But does it get goat's blood out?");
}  // end of setup

void loop()
{
static int counter = 0;
 delay(1000);
 if (digitalRead (3))
   if (++counter % 5 == 0)
     sleepNow(); 
}  // end ofloop

// interrupt service routine
void wake()
{
 sleep_disable();         // first thing after waking from sleep:
 detachInterrupt (1);     // stop many many interrupts
}

void sleepNow()
{
 set_sleep_mode(SLEEP_MODE_PWR_DOWN);   // sleep mode is set here
 sleep_enable();          // enables the sleep bit in the mcucr register
 //Serial.println("Going to sleep");  
 digitalWrite (LED, LOW);  // asleep
 attachInterrupt(1, wake, LOW); 
  PRR = 0xff;
 //sleep_mode();            // here the device is actually put to sleep!!
  ADCSRA &=127;
  ADCSRA &= ~_BV(ADEN);  // disable ADC
  MCUCR |= (1<<BODS) | (1<<BODSE);
   MCUCR &= ~(1<<BODSE);  // must be done right before sleep
  
  sleep_cpu();
  
  
  PRR = 0x00;
 digitalWrite (LED, HIGH);   // awake
 //Serial.println("Awake again!");
}  // end of sleepNow

I haven't tried it myself, but have previously read through it a number of times and bookmarked it in case I need a low power solution.

There's a low power library that might be able to help turn off different chip features to get where you need to be.

Thanks, I will try with it and will update my result in short!

Sorry But it didnt work for me at all, not going to sleep!

It worked some how but still its on 958mA current!

Hi,

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

Thanks.. Tom.. :slight_smile:

Using 16MHz at 3.3v is out of spec for the Atmega328, so that's probably why you can't get the current down any further. You must reduce the frequency to make any gains. 8MHz would be my preference as there are bootloaders and stuff readily available.