Go Down

Topic: When sleeping helps (Read 4771 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
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy