Timer interrupts and getting a constant time period

I'm new to using timer interrupts and have done a lot of reading around the subject and tried out some code but I'm fascinated to find out why I'm not getting a constant time period with the code below.

To be clear I don't really need a perfect time constant for the project I am doing, but I wrote this code expecting to get a very constant output on the Serial.print and I don't! Just looking for an explanation as to why this isn't constant, not trying to save the world..........

//sketch testing mills to space the time for a loop cycle time
#include "TimerThree.h"

bool Trigger = true; //triger from interupt.
unsigned long time;
volatile int TimeElapsed = 0; // the time elapsed in that cycle. 
unsigned long PreviousTimeVal = 0; //the time offset at the start of the cycle.

void setup() {
  Timer3.initialize(500000); //500000 is half a second
  Timer3.attachInterrupt(callback);  //attaches callback() as the timer overflow meaning when the fimer overflows the timer is trigered
  
Serial.begin(2000000);
}

void callback(){ // remenber this is an interupt so keep it short an sweet
// remenber this is an interupt so keep it short an sweet
// The Name's Bond,
Trigger = true;
//James Bond.
}
void loop() {
    if (Trigger == true){
          time = micros();  // time is a unsigned long
         // if (time  >= (PreviousTimeVal+ CycleTime)){
          TimeElapsed = time-PreviousTimeVal;
          PreviousTimeVal =time; // should print out a constant time perioud of 11 mils
          Trigger == false;
          Serial.println(TimeElapsed);
                        }
  }

Working with an Arduino Mega 2560 from EELEGOO

Consider:

//sketch testing mills to space the time for a loop cycle time
#include "TimerThree.h"

volatile int iCount = 0;
void setup() {
  Timer3.initialize(1); // or what ever a mSecond is for your timer
  Timer3.attachInterrupt(callback);  //attaches callback() as the timer overflow meaning when the timer overflows the timer is trigered
  
Serial.begin(2000000);
}

void callback(){ // remember this is an interupt so keep it short an sweet
// remember this is an interupt so keep it short an sweet
// The Name's Bond,
iCount++;
//James Bond.
}
void loop() {
    if ( iCount == PlaceYourFavoriteNumberHere)
{
DoYourThingHere;                        }
  }

if( iCount == 5XXXXXXXXXXXXXXXXXXXXXXXXXXX)
{
iCount = 0;
}
}

or at least try:volatile bool Trigger = true; //triger from interupt.
which library are you using ?

How un-constant is it, really?

I'd record the millis() or micros() value in the ISR, store it into a volatile unsigned int, and of course set a flag so you can print it out. That should do the trick. For added fun, keep track of the previous value and print the difference. Easier to see how constant (or not) it really is.

The jitter on handling the timer3 overflow interrupt will be contributed to by several things:

normal jitter due to interrupts having to wait for an insutrction to complete (different
instructions take different numbers of clock cycles to complete) - this is the other of a few clock cycles

system jitter due to other, higher priority, ISRs running and thus delaying your
ISR from starting - this can be many microseconds. Typically the timer0 interrupt that
maintains millis()/micros()/delay() is the prime candidate.

Your own code’s critical sections locking out interrupts briefly (hopefully a microsecond or so
in most cases).

This line is obviously incorrect:

Trigger == false;

Idahowalker:
Consider:

//sketch testing mills to space the time for a loop cycle time

#include "TimerThree.h"

volatile int iCount = 0;
void setup() {
  Timer3.initialize(1); // or what ever a mSecond is for your timer
  Timer3.attachInterrupt(callback);  //attaches callback() as the timer overflow meaning when the timer overflows the timer is trigered
 
Serial.begin(2000000);
}

void callback(){ // remember this is an interupt so keep it short an sweet
// remember this is an interupt so keep it short an sweet
// The Name's Bond,
iCount++;
//James Bond.
}
void loop() {
    if ( iCount == PlaceYourFavoriteNumberHere)
{
DoYourThingHere;                        }
  }

if( iCount == 5XXXXXXXXXXXXXXXXXXXXXXXXXXX)
{
iCount = 0;
}
}

Sorry, you've completely neglected the need for critical sections in that code...

First, did you know that:

[quote author=Arduino Reference]
On 16 MHz Arduino boards (e.g. Duemilanove and Nano), this function has a resolution of four microseconds (i.e. the value returned is always a multiple of four). On 8 MHz Arduino boards (e.g. the LilyPad), this function has a resolution of eight microseconds.[/quote]
If the timing is right on the edge of this resolution, you might see 4 to 8 microsecond jumps, due to varying lengths of instruction timing.
Second, try capturing the micros() value in the interrupt callback, thusly:

//sketch testing mills to space the time for a loop cycle time
#include "TimerThree.h"

bool Trigger = true; //triger from interupt.
volatile unsigned long time; // Changed this to "volatile" because it's being set in an Interrupt Handler
volatile int TimeElapsed = 0; // the time elapsed in that cycle.
unsigned long PreviousTimeVal = 0; //the time offset at the start of the cycle.

void setup() {
  Timer3.initialize(500000); //500000 is half a second
  Timer3.attachInterrupt(callback);  //attaches callback() as the timer overflow meaning when the fimer overflows the timer is trigered
 
  Serial.begin(2000000);
}

void callback(){ 
// The following is UNTESTED! 
// By capturing the micros() value within the Interrupt Handler, you're getting closer to the exact moment the
// interrupt happened.  
  time = micros();
// End UNTESTED

// The Name's Bond,
Trigger = true;
//James Bond.
}
void loop() {
    if (Trigger == true){
//          time = micros();  // Moved to the Interrupt Handler [callback].
         // if (time  >= (PreviousTimeVal+ CycleTime)){
          TimeElapsed = time-PreviousTimeVal;
          PreviousTimeVal =time; // should print out a constant time perioud of 11 mils
          Trigger == false;
          Serial.println(TimeElapsed);
     }
  }

Thanks for the replies!
I’ve now implemented the code from #7 and this is giving a very stable output with a variation of just 4 microseconds just as predicted, but this is completely within spec for my application!

In answer to an earlier question, i am using the library from the Arduino playground https://playground.arduino.cc/code/timer1

A combination of using a ‘volitle bool’, moving the ‘time = mills’ and removing the ‘Trigger == False’ to be ‘Trigger = False’, has solved the big time differences I was seeing in the serial output, thanks to everyone who has posted on this :slight_smile: