Author Topic: Arduino Menu Ideas, and MenuBackEnd problem  (Read 21171 times)

0 Members and 1 Guest are viewing this topic.

Offline cowboy303Topic starter

  • Regular Contributor
  • *
  • Posts: 82
  • Country: us
Arduino Menu Ideas, and MenuBackEnd problem
« on: April 30, 2013, 04:41:38 pm »
I'm using a arduino uno Rev3 and a LCD.

I'm working with MenuBackEnd right now.
It worked perfect for the first little bit when I kept the mune size small, but now that I'm trying to enlarge it, it doesn't like it, it compiles, but the arduino seems to keep looping through the setup function  :-//.

this is the current menu size that BARELY works;

Quote
    MenuItem menu1Item1 = MenuItem("Item1");
      MenuItem menuItem1SubItem1 = MenuItem("Item1SubItem1");
      MenuItem menuItem1SubItem2 = MenuItem("Item1SubItem2");
      MenuItem menuItem1SubItem3 = MenuItem("Item1SubItem3");
      MenuItem menuItem1SubItem4 = MenuItem("Item1SubItem4");
    MenuItem menu1Item2 = MenuItem("Item2");
      MenuItem menuItem2SubItem1 = MenuItem("Item2SubItem1");
         MenuItem menuItem2SubItem1Sub1 = MenuItem("Item2SubItem1Sub1");
         MenuItem menuItem2SubItem1Sub2 = MenuItem("Item2SubItem1Sub2");
         MenuItem menuItem2SubItem1Sub3 = MenuItem("Item2SubItem1Sub3");
         MenuItem menuItem2SubItem1Sub4 = MenuItem("Item2SubItem1Sub4");

      MenuItem menuItem2SubItem2 = MenuItem("Item2SubItem2");
         MenuItem menuItem2SubItem2Sub1 = MenuItem("Item2SubItem2Sub1");
         MenuItem menuItem2SubItem2Sub2 = MenuItem("Item2SubItem2Sub2");
         MenuItem menuItem2SubItem2Sub3 = MenuItem("Item2SubItem2Sub3");
         MenuItem menuItem2SubItem2Sub4 = MenuItem("Item2SubItem2Sub4");

      MenuItem menuItem2SubItem3 = MenuItem("Item2SubItem3");
         MenuItem menuItem2SubItem3Sub1 = MenuItem("Item2SubItem3Sub1");
         MenuItem menuItem2SubItem3Sub2 = MenuItem("Item2SubItem3Sub2");
         MenuItem menuItem2SubItem3Sub3 = MenuItem("Item2SubItem3Sub3");
         MenuItem menuItem2SubItem3Sub4 = MenuItem("Item2SubItem3Sub4");

      MenuItem menuItem2SubItem4 = MenuItem("Item2SubItem4");
         MenuItem menuItem2SubItem4Sub1 = MenuItem("Item2SubItem4Sub1");
         MenuItem menuItem2SubItem4Sub2 = MenuItem("Item2SubItem4Sub2");
         MenuItem menuItem2SubItem4Sub3 = MenuItem("Item2SubItem4Sub3");
         MenuItem menuItem2SubItem4Sub4 = MenuItem("Item2SubItem4Sub4");

    MenuItem menu1Item3 = MenuItem("Item3");
      MenuItem menuItem3SubItem1 = MenuItem("Item3SubItem1");
      MenuItem menuItem3SubItem2 = MenuItem("Item3SubItem2");
      MenuItem menuItem3SubItem3 = MenuItem("Item3SubItem3");
      MenuItem menuItem3SubItem4 = MenuItem("Item3SubItem4");


Now here's the funny part, in that Item3SubItem4 right now if you select it on the menu, I have it do nothing.  If I make it call a function or ANYTHING.  LCD backlight does not turn on (which is in the setup funtion), it's seems pretty well dead.

So I either need a fix for this, or maybe if anybody knows of a better Menu library that would be awesome.

Sorry for the lack of info,  so Please ask for any info that would help, and I would be happy to help in anyway I can.

Thanks,
Oh and the Sketch size is 900 lines long, so if you want the code if you could maybe say what part you would like.  So I don't have to make you look through the whole thing.
« Last Edit: April 30, 2013, 05:30:51 pm by cowboy303 »
 

Offline cowboy303Topic starter

  • Regular Contributor
  • *
  • Posts: 82
  • Country: us
Re: Arduino Menu Ideas, and MenuBackEnd problem
« Reply #1 on: May 02, 2013, 01:48:42 am »
Sorry that the first post didn't have a whole lot of info, BUT I've been working with it more, and I Decided to start from the example code that comes with the MenuBackend library.  And Make the menu the size I need it, and then add all the stuff and see what kills it, step by step.  And well, I have found my first culprit.

Serial.

Ok so I took the sample menu that you can find here, http://wiring.org.co/reference/libraries/MenuItem/MenuItem_addBefore_.html.  and I added a bunch of menus/submenus to it, and it worked still, when you "used" a item I didn't have it do anything, but none the less it work perfect.
Here's the current code I'm at now, I put "//" before I all the Serial stuff to cancel it out and now it works.

(over 20000 characters) so it's in the next post

OK as you might have seen, I have a function called blink LED (bottum of sketch), it's like a heartbeat, tells me if it's still working.  Anyway as you can see it not only blinks a LED but it also reports that to the Serial monitor.  Well this is what was on the serial monitor,
Quote
Setting up menu...
Starting navigation:
Up: w   Down/use: s   Left: a   Right: d   Exit: x
1

Serial monitor would only show a "1" once, while the LED is blinking away, and if I hit ANY button it would freeze (LED stops blinking), sometimes I don't have to hit anything for it to freeze.  But everything will work perfect if I get rid of the Serial stuff.

I have NO CLUE what's going on here, I'm really still a noob to this stuff.
 

Offline cowboy303Topic starter

  • Regular Contributor
  • *
  • Posts: 82
  • Country: us
Re: Arduino Menu Ideas, and MenuBackEnd problem
« Reply #2 on: May 02, 2013, 01:52:41 am »
Quote
#include <EEPROM.h>
#include <LiquidCrystal.h>
#include <MenuBackend.h>

//EEPROM Channels:
int BackLightChan = 1;

long lastBlunk = 0;
boolean LED = LOW;

int BackLightMem;
int BackLightLevel;

const int LEDPin = 13;
const int buttonPinLeft = 3;      // pin for the Up button
const int buttonPinRight = 2;    // pin for the Down button
const int buttonPinEsc = 4;     // pin for the Esc button
const int buttonPinEnter = 5;   // pin for the Enter button
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
int lastButtonLeftState = LOW;   // the previous reading from the Left input pin
int lastButtonRightState = 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 = 100;    // the debounce time

// LiquidCrystal display with:
// rs on pin 2
// rw on 3
// enable on pin 6
// d4, d5, d6, d7 on pins 4, 5, 6, 7
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
int BackLightPin = 6;
//this controls the menu backend and the event generation
MenuBackend menu = MenuBackend(menuUseEvent,menuChangeEvent);
   //beneath is list of menu items needed to build the menu
   MenuItem Item1= MenuItem("Item1");
      MenuItem Item1Sub1 = MenuItem("Item1Sub1");
      MenuItem Item1Sub2 = MenuItem("Item1Sub2");
      MenuItem Item1Sub3 = MenuItem("Item1Sub3");
      MenuItem Item1Sub4 = MenuItem("Item1Sub4");
      MenuItem Item1Sub5 = MenuItem("Item1Sub5");
      MenuItem Item1Sub6 = MenuItem("Item1Sub6");
      MenuItem Item1Sub7 = MenuItem("Item1Sub7");
      MenuItem Item1Sub8 = MenuItem("Item1Sub8");
           MenuItem Item2 = MenuItem("Item2");
      MenuItem Item2Sub1 = MenuItem("Item2Sub1");
         MenuItem Item2Sub1Sub1 = MenuItem("Item2Sub1Sub1");
         MenuItem Item2Sub1Sub2 = MenuItem("Item2Sub1Sub2");
         MenuItem Item2Sub1Sub3 = MenuItem("Item2Sub1Sub3");
         MenuItem Item2Sub1Sub4 = MenuItem("Item2Sub1Sub4");
         MenuItem Item2Sub1Sub5 = MenuItem("Item2Sub1Sub5");
         MenuItem Item2Sub1Sub6 = MenuItem("Item2Sub1Sub6");
         MenuItem Item2Sub1Sub7 = MenuItem("Item2Sub1Sub7");
         MenuItem Item2Sub1Sub8 = MenuItem("Item2Sub1Sub8");
      MenuItem Item2Sub2 = MenuItem("Item2Sub2");
         MenuItem Item2Sub2Sub1 = MenuItem("Item2Sub2Sub1");
         MenuItem Item2Sub2Sub2 = MenuItem("Item2Sub2Sub2");
         MenuItem Item2Sub2Sub3 = MenuItem("Item2Sub2Sub3");
         MenuItem Item2Sub2Sub4 = MenuItem("Item2Sub2Sub4");
         MenuItem Item2Sub2Sub5 = MenuItem("Item2Sub2Sub5");
         MenuItem Item2Sub2Sub6 = MenuItem("Item2Sub2Sub6");
         MenuItem Item2Sub2Sub7 = MenuItem("Item2Sub2Sub7");
         MenuItem Item2Sub2Sub8 = MenuItem("Item2Sub2Sub8");
      MenuItem Item2Sub3 = MenuItem("Item2Sub3");
         MenuItem Item2Sub3Sub1 = MenuItem("Item2Sub3Sub1");
         MenuItem Item2Sub3Sub2 = MenuItem("Item2Sub3Sub2");
         MenuItem Item2Sub3Sub3 = MenuItem("Item2Sub3Sub3");
         MenuItem Item2Sub3Sub4 = MenuItem("Item2Sub3Sub4");
         MenuItem Item2Sub3Sub5 = MenuItem("Item2Sub3Sub5");
         MenuItem Item2Sub3Sub6 = MenuItem("Item2Sub3Sub6");
         MenuItem Item2Sub3Sub7 = MenuItem("Item2Sub3Sub7");
         MenuItem Item2Sub3Sub8 = MenuItem("Item2Sub3Sub8");
      MenuItem Item2Sub4 = MenuItem("Item2Sub4");
         MenuItem Item2Sub4Sub1 = MenuItem("Item2Sub4Sub1");
         MenuItem Item2Sub4Sub2 = MenuItem("Item2Sub4Sub2");
         MenuItem Item2Sub4Sub3 = MenuItem("Item2Sub4Sub3");
         MenuItem Item2Sub4Sub4 = MenuItem("Item2Sub4Sub4");
         MenuItem Item2Sub4Sub5 = MenuItem("Item2Sub4Sub5");
         MenuItem Item2Sub4Sub6 = MenuItem("Item2Sub4Sub6");
         MenuItem Item2Sub4Sub7 = MenuItem("Item2Sub4Sub7");
         MenuItem Item2Sub4Sub8 = MenuItem("Item2Sub4Sub8");
           MenuItem Item3 = MenuItem("Item3");
         MenuItem Item3Sub1 = MenuItem("Item3Sub1");
         MenuItem Item3Sub2 = MenuItem("Item3Sub2");
         MenuItem Item3Sub3 = MenuItem("Item3Sub3");
         MenuItem Item3Sub4 = MenuItem("Item3Sub4");
         MenuItem Item3Sub5 = MenuItem("Item3Sub5");
         MenuItem Item3Sub6 = MenuItem("Item3Sub6");
         MenuItem Item3Sub7 = MenuItem("Item3Sub7");
         MenuItem Item3Sub8 = MenuItem("Item3Sub8");
         MenuItem Item3Sub9 = MenuItem("Item3Sub9");
         MenuItem Item3Sub10 = MenuItem("Item3Sub10");
           MenuItem Item4 = MenuItem("Item4");
         MenuItem Item4Sub1 = MenuItem("Item4Sub1");
         MenuItem Item4Sub2 = MenuItem("Item4Sub2");
         MenuItem Item4Sub3 = MenuItem("Item4Sub3");
         MenuItem Item4Sub4 = MenuItem("Item4Sub4");

//this function builds the menu and connects the correct items together
void menuSetup()
{
     Serial.println("Setting up menu...");
   //add the file menu to the menu root
   menu.getRoot().add(Item1);
   //setup the settings menu item
        //Item 1...
   Item1.addRight(Item2).addRight(Item3).addRight(Item4);
        Item1.add(Item1Sub1).addRight(Item1Sub2).addRight(Item1Sub3).addRight(Item1Sub4).addRight(Item1Sub5).addRight(Item1Sub6).addRight(Item1Sub7).addRight(Item1Sub8);
        //Item 2...
        Item2.add(Item2Sub1).addRight(Item2Sub2).addRight(Item2Sub3).addRight(Item2Sub4);
   Item2Sub1.add(Item2Sub1Sub1).addRight(Item2Sub1Sub2).addRight(Item2Sub1Sub3).addRight(Item2Sub1Sub4).addRight(Item2Sub1Sub5).addRight(Item2Sub1Sub6).addRight(Item2Sub1Sub7).addRight(Item2Sub1Sub8);
   Item2Sub2.add(Item2Sub2Sub1).addRight(Item2Sub2Sub2).addRight(Item2Sub2Sub3).addRight(Item2Sub2Sub4).addRight(Item2Sub2Sub5).addRight(Item2Sub2Sub6).addRight(Item2Sub2Sub7).addRight(Item2Sub2Sub8);
   Item2Sub3.add(Item2Sub3Sub1).addRight(Item2Sub3Sub2).addRight(Item2Sub3Sub3).addRight(Item2Sub3Sub4).addRight(Item2Sub3Sub5).addRight(Item2Sub3Sub6).addRight(Item2Sub3Sub7).addRight(Item2Sub3Sub8);
   Item2Sub4.add(Item2Sub4Sub1).addRight(Item2Sub4Sub2).addRight(Item2Sub4Sub3).addRight(Item2Sub4Sub4).addRight(Item2Sub4Sub5).addRight(Item2Sub4Sub6).addRight(Item2Sub4Sub7).addRight(Item2Sub4Sub8);
        //Item 3...
   Item3.add(Item3Sub1).addRight(Item3Sub2).addRight(Item3Sub3).addRight(Item3Sub4).addRight(Item3Sub5).addRight(Item3Sub6).addRight(Item3Sub7)
        .addRight(Item3Sub8).addRight(Item3Sub9).addRight(Item3Sub10);
        //Item 4...
        Item4.add(Item4Sub1).addRight(Item4Sub2).addRight(Item4Sub3).addRight(Item4Sub4);
      }

/*
   This is an important function
   Here all use events are handled
   
   This is where you define a behaviour for a menu item
*/
void menuUseEvent(MenuUseEvent used)
{
   Serial.print("Menu use ");
   Serial.println(used.item.getName());
   if (used.item == Item2Sub1) //comparison agains a known item
   {
//      Serial.println("menuUseEvent found Delay (D)");
   }
}

/*
   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)
{
   Serial.print("Menu change ");
   Serial.println(changed.to.getName());
        lcd.clear();
        lcd.print("   Main Menu    ");
        lcd.setCursor(0,1);
        lcd.print(changed.to.getName());
}


continued...
 

Offline cowboy303Topic starter

  • Regular Contributor
  • *
  • Posts: 82
  • Country: us
Re: Arduino Menu Ideas, and MenuBackEnd problem
« Reply #3 on: May 02, 2013, 01:54:49 am »
Quote
void setup()
{
   Serial.begin(57600);
        lcd.begin(16, 2);   
   menuSetup();
   Serial.println("Starting navigation:\r\nUp: w   Down/use: s   Left: a   Right: d   Exit: x");
 pinMode(LEDPin, OUTPUT);
 digitalWrite(LEDPin, LOW);
 pinMode(BackLightPin, OUTPUT);
 BackLightLevel = EEPROM.read(BackLightChan);
 analogWrite(BackLightPin, BackLightLevel);

  pinMode(buttonPinLeft, INPUT);
  pinMode(buttonPinRight, INPUT);
  pinMode(buttonPinEnter, INPUT);
  pinMode(buttonPinEsc, INPUT);

}

void loop()
{
ReadButtons();
NavigateMenu();
BlinkLED();
}
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(buttonPinEnter);// read the state of the switch into a local variable:
                  
                  if (reading != lastButtonEnterState) {
                    // reset the debouncing timer
                    lastEnterDebounceTime = millis();
                  } 
                  
                  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();
                  }
                  
                  lastButtonEnterState = reading;
                  
   //Esc button               
                reading = digitalRead(buttonPinEsc);

                  if (reading != lastButtonEscState) {
                    lastEscDebounceTime = millis();
                  } 
                  
                  if ((millis() - lastEscDebounceTime) > debounceDelay) {
                    buttonEscState = reading;
                    lastEscDebounceTime=millis();
                  }
                  
                  lastButtonEscState = reading; 
                  
 //Down button               
                  reading = digitalRead(buttonPinRight);

                  if (reading != lastButtonRightState) {
                    // reset the debouncing timer
                    lastRightDebounceTime = millis();
                  } 
                  
                  if ((millis() - lastRightDebounceTime) > debounceDelay) {
                    buttonRightState = reading;
                   lastRightDebounceTime =millis();
                  }
                  
                  lastButtonRightState = reading;                  
                  
                  
    //Up button               
                  reading = digitalRead(buttonPinLeft);

                  if (reading != lastButtonLeftState) {
                    // reset the debouncing timer
                    lastLeftDebounceTime = millis();
                  } 
                  
                  if ((millis() - lastLeftDebounceTime) > debounceDelay) {
                    buttonLeftState = reading;
                    lastLeftDebounceTime=millis();;
                  }
                  
                  lastButtonLeftState = reading;  

                  if (buttonEnterState==HIGH){
                    lastButtonPushed=buttonPinEnter;

                  }else if(buttonEscState==HIGH){
                    lastButtonPushed=buttonPinEsc;

                  }else if(buttonRightState==HIGH){
                    lastButtonPushed=buttonPinRight;

                  }else if(buttonLeftState==HIGH){
                    lastButtonPushed=buttonPinLeft;

                  }else{
                    lastButtonPushed=0;
                  }                  
}

void NavigateMenu(){

  MenuItem currentMenu=menu.getCurrent();

     if (lastButtonPushed != 0){// so if nothing happend then don't waste it's time
      switch (lastButtonPushed) {
  //case 'w': menu.moveUp(); break;
  case buttonPinRight: menu.moveRight(); break;
  case buttonPinLeft: menu.moveLeft(); break;
  case buttonPinEsc: menu.toRoot(); break;         
  case buttonPinEnter:
  if ((currentMenu.moveDown()))//if the current menu has a child and has been pressed
  menu.moveDown();// enter then menu
  else
  menu.use();// use the menu item
  break;
  }
 }
}
void SetBackLight(){
int LastSavedBL = EEPROM.read(BackLightChan);

}
void BlinkLED(){

int BlinkDelay = 1000;

if((millis() - lastBlunk) >= BlinkDelay){
LED = !LED;
digitalWrite(LEDPin, LED);
lastBlunk = millis();
Serial.println(LED);

}

 

Offline ecat

  • Frequent Contributor
  • **
  • Posts: 296
  • Country: gb
Re: Arduino Menu Ideas, and MenuBackEnd problem
« Reply #4 on: May 02, 2013, 03:50:35 am »
A few things to try...

In Setup() comment out menuSetup(); and in Loop() comment out ReadButtons(); and NavigateMenu();

// menuSetup();

// ReadButtons();
// NavigateMenu();

You should now have serial comms and a blinking LED that will run all day. It doesn't do anything else of course, but the idea is to get the code to a point that is stable. From this point you can add stuff until it breaks again at which point you can me fairly sure the problem is with the last bit of stuff you added.

If the above works try reinstating ReadButtons();

// menuSetup();

  ReadButtons();
// NavigateMenu();

If this works things start to become complicated since all the menu stuff is interrelated. Try reinstating menuSetup();

  menuSetup();

  ReadButtons();
// NavigateMenu();

My bones tell me this is where the problem is most likely to be, something in the setup is overwriting something important.

 

Offline cowboy303Topic starter

  • Regular Contributor
  • *
  • Posts: 82
  • Country: us
Re: Arduino Menu Ideas, and MenuBackEnd problem
« Reply #5 on: May 02, 2013, 04:25:56 am »
Awesome!  Great Idea, it seems that the problem lies in the ReadButtons() function, which I didn't expect.
I only "//" the ReadButton function, and it's working perfect (besides the fact that I can't navigate the Menu with no buttons lol) it's been sitting here for 10 minutes just blinking and reporting through Serial.

I also had this setup:
//MenuSetup()
//NavigateMenu()
ReadButtons()

and it was having problems, it would only report through Serial once if that and then freeze within 30 seconds.
 

Offline ecat

  • Frequent Contributor
  • **
  • Posts: 296
  • Country: gb
Re: Arduino Menu Ideas, and MenuBackEnd problem
« Reply #6 on: May 02, 2013, 04:56:29 am »
Surprising find.

The only interesting part I see in ReadButtons() is the declaration of 5 integers at the start, so 10 bytes on the stack if Arduino works that way.

Move

  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

out of the function so you have

  int reading;
  int buttonEnterState;             // the current reading from the Enter input pin
  int buttonEscState;             // the current reading from the input pin
  int buttonLeftState;             // the current reading from the input pin
  int buttonRightState;             // the current reading from the input pin

void  ReadButtons(){  //read buttons status

  buttonEnterState=LOW;             // the current reading from the Enter input pin
  buttonEscState=LOW;             // the current reading from the input pin
  buttonLeftState=LOW;             // the current reading from the input pin
  buttonRightState=LOW;             // the current reading from the input pin

this way you move these integers from the stack and into the main data memory.

 

Offline TerminalJack505

  • Super Contributor
  • ***
  • Posts: 1310
  • Country: 00
Re: Arduino Menu Ideas, and MenuBackEnd problem
« Reply #7 on: May 02, 2013, 05:14:45 am »
I suspect that you might have run out of ram.  Your stack is likely colliding with your data.

All of those menu item strings ("Item2Sub1SubThisSubThat") are likely in data memory.  If they don't change then a better place for them would be program memory.  I've never used that menu library so I don't know if there's a constructor that takes a pointer to program memory or not.  If it does then you might change all those strings so that they reside in program memory.
 

Offline ecat

  • Frequent Contributor
  • **
  • Posts: 296
  • Country: gb
Re: Arduino Menu Ideas, and MenuBackEnd problem
« Reply #8 on: May 02, 2013, 05:36:05 am »
I suspect that you might have run out of ram.  Your stack is likely colliding with your data.

All of those menu item strings ("Item2Sub1SubThisSubThat") are likely in data memory.  If they don't change then a better place for them would be program memory.  I've never used that menu library so I don't know if there's a constructor that takes a pointer to program memory or not.  If it does then you might change all those strings so that they reside in program memory.

I was just looking at this.
http://www.arduino.cc/playground/uploads/Profiles/MenuBackend_1-4.zip

From what I can see I think the strings are stored in flash (program memory) by default and MenuItem references them from there - though this could still be a problem. If they are stored in ram then TerminalJack505 is spot on.

Each MenuItem also defines 5 pointers stored in ram

   MenuItem *before;
   MenuItem *right;
   MenuItem *after;
   MenuItem *left;
   MenuItem *back;

Assuming 2 bytes per pointer = 10 bytes.
There are 62 MenuItems so, 620 bytes. The standard Arduino UNO has 2kB of ram.


Which ever way the menu system works, get rid of some MenuItems... How many? lol, Start with just 3 or 4 (or, 1 or 2). Then add them back in to see if and when the code goes silly.

Better still, try to find out how the Arduino environment informs you of flash used and ram used then check these numbers against the cpu on your Arduino board.


« Last Edit: May 02, 2013, 05:39:33 am by ecat »
 

Offline cowboy303Topic starter

  • Regular Contributor
  • *
  • Posts: 82
  • Country: us
Re: Arduino Menu Ideas, and MenuBackEnd problem
« Reply #9 on: May 02, 2013, 12:36:03 pm »
I tried moving the "buttonEnterState" like you said, still no show.

I tried taking off some of the menu, and that fixes it. if I remove two it works fine.  If I remove one, it doesn't work at all.

So I guess Mr.TerminalJack505 is right, that kinda makes sense to me because I was fighting this problem the whole way along with my project, I found removing serial helped. and where I"m at now, there is 1 line of code I have commented off

Quote
else if (used.item.getName() == "Item3SubItem4"){
//FindDataLogDelay();
}  


if I comment that out the whole thing works, if I don't, it don't.
So I guess I have to work with a smaller menu? or is there a way to fix this without making it TOOOO much smaller?

Thank you gentlemen for your help!
 

Offline ecat

  • Frequent Contributor
  • **
  • Posts: 296
  • Country: gb
Re: Arduino Menu Ideas, and MenuBackEnd problem
« Reply #10 on: May 02, 2013, 12:47:02 pm »
If it is just a string length problem then simply reducing the length of the names will help, instead of "Item2Sub1Sub1" try "I2S1S1" or "I2.1.1", the long string is 13 characters = 13 bytes + 1 byte (for the string terminator) and the short version shown here is 6 characters = 6 bytes + 1 byte. So, if you shorten the strings for all of the menu items you save a considerable amount of storage space.

If shortening the strings doesn't help and you still need to chop a menu item then it looks like the strings are stored in program memory by default and you may need some work on the Menu library to implement your full menu structure.

 

Offline cowboy303Topic starter

  • Regular Contributor
  • *
  • Posts: 82
  • Country: us
Re: Arduino Menu Ideas, and MenuBackEnd problem
« Reply #11 on: May 02, 2013, 01:22:30 pm »
Looks like you were right again, itn's now "I2S1S2" and it's working fine with nothing commented off.

Question,
as you can see here:
Quote
void menuChangeEvent(MenuChangeEvent changed)
{
   Serial.print("Menu change ");
   Serial.println(changed.to.getName());
        lcd.clear();
        lcd.print("   Main Menu    ");
        lcd.setCursor(0,1);
        lcd.print(changed.to.getName());
}


I use the menu name to display on the LCD,  So can I do the code below without any negitive effects?

Quote
   MenuItem I1= MenuItem("1 Options");
      MenuItem I1S1 = MenuItem("1 EEPROM TEST");
      MenuItem I1S2 = MenuItem("2 SAVE ALL");
      MenuItem I1S3 = MenuItem("Set BackLight");
      MenuItem I1S4 = MenuItem("Display Time");

I could also use a if statement, but that wouldn't be my favorite choice.
 

Offline ecat

  • Frequent Contributor
  • **
  • Posts: 296
  • Country: gb
Re: Arduino Menu Ideas, and MenuBackEnd problem
« Reply #12 on: May 02, 2013, 01:51:33 pm »
...

Only one way to find out ;)

1) You know how many characters you used when you had problems, just count them all up and 1 extra for each full string.
2) You know how many menu items you had to remove to make the code work, you can add up how many characters these entries used.

So, the total from 1) minus the total from 2) gives you a rough idea of the maximum number characters you can use. Whatever you decide to name your items just make sure the total number of characters is less than your safe total and you should be good.

Item1Sub1 = MenuItem("Item1Sub1");        is 9 characters + 1 = 10 bytes in total
Item1Sub1 = MenuItem("Main");                  is 4 characters + 1 = 5 bytes in total
^Name^                            ^String

Just keep track as you go. Also notice I've used Item1Sub1 as the name for the MenuItem variable (class instance to be pedantic), the character count rule we're describing here applies only to the characters in the strings "I'm a string", outside of the quotes you can use any names you wish (subject to whatever the Arduino language restrictions may be).

It's worth remembering that any additional functionality you need to add to finish your program will require additional memory and at some point going forward you may find your program breaks again. It maybe worth while thinking of ways to abbreviate your strings...

"1 EEPROM TEST"    Not much you can do about this ...
"Set BackLight"       "Set Light"  maybe?
"Display Time"         "Disp Time" ?

It's up to you if you spend the time now or wait and see if problems occur and then go on an abbreviation spree.
 
 

Offline cowboy303Topic starter

  • Regular Contributor
  • *
  • Posts: 82
  • Country: us
Re: Arduino Menu Ideas, and MenuBackEnd problem
« Reply #13 on: May 02, 2013, 11:39:23 pm »
Well I think I'm just going to keep in mind that I'm a little short on ram, and if I have problems then I'll go on a  abbreviation spree.

I really didn't understand how the whole thing worked, so thank you for helping, and useing such easy-to-understand examples, I know it takes a bit more time to do it that way.  :-+ 
 

Offline ecat

  • Frequent Contributor
  • **
  • Posts: 296
  • Country: gb
Re: Arduino Menu Ideas, and MenuBackEnd problem
« Reply #14 on: May 03, 2013, 01:00:30 am »
You're welcome.

And thanks to the prompting from TerminalJack505 I learned that Arduino stores constant strings in RAM  :-//

A few links I found:

Arduino and Memory - the bit at the bottom of the page, the F() syntax, may be worth investigating
http://playground.arduino.cc/Learning/Memory

Memory and full map file from Arduino .elf file
http://arduino.cc/forum/index.php?topic=72948.0

Memory usage if you use Arduino for Visual C
http://www.visualmicro.com/post/2012/08/24/Arduino-Memory-Usage-and-Disassembly-Reporting.aspx
 
Advanced Coding and Memory Handling
http://www.oreilly.de/catalog/arduinockbkger/Arduino_Kochbuch_englKap_17.pdf
 

Offline TerminalJack505

  • Super Contributor
  • ***
  • Posts: 1310
  • Country: 00
Re: Arduino Menu Ideas, and MenuBackEnd problem
« Reply #15 on: May 03, 2013, 09:06:26 am »
For grins I played around with the code to see what it would take to put the strings into program memory (aka flash.)  I've attached the changes in case you ever need that particular functionality.  In your case, since your menus are so big, it will save a lot of SRAM.  And SRAM can be a scarce resource.

I changed the library source and the example application to use strings from flash.  All of the menu names have to be stored in flash.  That is, you can't mix and match with some in flash and others in data memory.

You'll notice in the code there are a couple of ways to get at the string when it is in flash memory.  The Serial object can deal directly with strings in flash, for example.  If it is just a string literal then all you have to do is use the F() macro like so:

Code: [Select]
Serial.println(F("Starting navigation:\r\nUp: w   Down: s   Left: a   Right: d   Use: e"));
If a char * points to a string in flash then you use the fromFlash() inline function defined in the example code to tell the Serial object it's in flash:

Code: [Select]
Serial.println(fromFlash(used.item.getName()));
There's also an function called getItemNameFromFlash() that shows how to copy a string from flash to data memory. 

Code: [Select]
inline char * getItemNameFromFlash(const MenuItem & item, char * copyToBuffer, size_t bufferSize)
{
    strncpy_P(copyToBuffer, item.getName(), bufferSize);
    copyToBuffer[bufferSize - 1] = '\0'; // Make sure the buffer is null-terminated.

    return copyToBuffer;
}

As you can see it is pretty much just a wrapper for the strncpy_P() AVR Lib C function.  Consult the AVR Lib C manual for more information.

Finally, this is how you declare the MenuItem objects so that the menu name resides in flash:

Code: [Select]
char itemNameSettings[] PROGMEM = "Settings";
char itemNamePin[] PROGMEM      = "Pin";
char itemNameDebug[] PROGMEM    = "Debug";
char itemNameOptions[] PROGMEM  = "Options";
char itemNameDelay[] PROGMEM    = "Delay";
char itemName100ms[] PROGMEM    = "100 ms";
char itemName200ms[] PROGMEM    = "200 ms";
char itemName300ms[] PROGMEM    = "300 ms";
char itemName400ms[] PROGMEM    = "400 ms";

//this controls the menu backend and the event generation
MenuBackend menu = MenuBackend(menuUseEvent,menuChangeEvent);
//beneath is list of menu items needed to build the menu
MenuItem settings = MenuItem(itemNameSettings);
MenuItem pin = MenuItem(itemNamePin);
MenuItem debug = MenuItem(itemNameDebug);
MenuItem options = MenuItem(itemNameOptions);
MenuItem setDelay = MenuItem(itemNameDelay,'D');
MenuItem d100 = MenuItem(itemName100ms);
MenuItem d200 = MenuItem(itemName200ms);
MenuItem d300 = MenuItem(itemName300ms);
MenuItem d400 = MenuItem(itemName400ms);
 

Offline cowboy303Topic starter

  • Regular Contributor
  • *
  • Posts: 82
  • Country: us
Re: Arduino Menu Ideas, and MenuBackEnd problem
« Reply #16 on: May 05, 2013, 06:54:12 pm »
Thank you Mr.TerminalJack505! Your code/library are working perfectly!  I made a function to control the LCD bargraph, and like all my code I write it wasn't working at first  ::). by the end of troubleshooting, there was Serial.println stuff EVERYWHERE, and they were pretty long too, like "blocks is not oldBlocks". and it never froze up!

and something I noticed on my old sketch that was having problems,

Quote
      MenuItem menuItem2SubItem1 = MenuItem("Item2SubItem1");
         MenuItem menuItem2SubItem1Sub1 = MenuItem("Item2SubItem1Sub1");
         MenuItem menuItem2SubItem1Sub2 = MenuItem("Item2SubItem1Sub2");
         MenuItem menuItem2SubItem1Sub3 = MenuItem("Item2SubItem1Sub3");
         MenuItem menuItem2SubItem1Sub4 = MenuItem("Item2SubItem1Sub4");


that's 18 bytes (thank you ecat), and what's worse,

Quote
  if(newMenuItem.getName()=="Item1"){
      lcd.print("1 Settings           ");
  }else if(newMenuItem.getName()=="Item1SubItem1"){
      lcd.print("1-SAVE          ");
  }else if(newMenuItem.getName()=="Item1SubItem2"){
      lcd.print("2-Set BackLight ");


sooooo yeah, I was hard on it.  ;D

Thank you Gentlemen for heading me in the right direction.  it's really nice knowing that if I have a problem that I can't figure out, that there are gentlemen like you guys that are willing to help.  :-+
« Last Edit: May 05, 2013, 07:58:20 pm by cowboy303 »
 

Offline tom1147

  • Newbie
  • Posts: 3
Re: Arduino Menu Ideas, and MenuBackEnd problem
« Reply #17 on: January 20, 2015, 09:39:45 pm »
can you tell me how to post code on this site thanks tom
 

Offline electr_peter

  • Supporter
  • ****
  • Posts: 1298
  • Country: lt
Re: Arduino Menu Ideas, and MenuBackEnd problem
« Reply #18 on: January 20, 2015, 10:06:53 pm »
Select "#" symbol when writing a comment
Code: [Select]
2 + 2 == 4
 

Offline tom1147

  • Newbie
  • Posts: 3
Re: Arduino Menu Ideas, and MenuBackEnd problem
« Reply #19 on: January 21, 2015, 01:28:16 am »
hello again here is my arduino file having trouble with menuUseEvent if (used.item==item1);
want to run engineID() under loop aand save 4 digit number can someone let me have some
direction new to this if you cant figuare out what i am trying to do please contack me thanks tom

cann't upload my arduion file so you can email me at tamacdonald@cfl.rr.com i will send it to you
as an attachments save time retypeing code thanks tom any help
 

Offline TerminalJack505

  • Super Contributor
  • ***
  • Posts: 1310
  • Country: 00
Re: Arduino Menu Ideas, and MenuBackEnd problem
« Reply #20 on: January 21, 2015, 01:53:41 am »
To post your code you should be able to attach a zip file to a post by clicking "Attachments and other options" beneath the edit box and then clicking the "Browse..." button.

If this isn't available then it might be because you don't have enough posts to the forum.  It seems like I remember that users had certain limitations until they've made at least 5 posts.
 

Offline tom1147

  • Newbie
  • Posts: 3
Re: Arduino Menu Ideas, and MenuBackEnd problem
« Reply #21 on: January 22, 2015, 01:02:04 pm »
stuck how to i get from menuUseEvent item1
to run fuction tom() which is an array number,
then go back to read keypad() fuction which is the menu scroll up and down
sorry to such a pain new at this do not understand how to put things together
thanks tom1147
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf