Can someone please help explain this odd result?

This software is intended to take an input pulse on pin 3 (Arduino Uno) and output a phase delayed pulse (in this case set to 3 ms) on pin 9. As can be seen in the attached scope trace instead of 1 phase delayed pulse I get 4. Please help me to figure out why this happens.

//This is program to take in input pulse on pin 3 and with interrupts generate a phased delayed output pulse on pin 9
#include <TimerOne.h>

#define AC_PIN 9 // output pulse phase delayed by offTime

int period;

volatile int offTime;

double wait = 3276700000;

void setup() {

  offTime = 3000;

  attachInterrupt(1, zero_cross_detect, RISING); //interrupt 1 (pin 3, IRQ1), on rising pulse
  period = 8333;// define period as integer, must specify maximum period when timer is reset, max period=8333 µsec 1000000/60*2

  Timer1.initialize(period);

  Timer1.disablePwm(9);

  Timer1.disablePwm(10);

}
void zero_cross_detect()
{
  Timer1.restart();//reset timer

  Timer1.attachInterrupt(nowIsTheTime, offTime); //when counter hits offtime jump to nowIsThe Time
}

void nowIsTheTime () {


  digitalWrite(AC_PIN, HIGH);
  wait = sqrt(wait);    //delay won’t work in an interrupt.
  if (!wait)                      // this takes 80uS or so on a 16Mhz processor to compute sqrt.
  {
    wait = 3276700000;
  }
  digitalWrite(AC_PIN, LOW);



  attachInterrupt(1, zero_cross_detect, RISING);


}


void loop() {

  //reserved for future software


}

Looks like scope trace got lost on first post.

DS0019.jpg

gusr205: Looks like scope trace got lost on first post.

Have you tried delayMicroseconds() which does work during an interrupt?

Though I'm not sure it would work for that duration.

You should do this blink without delay style instead, using millis() or micros().

void loop(){
if ((digitalRead(3) == HIGH) && (timerRunningFlag == 0) ){
startTime = millis();
timerRunningFlag = 1;
}
if (timerRunningFlag == 1){
currentTime = millis();
if ((currentTime - startTime) >= duration){
timerRunningFlag = 0;
} 
}
}

Fill in the global variables, etc. to make it compile. All time variables are unsigned long.

Thanks for the quick reply. I have to decode a digital bit stream with 45 ms frame length in the main loop and I need to provide output pulses every 8 ms in response to the interrupt. That is why I was trying to use the timer to run async to the main loop. Does that make any sense?

  if (!wait)                      // this takes 80uS or so on a 16Mhz processor to compute sqrt.

That comment is nonsense when placed next to that code.

This software is intended to take an input pulse on pin 3 (Arduino Uno) and output a phase delayed pulse (in this case set to 3 ms) on pin 9.

How long do you want the pulse on pin 9 to last? You want it to start 3ms after an interrupt is received, but how long do you want the output.

I need to provide output pulses every 8 ms in response to the interrupt.

This does not make sense in relationship to the first statement of the problem. Is there an interrupt which triggers every individual output pulse, or is there one interrupt which requires a response of multiple pulses every 8 ms?

Can you please restate the desired output and the timing.

I'm thinking you could use an external interrupt, and the isr for that interrupt calls a routine on timer 1 which, after 3 ms, uses A and B compare interrupts to turn pin 9 on and off.

Hi Cattledog-I get a 120 Hz AC zero crossing detector pulse that I want to be able to phase delay to drive a Triac for AC Motor Control. I have an external interrupt that is called zero_cross_detect that triggers on the rising edge of the zero crossing pulse. That then calls a Timer1 ISR called NowIsTheTime that is supposed to delay for a programmable time (offTime) and then generates a 80 microsecond triac fire pulse. The way I have the s/w configured I get the 80 microsecond pulse when the zero crossing pulse fires and I also get the phase delayed 80 microsecond pulse. I can't figure out why I get the pulses right at zero cross (which is wrong) and then also the phase delayed pulses which are correct. I really appreciate any insight you can provide.

I have re-posted my software with better annotation to explain the code.What it does is provide a pulse when the zero crossing pulse goes high (which is wrong) and a phase delayed 80us pulse which is correct. I’m hoping someone can explain why I get the extra pulses or a better way to do it without being in the main loop.

//This is program to take a 120 Hz zero crossing input pulse on Arduino Uno pin 3 and use interrupts to provide a phased delayed output pulse on pin 9 to drive a Triac for 60 Hz AC motor control.

//Putting this software in the main loop causes timing conflicts with time sensitive software to be added to the loop, hence the dual interrupts

#include <TimerOne.h>

#define AC_PIN 9 // output pulse phase delayed by variable "offTime"

int period;

volatile int offTime;

double wait = 3276700000;

void setup() {

  offTime = 3000;

  attachInterrupt(1, zero_cross_detect, RISING); //input is zero crossing pulse interrupt 1 (pin 3, IRQ1), on rising pulse

  period = 8333;// define period as integer, must specify maximum period when timer is reset, max period=8333 µsec 1000000/60*2

  Timer1.initialize(period);

  Timer1.disablePwm(9);

  Timer1.disablePwm(10);

}
void zero_cross_detect()//restarts the timer based on rising edge of zero crossing pulse
{
  Timer1.restart();//reset timer

  Timer1.attachInterrupt(nowIsTheTime, offTime); //when Timer1 hits offtime "NowIsThe Time" ISR provides "offTime" delay and 80us pulse
}

void nowIsTheTime () {


  digitalWrite(AC_PIN, HIGH);

  wait = sqrt(wait);    //This calculation of sqrt of a large number takes 80uS or so on a 16Mhz processor which generates the 80us Triac drive pulse
  {
  if (!wait)                      
    wait = 3276700000;
  }
  digitalWrite(AC_PIN, LOW);

 

  attachInterrupt(1, zero_cross_detect, RISING);


}


void loop() {

  //reserved for S/W that decodes a 45 millisec serial pulse stream. Putting software to drive the triac pulse in the main loop causes timing conflicts


}

I'm not sure why the timer1 manipulations used by the library are causing the extra interrupt, but I think you will be better off directly using the timer, and following the Arduino Playground code on AC phase control.

http://playground.arduino.cc/Main/ACPhaseControl

Take a look at the referenced code and see if it meets your needs. In that sketch, the timer prescaler is set to 256 which make every timer count = 16 us.

The triac gate pulse length is at 64 us. If you need 80 us, change the 4 count to a 5.

#define PULSE 4   //trigger pulse width (counts)

For a 3ms delay, the value of OCR1A should be 187.

You may wish to change the prescaler from 256 if you need finer control over the output. In that case, you will need to modify the OCR1A value which is setting the turn on delay, and the pulse length (to get 80us).

Cattledog-Wow! This hit the nail on the head! Thanks so much for this information. I searched the playground for AC Motor Control and missed this one.

This code shows me what I was doing wrong. He uses Timer0 for the zero cross interrupt and Timer 1 for the timing. I was trying to do both with Timer1.

Thanks again for the help!

This code shows me what I was doing wrong. He uses Timer0 for the zero cross interrupt and Timer 1 for the timing. I was trying to do both with Timer1.

No. For zero crossing detection, the playground sketch uses external interrupt 0 on digital pin 2. You were using external interrupt 1 on digital pin 3. That was correct. The external interrupts do not involve any of the timers.

I believe that your issues were with the reattachment of the timer1 library interrupt controlling the delay and pulse width, and perhaps with the unusual way you were controlling the pulse width.

Cattledog-Thanks for clearing up my confusion relating interrupts to timers. I got it working now. Thanks again for the help!