Pages: [1]   Go Down
Author Topic: menubackend moveToLevel(lvl) resets uno  (Read 678 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Full Member
***
Karma: 0
Posts: 128
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.

Code:
//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());
}
Logged

Offline Offline
Full Member
***
Karma: 0
Posts: 128
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I've altered the exit menus to just moveLeft() instead of moveToLevel(); however still the timer to exit the menu still resets the uno. I've download the library from wiring again. If I comment out the only moveToLevel command left it no longer resets, the LCD updates to "button interrupt" and when you press a button your at the last position not the root of the menu.

Code:
//MENU SETUP
#include <MenuBackend.h>

//initialize menu
MenuBackend menu = MenuBackend(menuUseEvent,menuChangeEvent);
//initialize menuitems
//MenuItem configure = SubMenu(menuChanged);

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;
volatile int buttonValue = 0;
volatile int buttonPressed = 0;
volatile int lastButtonPressed = 0;
volatile int state = LOW;
volatile int lastState = HIGH;
void setup()
{
  //MENU SETUP
  //configure menu
  menu.getRoot().add(configure).addAfter(exit1).addAfter(configure);
                     configure.addRight(exit2).addAfter(config_heater).addAfter(exit2);
                                     config_heater.addRight(exit3).addAfter(heater_on).addAfter(heater_off).addAfter(heater_disable).addAfter(exit3);



  //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(){
  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.getName() == "EXIT"){
   Serial.println("exit call");
   menu.moveLeft();
 }
}

/*
  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());
}


Logged

Offline Offline
Full Member
***
Karma: 0
Posts: 128
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

no one have any ideas?

I've used 2 separate arduinos, current is an official board. USB powered and external powered. MoveToLevel as well as moveRelativeLevel resets the uno. Is there another way to reset the menu to the root of the menu besides moveToLevel? Or should I be posting to Wiring forums?
Logged

Offline Offline
Full Member
***
Karma: 0
Posts: 128
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Moderator please delete. I will try in "Displays" instead.
Logged

Offline Offline
Full Member
***
Karma: 0
Posts: 128
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I still haven't worked out hwy it resets the uno but I needed to move on so instead wrote a while loop to work its way back

Code:
// menu.moveToLevel(0);
    
    while(menu.getCurrent().getLevel() > 1){  // if we're not at the bottom of the menu
       if(menu.getCurrent().getLeft() != 0){  // getLeft returns a route, we should follow it
         menu.moveLeft();
         Serial.println("  L  ");
       }else{
         menu.moveUp(); // go up and we can try again next loop
         Serial.println("  U  ");
       }  
    }
« Last Edit: July 12, 2012, 05:12:51 pm by dannix » Logged

Pages: [1]   Go Up
Jump to: