Pages: 1 [2]   Go Down
Author Topic: Power Down consumption on custom board  (Read 6483 times)
0 Members and 1 Guest are viewing this topic.
Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 524
Posts: 26484
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm gonna add the other power down stuff then and see if the current draw goes down some then.
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 53
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Yes, I'm able to periodically wake up the atmega from sleep using the watchdog. No problem except for the  few uAmps that the watchdog sinks in power-down mode.
Logged

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 524
Posts: 26484
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Baseline test with current sleep mode on my RF transmitter is 1.09mA, with highest current seen on my multimeter of 14.25mA during virtualwire transmission of 1 commanded byte (and however many bytes virtualwire adds to it for).
Now to add the other power down methods & see what happens:

  // Disable ADC
  ADCSRA &= ~(1 << ADEN);

  // Power down functions
  PRR = 0xFF;
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Global Moderator
Dallas
Online Online
Shannon Member
*****
Karma: 200
Posts: 12773
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

A word of caution: some units may need to be reinitialized after power-off.  I vaguely recall the USART being mentioned.

In other words, if something flaky happens after the processor awakens, check the datasheet first then start debugging!
Logged

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 524
Posts: 26484
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Well, that sorta worked.
At initial power on, & first time entering sleep mode, current dropped to 0.99mA.
However, after the first key press/transmission, it jumped to 10.49mA after the send and stayed there.
Don't have the receiver with me so I can't tell if its still transmitting - the LED on D13 just stays on vs turning off after the transmission.

Did I get the code in the right place? And do I need to re-enable some part of it when I want to wake up for the next transmission?

Code:
// transmitter_Weapon_Feb2.pde
// Feb 2 - changed Lights Intensity to be used for Weapon select instead.
// Doesn't actually change any code, just a label change on the Remote keypad.

// -->> gave up on PCInts
// have to double Serial.Begin value with 8MHz ProMini
// have to double VirtualWire Bits/sec in Setup with 8MHz ProMini

// ALL SERIAL PRINTS COMMENTED OUT

// started with the code from this example
// http://www.arduino.cc/playground/Learning/arduinoSleepCode

// with sleep function called -> 1.09mA! should be >900 days (??) on 1000mAH batteries
// down from 8.95 mA in normal idle mode  -> just 7 days
// with bursts of ~14-15mA when a keypress is transmitted

// Processor: Arduino Mini-Pro running on PC USB power
// (ran on 3 AA batteries fed into VCC line prior to this Interrut attempt)
// Keypad: Velleman 4x4 Matrix
// RF Link Transmitter - Sparkfun MO-SAWR-A, 434MHz, WRL-08946

// Simple example of how to use VirtualWire to transmit messages
// Implements a simplex (one-way) transmitter with RF module.

// See VirtualWire.h for detailed API docs
// Author: Mike McCauley (mikem@open.com.au)
// Copyright (C) 2008 Mike McCauley
// $Id: transmitter.pde,v 1.3 2009/03/30 00:07:24 mikem Exp $

// uses default pin 12 for transmit data
// uses default pin 11 for receive data

// added Keypad example from playground
// modified to send character in a buffer to the receiver from 4x4 matrix

// Velleman 4 x 4 matrix keypad
// keypad 1 (Col1) to D10
// keypad 2 (Col2) to D9
// keypad 3 (Col3) to D8
// keypad 4 (Col4) to D7
// keypad 5 (Row1) to D6
// keypad 6 (Row2) to D5
// keypad 7 (Row3) to D4
// keypad 8 (Row4) to D3

// Rows have Internal Pullups

// Row 1, 2, 3, 4 Diode AND'D to D2 (INT0) to pull it low on a keypress
// Interrupt on D2 "wakePin" LOW - Input with Internal pullup

// D0, D1, D14, D15, D16, D17, D18, D19 set as inputs with internal pullups enabled

// 12/23/10 - started code to send out address read from switches to GND on D14, 15, 16, 17
// D14 - SW0
// D15 - SW1
// D16 - SW2
// D17 - SW3

// end of notes
// ***********************************************************************

                            // bring in the library(s)
#include <VirtualWire.h>    // Wireless transmitter/receiver library
#include <Keypad.h>         // Matrix Keypad library
#include <avr/sleep.h>      // powerdown library
#include <avr/interrupt.h>  // interrupts library

// ***********************************************************************
int SW0 = 14;               // bits to read in unique address - LSB
int SW1 = 15;               // bits to read in unique address
int SW2 = 16;               // bits to read in unique address
int SW3 = 17;               // bits to read in unique address - MSB
int address = 0;            // bits put together afteer reading switches
int add0;
int add1;
int add2;
int add3;

// define unused pins
int dpin0 = 0;              // apparently redefined by Serial as Serial Monitor works
int dpin1 = 1;              // apparently redefined by Serial as Serial Monitor works
int pin2 = 2;               // Int0 interrupt pin

int dpin18 = 18;
int dpin19 = 19;

// ***********************************************************************
// define the used pins

#define ledPin 13          // activity indicator, use for brief flash when transmit

// don't need to define pin12, handled by VirtualWire as default data_out pin to the transmitter

int sleep_count = 0;      // flag/counter to tell us to go sleep

// ***********************************************************************
// create an array to store data to be sent out
char msg[2]; // extra char added for address

// set up the Keypad
const byte ROWS = 4; // Four rows
const byte COLS = 4; // Four columns

// Define the Keymap
char keys[ROWS][COLS] =
{
  {    '1','2','3','A'      }  ,  // row 1
  {    '4','5','6','B'      }  ,  // row 2
  {    '7','8','9','C'      }  ,  // row 3
  {    '*','0','#','D'      }  ,  // row 4
};

// Connect keypad ROW1, ROW2, ROW3 and ROW4 to these Arduino pins.
byte rowPins[ROWS] = { 6, 5, 4, 3  };  // Keypad uses internal pullups? No externals supplied
// these pins have separate external Diodes, anodes connected to Pin2 (Int0)
// Column pins are set low just before shut down,
// and Pin2 is pulled high internally.
// Pressing a Row button connects to a Low Columna and pulls the appropriate Row Diode Low for a Pin2 Low interrupt.
// Column pins are then set back high for the keypad library button determination.

// Connect keypad COL1, COL2, COL3, COL4 to these Arduino pins.
byte colPins[COLS] = { 10, 9, 8, 7 };

// Create the Keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

//***************************************************
// *  Name:        pin2Interrupt, "ISR" to run when interrupted in Sleep Mode
void pin2Interrupt()
{
  /* This brings us back from sleep. */
}

//***************************************************
// *  Name:        enterSleep
void enterSleep()
{
  /* Setup pin2 as an interrupt and attach handler. */
  attachInterrupt(0, pin2Interrupt, LOW);
  delay(50); // need this?
  /* the sleep modes
   SLEEP_MODE_IDLE - the least power savings
   SLEEP_MODE_ADC
   SLEEP_MODE_PWR_SAVE
   SLEEP_MODE_STANDBY
   SLEEP_MODE_PWR_DOWN - the most power savings
   */
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);  // setting up for sleep ...
  sleep_enable();                       // setting up for sleep ...
  
// <<<<<<<<<<<<<<<<  March 2, 2011 - added some more power down stuff  >>>>>>>>>>>>>>>>

    // Disable ADC
  ADCSRA &= ~(1 << ADEN);

  // Power down functions
  PRR = 0xFF;
// <<<<<<<<<<<<<<<<<  end of new March 2 stuff  >>>>>>>>>>>>>>>>>>>>>>>

  sleep_mode();                         // now goes to Sleep and waits for the interrupt

  /* The program will continue from here after the interrupt. */
  detachInterrupt(0);                 //disable interrupts while we get ready to read the keypad

  /* First thing to do is disable sleep. */
  sleep_disable();

  // set all the keypad columns back high so can read keypad presses again
  digitalWrite(7, HIGH);
  digitalWrite(8, HIGH);
  digitalWrite(9, HIGH);
  digitalWrite(10, HIGH);
  // then go to the void Loop()
}

« Last Edit: March 02, 2011, 03:38:30 pm by CrossRoads » Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 524
Posts: 26484
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

here's the setup & loop code
Code:
// ***********************************************************************
// set up the pins as Inputs, Outputs, etc.
void setup()
{
  /* Setup the pin directions, write inputs High to turn on internal pullups */
  pinMode(pin2, INPUT);                 // our sleep interrupt pin
  digitalWrite(pin2, HIGH);

  // define all the unused pins as inputs with internal pullups for lower power state
  pinMode(dpin0, INPUT);                  // apparently redefined by Serial as Serial Monitor works (receiving anyway)
  digitalWrite(dpin0, HIGH);              // apparently redefined by Serial as Serial Monitor works
  pinMode(dpin1, INPUT);                  // apparently redefined by Serial as Serial Monitor works
  digitalWrite(dpin1, HIGH);              // apparently redefined by Serial as Serial Monitor works

  pinMode(SW0, INPUT); // LSB of remote Address
  digitalWrite(SW0, HIGH);
  byte add0 = 0; // read the value of SW0
  pinMode(SW1, INPUT); // LSB+1
  digitalWrite(SW1, HIGH);
  byte add1= 0;
  pinMode(SW2, INPUT);  // LSB+2
  digitalWrite(SW2, HIGH);
  byte add2 = 0;
  pinMode(SW3, INPUT);  // MSB of address
  digitalWrite(SW3, HIGH);
  byte add3 = 0;
 
  // put our address together
  // read our expansion address
  add3 = digitalRead(SW3); // not using for now, needed to use the pin on the receiver
  // shift it left 3 places
  add3 = add3 << 3;
  add2 = digitalRead(SW2);
  // shift it left 2 places
  add2 = add2 << 2;
  add1 = digitalRead(SW1);
  // shift it left 1 place
  add1 = add1 << 1;
  add0 = digitalRead(SW0);
  // now OR it together
  address = address|add3;
  address = address|add2;
  address = address|add1;
  address = address|add0;
  //Serial.println("my address is: ");
  //Serial.println(address, BIN);
  msg[1]= address;
 
  pinMode(dpin18, INPUT);
  digitalWrite(dpin18, HIGH);
  pinMode(dpin19, INPUT);
  digitalWrite(dpin19, HIGH);

  // default pin for data to be transmitted out
  // pinMode(dpin12, OUTPUT);                 // taken care of by VirtualWire
  //                                          // VirtualWire takes care of 11 also.
 
  digitalWrite(ledPin, LOW);                   // pin 13, turn off the LED
//    Serial.begin(9600);                // need for debug monitoring only with FTDI connected via USB to PC
//    Serial.println("TX setup");              // for debug only

  // ***********************************************************************
  // Initialise the IO and ISR for VirtualWire
  vw_setup(4000);                       // Bits per sec - had to double from 2000 with 8MHz 3.3V Pro-Mini

}                                            // end of void Setup()

// ***********************************************************************
// Main loop for reading the keypad and sending the button pushed out
// (with a unique address to be added eventually by reading 0-F from currently unused pins)

void loop()
{
  if (sleep_count>1000){                      // check if we should go to sleep because of "time" --> Try shorter versions of this
    sleep_count=0;                           // turn it off for when we wake up
//    Serial.println("Sleep");               // for debug only
                                             // set the columns low before sleeping, otherwise Keypad leaves them high and Rows have nothing to pull low.
    digitalWrite(7, LOW);
    digitalWrite(8, LOW);
    digitalWrite(9, LOW);
    digitalWrite(10, LOW);   
    delay(100);                               // need this?
    enterSleep();                             // call Sleep function to put us out
   
                                              //  THE PROGRAM CONTINUEs FROM HERE after waking up in enterSleep()
  }                                           // end of checking to go to sleep

    // go read the keypad
  char key = keypad.getKey();                 // reading the keypad
  if(key)                                     // same as if(key != NO_KEY)- did something change?
  {
    msg[0]=key;                               // load the array with the key character
    // msg[1]=NULL;                           // Rx side seems to work without this

    digitalWrite(ledPin, true);               // Flash a light to show transmitting

    vw_send((uint8_t *)msg, strlen(msg));     // send the character out

    vw_wait_tx();                             // Wait until the whole message is gone

    delay (50);                               // need some delay or seem to miss key presses

    digitalWrite(ledPin, false);              // turn off the flash of LED

    sleep_count = 0;                          // reset count up to sleep if transmitted a key press

  }                                           // end of if(key) & transmitting a character

  sleep_count = sleep_count+1;                // start counting to go to sleep

}                                             // end of void loop
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Global Moderator
Dallas
Online Online
Shannon Member
*****
Karma: 200
Posts: 12773
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
  // Power down functions
  PRR = 0xFF;

Two things...

1. You may have to power-up the units to get them running.

2. Be more selective in what you power-down.  The timers, for example, will not consume power while the processor is in SLEEP_MODE_PWR_DOWN simply because the processor clock will be stopped.  At a minimum, DON'T power-down the three timers.
Logged

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 524
Posts: 26484
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks Coding, do you know which three are those?
I am not measuring any time while sleeping, I just want to wake up and read the key press.
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 524
Posts: 26484
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

okay, read the Power Reduction Register part of the datasheet. Not really clear to me which part is keeping it from operating normally, so I just reset all of them on the interrupt and that seems to have it working normally.

Sleeping now comsumes 0.99mA. 1000mAH LiPo battery should go quite a while between charges now!

Code:
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);  // setting up for sleep ...
  sleep_enable();                       // setting up for sleep ...
 
// <<<<<<<<<<<<<<<<  March 2, 2011 - added some more power down stuff  >>>>>>>>>>>>>>>>

    // Disable ADC
  ADCSRA &= ~(1 << ADEN);

  // Power down functions
  PRR = 0xFF;
// <<<<<<<<<<<<<<<<<  end of new March 2 stuff  >>>>>>>>>>>>>>>>>>>>>>>

  sleep_mode();                         // now goes to Sleep and waits for the interrupt

  /* The program will continue from here after the interrupt. */
  detachInterrupt(0);                 //disable interrupts while we get ready to read the keypad
 
  // <<<<<<<<<<<<<<<<  March 2, 2011 - added some more power down stuff  >>>>>>>>>>>>>>>>
    // Power up functions
  PRR = 0x00;
  // <<<<<<<<<<<<<<<<<  end of new March 2 stuff  >>>>>>>>>>>>>>>>>>>>>>>9

  /* First thing to do is disable sleep. */
  sleep_disable();
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Global Moderator
Dallas
Online Online
Shannon Member
*****
Karma: 200
Posts: 12773
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Thanks Coding, do you know which three are those?

