Go Down

Topic: Using sleep mode effectivelly (Read 4 times) previous topic - next topic

april

Jan 11, 2010, 10:59 pm Last Edit: Jan 11, 2010, 11:02 pm by april.steel Reason: 1
An old thread was not answered at the time and was  in a funny place so I bring back here.

Is anyone able to bring chip out of sleep mode without external trigger.

Is chip able to count 30 minutes while in sleep mode then wake up . Any other way to count externally to 30 min then trigger wake up.

Any new thought here?


I see this comment at  http://www.sensor-networks.org/index.php?page=0820520514
but do not understand?
Quote

In Arduino we are going to use power save mode to save power and as interrupt source we are going to use the overflow interrupt in timer 2.

Timer 2 is a 8 bit counter (counts until 255)  and is able to trigger an overflow interrupt if we also use a 10 bits preescaler we divide the frecuency by 1024 and we get an interrupt source that is triggered 61 times per seconds (16000000 / 1024 / 255 = 61).



This is what I need .How can I program to do this and bring back after 30 minutes

Quote
From Data sheet ATMega328
9.5 Power-down Mode
              When the SM2..0 bits are written to 010, the SLEEP instruction makes the MCU enter Power-
              down mode. In this mode, the external Oscillator is stopped, while the external interrupts, the 2-
              wire Serial Interface address watch, and the Watchdog continue operating (if enabled). Only an
              External Reset, a Watchdog System Reset, a Watchdog Interrupt, a Brown-out Reset, a 2-wire
              Serial Interface address match, an external level interrupt on INT0 or INT1, or a pin change
              interrupt can wake up the MCU. This sleep mode basically halts all generated clocks, allowing
              operation of asynchronous modules only.
              Note that if a level triggered interrupt is used for wake-up from Power-down mode, the changed
              level must be held for some time to wake up the MCU. Refer to "External Interrupts" on page 70
              for details.
              When waking up from Power-down mode, there is a delay from the wake-up condition occurs
              until the wake-up becomes effective. This allows the clock to restart and become stable after
              having been stopped. The wake-up period is defined by the same CKSEL Fuses that define the
              Reset Time-out period, as described in "Clock Sources" on page 27.


I can turn off Watchdog and ADC and others and bring back on when awake.  I look for  the code to turn everything off except one timer to count the 30 minutes then bring it back and turn them all on again.
I have external occillator crystal operating on the arduino board anyway
     
 

Groove

#1
Jan 12, 2010, 12:31 pm Last Edit: Jan 12, 2010, 01:39 pm by GrooveFlotilla Reason: 1
There is no single "sleep mode".

In the first quote, they're using "power-save" mode, which leaves the timer oscillator enabled.
In the second quote, they're talking about "power-down" mode, which allows only external stimulii (INT0, INT1, TWI address match, WDT and BDO).

See section "9.1 Sleep Modes" in the device datasheet for a better explanation of the various sleep modes.
Per Arduino ad Astra

april

Is anyone able to bring chip out of sleep mode without external trigger.

Is chip able to count 30 minutes while in sleep mode then wake up . Any other way to count externally to 30 min then trigger wake up.

Any new thought here?

mircho

Hi! To answer your questions:
1. Yes. Anyone who reads the mentioned article will have the knowledge to wake up the Arduino without external trigger. Here is another good article:
http://interface.khm.de/index.php/lab/experiments/sleep_watchdog_battery/

2. If you want to not have a timer wake up the chip multiple times, increase a counter and when the counter has counted to a specific value, i.e. the 30 min, but to count only once you have to run the chip very slow - in the KHz area. That means to attach a "slow" resonator to the atmega chip. You are asking about the chip, not the Arduino itself, which is "locked" to 16 MHz.
And secondly - yes, you can build an external trigger circuit with an 555 timer in monostable mode, that you can generate a PCInt or an external interrupt. Here are some good descriptions of 555 circuits: http://www.kpsec.freeuk.com/555timer.htm

Groove

#4
Jan 13, 2010, 10:15 am Last Edit: Jan 13, 2010, 10:44 am by GrooveFlotilla Reason: 1
Quote
Is chip able to count 30 minutes while in sleep mode then wake up

Please note: there is no single "sleep mode" - there are several.
It is pointless to keep referring to "sleep mode" unless you specify which one you mean.

However, you could wake up the processor from power-down mode in little bursts every time the watchdog times out.
Count the watchdog timeouts until 30 minutes has elapsed.
This is what the nightingale example does.
To get a single 30 minute timeout in power-down mode, you'd probably have to supply a very slow external clock, which may well cost you more in micro-amps than you save.
[edit]Scratch that: the watchdog has its own oscillator, duh. {smacks forehead}[/edit]
Per Arduino ad Astra

april

Thanks . The last two posts offer more potential. I will use any sleep mode that gets the job done and attaching an external timer seems  will use more than chip in turned on mode.  

Coding Badly

#6
Jan 14, 2010, 04:21 am Last Edit: Jan 14, 2010, 04:21 am by bcook Reason: 1
Some important notes about the watchdog oscillator...


  • It is not accurate.  Expect it to be wrong by as much as 10%.
  • It is dependant on temperature.  Warm the processor and the oscillator runs at a different rate.
  • It is dependant on processor load.  Turn a few digital outputs high and the oscillator runs at a different rate.
  • It "jitters".  Even when everything is kept constant, the oscillator runs at slightly different rates.


april

Yes thank you . I do not care if it delays 30 minutes or 34 minutes as long as it turns off between these read times.

Trouble is it seems to interfere with Dallas temperature sensors atm and the chip will turn off for 30 mins but I cannot get a Dallas reading for some reason?

Odisej

#8
Feb 01, 2010, 04:01 pm Last Edit: Feb 01, 2010, 04:04 pm by Odisej Reason: 1
If you read that article, you probably see, that by default, you can set processor to sleep for max 8sec. My solution is to multiply this 8s to get the wanted down-time. See the code, this example will blink the led 10 times every 80 seconds (approx.):
Code: [Select]

#include <avr/sleep.h>
#include <avr/wdt.h>

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

int nint;
int pinLed=13;

volatile boolean f_wdt=1;

void setup(){

 Serial.begin(9600);
 pinMode(pinLed,OUTPUT);
 Serial.println("Setup watchdog");

 // CPU Sleep Modes
 // SM2 SM1 SM0 Sleep Mode
 // 0    0  0 Idle
 // 0    0  1 ADC Noise Reduction
 // 0    1  0 Power-down
 // 0    1  1 Power-save
 // 1    0  0 Reserved
 // 1    0  1 Reserved
 // 1    1  0 Standby(1)

 cbi( SMCR,SE );      // sleep enable, power down mode
 cbi( SMCR,SM0 );     // power down mode
 sbi( SMCR,SM1 );     // power down mode
 cbi( SMCR,SM2 );     // power down mode

 setup_watchdog(9);

}

byte del;
int cnt;
int counter = 10; // timer for counting watchdog cicles
long time = 0;

//****************************************************************
//****************************************************************
//****************************************************************
void loop(){

 if (f_wdt==1) {  // wait for timed out watchdog / flag is set when a watchdog timeout occurs
   f_wdt=0;       // reset flag

   ///// debuging purpose only /////
   time = millis();
   Serial.print(counter);
   Serial.print(" ");
   Serial.println(time);
   delay(2); //needed for serial.print operation to finish
   /////////////////////////////////////

   if(counter==10)  // if ==10 -> this will be true every 10x8 = 80seconds; set to 225 to get 225x8=1800s = 30min
   {

     //////////////// put code inside this IF ////////
     
     pinMode(pinLed,INPUT); // set all used port to intput to save power

     for(int i=0; i<10; i++)
     {
       digitalWrite(pinLed, HIGH);
       delay(90);
       digitalWrite(pinLed, LOW);
       delay(90);  
     }

     pinMode(pinLed,OUTPUT); // set all ports into state before sleep
     
     ////////////////////////////////////////////////////
     
     counter = 0;
   }
   else counter++;

   system_sleep();

 }

}


//****************************************************************
// set system into the sleep state
// system wakes up when wtchdog is timed out
void system_sleep() {

 cbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter OFF

 set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
 sleep_enable();

 sleep_mode();                        // System sleeps here

   sleep_disable();                     // System continues execution here when watchdog timed out
 sbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter ON

}

//****************************************************************
// 0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms
// 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec
void setup_watchdog(int ii) {

 byte bb;
 int ww;
 if (ii > 9 ) ii=9;
 bb=ii & 7;
 if (ii > 7) bb|= (1<<5);
 bb|= (1<<WDCE);
 ww=bb;
 Serial.println(ww);


 MCUSR &= ~(1<<WDRF);
 // start timed sequence
 WDTCSR |= (1<<WDCE) | (1<<WDE);
 // set new watchdog timeout value
 WDTCSR = bb;
 WDTCSR |= _BV(WDIE);

}
//****************************************************************
// Watchdog Interrupt Service / is executed when  watchdog timed out
ISR(WDT_vect) {
 f_wdt=1;  // set global flag
}



What dallas sensor are you using? 1-Wire? If so, do you have a delay before Read command?

Regards,
Peter

april

Thank you Odisej

No I dont have delay before read ,I will try
Thanks for above code I will work  it some while and come back

april

#10
Feb 05, 2010, 02:12 pm Last Edit: Feb 05, 2010, 02:18 pm by april.steel Reason: 1
Is so I do have a delay before the read. I saw this some time ago related to analog inputs only as they are multiplexed to the ADC.

I am using a digital pin 7 to read the 1 wire signal for the dallas device.
Watchdog example works fine The dallas example tester in the library works too if I just put that on arduino. Still working on your program to work

So both examples work apart on own. Problem comes when combining both into one program. Watchdog is interfering somehow.
On a tested and working  sensor I get one reading only eg 28.50C and it stays the same reading even when I heat sensor.

Udo Klein

I just would like to point out that the Arduino is NOT hardwired to 16 MHz. You can overwrite the prescaler with
Code: [Select]

#include <avr/power.h>

...

clock_prescale_set(value);


value = n --> prescale by 2^n maximum value for n is found in the datasheet. I think 8 is the maximum --> 16 MHz / 256 gives 62.6 kHz.

It is possible to combine this with sleep modes. I found in my project that if I put the processor to idle then it will consume less power if I prescale as well. In my project I could not use a deeper sleep mode, but idle plus prescaling gave significant power reduction as well.

Cheers, Udo
Check out my experiments http://blog.blinkenlight.net

Odisej

Ok, I don't have a sensor with me, but try this code:
Code: [Select]


#include <avr/sleep.h>
#include <avr/wdt.h>
#include <OneWire.h>

OneWire ds(7);

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

int nint;
int pinLed=13;

volatile boolean f_wdt=1;

//////// 1- wire variables /////////
int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract;

byte i;
byte present = 0;
byte data[12];
byte addr[8];
////////////////

void setup(){

 Serial.begin(9600);
 pinMode(pinLed,OUTPUT);
 Serial.println("Setup watchdog");

 // CPU Sleep Modes
 // SM2 SM1 SM0 Sleep Mode
 // 0    0  0 Idle
 // 0    0  1 ADC Noise Reduction
 // 0    1  0 Power-down
 // 0    1  1 Power-save
 // 1    0  0 Reserved
 // 1    0  1 Reserved
 // 1    1  0 Standby(1)

 cbi( SMCR,SE );      // sleep enable, power down mode
 cbi( SMCR,SM0 );     // power down mode
 sbi( SMCR,SM1 );     // power down mode
 cbi( SMCR,SM2 );     // power down mode

 setup_watchdog(9);

}

byte del;
int cnt;
int counter = 10; // timer for counting watchdog cicles
long time = 0;

//****************************************************************
//****************************************************************
//****************************************************************
void loop(){

 if (f_wdt==1) {  // wait for timed out watchdog / flag is set when a watchdog timeout occurs
   f_wdt=0;       // reset flag

   /* ///// debuging purpose only /////
    time = millis();
    Serial.print(counter);
    Serial.print(" ");
    Serial.println(time);
    delay(2); //needed for serial.print operation to finish
    */    ////////////////////////////////////

   if(counter==10)  // if ==10 -> this will be true every 10x8 = 80seconds; set to 225 to get 225x8=1800s = 30min
   {

     //////////////// put code inside this IF ////////

     pinMode(pinLed,INPUT); // set all used port to intput to save power

     for(int i=0; i<10; i++)
     {
       digitalWrite(pinLed, HIGH);
       delay(90);
       digitalWrite(pinLed, LOW);
       delay(90);  
     }

     ///////// 1-wire //////////
     ds.reset();
     ds.skip();
     ds.write(0x44,1);         // start conversion, with parasite power on at the end

     delay(1000);     // maybe 750ms is enough, maybe not
     // we might do a ds.depower() here, but the reset will take care of it.

     present = ds.reset();
     ds.skip();    
     ds.write(0xBE);         // Read Scratchpad


     for ( i = 0; i < 9; i++) {           // we need 9 bytes
       data[i] = ds.read();
     }


     LowByte = data[0];
     HighByte = data[1];
     TReading = (HighByte << 8) + LowByte;
     SignBit = TReading & 0x8000;  // test most sig bit
     if (SignBit) // negative
     {
       TReading = (TReading ^ 0xffff) + 1; // 2's comp
     }
     Tc_100 = (6 * TReading) + TReading / 4;    // multiply by (100 * 0.0625) or 6.25


     Whole = Tc_100 / 100;  // separate off the whole and fractional portions
     Fract = Tc_100 % 100;


     if (SignBit) // If its negative
     {
       Serial.print("-");
     }
     Serial.print(Whole);
     Serial.print(".");
     if (Fract < 10)
     {
       Serial.print("0");
     }
     Serial.print(Fract);

     Serial.print("\n");
     ///////////////1-wire end///////////

     pinMode(pinLed,OUTPUT); // set all ports into state before sleep

     ////////////////////////////////////////////////////

     counter = 0;
   }
   else counter++;

   system_sleep();

 }

}


//****************************************************************
// set system into the sleep state
// system wakes up when wtchdog is timed out
void system_sleep() {

 cbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter OFF

 set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
 sleep_enable();

 sleep_mode();                        // System sleeps here

   sleep_disable();                     // System continues execution here when watchdog timed out
 sbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter ON

}

//****************************************************************
// 0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms
// 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec
void setup_watchdog(int ii) {

 byte bb;
 int ww;
 if (ii > 9 ) ii=9;
 bb=ii & 7;
 if (ii > 7) bb|= (1<<5);
 bb|= (1<<WDCE);
 ww=bb;
 Serial.println(ww);


 MCUSR &= ~(1<<WDRF);
 // start timed sequence
 WDTCSR |= (1<<WDCE) | (1<<WDE);
 // set new watchdog timeout value
 WDTCSR = bb;
 WDTCSR |= _BV(WDIE);

}
//****************************************************************
// Watchdog Interrupt Service / is executed when  watchdog timed out
ISR(WDT_vect) {
 f_wdt=1;  // set global flag
}




Groove

Code: [Select]
     pinMode(pinLed,INPUT); // set all used port to intput to save power

     for(int i=0; i<10; i++)
     {
       digitalWrite(pinLed, HIGH);
       delay(90);
       digitalWrite(pinLed, LOW);
       delay(90);
     }



If you've just set the pin to INPUT, how does the LED light by simply enabling and disabling the internal pull-ups?
Per Arduino ad Astra

Udo Klein

It will light very dim and consume very little power... I did this once by mistake :)
Check out my experiments http://blog.blinkenlight.net

Go Up