Skip to content
Snippets Groups Projects
RotaryEncoder.h 3 KiB
Newer Older
#ifndef ROTARYENCODER_h
#define ROTARYENCODER_h

class RotaryEncoder {

    // Private members:

    int _pinA;
    int _pinB;

    int _state[2];
    int _position;

    unsigned long _timer;
    int _debounceInterval = 1;

    // {newPin2, newPin1, oldPin2, oldPin1}
    int movements[5][4][4] = {
      { // No movement
        {0, 0, 0, 0},
        {0, 1, 0, 1},
        {1, 0, 1, 0},
        {1, 1, 1, 1}
      },
      { // +1
        {0, 0, 0, 1},
        {0, 1, 1, 1},
        {1, 0, 0, 0},
        {1, 1, 1, 0}
      },
      { // -1
        {0, 0, 1, 0},
        {0, 1, 0, 0},
        {1, 0, 1, 1},
        {1, 1, 0, 1}
      },
      { // +2
        {0, 0, 1, 1},
        {1, 1, 0, 0}
      },
      { // -2
        {0, 1, 1, 0},
        {1, 0, 0, 1}
      },
    };

    // Private Functions:

    void _setState(int a, int b) {
      _state[0] = a;
      _state[1] = b;
    }

    void _incrementPosition(int delta) {
      _position = _position + delta;
    }

    int _findChange(int state1[2], int state2[2]) {
      int stateAppend[] = {state1[1], state1[0], state2[1], state2[0]};

      for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 4; j++) {
          if (_compareArrays(stateAppend, movements[i][j])) {
            if (i == 0) {
              return 0;
            }
            else if (i == 1) {
              return 1;
            }
            else if (i == 2) {
              return -1;
            }
            else if (i == 3) {
              return 2;
            }
            else if (i == 4) {
              return -2;
            }
          }
        }
      }

      for (int i = 3; i < 5; i++) {
        for (int j = 0; j < 2; j++) {
          if (_compareArrays(stateAppend, movements[i][j])) {
            if (i == 3) {
              return 2;
            }
            else if (i == 4) {
              return -2;
            }
          }
        }
      }
      Serial.println("INVALID DATA");
      return 0;
    }

    boolean _compareArrays(int a[4], int b[4]) {
      if (a[0] != b[0]) {
        return false;
      }
      if (a[1] != b[1]) {
        return false;
      }
      if (a[2] != b[2]) {
        return false;
      }
      if (a[3] != b[3]) {
        return false;
      }
      return true;
    }

  public:

    //Public Functions:

    RotaryEncoder(int pinA, int pinB) : _pinA(pinA), _pinB(pinB) {
      pinMode(_pinA, INPUT_PULLUP);
      pinMode(_pinB, INPUT_PULLUP);

      _timer = millis();
      _setState(digitalRead(_pinA), digitalRead(_pinB));
      setPosition(0);
    }

    void initInterupts(void(*function)()) {
      attachInterrupt(_pinA, function, CHANGE);
      attachInterrupt(_pinB, function, CHANGE);
    }

    void setPosition(int value) {
      _position = value;
    }

    void tick() {
      int tempState[] = {digitalRead(_pinA), digitalRead(_pinB)};
      int change = _findChange(tempState, _state);

      if (change != 0) {
        _incrementPosition(change);
        Serial.println(_position);
      }
      _setState(tempState[0], tempState[1]);
    }

};


#endif