TimerThree / adding delay between 2 triggers issue.

jonesyro

Active member
I'm trying to add a delay between an Input and output trigger and it's not working.

What I want to do is, when the input trigger receives a pulse, wait a small moment, and then trigger the output trigger.

I would like the "timerInterruptHandler" function to be called after the 10ms but it's always in sync with no delay.

Here's the sample code I'm using,


Code:
#include <TimerThree.h>

void setup() {
  pinMode(23, INPUT_PULLUP); //Input Trigger
  pinMode(21, OUTPUT); //Output Trigger

  attachInterrupt(digitalPinToInterrupt(23), inputInterruptHandler, RISING);

  Timer3.attachInterrupt(timerInterruptHandler);
}


void inputInterruptHandler() {
  Timer3.initialize(10000);  // Wait 10ms before changing output  
}


void timerInterruptHandler() { // Issue: This function should be called after the delay, but is called immediately
  digitalWrite(21, HIGH);
  delayMicroseconds(100);
  digitalWrite(21, LOW);
  Timer3.stop();
}


void loop() {
}

Here's a view of the scope, Input #1(yellow) is Pin 23(input trigger) and Input #2(Purple) is hooked to Pin 21(output trigger). You can see they are triggered at same time, without the delay.

scope.jpg
 
I updated your code so it doesn't need an external signal.
In my version, I use TimerOne to replace the external trigger.

Code:
#include <TimerOne.h>
#include <TimerThree.h>

void setup() {
  pinMode(0, OUTPUT);
  pinMode(1, OUTPUT);

  Timer1.initialize(1000);
  Timer1.attachInterrupt(togglePin0);

  Timer3.initialize(500);
  Timer3.stop();
  Timer3.attachInterrupt(togglePin1);
}

void togglePin0() {
  static bool state = false;
  digitalWrite(0, state);
  state = !state;
  Timer3.start();
}

void togglePin1() {
  static bool state = false;
  digitalWrite(1, state);
  state = !state;
  Timer3.stop();
}

void loop() {}

On the oscilloscope, we can see that both signals are in phase:

in-phase.jpg

I think the problem comes from Timer3.start(), which triggers an interrupt immediately.
As a workaround, you can ignore the first interrupt after Timer3.start(), like so:

Code:
#include <TimerOne.h>
#include <TimerThree.h>

void setup() {
  pinMode(0, OUTPUT);
  pinMode(1, OUTPUT);

  Timer1.initialize(1000);
  Timer1.attachInterrupt(togglePin0);

  Timer3.initialize(500);
  Timer3.stop();
  Timer3.attachInterrupt(togglePin1);
}

volatile int8_t ignoreTicks = 0;  // <- ADDED

void togglePin0() {
  static bool state = false;
  digitalWrite(0, state);
  state = !state;
  ignoreTicks = 1; // <- ADDED
  Timer3.start();
}

void togglePin1() {
  if (ignoreTicks > 0) {   // <- ADDED
    ignoreTicks--;
    return;
  }
  static bool state = false;
  digitalWrite(1, state);
  state = !state;
  Timer3.stop();
}

void loop() {}

The oscilloscope confirms that the second signal is delayed as expected:

out-of-phase.jpg
 
I updated your code so it doesn't need an external signal.
In my version, I use TimerOne to replace the external trigger.

Code:
#include <TimerOne.h>
#include <TimerThree.h>

void setup() {
  pinMode(0, OUTPUT);
  pinMode(1, OUTPUT);

  Timer1.initialize(1000);
  Timer1.attachInterrupt(togglePin0);

  Timer3.initialize(500);
  Timer3.stop();
  Timer3.attachInterrupt(togglePin1);
}

void togglePin0() {
  static bool state = false;
  digitalWrite(0, state);
  state = !state;
  Timer3.start();
}

void togglePin1() {
  static bool state = false;
  digitalWrite(1, state);
  state = !state;
  Timer3.stop();
}

void loop() {}

On the oscilloscope, we can see that both signals are in phase:

View attachment 28346

I think the problem comes from Timer3.start(), which triggers an interrupt immediately.
As a workaround, you can ignore the first interrupt after Timer3.start(), like so:

Code:
#include <TimerOne.h>
#include <TimerThree.h>

void setup() {
  pinMode(0, OUTPUT);
  pinMode(1, OUTPUT);

  Timer1.initialize(1000);
  Timer1.attachInterrupt(togglePin0);

  Timer3.initialize(500);
  Timer3.stop();
  Timer3.attachInterrupt(togglePin1);
}

volatile int8_t ignoreTicks = 0;  // <- ADDED

void togglePin0() {
  static bool state = false;
  digitalWrite(0, state);
  state = !state;
  ignoreTicks = 1; // <- ADDED
  Timer3.start();
}

void togglePin1() {
  if (ignoreTicks > 0) {   // <- ADDED
    ignoreTicks--;
    return;
  }
  static bool state = false;
  digitalWrite(1, state);
  state = !state;
  Timer3.stop();
}

void loop() {}

The oscilloscope confirms that the second signal is delayed as expected:

View attachment 28347

thanks for that - I wonder if it's a limitation of the Timer libraries and if there's a way to make it work with only 1 timer.
 
Back
Top