Go Down

Topic: When sleeping helps (Read 4294 times) previous topic - next topic

Coding Badly

@CB: conversion time may vary from sample to sample depending on the sensor/ADC/etc...


That's not what I remember with 1-Wire temperature sensors.  I believe, for a given configuration / sensor, the conversion time is fairly consistent.

tlharv

Quote
In either case, it should be replaced with a blink-without-delay pattern; a while-loop polling for 2 seconds to elapse.  In the while-loop body put the processor to sleep (Idle mode).


Ok, I've replaced my delay(2000) statement with IdleChip(2000), function defined as:

Code: [Select]
void IdleChip(unsigned long duration)
{
  unsigned long start = millis();
  set_sleep_mode(SLEEP_MODE_IDLE);  // choose idle mode for the chip
  sleep_enable();                              // this puts the chip into sleep mode, but doesn't command it to sleep yet
  sleep_mode();                                // put chip in idle mode
  while (millis() - start <= duration) {
    digitalWrite(13, LOW);                  // turn LED off to indicate sleep
  }
  sleep_disable();
  digitalWrite(13, HIGH);                   // turn LED on to indicate waking up
}

Coding Badly


Might want to move that sleep inside the body or it doesn't do much good...

Code: [Select]
void IdleChip(unsigned long duration)
{
  unsigned long start = millis();
  set_sleep_mode(SLEEP_MODE_IDLE);  // choose idle mode for the chip
  sleep_enable();                              // this puts the chip into sleep mode, but doesn't command it to sleep yet
  digitalWrite(13, LOW);  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<                  // turn LED off to indicate sleep
  while (millis() - start <= duration) {
    sleep_mode();  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<                              // put chip in idle mode
  }
  sleep_disable();
  digitalWrite(13, HIGH);                   // turn LED on to indicate waking up
}

Jack Christensen


Do we have data on how much power is consumed by an actual Arduino board in Sleep vs running, for various power sources?
I think I've dismissed this as "it doesn't get low enough for long-lived battery operation", but it occurs to me that that is not at all the same as "not significantly lower."


Here is some data from various Arduino I had kicking around. 5V power supply in all cases, fed to the 5V pin. While I would have to call a 25% to 30% reduction "significantly lower", I'm still in the "it doesn't get low enough for long-lived battery operation" camp where actual Arduino boards are concerned.

Uno R1
38mA running, 26mA with MCU in power-down mode.

Uno SMD edition
42mA running, 31mA power-down.

Adafruit Boarduino
Power select jumper set to "USB", USB (FTDI) not connected.
15mA running, 3mA power-down.

Adafruit Boarduino sans power LED
12mA running, 0.1µA power-down.

ATmega328P-PU on a breadboard
12mA running, 0.1µA power-down.

Code: [Select]
//Sketch to measure current while sleeping.
//Wire a button from pin D2 (INT0) to ground.
//Pushing the button wakes the MCU.
//Once awake, the MCU flashes the pin 13 LED, then
//waits 10 seconds before going back to sleep.
//
//Jack Christensen 07May2013

#include <avr/sleep.h>

#define LED LED_BUILTIN            //LED on pin 13

byte intCounter;                   //interrupt counter

void setup(void)
{
   makePinsInput();
   EICRA = 0x00;                  //configure INT0 to trigger on low level
}

void loop(void)
{
   for (byte i=0; i<5; i++) {
       digitalWrite(LED, HIGH);
       delay(100);
       digitalWrite(LED, LOW);
       delay(100);
   }
   delay(10000);
   goToSleep();
}

void goToSleep()
{
   byte intCounter, adcsra, mcucr1, mcucr2;

   makePinsInput();
   sleep_enable();
   set_sleep_mode(SLEEP_MODE_PWR_DOWN);
   EIMSK = _BV(INT0);             //enable INT0
   adcsra = ADCSRA;               //save the ADC Control and Status Register A
   ADCSRA = 0;                    //disable ADC
   cli();
   mcucr1 = MCUCR | _BV(BODS) | _BV(BODSE);  //turn off the brown-out detector
   mcucr2 = mcucr1 & ~_BV(BODSE);
   MCUCR = mcucr1;                //timed sequence
   MCUCR = mcucr2;                //BODS stays active for 3 cycles, sleep instruction must be executed while it's active
   sei();                         //ensure interrupts enabled so we can wake up again
   sleep_cpu();                   //go to sleep
   sleep_disable();               //wake up here
   ADCSRA = adcsra;               //restore ADCSRA
   makePinsInput();
}

ISR(INT0_vect)
{
   EIMSK = 0;                     //disable interrupts (only need one to wake up)
   ++intCounter;
}

//make all pins input pins with pullup resistors to minimize power consumption
void makePinsInput(void)
{
   for (byte i=0; i<20; i++) {
       pinMode(i, INPUT_PULLUP);  
   }
   pinMode(LED, OUTPUT);          //except the LED pin
   digitalWrite(LED, LOW);
}
MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

Go Up