My project is to have 3 rotary encoders (4 pin CLK, DT, VCC,GND) and 3 I2C 16x2 LCD displays on a Arduino Mega 2560 board. I want them to be interrupt attached. I got a sketch working for encoders and a sketch for the PCINT working separately and I tried combining them I got one rotary encoder working the one on pins A10 and A11, but I can't figure out how to change the code to read the other ones. The code will increment and decrement the encoder number up and down.
I changed the PINB to PINK for the for A8-A15 Pins. I tried changing the bits in B00001100 inside hte line if(EA_reading == B00001100 && EA_aFlag) and else if (EA_reading == B00000100) EA_bFlag = 1; but it didnt work.
Thank you for your help in advance.
Rotary Encoder Interrupt V1 working.ino (3.1 KB)
Below is my current code
//3x Encoders 3x LCD displays
//LCD display 1 0x27
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd1(0x27,16,2); // set the LCD address to 0x3F for a 16 chars and 2 line display
//LCD display 1
//LCD display 2 0x26
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd2(0x26,16,2); // set the LCD address to 0x3F for a 16 chars and 2 line display
//LCD display 2
//LCD display 3 0x25
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd3(0x25,16,2); // set the LCD address to 0x3F for a 16 chars and 2 line display
//LCD display 3
//PCINT
#include <YetAnotherPcInt.h>
#define ARRAY_SIZE(X) (sizeof(X)/sizeof(*X))
struct Pin{ int number; const char* name;};
// List of pins we are monitoring
Pin monitored_pins[] = {
{A8, "A8"},
{A9, "A9"},
{A10, "A10"},
{A11, "A11"},
{A12, "A12"},
{A13, "A13"},
{A14, "A14"},
{A15, "A15"},
};
//PCINT
//Rotary Encoder 1
volatile byte EA_aFlag = 0;
// let's us know when we're expecting a rising edge on pinA to signal that the encoder has arrived at a detent
volatile byte EA_bFlag = 0;
// let's us know when we're expecting a rising edge on pinB to signal that the encoder has arrived at a detent (opposite direction to when aFlag is set)
volatile byte EA_encoderPos = 0;
//this variable stores our current value of encoder position. Change to int or uin16_t instead of byte if you want to record a larger range than 0-255
volatile byte EA_oldEncPos = 0;
//stores the last encoder position value so we can compare to the current reading and see if it has changed (so we know when to print to the serial monitor)
volatile byte EA_reading = 0;
//somewhere to store the direct values we read from our interrupt pins before checking to see if we have moved a whole detent
//Rotary Encoder 1
void setup()
{
// LCD 1
lcd1.init();
lcd1.clear();
lcd1.backlight(); // Make sure backlight is on
// LCD 1
// LCD 2
lcd2.init();
lcd2.clear();
lcd2.backlight(); // Make sure backlight is on
// LCD 2
// LCD 3
lcd3.init();
lcd3.clear();
lcd3.backlight(); // Make sure backlight is on
// LCD 3
//PCINT //Tell each pin to start listening
for (int i=0; i<ARRAY_SIZE(monitored_pins); i++) {
pinMode(monitored_pins[i].number, INPUT_PULLUP);
PcInt::attachInterrupt(monitored_pins[i].number, pinChanged, &monitored_pins[i], CHANGE);
}
//PCINT
Serial.begin(9600);
}
//PCINT ISR
void pinChanged(Pin* pin, bool pinstate)
{
/*
Serial.print("Pin ");
Serial.print(pin->name);
Serial.print(" (");
Serial.print(pin->number);
Serial.print(") changed to ");
Serial.println(pinstate ? "HIGH" : "LOW");
*/
cli(); //stop interrupts happening before we read pin values
/* // working //---------------------------------------------------------
EA_reading = PINK & 0xC; // read all eight pin values then strip away all but pinA and pinB's values
if(EA_reading == B00001100 && EA_aFlag) { //check that we have both pins at detent (HIGH) and that we are expecting detent on this pin's rising edge
EA_encoderPos --; //decrement the encoder's position count
EA_bFlag = 0; //reset flags for the next turn
EA_aFlag = 0; //reset flags for the next turn
}
else if (EA_reading == B00000100) EA_bFlag = 1; //signal that we're expecting pinB to signal the transition to detent from free rotation
EA_reading = PINK & 0xC; //read all eight pin values then strip away all but pinA and pinB's values
if (EA_reading == B00001100 && EA_bFlag) { //check that we have both pins at detent (HIGH) and that we are expecting detent on this pin's rising edge
EA_encoderPos ++; //increment the encoder's position count
EA_bFlag = 0; //reset flags for the next turn
EA_aFlag = 0; //reset flags for the next turn
}
else if (EA_reading == B00001000) EA_aFlag = 1; //signal that we're expecting pinA to signal the transition to detent from free rotation
*/// working pins 10 and 11//---------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------
EA_reading = PINK & 0xC; //WAS PIND, read all eight pin values then strip away all but pinA and pinB's values
if(EA_reading == B00001100 && EA_aFlag) { //check that we have both pins at detent (HIGH) and that we are expecting detent on this pin's rising edge
EA_encoderPos --; //decrement the encoder's position count
EA_bFlag = 0; //reset flags for the next turn
EA_aFlag = 0; //reset flags for the next turn
}
else if (EA_reading == B00000100) EA_bFlag = 1; //signal that we're expecting pinB to signal the transition to detent from free rotation
EA_reading = PINK & 0xC; //WAS PIND, read all eight pin values then strip away all but pinA and pinB's values
if (EA_reading == B00001100 && EA_bFlag) { //check that we have both pins at detent (HIGH) and that we are expecting detent on this pin's rising edge
EA_encoderPos ++; //increment the encoder's position count
EA_bFlag = 0; //reset flags for the next turn
EA_aFlag = 0; //reset flags for the next turn
}
else if (EA_reading == B00001000) EA_aFlag = 1; //signal that we're expecting pinA to signal the transition to detent from free rotation
//-----------------------------------------------------------------------------------------------------------------
sei(); //restart interrupts
}
//PCINT ISR
void loop()
{
if(EA_oldEncPos != EA_encoderPos)
{
Serial.println(EA_encoderPos);
EA_oldEncPos = EA_encoderPos;
}
// Print a message on both lines of the LCD.
lcd1.setCursor(0,0); //Set cursor to character 2 on line 0 TOP
lcd1.print("Rotary1 = ");
lcd1.print(EA_encoderPos);
lcd2.setCursor(0,0); //Set cursor to character 2 on line 0 TOP
lcd2.print("Rotary2 = ");
lcd2.print(EA_encoderPos);
lcd3.setCursor(0,0); //Set cursor to character 2 on line 0 TOP
lcd3.print("Rotary3 = ");
lcd3.print(EA_encoderPos);
}
Here is the originial PCINT sketch that I got working
> /*
* This example shows how to monitor state changes on a pin
*/
#include <YetAnotherPcInt.h>
#define ARRAY_SIZE(X) (sizeof(X)/sizeof(*X))
struct Pin {
int number;
const char* name;
};
// List of pins we are monitoring
Pin monitored_pins[] = {
{A8, "A8"},
{A9, "A9"},
{A10, "A10"},
{A11, "A11"},
{A12, "A12"},
{A13, "A13"},
{A14, "A14"},
{A15, "A15"},
};
void pinChanged(Pin* pin, bool pinstate)
{
Serial.print("Pin ");
Serial.print(pin->name);
Serial.print(" (");
Serial.print(pin->number);
Serial.print(") changed to ");
Serial.println(pinstate ? "HIGH" : "LOW");
}
void setup()
{
Serial.begin(9600);
//Tell each pin to start listening
for (int i=0; i<ARRAY_SIZE(monitored_pins); i++) {
pinMode(monitored_pins[i].number, INPUT_PULLUP);
PcInt::attachInterrupt(monitored_pins[i].number, pinChanged, &monitored_pins[i], CHANGE);
}
}
void loop() {}
Here is the rotary encode sketch i used that i got working
> /*******Interrupt-based Rotary Encoder Sketch*******
by Simon Merrett, based on insight from Oleg Mazurov, Nick Gammon, rt, Steve Spence
*/
static int pinA = 9; // Our first hardware interrupt pin is digital pin 2
static int pinB = 8; // Our second hardware interrupt pin is digital pin 3
volatile byte aFlag = 0; // let's us know when we're expecting a rising edge on pinA to signal that the encoder has arrived at a detent
volatile byte bFlag = 0; // let's us know when we're expecting a rising edge on pinB to signal that the encoder has arrived at a detent (opposite direction to when aFlag is set)
volatile byte encoderPos = 0; //this variable stores our current value of encoder position. Change to int or uin16_t instead of byte if you want to record a larger range than 0-255
volatile byte oldEncPos = 0; //stores the last encoder position value so we can compare to the current reading and see if it has changed (so we know when to print to the serial monitor)
volatile byte reading = 0; //somewhere to store the direct values we read from our interrupt pins before checking to see if we have moved a whole detent
void setup() {
pinMode(pinA, INPUT_PULLUP); // set pinA as an input, pulled HIGH to the logic voltage (5V or 3.3V for most cases)
pinMode(pinB, INPUT_PULLUP); // set pinB as an input, pulled HIGH to the logic voltage (5V or 3.3V for most cases)
attachInterrupt(0,PinA,RISING); // set an interrupt on PinA, looking for a rising edge signal and executing the "PinA" Interrupt Service Routine (below)
attachInterrupt(1,PinB,RISING); // set an interrupt on PinB, looking for a rising edge signal and executing the "PinB" Interrupt Service Routine (below)
Serial.begin(9600); // start the serial monitor link
}
void PinA(){
cli(); //stop interrupts happening before we read pin values
reading = PIND & 0xC; // read all eight pin values then strip away all but pinA and pinB's values
if(reading == B00001100 && aFlag) { //check that we have both pins at detent (HIGH) and that we are expecting detent on this pin's rising edge
encoderPos --; //decrement the encoder's position count
bFlag = 0; //reset flags for the next turn
aFlag = 0; //reset flags for the next turn
}
else if (reading == B00000100) bFlag = 1; //signal that we're expecting pinB to signal the transition to detent from free rotation
sei(); //restart interrupts
}
void PinB(){
cli(); //stop interrupts happening before we read pin values
reading = PIND & 0xC; //read all eight pin values then strip away all but pinA and pinB's values
if (reading == B00001100 && bFlag) { //check that we have both pins at detent (HIGH) and that we are expecting detent on this pin's rising edge
encoderPos ++; //increment the encoder's position count
bFlag = 0; //reset flags for the next turn
aFlag = 0; //reset flags for the next turn
}
else if (reading == B00001000) aFlag = 1; //signal that we're expecting pinA to signal the transition to detent from free rotation
sei(); //restart interrupts
}
void loop()
{
if(oldEncPos != encoderPos) {
Serial.println(encoderPos);
oldEncPos = encoderPos;
}
}
[3x Rotary encoders 3x LCDs PCINT v1.ino|attachment](upload://yjEVU7qGFbMod3YrNGLvODuGlGj.ino) (5.8 KB)