Calling a function from an ISR

I am working on a project where I have a pulse train with pulse width x seconds as the pulse width. I am trying to write a code which produces a pulse on an output pin with pulse width, say, greater than 1.5x second at every 3rd pulse.

I am planning to attach an interrupt for raising signal on the input pulse and do a "count++" every time the ISR is called and every third count I want to hold the output pin high for 1.5x second.

I do not want to do a polling in the loop, if possible, and want to use pin interrupts. My concern is that by the time I come back from setting the output pin from high to low, I would have missed a pulse.

Would anyone please suggest how I can accomplish this? I am attaching a figure to make things a bit clearer.

Input Pulse width (x) is about 200E-6 second (frequency 5 kHz)

Thanks
Bu

What sort of frequency is the input?

A couple of ways to do this are...
Use a pin change interrupt and every 3rd/4th rising edge (depending if your looking at description or drawing) set output pin high and a timer interrupt to set it low after the desired amount of time.

Or...
Pin change interrupt that sets output high every 3rd/4th rising edge then waits 2x falling edges later to set the output low.

If the frequency is around 1 second then you have a process which is more than 100,000 times faster than needed. If I where doing this in ASM more than a 1,000,000 times faster than needed.

As for the rest forget the interrupts and see blink without delay.

Mark

Guys,

I am looking at input frequency of about 5kHz. I have modified my initial post to reflect this.

Thanks
Bu

Even so at 16MHz the processor has time to have a long lunch and a nap between pulses.

Do you know the frequency or does the program have to find it. If you have to find the frequency is going to be far simpler to use polling than an ISR.

Mark

Bugaboo:
I am planning to attach an interrupt for raising signal on the input pulse and do a "count++" every time the ISR is called and every third count I want to hold the output pin high for 1.5x second.
I do not want to do a polling in the loop, if possible, and want to use pin interrupts.

Since interrupts are quite unsuitable for this purpose, the question is - why?

Bugaboo:
My concern is that by the time I come back from setting the output pin from high to low, I would have missed a pulse.

You seem to have that backwards. Setting the output pin from high to low is much faster than servicing an interrupt. Unless the pulses are very narrow - and you indicate the very opposite - you will have plenty of time to poll them.

The very last thing you want to do in an interrupt routine, is something of any complexity and servicing the interrupt invokes an significant additional time penalty in itself. So long as you write your main loop properly so that it never waits for anything, you can manage very fast events.

On further consideration, I realise the absurdity of your proposed plan. You are imagining that you would perform timing inside the interrupt routine itself - now of course, the "millis" function itself is interrupt driven, so this could never work on that basis alone. You are suggesting that you would wait for pulses inside the routine that responds to pulses. Well, of course that does not make sense.

Looking at your diagram, I figure it is misleading. If the pulses are "square" - that is, 50% duty cycle, then what I think you are trying to do, is to symmetrically divide the frequency by three. Is that correct?

If so, the algorithm is a twelve step state machine. State zero (and all even states) waits for a rising edge, state 1 (and all odd states) waits for a falling edge. State 5 sets your output high, state 11 sets it low.

Paul__B:

Bugaboo:
I am planning to attach an interrupt for raising signal on the input pulse and do a "count++" every time the ISR is called and every third count I want to hold the output pin high for 1.5x second.
I do not want to do a polling in the loop, if possible, and want to use pin interrupts.

Since interrupts are quite unsuitable for this purpose, the question is - why?

Care to explain why interrupts are not suitable to do this sort of job?

If so, the algorithm is a twelve step state machine. State zero (and all even states) waits for a rising edge, state 1 (and all odd states) waits for a falling edge. State 5 sets your output high, state 11 sets it low.

Surely a 6 step machine is all you need. 1 step per edge. 0 = set output high, 3 = set output low, 5 = back to step 0.

Riva:
Care to explain why interrupts are not suitable to do this sort of job?

Sorry if my explanation was a little less than coherent, but I thought that was what I was explaining. :smiley:

In addition to the more general principle that people should not jump to interrupts when they do not understand what they are doing in the first place.

Riva:
Surely a 6 step machine is all you need. 1 step per edge. 0 = set output high, 3 = set output low, 5 = back to step 0.

I certainly thought about that, but detecting an edge requires a "state machine" in itself - "last state", "new state" and such, two states. I figured that it would be just as easy to have a twelve state machine, as to have a two state machine running inside a 6 state machine. I grant you, it's a close call though.

Maybe this will do the job the OP needs.

#define outPin 13

volatile byte state = 0;

void setup(){
  pinMode(outPin, OUTPUT);
  attachInterrupt(0,pin2ISR,CHANGE);
}

void loop(){
}

void pin2ISR(){
  if((digitalRead(2) == HIGH) && (state == 0)){
    digitalWrite(outPin,HIGH);
  }
  
  if((digitalRead(2) == LOW) && (state == 3)){
    digitalWrite(outPin,LOW);
  }
  
  state++;
  if (state == 6){
    state = 0;
  }
}