Rotary encoder not working with my menu

I'm confused...

I can get this code to work using the buttons on the ADAFRUIT shield, but using a rotary encoder with the rotary.h library doesn't seem to do anything. I feel like its not reading the encoder quick enough.

I'm using the MenuSystems Library (New Arduino library: MenuSystem - Libraries - Arduino Forum), a Rotary Library (GitHub - brianlow/Rotary: Rotary encoder library for Arduino) and the ADAFRUIT RGB LCD library. I choose the MenuSystems and Rotary libraries because they were very straight forward and seemed easy to use.

I'm just learning all of this, so i'm sure I am making all sorts of mistakes.

a nudge in the right direction is all I need. Here is my code (its not %100 done yet)

// ADAFRUIT Library
#include <Wire.h>
#include <Adafruit_MCP23017.h>
#include <Adafruit_RGBLCDShield.h>

//Rotary Library
#include <Rotary.h>

//Menu Library
#include <MenuSystem.h>

Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();

Rotary r = Rotary(5, 6);

const int buttonPin1 = 4; //Rotary pin for push button

// These make it easy to set the backlight color
#define RED 0x1
#define YELLOW 0x3
#define GREEN 0x2
#define TEAL 0x6
#define BLUE 0x4
#define VIOLET 0x5
#define WHITE 0x7

// Menu variables
MenuSystem ms;
Menu mm("");
MenuItem mm_mi1("TIMED GAME      ");
MenuItem mm_mi2("SHOTS GAME      ");
Menu mu1("SETTINGS      ");
MenuItem mu1_mi1("BACKLIGHT      ");
MenuItem mu1_mi2("PLAYERS        ");

// variables

int buttonState1 = 1;
int colorInt = 1;

void on_item1_selected(MenuItem* p_menu_item)
{
  lcd.setCursor(0, 1);
  lcd.print("Item1 Selected");
  delay(3000);
}

void on_item2_selected(MenuItem* p_menu_item)
{
  lcd.setCursor(0, 1);
  lcd.print("Item2 Selected");
  delay(3000);
}


void on_item3_selected(MenuItem* p_menu_item)
{
  lcd.setCursor(0, 1);
  lcd.print("Item3 Selected");
  delay(3000);

}

void on_item4_selected(MenuItem* p_menu_item)
{
  lcd.setCursor(0, 1);
  lcd.print("Item4 Selected");
  delay(3000);

}

void setup()
{
  Serial.begin(9600);
  lcd.begin(16, 2);
  lcd.clear();
  pinMode(buttonPin1, INPUT);
  // Menu setup
  mm.add_item(&mm_mi1, &on_item1_selected);
  mm.add_item(&mm_mi2, &on_item2_selected);
  mm.add_menu(&mu1);
  mu1.add_item(&mu1_mi1, &on_item3_selected);
  mu1.add_item(&mu1_mi2, &on_item4_selected);
  ms.set_root_menu(&mm);
}

void loop()
{
  process_input();
  update_menu();
}

void update_menu()
{
  lcd.setCursor(0, 0);
  // Display the menu
  lcd.print(ms.get_current_menu()->get_selected()->get_name());
  lcd.setCursor(0, 1);
}

void process_input()
{
  unsigned char result = r.process();
  if (result)
  {
  if (result == DIR_CW) 
    ms.next();
  if (result == DIR_CCW) 
    ms.prev();
  }
}

The three second delays whenever a menu item is selected will guarantee your controls are unresponsive.

Thank you for the quick reply.

I figured that those were only called when I selected something, not when I'm trying to use the encoder to navigate the menu.

I've removed all delays and still getting no response.

Perhaps displaying the menu title each time through loop() is overkill. Perhaps you should only update the LCD when there is actual input.

Did you get the rotary encoder working WITHOUT the LCD? Did the encoder library come with examples you can try?

Interesting about the display refresh. I will think about that.

I got the rotary encoder working without, and actually working with the LCD with the following code, and it works perfect. Displays Left when I rotate counter clockwise, and right when I rotate it clockise.

#include <Wire.h>
#include <Adafruit_MCP23017.h>
#include <Adafruit_RGBLCDShield.h>

#include <Rotary.h>

Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();
Rotary r = Rotary(5, 6);

void setup() {
  Serial.begin(9600);
  lcd.begin(16, 2);
}

void loop() {
  unsigned char result = r.process();
  if (result) {
    lcd.clear();
    lcd.print(result == DIR_CW ? "Right" : "Left");
  }
}

Just out of curiosity, why call Serial.begin() if you are never going to call Serial.print() or Serial.write()?

In process_input(), print the value of the rotary encoder reading. What do you see in the Serial Monitor?

-John,

Thank you! I moved the update_menu display to the end of the if loop in void process_input. It now works perfect. Now the void process_input() looks like this:

void process_input()
{
  int buttonVal = digitalRead(4);
  unsigned char result = r.process();
  if (result)
  {
    if (result == DIR_CW) 
      ms.next();
    if (result == DIR_CCW) 
      ms.prev();
    lcd.setCursor(0, 0);
    // Display the menu
    lcd.print(ms.get_current_menu()->get_selected()->get_name());
    lcd.setCursor(0, 1);
  }

  if (buttonVal == HIGH) {
    delay(500);
    ms.select();
    lcd.setCursor(0, 0);
    lcd.print(ms.get_current_menu()->get_selected()->get_name());
  }
}

The delay is my dirty way to debounce the button built into the encoder.

Paul -

I had Serial.begin() in there to help me debug things. I have just removed the Serial.prints from my code, but forgot to remove the Serial.begin.

oAUGGIEo