Go Down

Topic: Inturrupts and millis() function problem (Read 1 time) previous topic - next topic

jamesvote

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

jamesvote

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???

Nick Gammon

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

Moved back, sigh.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Nick Gammon

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

Code: [Select]

#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);
        }
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Nick Gammon

http://www.gammon.com.au/interrupts


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.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Nick Gammon

Actually it was in:

http://www.gammon.com.au/power


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?
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

jamesvote

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

Nick Gammon


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.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

jamesvote

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

Nick Gammon

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.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

jamesvote

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

PeterH

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.
I only provide help via the forum - please do not contact me for private consultancy.

jamesvote

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

CrossRoads

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.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

jamesvote

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

Go Up