Does the serial communication interfere with usage of external interrupts?

Hi,
I am using an arduino nano to count steps of a rotary encoder. Therefore I use the two external interrupts (phase A, B). In the ISRs the movement direction is checked and the counters will be incremented. If the counter reach a certain value, the nano triggers two devices via it's digital output pins and the counter will be resetted. All of this is done in the two ISRs.

The main loop of the code is used to check (poll) the value of a digital pin. If this pin changes, all variables are resetted. This is necessary, because the second device gets triggered delayed at the very first time of the beginning of the program.

So my question is:
Can I monitor the values of the internal variables via the serial monitor or does that interfere with the usage of the two external interrupts, as I have read somewhere that the serial communication (UART) also depends on interrupts.

Thanks in advance!

I would not be too afraid of that , as the both ext. int vectors have a (lot) higher priority than the USART interrupt vectors.


I would crank up the baudrate of serial though, to not waste too much time there.

When you tried printing the values of the internal variables via the serial monitor what issues did you have?

Will incoming interrupts be queued if an ISR is already started? Will a running ISR even be paused if a higher priority interrupt is incoming? Otherwise I don't see the role of the priority. I actually thought that interrupts are disabled when an ISR is already started.

I guess the Vector No. is equal to the priority?

Well I tried it and cranking up the baudrate as @hmeijdam already suggested was a good idea. My program seems to work as planned. Nevertheless there doesn't have to be an issue to clear that point. I mean, maybe it just worked out for me because my timing requirements weren't critical. But there has to be a way to monitor the variable or pin status of a microcontroller without this limitation or risk of interference?

Will incoming interrupts be queued if an ISR is already started?

Yes.

Will a running ISR even be paused if a higher priority interrupt is incoming?

No.

Otherwise I don't see the role of the priority.

I've never seen a good description of how "interrupt priority" is actually handled by the ATmega series, so you raise an important question. Presumably if two interrupts are pending, the higher priority one is executed, leading to the (remote) possibility that the lower one will never be executed.

I actually thought that interrupts are disabled when an ISR is already started.

They are. You can turn them on within an interrupt, then the next pending one will be executed, interrupting the first ISR. Given the lack of information on how pending interrupts are actually handled, that opens another can of worms.

Does the serial communication interfere with usage of external interrupts?

Yes, it introduces additional latency, because if a serial ISR currently being executed, that delays the response to pending interrupts.

1 Like

When an interrupt is being serviced all interrupts are off and the ISR will continue until it finishes. The return from the ISR will clear the interrupt flag. If in the meantime two other potential devices have asserted the interrupt then the one with the highest priority will get serviced and after that ISR is finished the remaining ISR will start. That is the normal course of events.

If however the first ISR enables interrupts this will allow any other interrupt to interrupt your first ISR regardless of priority. If this is done then this first ISR must disable the interrupts before it exits.

Chapter 6.7 of the datasheet tells you about the interrupt priority order, amongst other things

I think that using an interrupt to capture your pin changing is a good approach. Keep your ISR short by just setting a flag, that get's picked up in your main. Usually the sooner you can return from an ISR the better.
But if the triggers from your ISR's come in faster than your main loop can digest, you will run into trouble. Not because of the ISR's, but because how you deal with the results.
So printing on a low baudrate is slowing down your main loop, not slowing down the ISR's, hence the suggestion to cranck it up.

1 Like

I put together this example showing how one interrupt (in this case, external interrupt 0, digital pin 2 on an Uno) can block another (serial) completely.

The external interrupt is triggered by a button on pin 2, with condition LOW. The program will hang and Serial.print() will be blocked while the button is pressed.

// Uno R3
// demo of interrupt priority conflicts

volatile unsigned long current_ms = 0;

//external interrupt routine, get the current time
void pin2_isr() {
  current_ms = millis(); //get the elapsed time
}

void setup() {
  Serial.begin(115200);
  while (!Serial); //wait for connection

  pinMode(2, INPUT_PULLUP); //button pin
  pinMode(3, OUTPUT);
  digitalWrite(3, LOW); //ground for pin 2

  attachInterrupt(digitalPinToInterrupt(2), pin2_isr, LOW); //trigger constantly when button pushed
}
unsigned long ms_copy = 0;

void loop() {
  noInterrupts();  //avoid conflict with isr access
  ms_copy = current_ms; //get last button press time
  interrupts();

  Serial.println(ms_copy);  //print the time when the interrupt was triggered
}
2 Likes

Thanks for your answers so far. They are pretty helpful!

@jremington have you tested this code so far? I'm wondering about the second last paragraph of the data sheet snippet hmeijdam has posted. Where they say, after finishing an ISR the next instruction of the main part is executed even before any other interrupt can be served.

Just for general infor for others. Here is shown how the external interrupts behave (queued because of the set interrupt flag and the ones which trigger as long as the interrupt condition is present)

Does anybody know if there is any other possibility to check my microcontroller outputs or even the variables for debugging? Maybe with an emulation or an programmer? I'm asking for future projects...

If you mean the code I posted in #10, of course I did. Try it yourself, if you don't believe me.

1 Like

In the situations that serial slows down too much, I add a counter to only print every 10, 100, 1000, ....etc iterations, to avoid flooding the serial monitor.

and/or I add a filter, to only print something if the value has changed (above a threshold) compared to the previous value.

If that all is not possible, e.g. when programming a 1 kilobyte part, I use a led, oscilloscope, logic analyzer or frequency counter.

Oscilloscope, logic analyzer, LEDs (perhaps divided down in frequency to a visible rate?) In general, all means of examining variables, other than examining the pins directly are invasive to some extent.

Whether there is meaningful interference depends on the timing requirements of the encoder vs the timing of the serial interrupts.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.