Execution Time of Control Functions

"Faster"? What is this "event" that requires sub-microseconds to detect?

The use of external interrupts are often the best method to ensuring not missing an event as the ISR can just acknowledge the event by just setting a flag variable that the main loop function can test as it gets a chance to.

Lefty

The events being detected are beats in music, so events are about several milliseconds long and several hundreds of milliseconds apart. Just wondering roughly how fast these loops are and if I'm anywhere close to "missing a beat". Guessing the loops run in the many microsecond to single millisecond range.

As for interrupts, I realize that's ultimately the way to go but I'm currently using all six PWM channels so with an interrupt I'd lose two of them. Future implementations likely won't use PWM at all so that's when I'd use interrupts.

rickso234:
As for interrupts, I realize that's ultimately the way to go but I'm currently using all six PWM channels so with an interrupt I'd lose two of them.

Huh?

rickso234:
The events being detected are beats in music, so events are about several milliseconds long and several hundreds of milliseconds apart.

The processor runs at 16 MHz. Instructions typically take one or two clock cycles to execute. That's 62.5 nanoseconds to 125 nanoseconds.

Using "Port Manipulation", testing for a digital input to go HIGH is something like this...

  while ( (PINB & _BV(PINB0)) == 0 );

...which compiles to this...

  42:	b0 9b       	sbis	0x16, 0	; 22
  44:	fe cf       	rjmp	.-4      	; 0x42 <loop>

