Rotary Encoder Code

Hi,

I am currently planning my next arduino project where i would like to use a rotary encoder to navigate through menus displayed on an 16x2 LCD. I have been reading up on encoders and testing all the various libraries to see which works best with my encoder and have settle for the the following:

/* Encoder Library - Basic Example
 * http://www.pjrc.com/teensy/td_libs_Encoder.html
 *
 * This example code is in the public domain.
 */

#include <Encoder.h>

// Change these two numbers to the pins connected to your encoder.
//   Best Performance: both pins have interrupt capability
//   Good Performance: only the first pin has interrupt capability
//   Low Performance:  neither pin has interrupt capability
Encoder myEnc(3, 2);
//   avoid using pins with LEDs attached

void setup() {
  Serial.begin(9600);
  Serial.println("Basic Encoder Test:");
}

long oldPosition  = -999;

void loop() {
  readEncoder();
}
  
void readEncoder()
{
  long newPosition = myEnc.read();
  if (newPosition != oldPosition) {
    oldPosition = newPosition;
    Serial.println(newPosition);
  }
}

My issue is how and where do i expand this code so that i get 2 cases
1/ CW counter clockwise
2/ CCW counter clockwise

the reason for this question is i previously made a menu system working with the 5 buttons and to call a different menu withi the state machine it was as easy as

case SWITCH1:
      if (ButtonPush == ENTER)
      {
        state = CLOCKSETUP;
      }
      else if (ButtonPush == BACK)
      {
        state = TIMERSETUP;
      }
       break;

the section of code for the buttons was

int ReadKeypad()
{
  ButtonState = analogRead(ButtonPin);
  delay(20);                                        //debounce
  int k = (analogRead(ButtonPin) - ButtonState);
  if (20 < abs(k))
  return NONE;
  if(ButtonState < 50)          //ShieldRight used as BACK 
  return BACK;
  else if(ButtonState < 195)    //ShieldUp used as UP
  return UP;
  else if(ButtonState < 380)    //ShieldDown used as DOWN
  return DOWN;
  else if(ButtonState < 555)    //ShieldLeft used as ENTER
  return ENTER;
  else if(ButtonState < 790)    //ShieldSelect not used
  return VOID;
  else if(ButtonState < 1000)
  return NONE;
  return NONE;
}

So what i would like to end up with is something like this

if (ButtonRotate == CW)
{
state = CLOCKSETUP;
else if (ButtonRotate == CCW)
state = MAINMENU;
}

i would be glad for any advice and help.

Can’t you tell the direction from which of new and old position is the greater?

newposition > oldposition is one direction, newposition < oldposition is the other.

Do a test for that just after you found they were not equal, ie there had been a movement.

#include <rotary.h>
#include <Wire.h>


volatile int rotationDirection;             // Since in ISR, use volatile to force reload

Rotary r = Rotary(2, 3);                   // Instantiate rotary object on pins 2 and 3

void setup() {

  Serial.begin(115200);
  // Not active for testing
 
  PCICR |= (1 << PCIE2);                      // Set up ISR registers for the routine
  PCMSK2 |= (1 << PCINT18) | (1  << PCINT19);
  sei();                                      // Enable interrupts, just in case
  rotationDirection = 0;
}


void loop() {
   
  if (rotationDirection != 0) {            // Are they tuning?

    switch (rotationDirection) {
      case -1:                                      // CCW
        // decrease your menu position
        break;
      case 1:                                       // CW
        // increase your menu position
        break;
      default:
        Serial.println("Shouldn't be here. rotationDirection =");
        break;
    }
  }
}

/*****
 * Purpose: Interrupt Serice Routine (ISR) to sense turning of rotary encoder
 *
 * Parameter list:
 *  PCINT2_vect     the external service vector for ISR
 *
 *  Return value:
 *    N/A
 *****/
ISR(PCINT2_vect) {

  unsigned char result = r.process();         // Something happened...

  switch (result) {
    case 0:                     // No movement now?
      rotationDirection = 0;
      break;

    case DIR_CW:
      rotationDirection = 1;
      startTime = millis();
      break;

    case DIR_CCW:
      rotationDirection = -1;
      break;
  }
}

I haven’t tried compiling this snippet, but it should be close.

Edit: I forgot to define result and remove a time variable.

Thanks I will try both.