Interrupt issue on teensy 4.1

I am having an issue with correct interrupt behaviour on a Teensy 4.1. I have boiled it down to a small piece of code.

Basically I am attaching an interrupt to a RISING edge of a pin. Using a function generator I send a block of 10 pulses to the pin. I have confirmed with an oscilloscope that the pin sees 10 pulses. However, the interrupt routine is called 16 times!

Any ideas or help would be appreciated.

Code Here:

#include <arduino.h>
#include <elapsedMillis.h>

#define ENCA  11  
#define ENCB  12
#define LED   13


bool lastEncA;
bool lastEncB;
long countC;
void setup() {
  // put your setup code here, to run once:
  Serial.begin(57600);
  Serial.printf("hello world\n\r");

  pinMode(ENCA, INPUT);
  pinMode(ENCB, INPUT);
  pinMode(LED,OUTPUT);

  attachInterrupt(digitalPinToInterrupt(ENCA), encoder_shaft_moved, RISING);


}

const int cntDir = 1;
volatile long rCount = 0;
volatile bool currDir = 0;
 
void loop() {
  static elapsedMillis timeSinceLastChange=0;
  static elapsedMillis timeSinceLastDisplay=0;  
  static elapsedMillis  ledTimer=0;
  static bool lastLed=0;
  static bool sentOne = false;
  static long lastDisplayCnt = 0;

  if (ledTimer > 300) {
    if (lastLed == 1) lastLed = 0;
    else lastLed = 1;
    digitalWrite(LED,lastLed);
    ledTimer = 0;
  }

  if (rCount != lastDisplayCnt)
    timeSinceLastChange = 0;

  if ((((long)timeSinceLastChange) > 10) || (((long)timeSinceLastDisplay) > 2000)) {
    if ((lastDisplayCnt != rCount) || (((long)timeSinceLastDisplay) > 2000)) {
      if ((sentOne== false) || (((long)timeSinceLastDisplay) > 2000)) 
         Serial.printf("%lu: %ld %s\n\r",millis(), rCount,currDir == 1 ?"In":"out"); 
         sentOne = true;
         timeSinceLastDisplay = 0;
         lastDisplayCnt = rCount;
      }
      else sentOne = false;
  } 
}


void encoder_shaft_moved() {
  elapsedMillis timeSinceLastChange=0;
    bool newA, newB;
  // put your main code here, to run repeatedly:
  newA = digitalRead(ENCA);
  newB = digitalRead(ENCB);

  rCount++;

  return;
}

im guessing it's a hardware issue: maybe a loose connection?
if this is the case, i would suggest debouncing your input

Aldr,
thanks for the reply. Unfortunately I do not believe this to be the case. One of the scope images is from the actual pin on the teensy and as you can see it is essentially a perfect waveform (which I would expect given it was a signal generator source). Also the underlying issue has appears on all of the 15 or so systems we have built with this hardware. So virtually certain this is a software issue.

In the near-term I did exactly what you suggested which is to change the interrupt to "CHANGE" rather than "RISE" and added debounce code.

However I believe this may be a fundamental issue in the underlying library this I would prefer to make sure Paul sees it.

Thanks,
Rob

From "aldr3i via Arduino Forum" <notifications@arduino.discoursemail.com>
To robws@quayconsulting.net
Date 8/21/2023 8:06:23 PM
Subject [Arduino Forum] [Hardware] Interrupt issue on teensy 4.1

not sure if this would solve it but my other suggestion would be to shorten your isr, should be as short as possible.

  • declare your variables somewhere else.
  • you declared timeSinceLastChange again.
  • and iirc, it shouldnt return anything (?)

can write your isr like this:

void encoder_shaft_moved() {
 timeSinceLastChange=0; //if you intended to reset this variable. but declare as global
 rCount++;
}

Can your function generator do a triangle waveform?
If so, see if the number of false triggers changes as you vary the rise time?

Yes, intersting idea. When I did the triangle waveform I got a huge number of interrrupts, as I modified the duty cycle to give a sharper rising edge the number of interrupts decreased roughly in proportion.

Based on this my guess is that the low level interrupt gets released and immediately fires again if the slope is still rising. Wonder if this is a hardware issue in the iMX or a driver problem.

Aldr,
Generally on-board with making ISR's as short as possible, but in this case its almost the opposite where the ISR is so fast that the edge of the signal is still rising which causes another interrupt to fire because the first one finishes while the signal edge is still rising. See the discussion below on the triangle wave form.

A google search for "Teensy 4.1 hysteresis"
gave this which talks about the pullups setting influencing hysteresis

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