Arduino at 5volts and 5.3mA, and a Surprise

Submitted by Ed_B on Fri, 02/04/2011 - 04:18

Printer-friendly versionPrinter-friendly version

An ATmega168 Lilypad Arduino is the basis for a set of design experiments for a larger project. The larger project is not described here. Power consumption is an issue, so I set about trying strategies to reduce Arduino power consumption. As  basis of comparison, measurements were made based on settings that could be changed in a running program, not fuses or circuit adjustments. I set out to get three or four baseline numbers relating to clock speed and internal peripherals. There was a big surprise hiding under a rock: The Arduino-like circuit being tested had by default, active, open input lines that drastically increased the mcu power consumption. The open lines also caused the chip power consumption to fluctuate sporadically on its own, and the fluctuations became more extreme as I moved my hand around the board. It took me a while to notice the correlation between my hand position and the current draw on the mcu, but then the mystery was gone. This is a classic case of the old caveat about not leaving cmos input pins floating -- tie 'em high, or tie 'em low, but don't leave 'em open. In the MCU, two things will fix this in software: set the pin to output, or leave it as input and turn on its internal pullup resistor. 

CLICK READ MORE TO SEE THE REST OF THE POST

Conditions:
Evil Mad Scientist board with ATMega168, no crystal on board, internal rc clock 8Mhz vcc =4.95v Lilypad arduino configuration no componants on board xcpt 10k pullup on rst, vcc decoupling cap, 2-22pf caps on tosc1&2. ISP connector unplugged during measurements. The test programs are variations on the Arduino built-in example "BareMinimun.pde", which contains only empty setup() and loop() functions.

The board measrements were for comparing supply mA of the working circuit to a 16 MHz xtal oscillator version of the same setup under normal condiditons, and then modifing the test program in the Evil board to see what sorts of power reductions could be made without changing the structure of the arduino system. Sleep is a separate issue to be dealt with later.

Tests involved (1) the Power Reduction Register (PRR) (2) stopping the interrupt system with the CLear Interrupt "cli();" function, and (3) setting the data direction registers (DDRX) to input and enabling the pullup resistors. The PRR has control bits for individually turning off the internal peripherals. My test was a benchmark, so I flipped all the peripherals off in one shot. "PRR = 0xFF;"

chip current

-------------------

5.36mA - stable, non-drifting mA reading

void setup() {
  // put your setup code here, to run once:

  DDRB = 0x00;        //make port b input
  PORTB = 0xFF;       //enable all pull-ups 
 
  DDRC = 0x00;        //make port c input
  PORTC = 0xFF;       //enable all pull-ups 
 
  DDRD = 0x00;        //make port b input
  PORTD = 0xFF;       //enable all pull-ups  
 
  PRR=0xFF;
}

void loop() {
  // put your main code here, to run repeatedly:

}

-------------------------
7.35mA - stable, non-drifting mA reading

void setup() {
  // put your setup code here, to run once:

  DDRB = 0x00;        //make port b input
  PORTB = 0xFF;       //enable all pull-ups 
 
  DDRC = 0x00;        //make port c input
  PORTC = 0xFF;       //enable all pull-ups 
 
  DDRD = 0x00;        //make port b input
  PORTD = 0xFF;       //enable all pull-ups  

}

void loop() {
  // put your main code here, to run repeatedly:

}

-----------------------------------------------
7.41 mA - stable, non-drifting mA reading

void setup() {
  // put your setup code here, to run once:

  DDRB = 0x00;        //make port b input
  PORTB = 0xFF;       //enable all pull-ups 
 
  DDRC = 0x00;        //make port c input
  PORTC = 0xFF;       //enable all pull-ups 
 
  DDRD = 0x00;        //make port b input
  PORTD = 0xFF;       //enable all pull-ups  
 
  cli();

}

void loop() {
  // put your main code here, to run repeatedly:

}

-----------------------------------
10 - 11.5mA constantly varying

void setup() {
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:

}

--------------------------------
8.49 - 10.3mA constantly varying

void setup() {
  // put your setup code here, to run once:

  DDRC = 0x00;        //make port c input
  PORTC = 0xFF;       //enable all pull-ups 
 
  DDRD = 0x00;        //make port d input
  PORTD = 0xFF;       //enable all pull-ups  
}

void loop() {
  // put your main code here, to run repeatedly:

}

-----------------------------------------
9.4 -10.6mA constantly varying

void setup() {
  // put your setup code here, to run once:
 
  DDRD = 0x00;        //make port d input
  PORTD = 0xFF;       //enable all pull-ups  

}

void loop() {
  // put your main code here, to run repeatedly:

}

----------------------------
7.9 -8.7 mA constantly varying

void setup() {
  // put your setup code here, to run once:

  DDRB = 0x00;       
  PORTB = 0xFF;       //enable all pull-ups 

  DDRD = 0x00;       
  PORTD = 0xFF;       //enable all pull-ups  

}

void loop() {
  // put your main code here, to run repeatedly:

}
------------

8.8 - 10.0 mA  constantly varying

void setup() {
  // put your setup code here, to run once:

  DDRB = 0x00;      
  PORTB = 0xFF;       //enable all pull-ups 

}

void loop() {
  // put your main code here, to run repeatedly:

}

------------------

10.6 - 11.1mA constantly varying

void setup() {
  // put your setup code here, to run once:

  DDRC = 0x00;        //make port c input
  PORTC = 0xFF;       //enable all pull-ups 

}

void loop() {
  // put your main code here, to run repeatedly:

}

----------------------------
8.6 - 9.3mA constantly varying

void setup() {
  // put your setup code here, to run once:

 PRR=0xFF;
}

void loop() {
  // put your main code here, to run repeatedly:

}

Conclusion: don't leave input lines open.