Using more that one vector interrupt

Hello Members,

I am using pin change interrupts on an Arduino Nano to detect encoder pulses -
got help on this from Nick Gammon's site as well as others. I am currently using the Adafruit LCD shield with buttons to control a motor and select menu items. Using the library associated with reading the buttons produces multiple button clicks, etc. I found this post from Nick Gammon, http://www.gammon.com.au/forum/?id=10945, which has a nice solution for detecting key presses.

I am wondering if I can add the interrupt routine for digital pin 2 to my current program, which is using pin change interrupts on pins 11 and 13 (arduino digital pins).

This would give me two ISRs - for pin changes - here is my current code for pins 11 and 13:
I have configured the pins as inputs, etc

PCICR |= (1 << PCIE0); // enable group interrupts on PORTB PCINT[7:0]
PCMSK0 |= (1 << PCINT5); // enable interrupt pin 13-bit 5
PCMSK0 |= (1 << PCINT3); // enable interrupt pin 11-bit 3, added 21 Jan

and the ISR:
ISR (PCINT0_vect)//handle pin change interrupt for Port B (D8 to D13), triggered by pins 11 and 13
{
byte MSB = bitRead(PINB,3);
byte LSB = bitRead(PINB,5);

byte encoded = (MSB << 1) | LSB; //converting the 2 pin values to single value
//more compact is byte encoded = bitRead(PINB3)<<1 | bitRead(PINB5);

//sum = adding encoded to the previous encoded value, Nilton61 uses decimal representation of sum as an array index

byte sum = (lastEncoded << 2) | encoded;

if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderCount ++;
if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderCount --;

lastEncoded = encoded; //store this value for next time

}

I would like to add a similar structure to my program using the code from Nick's post - I can put the code into the current project and attempt to run it. I created a test program using Nick's example, but with an ISR pin change:

in setup():

// pin 19 of MCP23017 is plugged into D2 of the Arduino which is interrupt 0
//*** attachInterrupt(0, keypress, FALLING); add register code here
DDRD |= (0 << 2); // Set direction for Arduino pin 2 as Input
PORTD |= (1 << 2); // Set digial pin 2 HIGH

// set the mask bits, etc
PCMSK2 |= (1 << PCINT18);
PCIFR |= bit (PCIF1); // clear any outstanding interrupts
PCICR |= (1 << PCIE2);

sei(); // enable interrupts

and the ISR:
//ISR for pin change
ISR (PCINT2_vect)
{
// handle pin change interrupt for A0 to A5 here
keyPressed = true;
// toggle LED
//digitalWrite (LEDWAKE, !digitalRead (LEDWAKE));
} // end of PCINT2_vect

This works as a standalone program loaded into the Nano. I would like to place the key/button reading code into my main program that currently reads the Adafruit LCD buttons (replacing the Adafruit button reading code). I will still use the LCD for display, but not use the buttons or the associated library (for button reading).

Does this make sense? or should I convert Nick's I2C keypress example to a "library" and use a .h file, etc.

Any suggestions are welcome.

thanks,

ewholz

Does this make sense?

Not really. Pin 2 is an external interrupt pin. Use attachInterrupt() to add an interrupt service routine to interrupt 0, calling it whatever you like. Way easier.

If your code doesn't have anything that does process steps longer than about 200 usecs, you won't need interrupts to read and debounce buttons, even multiplexed many x many.

Hello and Thanks for the reply.

I am not using pin 2 for an interrupt. my project uses almost all of the digital pins available
on the Nano/Uno. I am using digital pins 11 and 13 to read an encoder on a motor. I am using the
pin change interrupt method to read the encoder.

Currently I am using digital pin 2 to provide a motor signal. I have dig pin 4 available to
detect the interrupt from the MCP23017 (pin 19), and hence the pin change interrupt for that pin.

Changing pins around: using 4 for the motor signal and 2 for the interrupt is not out of the question, but since I am using a PCB designed for the project - that means cutting traces, etc.

I currently have the code for the expander and the motor operation in one sketch, but when I press a button on the expander, it resets the whole system - just like pressing the reset button on the Nano board itself.

I know I must be doing something not quite right in terms of programming this, as I have pin change interrupts - should be for dig pin 4 (PCINT20), and dig pins 11 and 13 (PCINT3,PICINT5) which I thought would be no conflict.

Any tips here? I will look into changing the pins around and use pin 2 via the attach method, and pin 4
for the signal.

Thanks,

ewholz

I know I must be doing something not quite right in terms of programming this, as I have pin change interrupts - should be for dig pin 4 (PCINT20), and dig pins 11 and 13 (PCINT3,PICINT5) which I thought would be no conflict.

There should be no fundamental conflict with pin change interrupts on pins 4, 11, and 13.

You showed no code setting up D4 as a pin change interrupt only pin2 which as was previously stated, is more easily used as an external interrupt.

  DDRD  |= (0 << 2);  //  Set direction for Arduino pin 2 as Input

That is not correct syntax for writing a 0 onto a bit. It should be

 DDRD  &= ~(1 << 2);

The code only worked because the default state of a digital pin is INPUT, and your code did not change that.
I would just use pinMode(pin#,INPUT_PULLUP) for what you are doing.

Does the encoder reading code work? Because of the configuration of the on board led, Pin 13 maybe OK for INPUT on the Uno, but usually is not on the Nano.

ewholz:
I currently have the code for the expander and the motor operation in one sketch, but when I press a button on the expander, it resets the whole system - just like pressing the reset button on the Nano board itself.

I know I must be doing something not quite right in terms of programming this, as I have pin change interrupts - should be for dig pin 4 (PCINT20), and dig pins 11 and 13 (PCINT3,PICINT5) which I thought would be no conflict.

Any tips here? I will look into changing the pins around and use pin 2 via the attach method, and pin 4
for the signal.

Thanks,

ewholz

That reset kind of thing happens when Arduino voltage drops below 4.5V, usually due to too much current being pulled.

ewholz note, cattledog is right.

cattledog:

  DDRD  |= (0 << 2);  //  Set direction for Arduino pin 2 as Input

That is not correct syntax for writing a 0 onto a bit. It should be

With AND logic you can clear bits with 0's or leave them as they are with 1's. That's called masking.

With OR logic you can set bits with 1's or leave them as they are with 0's.

0 & 0 = 0 AND -- true if both are true, mask logic
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1

0 | 0 = 0 OR -- true if either is true, fill logic
0 | 1 = 1
1 | 0 = 1
1 | 1 = 1

0 ^ 0 = 0 XOR -- true if they're different, change detection/switch toggle logic
0 ^ 1 = 1
1 ^ 0 = 1
1 ^ 1 = 0

Learn these well, each Arduino Port lets you read/write many pins at once.

Hello,
As always some really good info here. Thanks. There is a mistake (now) in my original code sample above, it is now:
// pin 19 of MCP23017 is plugged into D4 of the Arduino
//*** attachInterrupt(0, keypress, FALLING); add register code here
DDRD |= (0 << 4); // Set direction for Arduino pin 4 as Input
PORTD |= (1 << 4); // Set digial pin 4 HIGH

I will review and revise my code as required - the syntax above seems to work fine, but a careful review of your information on bit wise math I will do!

I will make the appropriate changes - thanks again.

thanks so much for help.

ewholz