Inturrupts and millis() function problem

Ardunio Due'
I am using the millis() function to keep track of timed events, but as my hardware needs to go into "sleep" mode I need the millis() function to keep counting.
I have attached a sample program that has 3 different "ISR" samples taken from several Arduino blogs etc.
I can not get any to work with out stopping the millis timer....
I have tried all sleep modes, and yes I understand that some will cause the timers to stop, but pwrSave, ADC and Idle should be ok?
Please advice

Interrupt_01.ino (2.35 KB)

Hi
Actual this is a
Arduino Duemilanove w/ Atmega328, no a Arduino Due
Might have been mistaken as on the first line I put:
Ardunio Due'
(could not be bothered to put the rest of the Italian in, so used a " ' " on the end.....)
Please can you move it back???

Topic moved to "Arduino Due" section because it started with "Ardunio Due'".

Moved back, sigh.

You can post small sketches into the forum directly. Here it is:

#include <Sleep_n0m1.h>
#include <avr/sleep.h>
#include <avr/interrupt.h>
#include <avr/power.h>

/*
I am trying to keep the "millis()" timer going while I put the CPU to sleep.
I understand that full sleep mode will stop the "timers" 
but I can not get ANY of the sample interrupt functions to work without stopping millis() from counting
Samples are taken from several Arduino sites, so I assume "I" have a problem.......!
*/

Sleep sleep;    // Set up SLEEP   

void setup(void) 
{
  Serial.begin(9600);
  
}

void loop(void)
{  
    delay(1000);
 
//Sleep # 1
    Serial.print("Start of sleep # 1 milli count is  ");
    Serial.println(millis(), DEC);
    Serial.flush();
    sleep.pwrSaveMode(); //set sleep mode. pwrDownMode, or idleMode, adcMode
    sleep.sleepInterrupt(0,FALLING); //sleep intill....INT starts falling LOW, eg a new TAG is touched  
    // WAKE up from change in interrupt, INT0 going LOW/FALLING
        
    Serial.print("Wake up from sleep # 1 milli count is  ");
    Serial.println(millis(), DEC);
    delay(1000);
   
//Sleep # 2

    Serial.print("Start of sleep # 2 milli count is  ");
    Serial.println(millis(), DEC);
    Serial.flush();
    sleep_enable();
    attachInterrupt(0, wakeUp, LOW);
    // 0, 1, or many lines of code here 
    set_sleep_mode(SLEEP_MODE_PWR_SAVE);
    cli();
    //sleep_bod_disable();
    sei();
    sleep_cpu();
    //wake up here
    sleep_disable();
    
    Serial.print("Wake up from sleep # 2 milli count is  ");
    Serial.println(millis(), DEC);
    delay(1000);

//Sleep # 3

    Serial.print("Start of sleep # 3 milli count is  ");
    Serial.println(millis(), DEC);
    Serial.flush();
    set_sleep_mode(SLEEP_MODE_PWR_SAVE);   // sleep mode is set here
    sleep_enable();          // enables the sleep bit in the mcucr register // so sleep is possible. just a safety pin
    attachInterrupt(0, wakeUp, LOW);
    sleep_mode();            // here the device is actually put to sleep!!			 
    			 // THE PROGRAM CONTINUES FROM HERE AFTER WAKING UP
    sleep_disable();         // first thing after waking from sleep:	// disable sleep...    
    
    Serial.print("Wake up sleep # 3 milli count is  ");
    Serial.println(millis(), DEC);
    delay(1000);
    Serial.println("Start again....");
    
}   
 void wakeUp()
	{
	sleep_disable();
        detachInterrupt(0);
        //pin2_interrupt_flag = 1;
	delay(10);
        }

One thing I note there is that the millis() timer causes an interrupt, and thus your sketch will wake up about 1 mS later. You'll have to stop timer 0 if you don't want that.

Actually it was in:

A lot of stuff there about power saving.

What hardware do you have connected? Is pin 2 kept high by a pull-up or something?

Pin 2 is connected via a 4.7k to Vcc
Re stopping timer, will this stop millis()?
I put in all 3 ISR to test, but would like just to have millis() running while the CPU is in a lower power mode, and then wake up when INT0 goes low.

Thanks

jamesvote:
I ...would like just to have millis() running while the CPU is in a lower power mode, and then wake up when INT0 goes low.

No doubt. But it doesn't.

Timer 0 is what drives millis(). Without timer 0, millis() won't increment.

One approach is to attach a RTC chip (around $9 on a board) and have that keep track of the time. My post (http://www.gammon.com.au/power) shows how you might "power up" such a chip when required, and get the time from it.

Hi Nick

Would have liked to keep my chip count down, but if no other way, then add hardware....
Thanks the help, best regards
James

Depends how accurate you want it to be. If you are sleeping for 8 seconds with the watchdog timer, you know 8 seconds are up, right? However there would probably be a bit of creep, but you might be able to factor that in by trial and error.

Basically you could take the millis result (from when it is awake) and add in 8000 for every time it slept for 8 seconds, plus some factor you might determine, which is the time taken to wake up and get millis up and running.

Ok, so I sleep for a fixed period of time (save the millis) wake up add fixed amount to millis and if no INT(0) go back to sleep...?
As I was hoping to use millis for an RTC, I don't think it would be very accurate over a day.....
Also if INT(0) is triggered by the operator I would have to add the watchdog timer to millis to get a true figure...
Getting a bit complex just to get timed events recorded.

Thanks, but it looks like more hardware....

James

There are various power saving libraries that will take care of the different power saving modes for you. At least some of these will also take care of correcting the millis() value afterwards.

Hi Peter

I have had a look over some of these but can not see any that look after the millis() while sleeping?
If you have a chance please supply a "hint" on were to look, or if possible, sample code

Thanks

You have a duemilanove?
What is the power source?
The FTDI does not sleep, the regulator does not sleep, the power LED does not sleep, the op-amp/comparator does not sleep.
Your sketch does not put all the unused inputs as either high or low (high with internal pullup is best).
Given all that, you may be disappointed with your power savings when sleeping vs just being on & waiting.

Hi Crossroads

Arduino Duemilanove w/ Atmega328
My problem is NOT that I can put the CPO to sleep it is that I want to keep millis() running.....
See sample's on ISR, these are just test programs to see if millis() will still work while either IDLE, ADC or in SAVE mode
But what I have been shown via Nick is that the Timer 0 stops on ANY sleep function (Arduino compiler problem !!?)

James

So if you're not going to sleep why would millis stop?

Do the other timers stop in the various sleep modes also?

Hi
Bit of confusion.
It is going to sleep but millis() stops.....
I would like to find a way to put the CPU to sleep (save power) but I need millis() to keep running, so when I trigger INT(0) low, I use it to record timed events and run off and do other stuff, then go back to sleep again.
From reading the Atmel328 I was under the impression that power SAVE mode would still keep the timers running.
But it seems that the "Arduino" has other ideas.....

I will admit that I haven't ever played with the various sleep modes, but I was under the impression that when one is in any of the sleep modes that code will not be executing with the millis() function requires. So I don't see how your desire to sleep but also run code at the same time is possible?

Lefty

Hi Lefty

Yes it is looking like millis stops on all sleep modes.
I might see if I can go down to machine code and get the timer 0 count rather use millis()

James

I thought the goal was that after a sleep the result from millis() reflected the time that had elapsed during the sleep, rather than freezing. Presumably because it makes the calculations of subsequent timed events easier since the sleep can be ignored for all practical purposes.

I thought the Rocket Scream power management library did this but I seem to have misremembered since it isn't mentioned in the description. I would have thought it was easy enough to increment the millis() count by however long the sleep has lasted when doing a timed sleep, and I'd be disappointed if nobody writing power management libraries had added that capability. I suppose there's nothing stopping you from just incrementing timer0_millis for yourself, if you wanted.