Pages: 1 2 [3]   Go Down
Author Topic: When sleeping helps  (Read 3438 times)
0 Members and 1 Guest are viewing this topic.
Global Moderator
Dallas
Online Online
Shannon Member
*****
Karma: 207
Posts: 12928
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

@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.
Logged

Seattle, WA
Offline Offline
Jr. Member
**
Karma: 0
Posts: 57
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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
}
Logged

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


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

Code:
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
}
Logged

Grand Blanc, MI, USA
Offline Offline
Faraday Member
**
Karma: 95
Posts: 4084
CODE is a mass noun and should not be used in the plural or with an indefinite article.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
//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);
}
Logged

MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

Pages: 1 2 [3]   Go Up
Jump to: