Hi, I've been scratching my head for days on this one.I'd appreciate some assistance. Code below, is part of a project but it's just a interrupt and a LCD menu at present. I've not used LCD menus or menubackend before.
3 button resistor array, on an analog pin, when buttons pressed they trigger interrupt on pin2(int0) which remembers which button was pressed and sets a flag to say action required.
I've setup a menu likeso:
CONFIGURE (0)
CONFIG HEATER (1)
HEATER ON (2)
HEATER OFF (2)
HEATER DISABLE (2)
EXIT (2)
EXIT (1)
EXIT (0)
If a button ins't pressed for 10 secs it should exit to main LCD screen, in this case just "button interrupt" on line 1. Or selecting exit in the menu structure should move back a level. However when either is done it just resets the Arduino Uno R3 and I can't work out why. moveToLevel just won't work it seems.
//MENU SETUP
#include <MenuBackend.h>
//initialize menu
MenuBackend menu = MenuBackend(menuUseEvent,menuChangeEvent);
//initialize menuitems
MenuItem configure = MenuItem(menu,"CONFIGURE",0);
MenuItem exit1 = MenuItem(menu,"EXIT",0);
MenuItem config_heater = MenuItem(menu,"CONFIG HEATER",1);
MenuItem exit2 = MenuItem(menu,"EXIT",1);
MenuItem heater_on = MenuItem(menu, "HEATER ON",2);
MenuItem heater_off = MenuItem(menu, "HEATER OFF",2);
MenuItem heater_disable = MenuItem(menu,"HEATER DISABLE",2);
MenuItem exit3 = MenuItem(menu,"EXIT",2);
unsigned long menuTimer = millis();
byte timerEnable = 0;
//END MENU
/*LCD*/
#include <LCD.h>
#include <LiquidCrystal_SR.h>
LiquidCrystal_SR iLCD(10, 11, 12); //Data,Clk,Enable Assuming that the header is connected to the same digital IO pin.
//END LCD
int pin = 13;
int buttonPin = A0;
volatile byte buttonAct = 0; //button was pressed when high
volatile int buttonValue = 0; // button analog value
volatile int buttonPressed = 0; // button pressed
volatile int lastButtonPressed = 0; //last button pressed
volatile int state = LOW; // LED on pin 13 flips state when interrupt0 is triggered.
volatile int lastState = HIGH;
void setup()
{
//MENU SETUP
//configure menu
menu.getRoot().add(configure).addAfter(exit1).addAfter(configure);
configure.addRight(config_heater);
config_heater.addAfter(exit2).addAfter(config_heater);
config_heater.addRight(heater_on);
heater_on.addAfter(heater_off).addAfter(heater_disable).addAfter(exit3).addAfter(heater_on);
//END MENU SETUP
Serial.begin(9600);
Serial.println("STARTED");
pinMode(pin, OUTPUT);
attachInterrupt(0, readButtons, RISING);
iLCD.begin(20,4); // initialize the lcd
delay(400); // wait to start lcd writing
iLCD.home (); // go home
iLCD.print("Button Interrupt");
}
void buttonStat(){
Serial.print(buttonPressed);
Serial.print(" ");
Serial.println(lastButtonPressed);
}
void loop(){
if(buttonAct == 1){ //buttonAct eq 1 when interrupt received
buttonAct = 0;
navMenu();
}
if(timerEnable == 1 && millis() - menuTimer >= 10000){
Serial.println("Timer Clear.........");
menu.moveToLevel(0);
//menu.moveRelativeLevels(1);
timerEnable = 0;
iLCD.clear(); // go home
iLCD.print("Button Interrupt");
delay(60);
buttonAct = 0;
}
//lastButtonPressed = 0;
delay(100);
}
void readButtons(){ // getting some bounce here, hardware debounce required.
state = !state;
digitalWrite(pin, state);
/* 511 : none | 614 : up | 768 : down | 1023 : select */
lastButtonPressed = buttonPressed;
buttonValue = analogRead(buttonPin);
if(buttonValue >= 900) {
buttonPressed = 3;
}
else if(buttonValue >= 700){
buttonPressed = 2;
}
else if(buttonValue >= 600){
buttonPressed = 1;
}
buttonAct = 1;
Serial.print(buttonPressed);
Serial.print(" ");
Serial.println(buttonValue);
}
void navMenu(){
//MenuItem currentMenu=menu.getCurrent();
switch (buttonPressed){
case 3: //select
if (menu.getCurrent().getRight() != 0) //The current item has an element right, it's a sub menu so nav right.
{
menu.moveRight();
Serial.print(menu.getCurrent().getName());
Serial.println("has menu right");
}
else{ //otherwise, menu has no child and has been pressed. enter the current menu
menu.use();
}
break;
case 2: //down
menu.moveDown();
break;
case 1: //up
menu.moveUp();
break;
}
}
/*This is where you define a behaviour for a menu item
*/
void menuUseEvent(MenuUseEvent used)
{
Serial.print("Menu use: ");
Serial.println(used.item.getName());
iLCD.clear(); // go home
iLCD.print("USED: ");
iLCD.print(used.item.getName());
if (used.item.isEqual(exit1)){
Serial.println("exit menu");
menu.moveToLevel(0);
}else if (used.item.isEqual(exit2)){
Serial.println("exit2");
menu.moveToLevel(1);
}else if (used.item.isEqual(exit3)){
Serial.println("exit3");
menu.moveToLevel(2);
}
}
/*
This is an important function
Here we get a notification whenever the user changes the menu
That is, when the menu is navigated
*/
void menuChangeEvent(MenuChangeEvent changed)
{
menuTimer = millis();
timerEnable = 1;
//MenuItem currentMenu=menu.getCurrent();
iLCD.clear(); // go home
iLCD.setCursor ( 0, 0 ); // go to the next line
iLCD.print("1)");
iLCD.print(changed.from.getName());
iLCD.setCursor ( 0, 1 ); // go to the next line
iLCD.print("2)");
iLCD.print(changed.to.getName());
Serial.print("Menu change FROM:TO ");
Serial.print(changed.from.getName());
Serial.print(":");
Serial.println(changed.to.getName());
}