Created
November 9, 2019 18:06
-
-
Save dkgrieshammer/66cce6ec92a6427c16804df84c22cc83 to your computer and use it in GitHub Desktop.
Rotary Encoder + Button Keyboard Output (Arduino Pro Micro)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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