I'm afraid I know very little about the PRR register.  Probably the best choice for fine-tuning is to use the "power" functions from LIBC to manipulate the PRR register...

  power_adc_disable();
  power_spi_disable();
  power_twi_disable();
  power_usart0_disable();

  power_adc_enable();
  power_spi_enable();
  power_twi_enable();
  power_usart0_enable();

For my sleepy applications I modify the core so the ADC is never enabled and only Timer 0 is started.  This seems to give about the same results as mucking with the PRR register with the benefit of not having to muck with the PRR register.   smiley
Logged

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 524
Posts: 26484
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Seems to be direct correlation for 4 of them:

Bit 7 – PRTWI: Power Reduction TWI -> power_twi_disable();  power_twi_enable();
Writing a logic one to this bit shuts down the TWI by stopping the clock to the module. When
waking up the TWI again, the TWI should be re initialized to ensure proper operation.

• Bit 6 – PRTIM2: Power Reduction Timer/Counter2  -> Not Listed!
Writing a logic one to this bit shuts down the Timer/Counter2 module in synchronous mode (AS2
is 0). When the Timer/Counter2 is enabled, operation will continue like before the shutdown.

• Bit 5 – PRTIM0: Power Reduction Timer/Counter0   -> Not Listed!
Writing a logic one to this bit shuts down the Timer/Counter0 module. When the Timer/Counter0
is enabled, operation will continue like before the shutdown.

• Bit 4 – RReserved   -> Not Listed!
This bit is reserved in ATmega48A/48PA/88A/88PA/168A/168PA/328/328P and will always read
as zero.

• Bit 3 – PRTIM1: Power Reduction Timer/Counter1   -> Not Listed!
Writing a logic one to this bit shuts down the Timer/Counter1 module. When the Timer/Counter1
is enabled, operation will continue like before the shutdown.

• Bit 2 – PRSPI: Power Reduction Serial Peripheral Interface -> power_spi_disable();  power_spi_enable();
If using debugWIRE On-chip Debug System, this bit should not be written to one.
Writing a logic one to this bit shuts down the Serial Peripheral Interface by stopping the clock to
the module. When waking up the SPI again, the SPI should be re initialized to ensure proper
operation.

• Bit 1 – PRUSART0: Power Reduction USART0  -> power_usart0_disable();  power_usart0_enable();
Writing a logic one to this bit shuts down the USART by stopping the clock to the module. When
waking up the USART again, the USART should be re initialized to ensure proper operation.

• Bit 0 – PRADC: Power Reduction ADC  -> power_adc_disable();  power_adc_enable();
Writing a logic one to this bit shuts down the ADC. The ADC must be disabled before shut down.
The analog comparator cannot use the ADC input MUX when the ADC is shut down.

So, are there something like these?
power_tim0_enable(); & power_tim0_enable();
power_tim1_enable(); & power_tim1_enable();
power_tim2_enable(); & power_tim2_enable();
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Global Moderator
Dallas
Online Online
Shannon Member
*****
Karma: 200
Posts: 12773
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Yes...

power_timer0_disable();
power_timer1_disable();
power_timer2_disable();

http://arduino.cc/forum/index.php/topic,53821.msg385930.html#msg385930
 smiley-wink
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 53
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

CrossRoads, 0.99 mA seems a bit too much for the power-down mode. Are you powering your RF interface down too?

My board, RF circuitry included (CC1101), consumes less than 6 uA in Power-Down state. Watchdog enabled. If I wanted to wake up the atmega from an external INTX pin instead of the watchdog, I should be able to reduce the consumption down to 0.2 uA.
« Last Edit: March 02, 2011, 06:12:59 pm by estratos » Logged

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 524
Posts: 26484
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I don't think I have a way to do that without adding more hardware to cut power to the transmitter.
I have a promini.
The power-LED draws a little.
The Max1811 might draw some too.
Power goes from the battery to the VCC pins.

* MO-SAWR, WRL-08946 TX.pdf (131.16 KB - downloaded 10 times.)
* MAX1811.pdf (270.82 KB - downloaded 9 times.)

* Simpler_remote.jpg (74.58 KB, 960x720 - viewed 33 times.)
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 53
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I've somehow documented the cyclic power-down procedure in my blog:
http://panstamp.blogspot.com/2011/03/power-consumption.html

Thanks again for your help.
Logged

Pages: 1 [2]   Go Up
Jump to: