hello, I have a working menu using push buttons and have attached the navigation function of this menu below. I want to use an encoder and have included the encoder sketch here too.
what do I have to change to get the navigation menu working off the encoder....... instead of the push buttons.
I will use the right direction of the encoder to move the menu right and left for left. The encoder has a built in push button so I will use that as the "buttonPinEnter" .
I have tried putting some of the encoder sketch into the navigation menu but it just stops any menu working. I sure anyhelp here may help others.
void navigateMenus() {
MenuItem currentMenu=menu.getCurrent();
switch (lastButtonPushed){
case buttonPinEnter: // enter pin this is set up to use a push button BUT need it to use PUSH BUTTON ON ENCODER
if(!(currentMenu.moveDown())){ //if the current menu has a child and enter has been pressed then navigate menu to item below
menu.use();
}
else{ //otherwise, if menu has no child and enter has been pressed---- the current menu is used
menu.moveDown();
}
break;
case buttonPinEsc: //not Set up yet but this will have a push button
menu.toRoot(); //back to main
break;
case buttonPinRight:
menu.moveRight();
break;
case buttonPinLeft:
menu.moveLeft();
break;
lastButtonPushed=0; //reset the lastButtonPushed variable
}
}
and here is a separate working sketch of the encoder
int val;
int encoder0PinA = 2;
int encoder0PinB = 3;
int encoder0Pos = 0;
int encoder0PinALast = LOW;
int n = HIGH;
void setup() {
pinMode (encoder0PinA,INPUT);
pinMode (encoder0PinB,INPUT);
Serial.begin (9600);
}
void loop() {
n = digitalRead(encoder0PinA);
if ((encoder0PinALast == HIGH) && (n == LOW)) {
if (digitalRead(encoder0PinB) == LOW) {
encoder0Pos--;
} else {
encoder0Pos++;
}
Serial.print (encoder0Pos);
Serial.print ("/");
}
encoder0PinALast = n;
}
Any help on implimenting this change would be appreciated.
It should be easy enough to read the button on the encoder. Get that working first by plugging it in instead of the current button.
To use the encoder to navigate the menu you need to determine which way it is rotating. In your encoder sketch you are already working this out and changing the value of encoder0Pos appropriately, so instead of changing the value treat an increasing value as one button and a decreasing value as the other and call menu.moveRight(); or menu.moveLeft(); to suit.
If this is what you have already tried then seeing your code would be helpful.
You seem to have tried to do something with the value of encoder0Pos but
if (encoder0Pos++);
is not testing whether its value has changed
When you get this working I suggest that you tidy up the variable and function names to remove confusion about whether buttons are being pressed or the encoder is being rotated.
No need for anything to go there. You will have already determined that the encoder is moving and which way and just need to act on it.
Once it works save that version and set about tidying it up in a new sketch. Even if it works then there is plenty that you could do as it seems quite tangled at the moment.
I can see what Its trying to do but cant code what it needs to do. No matter what I do I cant get his to work. I've tried so many ways, i'm out of Ideas and feel I need to come up with a third option for the menu using a different encoder sketch. Which is not going to help me as I will be back to square one.
This is my entire sketch. I have a rotary encoder with pushbutton and one external button that is the exit menu.
Thanks for all the help everyone but even now I still dont understand it. Is there a level under noob.
#include <MenuBackend.h> //MenuBackend library - copyright by Alexander Brevig
#include <LiquidCrystal.h> //this library is included in the Arduino IDE
int encoder0PinA = 2;
int encoder0PinB =3;
int encoder0Pos = 0;
int encoder0PinALast = LOW;
int n = HIGH;
const int encoderRight = ?????; //what should go here????
const int encoderLeft = ??????;// and here ????
const int buttonPinEsc = 42;
const int encoderPushButton = 45; // pin for the Enter button
int lastButtonPushed = 0;
LiquidCrystal lcd(7,8,9,10,11,12);
//Menu variables
MenuBackend menu = MenuBackend(menuUsed,menuChanged);
//initialize menuitems
MenuItem menuLcd = MenuItem("menuLcd");// first menu item
MenuItem menuItemOn = MenuItem("menuItemOn");// sub menu
MenuItem menuItemOff = MenuItem("menuItemOff");// sub menu
MenuItem menuSetClock = MenuItem("menuSetClock");// 2nd menu item
MenuItem menuItemHr = MenuItem("menuItemHr");// sub menu
MenuItem menuItemMin = MenuItem("menuItemMin");//sub menu
MenuItem menuItemSec = MenuItem("menuItemSec");//sub menu
MenuItem menuItemConfirm = MenuItem("menuItemConfirm");//sub menu
MenuItem menuSetDate = MenuItem("menuSetDate");// 2nd menu item
MenuItem menuItemDay = MenuItem("menuItemDay");// sub menuu
MenuItem menuItemMonth = MenuItem("menuItemMonth");//sub menu
MenuItem menuItemYear = MenuItem("menuItemYear");//sub menu
MenuItem menuExit = MenuItem("menuExit");// 3rdh menu item
void setup()
{
pinMode(encoderRight, INPUT);
pinMode(encoderLeft, INPUT);
pinMode(encoderPushButton, INPUT);
pinMode(buttonPinEsc, INPUT);
pinMode (encoder0PinA,INPUT);
pinMode (encoder0PinB,INPUT);
lcd.begin(16, 2);
//configure menu
lcd.setCursor(0,1);
menu.getRoot().addRight(menuLcd).addRight(menuSetClock).addRight(menuSetDate);//set main menu items
menuLcd.add(menuItemOn).addRight(menuItemOff);// add first sub menu then addright additional sub menues for that menu
menuSetClock.add(menuItemHr).addRight(menuItemMin).addRight(menuItemSec).addRight(menuItemConfirm);// add first sub menu then addright additional sub menues for that menu
menuSetDate.add(menuItemDay).addRight(menuItemMonth).addRight(menuItemYear);// add first sub menu then addright additional sub menues for that menu
menu.toRoot();
}
void loop()
{
//readButtons(); //I splitted button reading and navigation in two procedures because
navigateMenus(); //in some situations I want to use the button for other purpose (eg. to change some settings)
n = digitalRead(encoder0PinA);
if ((encoder0PinALast == HIGH) && (n == LOW))
{
if (digitalRead(encoder0PinB) == LOW)
{
lastButtonPushed = encoderRight;//encoder0Pos--;
}
else {
lastButtonPushed = encoderLeft;//encoder0Pos++;
}
encoder0PinALast = n;
}
}
void menuChanged(MenuChangeEvent changed){
MenuItem newMenuItem=changed.to; //get the destination menu
lcd.setCursor(0,0); //set the start position for lcd printing to the second row
if(newMenuItem.getName()==menu.getRoot())
{
lcd.print("Main Menu ");
}
//menu lcd
else if(newMenuItem.getName()=="menuLcd"){
lcd.clear();
lcd.print("Lcd");
}
else if(newMenuItem.getName()=="menuItemOn"){
lcd.clear();
lcd.setCursor(0,1);
lcd.print("On");
}
else if(newMenuItem.getName()=="menuItemOff"){
lcd.clear();
lcd.setCursor(0,1);
lcd.print("Off");
}
//menu set clock
else if(newMenuItem.getName()=="menuSetClock"){
lcd.clear();
lcd.print("Set Clock");
}
else if(newMenuItem.getName()=="menuItemHr"){
lcd.clear();
lcd.setCursor(0,1);
lcd.print("Hr");
}
else if(newMenuItem.getName()=="menuItemMin"){
lcd.clear();
lcd.setCursor(0,1);
lcd.print("Min");
}
else if(newMenuItem.getName()=="menuItemSec"){
lcd.clear();
lcd.setCursor(0,1);
lcd.print("Sec");
}
else if(newMenuItem.getName()=="menuItemConfirm"){
lcd.clear();
lcd.print("Confirmed");
}
//menu set date
else if(newMenuItem.getName()=="menuSetDate"){
lcd.clear();
lcd.print("Set Date");
}
else if(newMenuItem.getName()=="menuItemDay"){
lcd.clear();
lcd.print("Set Day");
}
else if(newMenuItem.getName()=="menuItemMonth"){
lcd.clear();
lcd.print("Set Month");
}
else if(newMenuItem.getName()=="menuItemYear"){
lcd.clear();
lcd.print("Set Year");
}
//menu exit
else if(newMenuItem.getName()=="menuExit"){
lcd.clear();
lcd.print("Exit");
}
}
void menuUsed(MenuUseEvent used){ //**if you have a function call it here**
if( used.item == menuItemOn ){
lcd.display();
//digitalWrite(10, HIGH);
//delay(3000);
//digitalWrite(10, LOW);
lcd.clear();
menu.toRoot();
}
if ( used.item == menuItemOff ){
lcd.noDisplay();//your code here
menu.toRoot();
}
//etc.
}
void navigateMenus() {
MenuItem currentMenu=menu.getCurrent();
switch (lastButtonPushed){
digitalWrite (ledPin, HIGH);
case encoderPushButton: // enter pin this is set up to use a push button BUT need it to use PUSH BUTTON ON ENCODER
if (!(currentMenu.moveDown())){ //if the current menu has a child and enter has been pressed then navigate menu to item below
menu.use();
}
else{ //otherwise, if menu has no child and enter has been pressed---- the current menu is used
menu.moveDown();
}
break;
case encoderRight:
menu.moveRight();
break;
case encoderLeft:
menu.moveLeft();
break;
case buttonPinEsc: //not Set up yet but this will have a push button
lcd.clear();
menu.toRoot(); //back to main
break;
lastButtonPushed=0; //reset the lastButtonPushed variable
}
}
You have started to tidy up the code as well as using the encoder to fool the program into thinking that buttons have been pressed which has confused things somewhat.
In post 5 I suggested setting the value of LastButtonPushed to buttonPinRight or buttonPinLeft when the encoder moved. You could then use the same code as you did to respond to the fake button presses. What you have done is to set LastButtonPressed to encoderRight or encoderLeft. That is a start at tidying up. It should still work, but in setup() you need to set encoderRight and encoderLeft to the values that buttonPinRight and buttonPinLeft would return when the button(s) are pressed.
NOTE - I have not checked any other parts of your code to see if you have changed anything else.
I have just added some brackets and encoder0Pos-- and encoder0Pos++ and it worked.
void loop()
{
n = digitalRead(encoder0PinA);// value of n = n is default LOW
if ((encoder0PinALast == HIGH) && (n == LOW)) // int encoder0PinALast default LOW
{
if (digitalRead(encoder0PinB) == LOW)
{
if(lastButtonPushed = buttonPinLeft)
encoder0Pos--;
}
else if
(lastButtonPushed = buttonPinRight)
encoder0Pos++;
}
encoder0PinALast = n;
navigateMenus(); //in some situations I want to use the button for other purpose (eg. to change some settings)
readButtons(); //I splitted button reading and navigation in two procedures because
}
ONE thing about this is that I have PINS assisigned to 43 and 45 for "buttonPinLeft" and "buttonPinRight". I can remove the wire connections for these and it still works but I have lost the use of TWO pins? If I remove 43 and 45 to become
const int encoderLeftRotation;
const int encoderRightRotation;
I get an uninitialized error.
Any Ideas on this...............anyone!
UKHeliBob as a reward for all your help Karma is duly awarded.
A const is designed to hold a value that will not change, ie it is constant, so you cannot have a const with no value, hence the error. If you set encoderLeftRotation and encoderRightRotation to 43 and 45 respectively that has nothing to do with using pins 43 and 45 so you could use them for something else.
Can you please post your whole code as it is now ?
Hers my code. I had to split it in half as the character count exceeds forum limit. now using PINS 42 and 49 as mega board pin to slack.
/*
This is a Test of a menu and Encoder to be used in a bigger project. I am building it in modules
so I can test each one. This module is As. A lcd displayed Menu System using a rotary encoder to navigate the menu system.
The "void menuUsed(MenuUseEvent used)" is where I will call functions related to the menu. At present I have just explored turning
the lcd light On and Off. The menu is self explanatory and functions to this will follw.
*/
#include <MenuBackend.h> //MenuBackend library - copyright by Alexander Brevig
#include <LiquidCrystal.h> //this library is included in the Arduino IDE
int ledPin = 13;
int val;
int encoder0PinA = 2;// pin A signal on encoder
int encoder0PinB =3;// pin B signal on encoder
int encoder0Pos = 0;
int encoder0PinALast = LOW;
int n = HIGH;
LiquidCrystal lcd(7,8,9,10,11,12);
const int encoderLeftRotation = 44; // pin for the Up button
const int encoderRightRotation = 46; // pin for the Down button
const int encoderPushButton = 49; // pin for the Enter button
const int buttonPinEsc = 42; // pin for the Esc button
int lastButtonPushed = HIGH;
int lastEncoderButtonState = LOW; // the previous reading from the Enter input pin
int lastButtonEscState = LOW; // the previous reading from the Esc input pin
int lastRotationLeftState = LOW; // the previous reading from the Left input pin
int lastRotationRightState = LOW; // the previous reading from the Right input pin
long lastEnterDebounceTime = 0; // the last time the output pin was toggled
long lastEscDebounceTime = 0; // the last time the output pin was toggled
long lastLeftDebounceTime = 0; // the last time the output pin was toggled
long lastRightDebounceTime = 0; // the last time the output pin was toggled
long debounceDelay = 15; // the debounce time was 100
//Menu variables
MenuBackend menu = MenuBackend(menuUsed,menuChanged);
//initialize menuitems
MenuItem menuLcd = MenuItem("menuLcd");// first menu item
MenuItem menuItemOn = MenuItem("menuItemOn");// sub menu
MenuItem menuItemOff = MenuItem("menuItemOff");// sub menu
MenuItem menuSetClock = MenuItem("menuSetClock");// 2nd menu item
MenuItem menuItemHr = MenuItem("menuItemHr");// sub menu
MenuItem menuItemMin = MenuItem("menuItemMin");//sub menu
MenuItem menuItemSec = MenuItem("menuItemSec");//sub menu
MenuItem menuItemConfirm = MenuItem("menuItemConfirm");//sub menu
MenuItem menuSetDate = MenuItem("menuSetDate");// 2nd menu item
MenuItem menuItemDay = MenuItem("menuItemDay");// sub menuu
MenuItem menuItemMonth = MenuItem("menuItemMonth");//sub menu
MenuItem menuItemYear = MenuItem("menuItemYear");//sub menu
MenuItem menuSetPhone = MenuItem("menuSetPhone");// 3rd menu item
MenuItem menuItemNumber = MenuItem("menuItemNumber");// sub menu
MenuItem menuSetPin = MenuItem("menuSetPin");// 4th menu item
MenuItem menuItemPin = MenuItem("menuItemPin");// sub menuu
MenuItem menuSms = MenuItem("menuSms");// 5th menu item
MenuItem menuItemSigStr = MenuItem("menuItemSigStr");// sub menu
MenuItem menuItemBalance = MenuItem("menuItemBalance");// sub menuu
MenuItem menuItemTest = MenuItem("menuItemTest");// sub menuu
MenuItem menuExit = MenuItem("menuExit");// 6th menu item
void setup()
{
lcd.begin(16, 2);
pinMode(encoderLeftRotation, INPUT);
pinMode(encoderRightRotation, INPUT);
pinMode(encoderPushButton, INPUT);
pinMode(buttonPinEsc, INPUT);
pinMode (encoder0PinA,INPUT);
pinMode (encoder0PinB,INPUT);
//configure menu
lcd.setCursor(0,1);
menu.getRoot().addRight(menuLcd).addRight(menuSetClock).addRight(menuSetDate).addRight(menuSetPhone).addRight(menuSetPin).addRight(menuSms).addRight(menuExit);//set main menu items
menuLcd.add(menuItemOn).addRight(menuItemOff);// add first sub menu then addright additional sub menues for that menu
menuSetClock.add(menuItemHr).addRight(menuItemMin).addRight(menuItemSec).addRight(menuItemConfirm);// add first sub menu then addright additional sub menues for that menu
menuSetDate.add(menuItemDay).addRight(menuItemMonth).addRight(menuItemYear);// add first sub menu then addright additional sub menues for that menu
menuSetPhone.add(menuItemNumber);
menuSetPin.add(menuItemPin);
menuSms.add(menuItemSigStr).addRight(menuItemBalance).addRight(menuItemTest);
menuExit.add(menuExit);
menu.toRoot();
}
void loop()
{
n = digitalRead(encoder0PinA);// value of n = n is default LOW
if ((encoder0PinALast == HIGH) && (n == LOW)) // int encoder0PinALast default LOW
{
if (digitalRead(encoder0PinB) == LOW)
{
if(lastButtonPushed = encoderLeftRotation)
encoder0Pos--;
}
else if
(lastButtonPushed = encoderRightRotation)
encoder0Pos++;
}
encoder0PinALast = n;
navigateMenus(); //in some situations I want to use the button for other purpose (eg. to change some settings)
readButtons(); //I splitted button reading and navigation in two procedures because
}
//Debouncing also- hardware Debounce inplace
void readButtons(){ //read buttons status
int reading;
int buttonEnterState=LOW; // the current reading from the Enter input pin
int buttonEscState=LOW; // the current reading from the input pin
int buttonLeftState=LOW; // the current reading from the input pin
int buttonRightState=LOW; // the current reading from the input pin
//Enter button
reading = digitalRead(encoderPushButton);// read the state of the switch into a local variable:
if (reading != lastEncoderButtonState) {// If the switch changed, due to noise or pressing:
lastEnterDebounceTime = millis(); // reset the debouncing timer
}
if ((millis() - lastEnterDebounceTime) > debounceDelay) {
// whatever the reading is at, it's been there for longer than the debounce delay, so take it as the actual current state:
buttonEnterState=reading;
lastEnterDebounceTime=millis();
}
lastEncoderButtonState = reading;// save the reading. Next time through the loop, it'll be the lastButtonState:
//Esc button
reading = digitalRead(buttonPinEsc);// read the state of the switch into a local variable:
if (reading != lastButtonEscState) {// If the switch changed, due to noise or pressing:
lastEscDebounceTime = millis();// reset the debouncing timer
}
if ((millis() - lastEscDebounceTime) > debounceDelay) {
// whatever the reading is at, it's been there for longer than the debounce delay, so take it as the actual current state:
buttonEscState = reading;
lastEscDebounceTime=millis();
}
lastButtonEscState = reading;// save the reading. Next time through the loop, it'll be the lastButtonState:
//Right or Down button
reading = digitalRead(encoderRightRotation);// read the state of the switch into a local variable
if (reading != lastRotationRightState) {//last button state is defaulted int LOW
lastRightDebounceTime = millis();// reset the debouncing timer
}
if ((millis() - lastRightDebounceTime) > debounceDelay) {
// whatever the reading is at, it's been there for longer than the debounce delay, so take it as the actual current state:
buttonRightState = reading;
lastRightDebounceTime =millis();
}
lastRotationRightState = reading; // save the reading. Next time through the loop, it'll be the lastButtonState:
//Left or Up button
reading = digitalRead(encoderLeftRotation);// read the state of the switch into a local variable:
if (reading != lastRotationLeftState) {// If the switch changed, due to noise or pressing:
lastLeftDebounceTime = millis();// reset the debouncing timer
}
if ((millis() - lastLeftDebounceTime) > debounceDelay) {
// whatever the reading is at, it's been there for longer than the debounce delay, so take it as the actual current state:
buttonLeftState = reading;
lastLeftDebounceTime=millis();
}
lastRotationLeftState = reading; // save the reading. Next time through the loop, it'll be the lastButtonState:
//records which button has been pressed
if (buttonEnterState==HIGH){
lastButtonPushed=encoderPushButton;
}
else if(buttonEscState==HIGH){
lastButtonPushed=buttonPinEsc;
}
else if(buttonRightState==HIGH){
lastButtonPushed=encoderRightRotation;
}
else if(buttonLeftState==HIGH){
lastButtonPushed=encoderLeftRotation;
}
else{
lastButtonPushed=0;
}
}
void menuChanged(MenuChangeEvent changed){
MenuItem newMenuItem=changed.to; //get the destination menu
lcd.setCursor(0,0); //set the start position for lcd printing to the second row
if(newMenuItem.getName()==menu.getRoot())
{
lcd.print("Main Menu ");
}
//menu lcd
else if(newMenuItem.getName()=="menuLcd"){
lcd.clear();
lcd.print("Lcd");
}
else if(newMenuItem.getName()=="menuItemOn"){
lcd.clear();
lcd.setCursor(0,1);
lcd.print("On");
}
else if(newMenuItem.getName()=="menuItemOff"){
lcd.clear();
lcd.setCursor(0,1);
lcd.print("Off");
}
//menu set clock
else if(newMenuItem.getName()=="menuSetClock"){
lcd.clear();
lcd.print("Set Clock");
}
else if(newMenuItem.getName()=="menuItemHr"){
lcd.clear();
lcd.setCursor(0,1);
lcd.print("Hr");
}
else if(newMenuItem.getName()=="menuItemMin"){
lcd.clear();
lcd.setCursor(0,1);
lcd.print("Min");
}
else if(newMenuItem.getName()=="menuItemSec"){
lcd.clear();
lcd.setCursor(0,1);
lcd.print("Sec");
}
else if(newMenuItem.getName()=="menuItemConfirm"){
lcd.clear();
lcd.print("Confirmed");
}
//menu set date
else if(newMenuItem.getName()=="menuSetDate"){
lcd.clear();
lcd.print("Set Date");
}
else if(newMenuItem.getName()=="menuItemDay"){
lcd.clear();
lcd.print("Set Day");
}
else if(newMenuItem.getName()=="menuItemMonth"){
lcd.clear();
lcd.print("Set Month");
}
else if(newMenuItem.getName()=="menuItemYear"){
lcd.clear();
lcd.print("Set Year");
}
//menu set phone number
else if(newMenuItem.getName()=="menuSetPhone"){
lcd.clear();
lcd.print("Set Phone");
}
//menu set pin number
else if(newMenuItem.getName()=="menuSetPin"){
lcd.clear();
lcd.print("Set Pin");
}
//menu set sms
else if(newMenuItem.getName()=="menuSms"){
lcd.clear();
lcd.print("Sms ");
}
else if(newMenuItem.getName()=="menuItemSigStr"){
lcd.clear();
lcd.print("Signal Stre");
}
else if(newMenuItem.getName()=="menuItemBalance"){
lcd.clear();
lcd.print("Balance");
}
else if(newMenuItem.getName()=="menuItemTest"){
lcd.clear();
lcd.print("Test Sms");
}
//menu exit to time
else if(newMenuItem.getName()=="menuExit"){
lcd.clear();
lcd.print("Exit");
}
}
void menuUsed(MenuUseEvent used){ //**if you have a function call it here**
if( used.item == menuItemOn ){
lcd.display();
//digitalWrite(10, HIGH);
//delay(3000);
//digitalWrite(10, LOW);
lcd.clear();
menu.toRoot();
}
if ( used.item == menuItemOff ){
lcd.noDisplay();//your code here
menu.toRoot();
}
//etc.
}
void navigateMenus() {
MenuItem currentMenu=menu.getCurrent();
switch (lastButtonPushed){
case encoderPushButton: // enter pin
if(!(currentMenu.moveDown())){ //if the current menu has a child and enter has been pressed then navigate menu to item below
menu.use();
}
else{ //otherwise, if menu has no child and enter has been pressed---- the current menu is used
menu.moveDown();
}
break;
case buttonPinEsc:
menu.toRoot(); //back to main
break;
case encoderRightRotation:
menu.moveRight();
break;
case encoderLeftRotation:
menu.moveLeft();
break;
}
lastButtonPushed=0; //reset the lastButtonPushed variable
}
I still would like to remove
const int encoderLeftRotation = 44; // pin for the Up button
const int encoderRightRotation = 46; // pin for the Down button
I have tried to remove it but my code fails if I do? even thou they're not wired up? Is the a way rount this?
Mark - this is difficult for me to help with in detail because I don't have the same hardware as you and my Arduino is tied up with a project of my own. I think that the time has come for you to step back and start again.
Load the menu navigation sketch that works with buttons and save it with a new name.
Copy the encoder declarations and pin setup into the new sketch to create the variables.
Make a new function in the sketch called readEncoder()
void readEncoder() //read the encoder and set lastButtonPushed to values used by navigateMenu()
{
n = digitalRead(encoder0PinA);
if ((encoder0PinALast == HIGH) && (n == LOW))
{
if (digitalRead(encoder0PinB) == LOW)
{
lastButtonPushed = 46;
}
else
{
lastButtonPushed = 44;
}
}
encoder0PinALast = n;
}
At this point the sketch should still work with buttons as it is not reading the encoder. Fix any compile errors.
Change the readButtons() function to read only the button on the encoder and to leave lastButtonPushed alone unless it was pushed.
Now, before you call navigateMenu() in loop() call readButtons() and readEncoder()
readEncoder() will set lasButtonPushed to 44 or 46 if the encoder has moved and navigateMenu() will interpret that as a button push. Try this much and let us know how you get on. As I said before, once this works you can tidy up. For instance, readEncoder() could read the button as well.
I have made the changes you advised and it's working perfectly.
Here is the new code split again. I have tided it up too, so I think?
/*
This is a Test of a menu and Encoder to be used in a bigger project. I am building it in modules
so I can test each one. This module is As. A lcd displayed Menu System using a rotary encoder to navigate the menu system.
The "void menuUsed(MenuUseEvent used)" is where I will call functions related to the menu. At present I have just explored turning
the lcd light On and Off. The menu is self explanatory and functions to this will follw.
*/
#include <MenuBackend.h> //MenuBackend library - copyright by Alexander Brevig
#include <LiquidCrystal.h> //this library is included in the Arduino IDE
const int encoderPushButton = 45; // pin for the Enter button
const int buttonPinEsc = 42; // pin for the Esc button
int encoder0PinA = 2;
int encoder0PinB = 3;
int encoder0Pos = 0;
int encoder0PinALast = LOW;
int n = HIGH;
int lastButtonPushed = 0;
int lastButtonEnterState = LOW; // the previous reading from the Enter input pin
int lastButtonEscState = LOW; // the previous reading from the Esc input pin
long lastEnterDebounceTime = 0; // the last time the output pin was toggled
long lastEscDebounceTime = 0; // the last time the output pin was toggled
long debounceDelay = 150; // the debounce time
LiquidCrystal lcd(7,8,9,10,11,12);
//Menu variables
MenuBackend menu = MenuBackend(menuUsed,menuChanged);
//initialize menuitems
MenuItem menuLcd = MenuItem("menuLcd"); // first menu item
MenuItem menuItemOn = MenuItem("menuItemOn"); // sub menu
MenuItem menuItemOff = MenuItem("menuItemOff"); // sub menu
MenuItem menuSetClock = MenuItem("menuSetClock"); // 2nd menu item
MenuItem menuItemHr = MenuItem("menuItemHr"); // sub menu
MenuItem menuItemMin = MenuItem("menuItemMin"); //sub menu
MenuItem menuItemSec = MenuItem("menuItemSec"); //sub menu
MenuItem menuItemConfirm = MenuItem("menuItemConfirm"); //sub menu
MenuItem menuSetDate = MenuItem("menuSetDate"); // 2nd menu item
MenuItem menuItemDay = MenuItem("menuItemDay"); // sub menuu
MenuItem menuItemMonth = MenuItem("menuItemMonth"); //sub menu
MenuItem menuItemYear = MenuItem("menuItemYear"); //sub menu
MenuItem menuSetPhone = MenuItem("menuSetPhone"); // 3rd menu item
MenuItem menuItemNumber = MenuItem("menuItemNumber"); // sub menu
MenuItem menuSetPin = MenuItem("menuSetPin"); // 4th menu item
MenuItem menuItemPin = MenuItem("menuItemPin"); // sub menuu
MenuItem menuSms = MenuItem("menuSms"); // 5th menu item
MenuItem menuItemSigStr = MenuItem("menuItemSigStr"); // sub menu
MenuItem menuItemBalance = MenuItem("menuItemBalance"); // sub menuu
MenuItem menuItemTest = MenuItem("menuItemTest"); // sub menuu
MenuItem menuExit = MenuItem("menuExit"); // 6th menu item
void setup()
{
pinMode(encoderPushButton, INPUT);
pinMode(buttonPinEsc, INPUT);
pinMode (encoder0PinA,INPUT);
pinMode (encoder0PinB,INPUT);
Serial.begin (9600);
lcd.begin(16, 2);
//configure menu
lcd.setCursor(0,1);
menu.getRoot().addRight(menuLcd).addRight(menuSetClock).addRight(menuSetDate).addRight(menuSetPhone).addRight(menuSetPin).addRight(menuSms).addRight(menuExit); //set main menu items
menuLcd.add(menuItemOn).addRight(menuItemOff); // add first sub menu then addright additional sub menues for that menu
menuSetClock.add(menuItemHr).addRight(menuItemMin).addRight(menuItemSec).addRight(menuItemConfirm); // add first sub menu then addright additional sub menues for that menu
menuSetDate.add(menuItemDay).addRight(menuItemMonth).addRight(menuItemYear); // add first sub menu then addright additional sub menues for that menu
menuSetPhone.add(menuItemNumber);
menuSetPin.add(menuItemPin);
menuSms.add(menuItemSigStr).addRight(menuItemBalance).addRight(menuItemTest);
menuExit.add(menuExit);
menu.toRoot();
}
void loop()
{
readButtons(); //I splitted button reading and navigation in two procedures because
readEncoder();
navigateMenus(); //in some situations I want to use the button for other purpose (eg. to change some settings)
}
void readButtons() //read buttons status
{
int reading;
int buttonEnterState=LOW; // the current reading from the Enter input pin
int buttonEscState=LOW; // the current reading from the input pin
//ENTER BUTTON DEBOUNCE
reading = digitalRead(encoderPushButton); // read the state of the switch into a local variable:
if (reading != lastButtonEnterState) // If the switch changed, due to noise or pressing:
{
lastEnterDebounceTime = millis(); // reset the debouncing timer
}
if ((millis() - lastEnterDebounceTime) > debounceDelay) // whatever the reading is at, it's been there for longerthan the debounce delay, so take it as the actual current state:
{
buttonEnterState=reading;
lastEnterDebounceTime=millis();
}
lastButtonEnterState = reading; // save the reading. Next time through the loop, it'll be the lastButtonState:
//ESC BUTTON DEBOUNCE
reading = digitalRead(buttonPinEsc); // read the state of the switch into a local variable:
if (reading != lastButtonEscState) // If the switch changed, due to noise or pressing:
{
lastEscDebounceTime = millis(); // reset the debouncing timer
}
if ((millis() - lastEscDebounceTime) > debounceDelay)// whatever the reading is at, it's been there for longerthan the debounce delay, so take it as the actual current state:
{
buttonEscState = reading;
lastEscDebounceTime=millis();
}
lastButtonEscState = reading; // save the reading. Next time through the loop, it'll be the lastButtonState:
//Records which button has been pressed
if (buttonEnterState==HIGH){
lastButtonPushed=encoderPushButton;
}
else if(buttonEscState==HIGH){
lastButtonPushed=buttonPinEsc;
}
else{
lastButtonPushed=0;
}
}
void readEncoder() //read the encoder and set lastButtonPushed to values used by navigateMenu()
{
n = digitalRead(encoder0PinA);
if ((encoder0PinALast == HIGH) && (n == LOW))
{
if (digitalRead(encoder0PinB) == LOW)
{
lastButtonPushed = 46;
}
else
{
lastButtonPushed = 44;
}
}
encoder0PinALast = n;
}
For instance, readEncoder() could read the button as well.
Do I have to move ALL my button bounce code to "Read encoder" as well? what about the separate "Esc button" does that move there too.