(solved?) Sudden power jump in sleep mode

I'm playing with a Pro Mini I got off ebay. It's a new model and I was looking it it to see how easy it would be to get it to go into low power sleep. Very easy as it turns out - all the power inputs lead to a single diode. Remove the diode and it's a mega328p on a board with a 16MHz crystal and an ISP connector!

I wrote a test program and in sleep mode the board uses about 10uA (I expected about 5uA but maybe it's the 16MHz crystal or something. 10uA is good enough for me...)

But...after about 10 seconds or so of sleeping/waking up the power consumption suddenly jumps to 40uA (it's not a gradual increase, it's a definite step). The 40uA is completely steady after that (never goes up or down).

Pressing reset doesn't make any difference. Powering off the board puts it back to 10uA for a while. Changing the watchdog time makes no difference, it happens after about 10 seconds of world time.

What could be causing this?

Here's my sketch:

(Based on code from this page: Gammon Forum : Electronics : Microprocessors : Power saving techniques for microprocessors )

#include <avr/sleep.h>
#include <avr/wdt.h>
#include <avr/power.h>

// Flash the LED
const byte LED = 13;
void pulse()
{
  pinMode (LED, OUTPUT);
  digitalWrite (LED, HIGH);
  volatile long count = 0;
  while (count < 500) {
    ++count;
  }
  digitalWrite (LED, LOW);
}

// watchdog interrupt
ISR (WDT_vect) 
{
  wdt_disable();
  sleep_disable();
  pulse();    // Flash the LED a while
}

void sleep()
{
  // Disable interrupts
  cli();

  // Power off all hardware
  ADCSRA = 0;
  power_all_disable();

  // Set ports low
  DDRB = DDRC = DDRD = 0xff;
  PORTB = PORTC = PORTD = 0;

  // Configure watchdog sleep time
  MCUSR = 0;
  WDTCSR = bit(WDCE) | bit (WDE);                                      // allow changes, disable reset
  WDTCSR = bit(WDIE) | (0<<WDP3) | (1<<WDP2) | (1<<WDP1)| (1<<WDP0);   // set WDIE, and 2 second delay
  wdt_reset();  // pat the dog (reset timer to zero)
  
  // Enable sleep mode
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);  
  sleep_enable();
  
  // Disable brownout detector (25 uAmps...)
  // This only stays active for three clock cycles so "sleep" *must* be next
  MCUCR = bit(BODS) | bit(BODSE);
  MCUCR = bit(BODS);

  // Re-enable interrupts
  sei();

  // Sleep
  sleep_cpu();
}


void setup ()
{
  // Long LED pulse (so we can see a reset)
  for (byte i=0; i<255; ++i) {
    pulse();
  }
}

void loop () 
{
  while (1) {
    sleep();
  }
}

The Pro Mini is shown below with some annotations.

There is still a voltage regulator on a Pro Mini. Even if power is fed to the 5V pin, I'm not sure that it wouldn't draw some small current in that situation.

Try this code, I know that it gets the MCU down to about 0.1µA .

Sure, but (a) It's disconnected, and (b) it would be constant, it wouldn't cause a jump after ten seconds.

That code puts it down to about 4uA, about 5uA more than theory.

I expected 5uA with watchdog-wakeup enabled. I got 10uA, also 5uA more than theory. Something on the board is using 5uA, (probably the external crystal).

But...I swapped the brown-out-disable code from that page into mine and it stayed at 10uA - no jump! On Nick Gammon's page it says the BOD circuit uses about 25 µA....so that's in the right ballpark.

I don't know the exact reason yet, but it's working. (You can use $3 eBay Pro Minis in low power applications!)

Noooo! Right after I hit 'send' it jumped up to 40uA!

It had been working at 10uA for about 10 minutes. I have no idea what changed.

Update: I ran the code from that page again and it ran at 4uA for a while then jumped up to 34uA.

So...it seems like it's something on the PCB. What could use 5uA for about 10 seconds then leap up to 35uA?

under some conditions unconnected io can cause exactly that symptom. waving your hand 2' away could result in 1ua or 1ma jump. or just sitting there gates drifting down into threshold can do this.

also be aware that unless the ldo is actually removed from the board ground current can vary with unconnected terminals too.

john1993:
under some conditions unconnected io can cause exactly that symptom. waving your hand 2' away could result in 1ua or 1ma jump. or just sitting there gates drifting down into threshold can do this.

The code does this:

  // Set ports low
  DDRB = DDRC = DDRD = 0xff;
  PORTB = PORTC = PORTD = 0;

also be aware that unless the ldo is actually removed from the board ground current can vary with unconnected terminals too.
[/quote]

Yep. I'm starting to think it must be something on the board. Time to remove more components...

