Interrupts offer the possibility to execute code triggered by a state change of a pin. At the Arduino Uno, there are two interrupt pins (2 and 3) and in the code you specify which routine must be called if the pin changes its state.
This is the same with the ChipKit family and the HelvePic32 has 5 interrupt pins. These are the following pins:
Interrupt | Pin |
Comment |
int_0 |
RIGHT - 2 |
fixed |
int_1 |
RIGHT - 4 |
PPS default |
int_2 |
LEFT - 6 |
PPS default |
int_3 |
RIGHT - 3 |
PPS default |
int_4 |
RIGHT - 1 / LEFT - 1 |
PPS default |
Where int_0 is fixed on the pin, the other interrupts can be moved to several other pins through PPS (=Peripheral Pin Select). This offers the possibility to shift an interrupt to a different pin if the default pin is used or blocked by something.
In this example we will use the default interrupts and come back to PPS in a later stage.
The following picture shows the interrupts and their alternative pins.
We can use the interrupts to pick up every move of the encoder. For that we hook up the encoder pin A to an interrupt pin (e.g. RIGHT-2).
Is the encoder turned, the pin changes its state and the interrupt routine is called, interrupting the execution of any code in the loop() routine. As the HelvePic32 has no built in pull-up or pull-down resistors, we need to pull-up the input pins. This should look like the following picture:
The code is straight forward. The variables used in the interrupt routines have to be declared as volatile so that the compiler makes them available to the interrupt
routines
#include
#include
volatile int encoderPin1 = nP[RIGHT][4]; // pin connected to INT-1 by default
volatile int encoderPin2 = nP[RIGHT][5];
volatile int number = 0;
int oldnumber = number;
void setup(){
Serial.begin(9600);
pinMode(encoderPin1, INPUT);
pinMode(encoderPin2, INPUT);
attachInterrupt(1, isr_A, FALLING);
Serial.println("Starting Encoder");
}
void loop(){
int val;
for (int i=0; i<256; i++){
delay(30);
if (oldnumber != number){
Serial.print(number);
oldnumber = number;
Serial.println();
}
}
}
void isr_A(){
delay(3); // Debounce time
// Trade off bounce vs missed counts
int LSB = digitalRead(encoderPin1);
int MSB = digitalRead(encoderPin2);
if(LSB == LOW){ // A still LOW ?
if(MSB == HIGH) number++;
if(MSB == LOW) number--;
}
}
In a similar way, we connect the Switch to the pin RIGHT-3 which is by default mapped to interrupt 3. It is a nice exercise to write the code for reading the switch by yourself. In the final
code, you will see the solution I came up with.
The switch pin needs no pull-up resistor as the breakout already has a resistor connected. However, the breakout makes it a pull-down to ground, so the attachInterrupt routine must trigger on a
RISING signal.