@ironmarvel
in post #35 I have asked you if and if yes how you have tried the default liquid crystal library.
I've just connected a default (HD44780) LCD with your code, modified the rs/rw pins and voila ... a HD44780 LCD works with the code from your starting post.
So it is VERY LIKELY that a LCD library will work with your OLED Display when you set up the pins correctly.
And yes ... I would have a "simple" Menu code for a LCD with standard LCD API...
@ironmarvel Here is the link to the software, the menu stuff in when it is in the setup mode not the play mode. midi trill guitar
I would say it is very unlikely an LCD library would work with an OLED display.
An LCD library has no concept of a buffer that contains all the data written to the display. An LCD driver simply writes the ASCII characters directly into the LCD display at a character position set up or by default the position after the previous position.
Where as all OLEDs have a buffer that matches the display bit for pixel. The act of setting up the display is the act of writing into this buffer. The act of showing the display is to move this buffer into the display.
Some displays have a default ASCII mode where you can print to them just like a text LCD. You use this to annotate graphs. Spec start location and print. A device might emulate an LCD for that level of functionality. You won't be able to dot plot using it, but it should simplify text only apps.
We're back from holiday! Haven't had much time trying to switch over to the SPI interface but we made a few modifications to the keypad definitions:
#include <Keypad.h>
const byte ROWS = 2; // 2 rows
const byte COLS = 2; // 2 columns
char keys[ROWS][COLS] = {
{'1','2'},
{'4','5'},
};
byte rowPins[ROWS] = {0, 1}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {2, 3}; //connect to the column pinouts of the keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
void setup(){
Serial.begin(115200); // make sure to adjust the serial monitor to 115200 baud
}
void loop(){
char key = keypad.getKey();
if (key == '1'){
Serial.println("UP Key Pressed");
}
if (key == '4'){
Serial.println("DOWN Key Pressed");
}
if (key == '2'){
Serial.println("SELECT Key Pressed");
}
if (key == '5'){
Serial.println("MAIN MENU Key Pressed");
}
}
This change happened as we only needed 4 total buttons, so to save 4 extra Arduino pins, we will leave the other keypad lines disconnected. Plus, we can connect more LEDs later!
There are many many ways to implement a menu. The more complex you get the less intuitive it becomes. A lot depends on your final application.
The big thing in my opinion is being consistent. That is always have the same way of getting to a parameter, and always the same way of changing a number.
For example when changing a parameter you have to choice of restricting the value between two limits, or letting it change without limits. If you hit a limit do you stick at that limit or do you wrap round to the beginning. Once you have reached the right number what happens? Does it require some sort of "that's it" confirmation or do you carry on and move back to another screen? Do you want an abandon message?
Do you climb out of a deep menu, level by level or do you go back to the top?
The possibility are endless. So don't try and make up the structure of the menu as you code. Make sure you have a plan and if you have not coded many menus before make that plan on a piece of paper before you begin to code. Once you do that you will find that the code is simple to implement. Have a function for each screen, don't try and do it all in one function or you will end up with a unfathomable mess.
How can the code below be modified to use a 4x20 LCD for a sub-menu system? For instance, my son and I would like a system like this:
START MENU/MAIN MENU will have up to 4 options:
1. //
2. //
3. LED LIGHTS!
4. //
These options will be user selectable using the UP, DOWN, SELECT, and MAIN MENU keypad buttons to navigate. '1' for UP, '4' for DOWN, '2' for SELECT, and '5' for MAIN MENU, like this:
When the 3. LED LIGHTS! option is selected, the LCD changes to a sub menu that has:
>LED 1 ON
LED 2 OFF
LED 3 OFF
LED 4 OFF
Again, the user can select which LED to control using the UP/DOWN keys and pressing the SELECT key to toggle them on and off, similar to how this GIF shows:
Template Code:
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
int upButton = 10;
int downButton = 11;
int selectButton = 12;
int menu = 1;
void setup() {
lcd.begin();
lcd.backlight();
pinMode(upButton, INPUT_PULLUP);
pinMode(downButton, INPUT_PULLUP);
pinMode(selectButton, INPUT_PULLUP);
updateMenu();
}
void loop() {
if (!digitalRead(downButton)){
menu++;
updateMenu();
delay(100);
while (!digitalRead(downButton));
}
if (!digitalRead(upButton)){
menu--;
updateMenu();
delay(100);
while(!digitalRead(upButton));
}
if (!digitalRead(selectButton)){
executeAction();
updateMenu();
delay(100);
while (!digitalRead(selectButton));
}
}
void updateMenu() {
switch (menu) {
case 0:
menu = 1;
break;
case 1:
lcd.clear();
lcd.print(">MenuItem1");
lcd.setCursor(0, 1);
lcd.print(" MenuItem2");
break;
case 2:
lcd.clear();
lcd.print(" MenuItem1");
lcd.setCursor(0, 1);
lcd.print(">MenuItem2");
break;
case 3:
lcd.clear();
lcd.print(">MenuItem3");
lcd.setCursor(0, 1);
lcd.print(" MenuItem4");
break;
case 4:
lcd.clear();
lcd.print(" MenuItem3");
lcd.setCursor(0, 1);
lcd.print(">MenuItem4");
break;
case 5:
menu = 4;
break;
}
}
void executeAction() {
switch (menu) {
case 1:
action1();
break;
case 2:
action2();
break;
case 3:
action3();
break;
case 4:
action4();
break;
}
}
void action1() {
lcd.clear();
lcd.print(">Executing #1");
delay(1500);
}
void action2() {
lcd.clear();
lcd.print(">Executing #2");
delay(1500);
}
void action3() {
lcd.clear();
lcd.print(">Executing #3");
delay(1500);
}
void action4() {
lcd.clear();
lcd.print(">Executing #4");
delay(1500);
}