I just removed a couple more components including the LDO and power went from 10uA to 6uA.

4uA less and no jumps so far...looks like it was a hardware problem.

Try setting all the IO to inputs with pullup resistors enabled. Will ensure none are floating or oscillating.

AtmelAVR4013 picoPower.pdf (92.4 KB)

he already set pins to outputs which does the same thing. looking more and more like it was the ldo. unconnected pins there can also cause spurious draw. specially those 2980 clones.

fungus:

[quote author=Jack Christensen link=topic=221246.msg1607878#msg1607878 date=1393337164]
There is still a voltage regulator on a Pro Mini. Even if power is fed to the 5V pin, I'm not sure that it wouldn't draw some small current in that situation.

Sure, but (a) It's disconnected, and (b) it would be constant, it wouldn't cause a jump after ten seconds.
[/quote]

It's output is connected, I wouldn't be so sure, I have no idea what it might do in that situation.

[quote author=Jack Christensen link=topic=221246.msg1607878#msg1607878 date=1393337164]
Try this code, I know that it gets the MCU down to about 0.1µA .

That code puts it down to about 4uA, about 5uA more than theory.
[/quote]

Then it has to be the circuit.

I expected 5uA with watchdog-wakeup enabled. I got 10uA, also 5uA more than theory. Something on the board is using 5uA,

Absolutely.

(probably the external crystal).

Absolutely not.

You were right. I started removing more components and the problem went away. If I do another one I'll try removing them in a different order, starting with the LDO.

How much power does a crystal use (roughly)?

fungus:
How much power does a crystal use (roughly)?

Zero in power down mode, as the oscillator is stopped. When running, drive level for a crystal is about 100µW, give or take. Haven't seen a spec for ceramic resonators (which what the Pro Mini has, the official one anyway) but I'd have to believe they're in the same ballpark.

fungus:

john1993:
under some conditions unconnected io can cause exactly that symptom. waving your hand 2' away could result in 1ua or 1ma jump. or just sitting there gates drifting down into threshold can do this.

The code does this:

  // Set ports low

DDRB = DDRC = DDRD = 0xff;
  PORTB = PORTC = PORTD = 0;



also be aware that unless the ldo is actually removed from the board ground current can vary with unconnected terminals too.

Yep. I'm starting to think it must be something on the board. Time to remove more components...

[/quote]
I can't remember where (think it was an Atmel Application Note), but I know I read somewhere to not chain assigns with microcontroller ports like that. Any ports that aren't fully implemented (like C and D) will cause problems with a multiple-assign like that. Assign each of them with their own statement.

DDRB = 0xFF;
DDRC = 0xFF;
DDRD = 0xFF;

PORTB = 0;
PORTC = 0;
PORTD = 0;

I don't know if that would cause your problem, but it's bad practice.

Any ports that aren't fully implemented (like C and D)...

D is complete. Only C is partial.

Jiggy-Ninja:
I can't remember where (think it was an Atmel Application Note), but I know I read somewhere to not chain assigns with microcontroller ports like that.

Yup. That's a potential problem...

000000a6 <setup>:
  a6:	8f ef       	ldi	r24, 0xFF	; 255
  a8:	8a b9       	out	0x0a, r24	; 10
  aa:	8a b1       	in	r24, 0x0a	; 10
  ac:	87 b9       	out	0x07, r24	; 7
  ae:	87 b1       	in	r24, 0x07	; 7
  b0:	84 b9       	out	0x04, r24	; 4
  b2:	1b b8       	out	0x0b, r1	; 11
  b4:	8b b1       	in	r24, 0x0b	; 11
  b6:	88 b9       	out	0x08, r24	; 8
  b8:	88 b1       	in	r24, 0x08	; 8
  ba:	85 b9       	out	0x05, r24	; 5
  bc:	08 95       	ret

If the assignments are done with C last / left-most it will work. But it's a very bad idea. The code becomes a mine field for the person performing maintenance and a nightmare for the person trying to port to another processor. As an added penalty the code is larger...

000000a6 <setup>:
  a6:	8f ef       	ldi	r24, 0xFF	; 255
  a8:	84 b9       	out	0x04, r24	; 4
  aa:	87 b9       	out	0x07, r24	; 7
  ac:	8a b9       	out	0x0a, r24	; 10
  ae:	15 b8       	out	0x05, r1	; 5
  b0:	18 b8       	out	0x08, r1	; 8
  b2:	1b b8       	out	0x0b, r1	; 11
  b4:	08 95       	ret

Well spotted @Jiggy-Ninja!

LOL!

Point taken...don't chain volatiles.

PS: It's all working now. A Mega328 on a PCB with 16MHz crystal+ISP connector for $3+2 minutes of surgery - bargain!