Library for manual Encoders as used in user interfaces. Very simple, reduced and rock solid encoder library. Counts full pulses only. Inherent debouncing through state machine. Running on a regular timer IRQ. No IRQ jamming through bouncing. Immune to false edges giving unwanted counts when moving partial steps. Not depending on PinDetect or anything else. May be enhanced by adding acceleration and push button debouncing in the future.

Library for manual Encoders as used in user interfaces. Very simple, reduced and rock solid. Counts full pulses/steps only. Inherent debouncing through state machine. No time dependency for debouncing. Very tight code running in a regular timer IRQ. No IRQ jamming through bouncing edges. Immune to false edges giving unwanted counts when moving partial steps back and forth. Not depending on PinDetect or any other debouncing library. May be enhanced in the near future by adding acceleration and push button debouncing.

Committer:
eduardoG26
Date:
Mon Nov 24 17:06:08 2014 +0000
Revision:
0:fc87dcec05fd
First Revision

Who changed what in which revision?

UserRevisionLine numberNew contents of line
eduardoG26 0:fc87dcec05fd 1 #include "mbed.h"
eduardoG26 0:fc87dcec05fd 2 #include "UI_Encoder.h"
eduardoG26 0:fc87dcec05fd 3
eduardoG26 0:fc87dcec05fd 4 static volatile uint16_t Pulses;
eduardoG26 0:fc87dcec05fd 5 static bool UpDown, Ready;
eduardoG26 0:fc87dcec05fd 6
eduardoG26 0:fc87dcec05fd 7 DigitalIn PinA(ENCODER_PIN_A), PinB(ENCODER_PIN_B);
eduardoG26 0:fc87dcec05fd 8
eduardoG26 0:fc87dcec05fd 9 static Ticker EncoderTick;
eduardoG26 0:fc87dcec05fd 10
eduardoG26 0:fc87dcec05fd 11 static void EncoderTickIRQ()
eduardoG26 0:fc87dcec05fd 12 {
eduardoG26 0:fc87dcec05fd 13 if(PinB) {
eduardoG26 0:fc87dcec05fd 14 if(PinA) { // clockwise?
eduardoG26 0:fc87dcec05fd 15 Ready = true;
eduardoG26 0:fc87dcec05fd 16 } else {
eduardoG26 0:fc87dcec05fd 17 UpDown = true;
eduardoG26 0:fc87dcec05fd 18 }
eduardoG26 0:fc87dcec05fd 19 } else {
eduardoG26 0:fc87dcec05fd 20 if(PinA) { // counterclockwise?
eduardoG26 0:fc87dcec05fd 21 UpDown = false;
eduardoG26 0:fc87dcec05fd 22 } else {
eduardoG26 0:fc87dcec05fd 23 if(Ready) {
eduardoG26 0:fc87dcec05fd 24 if (UpDown) {
eduardoG26 0:fc87dcec05fd 25 Pulses++; //moving forward
eduardoG26 0:fc87dcec05fd 26 } else {
eduardoG26 0:fc87dcec05fd 27 Pulses--; //moving reverse
eduardoG26 0:fc87dcec05fd 28 }
eduardoG26 0:fc87dcec05fd 29 Ready = false;
eduardoG26 0:fc87dcec05fd 30 }
eduardoG26 0:fc87dcec05fd 31 }
eduardoG26 0:fc87dcec05fd 32 }
eduardoG26 0:fc87dcec05fd 33 }
eduardoG26 0:fc87dcec05fd 34
eduardoG26 0:fc87dcec05fd 35 void EncoderStart ()
eduardoG26 0:fc87dcec05fd 36 {
eduardoG26 0:fc87dcec05fd 37 PinA.mode(PullUp);
eduardoG26 0:fc87dcec05fd 38 PinB.mode(PullUp);
eduardoG26 0:fc87dcec05fd 39 EncoderTick.attach_us (&EncoderTickIRQ, 1000);
eduardoG26 0:fc87dcec05fd 40 }
eduardoG26 0:fc87dcec05fd 41
eduardoG26 0:fc87dcec05fd 42 uint16_t EncoderGet ()
eduardoG26 0:fc87dcec05fd 43 {
eduardoG26 0:fc87dcec05fd 44 return Pulses;
eduardoG26 0:fc87dcec05fd 45 }
eduardoG26 0:fc87dcec05fd 46 /*
eduardoG26 0:fc87dcec05fd 47 UI_Encoder::UI_Encoder(PinName pinA, PinName pinB, PinName pinSW, PinMode pullMode, int debounceTime_ms)
eduardoG26 0:fc87dcec05fd 48 {
eduardoG26 0:fc87dcec05fd 49
eduardoG26 0:fc87dcec05fd 50 m_pinA = new DigitalIn(pinA); // interrrupts on pinA & PinB
eduardoG26 0:fc87dcec05fd 51 m_pinB = new DigitalIn(pinB); //
eduardoG26 0:fc87dcec05fd 52
eduardoG26 0:fc87dcec05fd 53 //set pins with internal PullUP-default
eduardoG26 0:fc87dcec05fd 54 m_pinA->mode(pullMode);
eduardoG26 0:fc87dcec05fd 55 m_pinB->mode(pullMode);
eduardoG26 0:fc87dcec05fd 56
eduardoG26 0:fc87dcec05fd 57 // attach interrrupts on pins
eduardoG26 0:fc87dcec05fd 58
eduardoG26 0:fc87dcec05fd 59 m_pinA->attach_asserted(this, &mRotaryEncoder::EncoderIsr);
eduardoG26 0:fc87dcec05fd 60 m_pinA->attach_deasserted(this, &mRotaryEncoder::EncoderIsr);
eduardoG26 0:fc87dcec05fd 61 m_pinB->attach_asserted(this, &mRotaryEncoder::EncoderIsr);
eduardoG26 0:fc87dcec05fd 62 m_pinB->attach_deasserted(this, &mRotaryEncoder::EncoderIsr);
eduardoG26 0:fc87dcec05fd 63
eduardoG26 0:fc87dcec05fd 64 InterruptIn ISR_PinA(pinA);
eduardoG26 0:fc87dcec05fd 65 InterruptIn ISR_PinB(pinB);
eduardoG26 0:fc87dcec05fd 66 ISR_PinA.rise(&EncoderIsr);
eduardoG26 0:fc87dcec05fd 67 ISR_PinA.fall(&EncoderIsr);
eduardoG26 0:fc87dcec05fd 68 // Switch on pinSW
eduardoG26 0:fc87dcec05fd 69 m_pinSW = new PinDetect(pinSW); // interrupt on press switch
eduardoG26 0:fc87dcec05fd 70 m_pinSW->mode(pullMode);
eduardoG26 0:fc87dcec05fd 71
eduardoG26 0:fc87dcec05fd 72 m_pinSW->setSampleFrequency(debounceTime_ms * 1000uL); // Start timers an Defaults debounce time.
eduardoG26 0:fc87dcec05fd 73
eduardoG26 0:fc87dcec05fd 74 }
eduardoG26 0:fc87dcec05fd 75
eduardoG26 0:fc87dcec05fd 76 void UI_Encoder::EncoderIsr(void)
eduardoG26 0:fc87dcec05fd 77 {
eduardoG26 0:fc87dcec05fd 78 if(digitalRead(PinB)==HIGH) {
eduardoG26 0:fc87dcec05fd 79 if(digitalRead(PinA)==HIGH) { // clockwise?
eduardoG26 0:fc87dcec05fd 80 Ready = true;
eduardoG26 0:fc87dcec05fd 81 } else {
eduardoG26 0:fc87dcec05fd 82 UpDown = true;
eduardoG26 0:fc87dcec05fd 83 }
eduardoG26 0:fc87dcec05fd 84 } else {
eduardoG26 0:fc87dcec05fd 85 if(digitalRead(PinA)==HIGH) { // counterclockwise?
eduardoG26 0:fc87dcec05fd 86 UpDown = false;
eduardoG26 0:fc87dcec05fd 87 } else {
eduardoG26 0:fc87dcec05fd 88 if(Ready) {
eduardoG26 0:fc87dcec05fd 89 if (UpDown) {
eduardoG26 0:fc87dcec05fd 90 Pulses++; //moving forward
eduardoG26 0:fc87dcec05fd 91 } else {
eduardoG26 0:fc87dcec05fd 92 Pulses--; //moving reverse
eduardoG26 0:fc87dcec05fd 93 }
eduardoG26 0:fc87dcec05fd 94 Ready = false;
eduardoG26 0:fc87dcec05fd 95 }
eduardoG26 0:fc87dcec05fd 96 }
eduardoG26 0:fc87dcec05fd 97 }
eduardoG26 0:fc87dcec05fd 98 }
eduardoG26 0:fc87dcec05fd 99 */
eduardoG26 0:fc87dcec05fd 100 // End of file