Interactive Menus for your project with a Display and an Encoder
Ever wondered about how simple an User Interface (UI) for your next electronics hack or project be? Indeed, and you should also seen the humble rotary encoder and a Display as UI for 3D printer or other gadgets. In this tutorial we will look at building such a system with a Nokia 5110 display and a rotary encoder KY-040.
You may use any other character or graphics displays as well as other encoder models. Instead making the code generic, we will start building an UI for a digital clock. On it's home screen it will show time. The pushing of the select switch on the encoder will display the Menu. The Menu in turn will have numerous setting for time, date, time format (12 Hour vs 24 Hour ), time Zone etc..,
The basic hookup will remain same during the entire tutorial. We will test the encoder first and then the display. You may want to hook-up all the things at once or do it step by step. The encoder first and then the display. I would recommend doing it step by step.
Encoders are great input devices which have infinite travel in both clockwise(CW) and anti-clockwise directions(CCW). What that essentially means is that the input range for your gizmo can be decided in software. As in case of your clock, the user may have to transverse a menu of say 8 items. The range for the Menu will be 0 to 7 in both directions . However to input time from the user, the hours will be (0 to 23), minutes and seconds will be (0 to 60). Encoders will help us do all of the above. Apart from this the encoder we will be using also has a select switch. Which can be used to select menu items or confirm an action.
I would highly recommend you to go through the Improved Arduino Rotary Encoder Reading instructable to understand the types of encoders, the internal mechanism and all the related terminology.
I started out with hooking up just the encoder with Arduino and printing the message on the terminal. The code is brilliantly written. It simply increments a variable called encoderPos if the encoder is turned CW and decremented if turned CCW.
The code uses to Interrupt pins 2 and 3 on Arduino. These are setup to trigger on a rising edge of the pulse. The interrupts trigger functions PinA() and PinB() for interrupts on pins 2 and 3 respectively which eventually result in decremented or increment the count. Since these are interrupt functions these aren't called anywhere in the setup() and loop() functions. Also notice the use of keyword volatile for the variables used in the Interrupt functions. We will cover more on interrupts in some other tutorial. However note that this code will only work if the pins 2 and 3 are used. Because other pins on Atmega328 will not have interrupt handling capability.
The code below is all that is required to read the encoder position as well as the select switch.
As said earlier I will be using a Nokia 5110 84x48 pixels graphic display for this tutorial. I will be using the well written Adafruit display and graphics libraries. The display is instantiated with the following pins.
// Software SPI: // pin 7 - Serial clock out (SCLK) // pin 6 - Serial data out (DIN) // pin 5 - Data/Command select (D/C) // pin 4 - LCD chip select (CS) // pin 8 - LCD reset (RST)
You may use the sample sketch that comes with the library to test if the display is indeed working with the setup.
The image below shows, exactly what we are trying to achieve. The Menu is stored in the memory as an array of character strings. The display can show 6 lines at one time. We would like to scroll through the menu, giving user an option to select one item at a time.
int displayMenu(char menuInput[maxItemSize], int menuLength)
Takes the 2D character array as input shows it on the display and returns the item selected. Then we use a case switch statement to execute the next action. The code can be further expanded for all cases and user inputs can be validated to a certain range like 0 to 60 for minutes and seconds.
Going further, there are lots of improvements that can be done. Like inverted first row instead of simple arrow. The validation of user input range and other things. This can be best done in a end project.
If you've made a similar menu with the display and an encoder, do let us know in the comments!