Rotary Encoder, Button, and LCD User interface with Menu

I've been using this same code for a few projects now to create a user interface using a single rotary encoder and a button to drive a menu on an LCD as well as the various user input functions. I got tired of moving the code from one project to another the hard way so I decided to condense it into a library. And in response to a few recent posts I thought I would share what I'm doing. It's called REBL_UI.

It currently uses a different LiquidCrystal library that uses a shift register to save pins on the Arduino and drives the LCD through a shift register on the SPI bus, but could easily be adapted to work with any of the existing flavors of LiquidCrystal with only a few lines of code needing to change. If you need help with modifications, ask here or on my github page.

The code can be found on my github page along with my LCD library. There is one simple example code included but for a bigger example see my Disco_Doser code on the same page.

I don't know if you'll find it useful or not, but it doesn't cost me anything to share it so here it is.

Link to REBL_UI repo.

Link to LiquidCrystal_SPI_8Bit

I have a feeling that a lot of people will find it useful :wink:

Thank you Delta-Force Delta-G :wink:

Do you by any chance have an example that uses the LiquidCrystal.h library and an LCD without a shift register?

I join to the above request

Kuba_eM:
I join to the above request

in REBLDisplay.cpp

change to this...
void initLCD(uint8_t aRsPin, uint8_t aEnablePin, uint8_t aD1, uint8_t aD2, uint8_t aD3, uint8_t aD4) {

#ifdef USING_SERIAL
Serial.begin(19200);
#else
LCD = new LiquidCrystal(aRsPin, aEnablePin, aD1, aD2, aD3, aD4);
LCD->begin(NUM_LCD_COLS, NUM_LCD_ROWS);
LCD->noCursor();
LCD->clear();
//setColor(BLUE);

#endif
}

in REBLDisplay.h
Change to this
void initLCD(uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t);

In your sketch add these
#define LCD_D1 4
#define LCD_D2 5
#define LCD_D3 6
#define LCD_D4 7

and change to this.
initLCD(LCD_RS_PIN, LCD_ENABLE_PIN, LCD_D1, LCD_D2, LCD_D3, LCD_D4);

Pretty sure that was all i used to make it work :slight_smile:

Oh and I changed the include to use
#include <LiquidCrystal.h>
instead of the SPI one.

Not sure if there will be any response but I'll give it a shot anyway.

I would like to use it with and I2C LCD Library and would like to know what it is I should modify?

I've seen several different libraries but planning to use this one: Library

Thanks!

vangalvin:
in REBLDisplay.cpp

change to this...
void initLCD(uint8_t aRsPin, uint8_t aEnablePin, uint8_t aD1, uint8_t aD2, uint8_t aD3, uint8_t aD4) {

#ifdef USING_SERIAL
Serial.begin(19200);
#else
LCD = new LiquidCrystal(aRsPin, aEnablePin, aD1, aD2, aD3, aD4);
LCD->begin(NUM_LCD_COLS, NUM_LCD_ROWS);
LCD->noCursor();
LCD->clear();
//setColor(BLUE);

#endif
}

in REBLDisplay.h
Change to this
void initLCD(uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t);

In your sketch add these
#define LCD_D1 4
#define LCD_D2 5
#define LCD_D3 6
#define LCD_D4 7

and change to this.
initLCD(LCD_RS_PIN, LCD_ENABLE_PIN, LCD_D1, LCD_D2, LCD_D3, LCD_D4);

Pretty sure that was all i used to make it work :slight_smile:

Oh and I changed the include to use
#include <LiquidCrystal.h>
instead of the SPI one.

Tried all this but still loads of errors.

tried your example but am getting this

exit status 1
'fun1' was not declared in this scope

Delta_G:
I've been using this same code for a few projects now to create a user interface using a single rotary encoder and a button to drive a menu on an LCD as well as the various user input functions. I got tired of moving the code from one project to another the hard way so I decided to condense it into a library. And in response to a few recent posts I thought I would share what I'm doing. It's called REBL_UI.

It currently uses a different LiquidCrystal library that uses a shift register to save pins on the Arduino and drives the LCD through a shift register on the SPI bus, but could easily be adapted to work with any of the existing flavors of LiquidCrystal with only a few lines of code needing to change. If you need help with modifications, ask here or on my github page.

The code can be found on my github page along with my LCD library. There is one simple example code included but for a bigger example see my Disco_Doser code on the same page.

I don't know if you'll find it useful or not, but it doesn't cost me anything to share it so here it is.

Link to REBL_UI repo.

Link to LiquidCrystal_SPI_8Bit

Which example? Post exactly what you have on YOUR code. Because the code in the example definitely has those functions defined.

Also trying to get the REBL_UI_Example to work:

Arduino: 1.8.5 (Windows 7), Board: "Arduino/Genuino Mega or Mega 2560, ATmega2560 (Mega 2560)"

REBL_UI_Example:17: error: 'fun1' was not declared in this scope

    "display", fun1   }

               ^

REBL_UI_Example:20: error: 'pressToExit' was not declared in this scope

    "press", pressToExit   }

             ^

REBL_UI_Example:23: error: 'pickNumber' was not declared in this scope

    "enter number", pickNumber   }

                    ^

REBL_UI_Example:26: error: 'fourLetterWord' was not declared in this scope

    "enter string", fourLetterWord   }

                    ^

REBL_UI_Example:29: error: 'enterTime' was not declared in this scope

    "set time", enterTime   }

                ^

REBL_UI_Example:32: error: 'showTime' was not declared in this scope

    "show time", showTime   }

                 ^

C:\Users\uraynara\Documents\Arduino\REBL_UI_Example\REBL_UI_Example.ino: In function 'boolean enterTime()':

REBL_UI_Example:161: error: 'now' was not declared in this scope

      timeSetTime = now();

                        ^

REBL_UI_Example:169: error: 'setTime' was not declared in this scope

        setTime(timeSetTime);

                           ^

REBL_UI_Example:175: error: 'now' was not declared in this scope

      displayTime(now());

                      ^

C:\Users\uraynara\Documents\Arduino\REBL_UI_Example\REBL_UI_Example.ino: In function 'boolean showTime()':

REBL_UI_Example:192: error: 'now' was not declared in this scope

  displayTime(now());  // display the running time

                  ^

exit status 1
'fun1' was not declared in this scope

Delta_G:
Post exactly what you have on YOUR code. Because the code in the example definitely has those functions defined.

This is your example, your code. I see the functions defined...so I'm confused. Maybe, where is the Time.h library?

adamaero:
where is the Time.h library?

It's the normal Time library that everyone uses. You can pick it up off this site or from the library manager.

Ok, so by Michael Margolis. Was there any resolution on how to fix the error?

I just don't understand how you got this to work, and it doesn't work for other people.

Thank-you to contributor per1234 on github for submitting the fix. Code should be good now.

The function not declared in this scope errors are fixed. I just compiled on 1.8.5 and it works as it is now on the github. Sorry for the errors.

vangalvin:
Do you by any chance have an example that uses the LiquidCrystal.h library and an LCD without a shift register?

Changes
Defines.h

#define NUM_LCD_ROWS 4
#define NUM_LCD_COLS 20

REBLDisplay.h

#include "REBLDisplay.h"

#ifdef USING_SERIAL
extern HardwareSerial Serial;
#endif

LiquidCrystal *LCD;

uint8_t redPin;
uint8_t greenPin;
uint8_t bluePin;


char lineBuffer[NUM_LCD_ROWS][NUM_LCD_COLS + 1]; // Leave an extra space for terminating null

color_vars current_color;

boolean cursorActive = false;
uint8_t cursorRow;
uint8_t cursorCol;

void initLCD(uint8_t aRsPin, uint8_t aEnablePin, uint8_t aD1, uint8_t aD2, uint8_t aD3, uint8_t aD4) {

#ifdef USING_SERIAL
   Serial.begin(19200);
#else
   LCD = new LiquidCrystal(aRsPin, aEnablePin, aD1, aD2, aD3, aD4);
   LCD->begin(NUM_LCD_COLS, NUM_LCD_ROWS);
   LCD->noCursor();
   LCD->clear();

#endif
}

REBL_UI_Example

#include <LiquidCrystal>
#define ENCODER_INTERRUPT_PIN 2 // MUST keep pin 2.
#define ENCODER_B_PIN A0
#define BUTTON_PIN A1
#define LCD_ENABLE_PIN 13
#define LCD_RS_PIN 12
#define HEART_BEAT_PIN A15
//#define LCD_BLUE A0
//#define LCD_GREEN A2
//#define LCD_RED A4
#define LCD_D1 5    // New ↓
#define LCD_D2 4
#define LCD_D3 3
#define LCD_D4 7
const int contrast = 20;    // min. PWM value

void setup() [Replace everything in the curly braces.]

initLCD(LCD_RS_PIN, LCD_ENABLE_PIN, LCD_D1, LCD_D2, LCD_D3, LCD_D4); // New
  initInterface(BUTTON_PIN, ENCODER_INTERRUPT_PIN, ENCODER_B_PIN);
  reblMenu.setCurrentMenu(&menuList);
  pinMode(8,HIGH);  // LCD pin 15: backlight (anode)
//  pinMode(11,OUTPUT);
//  analogWrite(11,700);
  analogWrite(6,contrast); // PWM~ pins: 3,5,(6),9,10,11. LCD pin 3: Vo (supply for LCD driver)
// Turn on LCD Backlight:
//    lcd.setLED1Pin(1);

Or you can try out the above from this link: github.com/adamaero/REBL_UI

It finally works. The schematic is for the Mega 2560. But it only shows up on half of the LCD (2x16 instead of 4x20). So I think something in "REBLDisplay.cpp" around line 85ish and down would be the change...

pinoutLCD.PNG

Good morning all i hope that someone can assist me.

I have been trying to get this to compile and work on an adafruit M0 Express board and there were 3 errors. I believe that i have them all resolved but hope this helps someone else.

Steps i did to create the error was clone the repository from GitHub - adamaero/REBL_UI: Simple menu UI for Arduino with 16x2 LCD, rotary encoder, and a single button, Set my board to be adafruit M0 Express and click on verify.

Error 1:
C:\Users\Davey\Documents\Arduino\libraries\REBL_UI\REBLInterface.cpp:28:7: error: cannot convert 'volatile uint32_t* {aka volatile long unsigned int*}' to 'volatile byte* {aka volatile unsigned char*}' in assignment

bReg = portInputRegister(digitalPinToPort(aBPin));

Fix:
Update line 28 to be: bReg = (unsigned char*) portInputRegister(digitalPinToPort(aBPin));

Error 2:
REBLInterface.cpp:61:7: error: 'cli' was not declared in this scope
Fix:
replace cli(); with noInterrupts(); on line 61

Error 3:
REBLInterface.cpp:64:7: error: 'sei' was not declared in this scope
Fix:
replace sei(); with interrupts(); on line 64

Thanks and have a great day.

The code here wasn't written for that board. I don't have one of those M0. So you're going to have to use this as an example to write code for that board. Or find some other code that does go with that board. This was all written for AVR Arduino like UNO and Mega.

Hi guys I know this is an older thread but has anyone been able to get this UI to work with an I2C LCD?

I'm a noob and can't seem to figure out what to change.

My LCD works using the hd44780.h base class by Bill Perry along with the hd44780ioClass/hd44780_I2Cexp.h for the I2C expander on the LCD.

I appreciate any help you can give me.