...(that's right; two machine instructions) which executes in three cycles if the input is LOW and three cycles if the input is HIGH which is 187.5 nanoseconds.

Assuming "several milliseconds" is five, that loop executes approximately 26 times during a beat.

So, going back to your original question...

I'm using a while loop function to look for an event and am wondering if some of the loop functions (if, for, switch case, while) execute faster than others...

Makes no difference. They are all at least one order of magnitude faster then you will need.

To ensure you don't miss a beat, interrupts are definitely the way to go. How is a beat presented to the processor? Digital input goes HIGH?

To put all this into context, look at this video which shows me decoding MIDI input and showing the results, in a rather wordy (and thus, time-consuming) way on serial output:

That sketch doesn't even use interrupts, apart from the normal serial ones.

It easily keeps up with music.

How is a beat presented to the processor? Digital input goes HIGH?
Using an analog input "above threshold" from a hardware peak detector with some software debounce.

As for the PWM outputs, they use interrupts, and if I designate an interrupt for my own use I have to give up one of the PWM pin pairs, correct?

They (looping functions) are all at least one order of magnitude faster then you will need."
If I start nesting loops and performing operations in the loops, I am concerned I'll start missing beat triggers, but the operations (counting, comparing, etc) are likely much slower than the loop functions so I shouldn't be concerned about looping time. Beats typically are at least 400msec apart so should be plenty of time between them.

400 mS? 4/10 of a second per beat? That's quite slow.

Anyway to answer your original question, if, while, for etc. will effectively turn out very similar code at the machine level.

You can use interrupts to notice events that you don't want to miss, even if you are a few microseconds late in servicing them.

Do the external interrupts intefere with the ability to do PWM, in the same way that timer interrupts do ?

As for the PWM outputs, they use interrupts, and if I designate an interrupt for my own use I have to give up one of the PWM pin pairs, correct?

I'm not sure what you mean by this. The PWM outputs don't use interrupts. They can raise an interrupt if you want them to.

Do the external interrupts intefere with the ability to do PWM, in the same way that timer interrupts do ?

No interrupts interfere with PWM, that is generated by the hardware.

rickso234:

How is a beat presented to the processor? Digital input goes HIGH?
Using an analog input "above threshold" from a hardware peak detector with some software debounce.

The processor has an analog comparator capable of generating an interrupt that may help. It would be especially easy to use if debouncing was done with hardware.

As for the PWM outputs, they use interrupts, ...

Nope. The pin state is changed entirely by hardware.

...and if I designate an interrupt for my own use I have to give up one of the PWM pin pairs, correct?

If, for some reason, you need to use a timer then you may have to give up a PWM pair. At this point, there is nothing in your description to indicate the need.

They (looping functions) are all at least one order of magnitude faster then you will need."
If I start nesting loops and performing operations in the loops, I am concerned I'll start missing beat triggers, ...

In which case, using an interrupt is a good choice.

...but the operations (counting, comparing, etc) are likely much slower than the loop functions so I shouldn't be concerned about looping time. Beats typically are at least 400msec apart so should be plenty of time between them.

(400/1000)/(1/16000000) = 6,400,000 clock cycles; 3.2 million to 6.4 million machine instructions.

Okay, my bad... I mistakenly associated interrupts with timers, and PWM uses timers. Using interrupts would be great!

From the playground...

Arduino has two different kinds of interrupts: “external”, and “pin change”.
Both can be triggered on RISING or FALLING signal edges, correct? Is there any other significant difference between these two kinds of interrupts?

External interrupt pins are mapped to Arduino pins 2 and 3. Pin change interrupts can be enabled on many more pins.
Using pin 3 for PWM, but pin 2 is available, and then there are the "pin change" interrupts. Currently using an analog pin to detect an analog level (peak-detected audio) so may have to add some external hardware to create logic-level output? Can I generate an interrupt on an analog input from an analog level?

and from Coding Badly...

The processor has an analog comparator capable of generating an interrupt that may help.
Is this different than the interrupts discussed above?

I'll need to re-structure my code flow to use interrupts but it'll be worth it. Works now with just a loop, but while I'm there waiting for a beat trigger, I can't be doing much else. Using interrupts will change all that!

Time to do more reading about interrupts...

rickso234:
Both can be triggered on RISING or FALLING signal edges, correct? Is there any other significant difference between these two kinds of interrupts?

External interrupts can trigger on RISING, FALLING, CHANGE or LOW. Pin change interrupts are only on changes, plus you get them in batches. So a change to any pin in that batch (if enabled) signals one interrupt.

Can I generate an interrupt on an analog input from an analog level?

The analog comparator will generate an interrupt on a rising or falling edge of comparing a target voltage to a reference voltage.

Wonderful! Your page on interrupts seems quite helpful. I'll need to research the analog comparator further but it should do the job of generating an interrupt on the analog beat trigger which is what I want to do. The trigger signal is 0 - 5v and I assume I can vary the threshold at which the comparator trips by changing the reference voltage.

Indeed. I did a short post about using the comparator:

If I remember correctly, with the analog comparator, you do not need to actually generate an interrupt. You can check for and reset the flag. The advantages: all the issues with interrupts are eliminated; uses a bit less SRAM; possibly generates less code.

I think this modified version of Nick's example shows how...

ISR (ANALOG_COMP_vect)
  {
  }

void setup ()
  {
  Serial.begin (115200);
  Serial.println ("Started.");
  ADCSRB = 0;           // (Disable) ACME: Analog Comparator Multiplexer Enable
  ACSR =  _BV (ACI)     // (Clear) Analog Comparator Interrupt Flag
        | _BV (ACIS1);  // ACIS1, ACIS0: Analog Comparator Interrupt Mode Select (trigger on falling edge)
   }  // end of setup

void loop ()
  {
  if ( (ACSR & _BV (ACI)) != 0 )
    {
    Serial.println ("Triggered!"); 
    ACSR |=  _BV (ACI);     // (Clear) Analog Comparator Interrupt Flag
    }
  
  }  // end of loop

Of course I'm currently using D6 as a PWM output so can't use the analog comparator?

May have to add my own comparator to the circuit and connect its output to a pin change interrupt.

rickso234:
Of course I'm currently using D6 as a PWM output so can't use the analog comparator?

Correct.

May have to add my own comparator to the circuit and connect its output to a pin change interrupt.

Or, you could add an LED driver that supports PWM.

I did a comparator here:

Not that they are complex. :slight_smile: