Skip to content

Commit

Permalink
Added polling and multiple encoder support.
Browse files Browse the repository at this point in the history
Added: 
  -polling support
  -multiple encoder support
  -a better readme
  • Loading branch information
sabeechen authored Apr 30, 2018
1 parent 265f232 commit d303a57
Show file tree
Hide file tree
Showing 6 changed files with 209 additions and 10 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.DS_Store
36 changes: 36 additions & 0 deletions examples/encoder_basic/encoder_basic.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#include <RotaryEncoder.h>

#define ENCODER_PIN1 13
#define ENCODER_PIN2 14
#define BUTTON_PIN 12

RotaryEncoder encoder(ENCODER_PIN1, ENCODER_PIN2, BUTTON_PIN);

void buttonDown() {
Serial.println("button down");
}

void buttonUp() {
Serial.println("button up");
}

void movedClockwise() {
Serial.println("moved clockwise");
}

void movedCounterClockwise() {
Serial.println("moved counter-clockwise");
}

void setup() {
Serial.begin(115200);
encoder.setup();
encoder.setupInterrupts();
encoder.setButtonDownCallback(buttonDown);
encoder.setButtonUpCallback(buttonUp);
encoder.setRotateCWCallback(movedClockwise);
encoder.setRotateCCWCallback(movedCounterClockwise);
}

void loop() {
}
36 changes: 36 additions & 0 deletions examples/encoder_without_interrupts/encoder_without_interrupts.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#include <RotaryEncoder.h>

#define ENCODER_PIN1 13
#define ENCODER_PIN2 14
#define BUTTON_PIN 12

RotaryEncoder encoder(ENCODER_PIN1, ENCODER_PIN2, BUTTON_PIN);

void buttonDown() {
Serial.println("button down");
}

void buttonUp() {
Serial.println("button up");
}

void movedClockwise() {
Serial.println("moved clockwise");
}

void movedCounterClockwise() {
Serial.println("moved counter-clockwise");
}

void setup() {
Serial.begin(115200);
encoder.setup();
encoder.setButtonDownCallback(buttonDown);
encoder.setButtonUpCallback(buttonUp);
encoder.setRotateCWCallback(movedClockwise);
encoder.setRotateCCWCallback(movedCounterClockwise);
}

void loop() {
encoder.loop();
}
43 changes: 43 additions & 0 deletions examples/multiple_encoders/multiple_encoders.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#include <RotaryEncoder.h>

#define ENCODER1_PIN1 13
#define ENCODER1_PIN2 14

#define ENCODER2_PIN1 12
#define ENCODER2_PIN2 11

RotaryEncoder encoder1(ENCODER1_PIN1, ENCODER1_PIN2);
RotaryEncoder encoder2(ENCODER2_PIN1, ENCODER2_PIN2);

void movedClockwise() {
Serial.println("moved clockwise");
}

void movedCounterClockwise() {
Serial.println("moved counter-clockwise");
}

void encoder1Interrupt() {
encoder1.loop();
}

void encoder2Interrupt() {
encoder2.loop();
}

void setup() {
Serial.begin(115200);

encoder1.setup();
encoder1.setupInterrupts(encoder1Interrupt);
encoder1.setRotateCWCallback(movedClockwise);
encoder1.setRotateCCWCallback(movedCounterClockwise);

encoder2.setup();
encoder2.setupInterrupts(encoder2Interrupt);
encoder2.setRotateCWCallback(movedClockwise);
encoder2.setRotateCCWCallback(movedCounterClockwise);
}

void loop() {
}
53 changes: 44 additions & 9 deletions src/RotaryEncoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

RotaryEncoder* theEncoder;

void rotaryEncoderIsr() {
void veryHackyRotaryEncoderIsr() {
theEncoder->loop();
}

Expand All @@ -12,18 +12,39 @@ RotaryEncoder::RotaryEncoder(int rotaryPin1, int rotaryPin2, int buttonPin) {
buttonpin = buttonPin;
}

RotaryEncoder::RotaryEncoder(int rotaryPin1, int rotaryPin2) {
rotarypin1 = rotaryPin1;
rotarypin2 = rotaryPin2;
buttonpin = -1;
}

void RotaryEncoder::setup() {
pinMode(rotarypin1, INPUT_PULLUP);
pinMode(rotarypin2, INPUT_PULLUP);
pinMode(buttonpin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(rotarypin1), rotaryEncoderIsr, CHANGE);
attachInterrupt(digitalPinToInterrupt(rotarypin2), rotaryEncoderIsr, CHANGE);
attachInterrupt(digitalPinToInterrupt(buttonpin), rotaryEncoderIsr, CHANGE);
buttonWasDown = digitalRead(buttonpin) == LOW;
encoderLastState = (digitalRead(rotarypin1) << 1) | digitalRead(rotarypin2);
if (buttonpin >= 0) {
buttonWasDown = digitalRead(buttonpin) == LOW;
}
if (rotarypin1 >=0 && rotarypin2 >= 0) {
encoderLastState = (digitalRead(rotarypin1) << 1) | digitalRead(rotarypin2);
}
}

void RotaryEncoder::setupInterrupts() {
setupInterrupts(veryHackyRotaryEncoderIsr);
theEncoder = this;
}

void RotaryEncoder::setupInterrupts(void (*cb)()) {
if (rotarypin1 >=0 && rotarypin2 >= 0) {
attachInterrupt(digitalPinToInterrupt(rotarypin1), cb, CHANGE);
attachInterrupt(digitalPinToInterrupt(rotarypin2), cb, CHANGE);
}
if (buttonpin >= 0) {
attachInterrupt(digitalPinToInterrupt(buttonpin), cb, CHANGE);
}
}

void RotaryEncoder::setButtonDownCallback(void (*cb)()) {
buttondowncb = cb;
}
Expand All @@ -40,13 +61,18 @@ void RotaryEncoder::setRotateCCWCallback(void (*cb)()) {
ccwcb = cb;
}

bool RotaryEncoder::buttonIsDown() {
return buttonWasDown;
}

void RotaryEncoder::loop() {
if ((digitalRead(buttonpin) == LOW) != buttonWasDown) {
if (buttonpin >= 0 && (digitalRead(buttonpin) == LOW) != buttonWasDown) {
if (buttonWasDown && buttonupcb != NULL) buttonupcb();
else if (buttondowncb != NULL) buttondowncb();
buttonWasDown = !buttonWasDown;
}

if (rotarypin1 < 0 || rotarypin2 < 0) return;
int rotaryState = (digitalRead(rotarypin1) << 1) | digitalRead(rotarypin2);
if (encoderLastState != rotaryState) {
if (pattern[encoderLastState] == rotaryState
Expand All @@ -55,14 +81,23 @@ void RotaryEncoder::loop() {
&& lastReportedState != rotaryState) {
cwcb();
lastReportedState = rotaryState;
}
lastWasClockwise = true;
}
else if (pattern[3-encoderLastState] == rotaryState
&& ccwcb != NULL
&& (rotaryState == 0 || rotaryState == 3)
&& lastReportedState != rotaryState) {
ccwcb();
lastReportedState = rotaryState;
}
lastWasClockwise = false;
} else if (rotaryState == 0 || rotaryState == 3) {
// Either the switch malfunctioned or we didn't get updates fast enough to catch the
// transitions, so do our best to infer what the rotation direction was from the last
// rotation.
if (lastWasClockwise) cwcb();
else ccwcb();
}

encoderLastState = rotaryState;
}
}
50 changes: 49 additions & 1 deletion src/RotaryEncoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,62 @@ class RotaryEncoder {
bool buttonWasDown;
int encoderLastState;
int lastReportedState;
bool lastWasClockwise = true;

public:
/* Configures this to use a rotary encoder with an additional button. */
RotaryEncoder(int rotaryPin1, int rotaryPin2, int buttonPin);
void setup() ;

/* Configures this to use a rotary encoder without a button. */
RotaryEncoder(int rotaryPin1, int rotaryPin2);

/* Must be called before other methods, sets up pullup mode for each pin. */
void setup();

/*
* Configures the encoder to use interrupts. Using interrupts mitigates the need to call
* loop() periodically.
*/
void setupInterrupts();

/*
* Configures the encoder to use interrupts. The passed in callback must call this->loop().
*/
void setupInterrupts(void (*cb)());

/*
* Sets the callback to be called when the button is pushed down.
* Expects a no argument method returning void.
*/
void setButtonDownCallback(void (*cb)());

/*
* Sets the callback to be called when the button is released.
* Expects a no argument method returning void.
*/
void setButtonUpCallback(void (*cb)());

/*
* Sets the callback to be called when the encoder is rotated clockwise.
* Expects a no argument method returning void.
*/
void setRotateCWCallback(void (*cb)());

/*
* Sets the callback to be called when the encoder is counter-rotated clockwise.
* Expects a no argument method returning void.
*/
void setRotateCCWCallback(void (*cb)());

/*
* Returns true if the button ahs been pressed.
*/
bool buttonIsDown();

/*
* If using interrupts, this method can be ignored. If not, call this method very frequently
* from your loop to decet the encoder state and handle events.
*/
void loop();
};

Expand Down

0 comments on commit d303a57

Please sign in to comment.