This is my first time working with a rotary encoder and interrupts. I am using a Pro Micro which has interrupt pins at pin0 and pin1. The code below works as expected.
My question: do I need to use an interrupt pin for PinB as well, or can I use any digital pin?
It does not seem to work when I choose PinB = 9, for example.
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2); // set the LCD address to 0x27 for a 16 chars and 2 line display
// Used for generating interrupts using CLK signal
const int PinA = 0;
// Used for reading DT signal
const int PinB = 1;
// Used for the push button switch
const int PinSW = 8;
// Keep track of last rotary value
int lastCount = 50;
// Updated by the ISR (Interrupt Service Routine)
volatile int virtualPosition = 50;
// ------------------------------------------------------------------
// INTERRUPT INTERRUPT INTERRUPT INTERRUPT INTERRUPT
// ------------------------------------------------------------------
void isr () {
static unsigned long lastInterruptTime = 0;
unsigned long interruptTime = millis();
// If interrupts come faster than 5ms, assume it's a bounce and ignore
if (interruptTime - lastInterruptTime > 5) {
if (digitalRead(PinB) == LOW)
{
virtualPosition-- ; // Could be -5 or -10
}
else {
virtualPosition++ ; // Could be +5 or +10
}
// Restrict value from 0 to +100
//virtualPosition = min(100, max(0, virtualPosition));
}
// Keep track of when we were here last (no more than every 5ms)
lastInterruptTime = interruptTime;
}
// ------------------------------------------------------------------
// SETUP SETUP SETUP SETUP SETUP SETUP SETUP
// ------------------------------------------------------------------
void setup() {
// Just whilst we debug, view output on serial monitor
// Serial.begin(9600);
lcd.init(); // initialize the lcd
lcd.backlight();
// Rotary pulses are INPUTs
pinMode(PinA, INPUT);
pinMode(PinB, INPUT);
// Switch is floating so use the in-built PULLUP so we don't need a resistor
pinMode(PinSW, INPUT_PULLUP);
// Attach the routine to service the interrupts
attachInterrupt(digitalPinToInterrupt(PinA), isr, LOW);
}
// ------------------------------------------------------------------
// MAIN LOOP MAIN LOOP MAIN LOOP MAIN LOOP MAIN LOOP
// ------------------------------------------------------------------
void loop() {
// Is someone pressing the rotary switch?
if ((!digitalRead(PinSW))) {
virtualPosition = 50;
while (!digitalRead(PinSW))
delay(10);
// Serial.println("Reset");
}
// If the current rotary switch position has changed then update everything
if (virtualPosition != lastCount) {
lcd.clear();
lcd.print(virtualPosition);
// Keep track of this new value
lastCount = virtualPosition ;
}
//delay(100);
}
attachInterrupt(digitalPinToInterrupt(PinA), isr, LOW);
I think you meanFALLING
, otherwise the ISR will continuously get called when the pin is LOW, leaving barely any CPU cycles for you main code.