Skip to content

Instantly share code, notes, and snippets.

@dkgrieshammer
Created November 9, 2019 18:06
Show Gist options
  • Save dkgrieshammer/66cce6ec92a6427c16804df84c22cc83 to your computer and use it in GitHub Desktop.
Save dkgrieshammer/66cce6ec92a6427c16804df84c22cc83 to your computer and use it in GitHub Desktop.
Rotary Encoder + Button Keyboard Output (Arduino Pro Micro)
#include <Keyboard.h>
/* interrupt routine for Rotary Encoders
tested with Noble RE0124PVB 17.7FINB-24 https://www.nobleusa.com/pdf/xre.pdf - available at pollin.de
and a few others, seems pretty universal
The average rotary encoder has three pins, seen from front: A C B
Clockwise rotation A(on)->B(on)->A(off)->B(off)
CounterCW rotation B(on)->A(on)->B(off)->A(off)
and may be a push switch with another two pins, pulled low at pin 8 in this case
[email protected] 20120107
modified to keyboard Version davidgrieshammer.com 20191101
*/
// usually the rotary encoders three pins have the ground pin in the middle
enum PinAssignments {
encoderPinA = 2, // right
encoderPinB = 3, // left
clearButton = 7 // another two pins
};
volatile unsigned int encoderPos = 0; // a counter for the dial
unsigned int lastReportedPos = 1; // change management
static boolean rotating = false; // debounce management
volatile int rotationPos = 0; // can be 0, -1, 1
// interrupt service routine vars
boolean A_set = false;
boolean B_set = false;
boolean clicked = false;
void setup() {
pinMode(encoderPinA, INPUT);
pinMode(encoderPinB, INPUT);
pinMode(clearButton, INPUT);
// turn on pullup resistors
digitalWrite(encoderPinA, HIGH);
digitalWrite(encoderPinB, HIGH);
digitalWrite(clearButton, LOW);
// encoder pin on interrupt 0 (pin 2)
attachInterrupt(0, doEncoderA, CHANGE);
// encoder pin on interrupt 1 (pin 3)
attachInterrupt(1, doEncoderB, CHANGE);
Keyboard.begin();
//Serial.begin(9600); // output
}
// main loop, work is done by interrupt service routines, this one only prints stuff
void loop() {
rotating = true; // reset the debouncer
if(rotationPos == -1) {
Keyboard.press(KEY_LEFT_ARROW);
Keyboard.releaseAll();
//Serial.println("Left");
rotationPos = 0;
}
if(rotationPos == 1) {
Keyboard.press(KEY_RIGHT_ARROW);
Keyboard.releaseAll();
//Serial.println("Right");
rotationPos = 0;
}
if (digitalRead(clearButton) == HIGH && clicked == false) {
clicked = true;
rotationPos = 0;
//Serial.println("click");
Keyboard.press(KEY_DOWN_ARROW);
Keyboard.releaseAll();
delay(50);
}
if(clicked == true && digitalRead(clearButton) == LOW) {
clicked = false;
delay(50);
}
}
// Interrupt on A changing state
void doEncoderA() {
// debounce
if ( rotating ) delay (1); // wait a little until the bouncing is done
// Test transition, did things really change?
if ( digitalRead(encoderPinA) != A_set ) { // debounce once more
A_set = !A_set;
// adjust counter + if A leads B
if ( A_set && !B_set )
// encoderPos += 1;
rotationPos = 1;
rotating = false; // no more debouncing until loop() hits again
}
}
// Interrupt on B changing state, same as A above
void doEncoderB() {
if ( rotating ) delay (1);
if ( digitalRead(encoderPinB) != B_set ) {
B_set = !B_set;
// adjust counter - 1 if B leads A
if ( B_set && !A_set )
//encoderPos -= 1;
rotationPos = -1;
rotating = false;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment