Arduino Leonardo Interrupts 2/3 Problem

Hello,

I am having a weird problem with the Leonardo mini board and using INT 2 and INT 3.

The problem is I attach an interrupt handler to INT 2 and to INT 3. But when the interrupt fires on INT 2 it also calls the interrupt handler attached to INT 3, even when I completely detach the input sensor from the assigned pin for INT 3.

Yet, it does not do this on the Duemilanove. There, it works fine with the interrupts.

Below is sample code that will activate when either switch is fired. Ideally each switch fires only once per revolution. But on the Leonard you get two activations on a single switch per revolution. One reports the correct time, the other always shows a pulse time of 0. The pulse time of 0 happens at the same moment the first interrupt handler is activated.

The circuit used is simple simple. Two reed switches on either pins 2/3 on the Duemilanove or Pins 0/1 on the Leonardo. Other side to ground.

On each revolution you get switch 1 activated, then switch 2. The triggers are timed and debounced.

// Interrupts 
// For Duemilanove
//#define INPUT1_INTERRUPT 0
//#define INPUT2_INTERRUPT 1

// For Leonardo
#define INPUT1_INTERRUPT 2
#define INPUT2_INTERRUPT 3

// PIN Assignments
// For Duemilanove
//#define  INPUT1_PIN   2
//#define  INPUT2_PIN   3

// For Leonardo
#define  INPUT1_PIN   0
#define  INPUT2_PIN   1


#define DEBOUNCE_DELAY 50
long int gblInput1Debounce = 0;
long int gblInput1Start = 0;
long int gblInput1Stop = 0;
long int gblInput1TotalPulseTime = 0;

long int gblInput2Debounce = 0;
long int gblInput2TotalTime = 0; 


void setup() {
    Serial.begin(9600);
  Serial.println("Initializing");

  // Sets our digital pin  
  pinMode(INPUT1_PIN, INPUT);
  // Turns on internal pull-up resistor. 
  digitalWrite(INPUT1_PIN, HIGH);
  // Attach our interrupt and interrupt handler 
  attachInterrupt(INPUT1_INTERRUPT, input1Count, FALLING);

  // Sets our digital pin
  pinMode(INPUT2_PIN, INPUT);
  // Turns on internal pull-up resistor. 
  digitalWrite(INPUT2_PIN, HIGH);
  // Attach our interrupt and interrupt handler
  attachInterrupt(INPUT2_INTERRUPT, input2Count, FALLING);


}

void loop() {
  // Testing
  
}


void input1Count()
{
  
  // debounce and increment timers. 
  if ((millis() - gblInput1Debounce) > DEBOUNCE_DELAY)
  {

    gblInput1Debounce = millis();
    gblInput1TotalPulseTime = millis() - gblInput1Start;
    gblInput1Start = gblInput1Debounce;
    Serial.print("Input1 Pulse Time:");
    Serial.println(gblInput1TotalPulseTime);
  }    
}

void input2Count()
{

  // debounce and increment timers
  if ((millis() - gblInput2Debounce) > DEBOUNCE_DELAY)
  {
    gblInput2Debounce = millis();
    gblInput2TotalTime = millis() - gblInput1Start;

    Serial.print("Input2 Total Pulse Time: ");
    Serial.println(gblInput2TotalTime);
  }  
}

When you run the code on the Leo you get this:

Input1 Pulse Time:5673
Input2 Total Pulse Time: 0
Input2 Total Pulse Time: 163
Input1 Pulse Time:356
Input2 Total Pulse Time: 0
Input2 Total Pulse Time: 174
Input1 Pulse Time:390
Input2 Total Pulse Time: 0
Input2 Total Pulse Time: 196
Input1 Pulse Time:433
Input2 Total Pulse Time: 0
Input2 Total Pulse Time: 215

When you run it one the Duemilanove you get this:

nput1 Pulse Time:228
Input2 Total Pulse Time: 115
Input1 Pulse Time:219
Input2 Total Pulse Time: 126
Input1 Pulse Time:243
Input2 Total Pulse Time: 140
Input1 Pulse Time:264
Input2 Total Pulse Time: 154

The above is correct. One pulse per revolution. The leo is incorrect. I'm getting two pulses per revolution, and one of them (the one at 0ms) fires exactly when the first interrupt handler activates.

Bonus problem: Even when I disconnect the input2 wire, the input1 interrupt handler will fire off the input2 handler at the same time. Again, with nothing attached to that pin/interrupt combo.

Any help is appreciated. I'm out of options and maybe I'm overlooking something obvious.

I have tried the above code with IDE 1.0.2, 1.0.3 and 1.5.2 Beta. All the same results.

I'm thinking: "hardware".
The ATmega32U4 accepts lower digital input voltages than other chips.
The other (older) chips switches from low to high somewhere in the middle of 5V, but the Leonardo switches at lower voltages.

Erdin:
I'm thinking: "hardware".
The ATmega32U4 accepts lower digital input voltages than other chips.
The other (older) chips switches from low to high somewhere in the middle of 5V, but the Leonardo switches at lower voltages.

I have the two reed switches directly on the pins and going to ground. I have turned on the internal pull-up resistors. I am measuring 5V on the circuit when closed. Should I be trying to tie into a lower reference voltage?

My oscilloscope is showing a clean square wave when the switches are cycling as well. Still at a loss. I just tried again on the Duemilanove and it's working. It's only on the Leo that it does this.

Perhaps you can add external 10k pull-up resistors. It that changes something, it is hardware related.
I don't care what you see on the scope, the reed contacts do bounce when closed.

You could even do this:
Use 10k resistor to 5V and the reed contacts.
A low-pass filter from the reed contact to the Arduino input with 1k and 1nF.
And the Arduino input without pull up.

Don't use a capacitor directly parallel with the reed contact, the current spike is not good for the contacts and introduces electrical noise.

Just guessing... but what if digital pins 0 and 1 maintain their RX/TX functions? Is it possible that serial communication interferes with their state? Can you try (at least for testing) to keep the 2009 interrupt assignments (switching 2 with 3)?

spatula:
Just guessing... but what if digital pins 0 and 1 maintain their RX/TX functions? Is it possible that serial communication interferes with their state? Can you try (at least for testing) to keep the 2009 interrupt assignments (switching 2 with 3)?

Sadly, this won't work because I need i2C and it shares the same pins. I will try though moving to those pins as a test and the external pull-up as well.

I am debouncing the switch to prevent false triggers. My oscilloscope just isn't showing any spikes outside of the where I expect them to be. The main thing that is very strange is that when the first interrupt is triggered, it also fires the second interrupt handler at the exact same time. This is why I'm also suspicious of hardware or maybe something odd in the interrupt handling.

Moving to pins 2,3 and disabling the i2c functions still has the same result. I'm now feeding the reed switches directly into a bare Leonardo on pins 2,3 and to gnd with no other code running. It still does the same thing. I'll have to try the external pull-ups next.

void input1Count()

{

// debounce and increment timers.
  if ((millis() - gblInput1Debounce) > DEBOUNCE_DELAY)
  {

gblInput1Debounce = millis();
    gblInput1TotalPulseTime = millis() - gblInput1Start;
    gblInput1Start = gblInput1Debounce;
    Serial.print("Input1 Pulse Time:");
    Serial.println(gblInput1TotalPulseTime);
  }   
}

Don't do serial prints inside an ISR.

I can't reproduce your problem. I eliminated the stuff like debouncing and doing serial prints inside an ISR, and came up with:

const byte pin0led = 11;
const byte pin1led = 12;

void pin0falls ()
  {
  digitalWrite (pin0led, HIGH);
  digitalWrite (pin0led, LOW);
  }
  
void pin1falls ()
  {
  digitalWrite (pin1led, HIGH);
  digitalWrite (pin1led, LOW);
  }
  
void setup ()
  {
  pinMode (pin0led, OUTPUT);
  pinMode (pin1led, OUTPUT);
  
  digitalWrite (pin0led, LOW);
  digitalWrite (pin1led, LOW);
  
  pinMode (0, INPUT_PULLUP);
  pinMode (1, INPUT_PULLUP);
  
  attachInterrupt (2, pin0falls, FALLING);
  attachInterrupt (3, pin1falls, FALLING);
  }  // end of setup

void loop () { }

That just toggles pins 11 and 12 in sympathy with a falling interrupt on pins 0 and 1. And it works! Testing pin 0 (the logic analyzer set up to trigger on a fall):

You can see the toggle on pin 11, only.

Then changing to making pin 1 fall:

So there is no problem with interrupts.

The multiple pulses are bouncing, as I brush one wire against a ground wire.

Thanks Nick. The Serial prints, etc. inside the handlers was out of desperation to debug this thing!

I am backing out everything and starting from scratch again just to re-verify the entire project. I can't explain the problem either, but I'm assuming user error. I just can't figure out why it works fine on the 328 chip and not this one. I'll keep digging and post a follow-up. I appreciate your input.