Scrolling menu program hangs...

I wrote this code (yes I know it’s pretty crap but it was quick) for a 16x2 Serial LCD scrolling menu (tested on 20x4 and 16x2) but it’s not quite working :(:

#include <NewSoftSerial.h>

NewSoftSerial LCDserial(0, 2);

int prognumber = 1;
int line = 1;

int down = 8;
int select = 9;
int up = 10;

void menu();
void LCDclear();
void LCDfirst();
void LCDsecond();
void LCDmenudisplay();

void first();
void second();
void third();
void fourth();
void fifth();

void setup() {
  LCDserial.begin(9600);
  menu();
}

void loop() {
  //nothing to loop but is required in every sketch.
}

void LCDclear(){
  LCDserial.print(0xFE, BYTE);      
  LCDserial.print(0x01, BYTE);
}

void LCDfirst(){
  LCDserial.print(0xFE, BYTE);
  LCDserial.print(128, BYTE);
}
void LCDsecond(){
  LCDserial.print(0xFE, BYTE);
  LCDserial.print(192, BYTE);
}

void menu() {
  while(digitalRead(up) == HIGH or digitalRead(down) == HIGH or digitalRead(select) == HIGH){};
  delay(50);
  LCDclear();
  LCDfirst();
  if(prognumber > 1){
  prognumber--;
  }
  else{
    prognumber == 1;
  }
  LCDmenudisplay();
  LCDsecond();
  prognumber++;
  LCDmenudisplay();
  if(line == 1){
    LCDserial.print(0xFE, BYTE);
    LCDserial.print(143, BYTE);
    LCDserial.print("<");
  }
  else {
    LCDserial.print(0xFE, BYTE);
    LCDserial.print(207, BYTE);
    LCDserial.print("<");
  }
  while(digitalRead(up) == LOW && digitalRead(down) == LOW && digitalRead(select) == LOW){}
  if(digitalRead(down) == HIGH){
  line++;
  if(line > 2){
  line = 2;
  prognumber++;
  if(prognumber > 4){
  prognumber = 5;
  }
  }
  menu();
  }
  else if(digitalRead(up) == HIGH){
  line--;
  if(line < 1){
  line = 1;
  prognumber--;
  }
  menu();
  }
  else if(digitalRead(select) == HIGH){
  if(line == 1){
    prognumber--;
  }
  switch (prognumber) {                  
  case 1:                                
    first(); 
    break;                              
  case 2:
    second();
    break;
  case 3:
    third();
    break;
  case 4:
    fourth();
    break;
  case 5:
    fifth();
    break;
  default:
    first();
  }
  }
}

void LCDmenudisplay() {
  switch (prognumber) {                  
  case 1:                                
    LCDserial.print("First");  
    break;                              
  case 2:
    LCDserial.print("Second");
    break;
  case 3:
    LCDserial.print("Third");
    break;
  case 4:
    LCDserial.print("Fourth");
    break;
  case 5:
    LCDserial.print("Fifth");
    break;
  default:
    LCDserial.print("First");
  }
  
}

void first() {
  digitalWrite(13, HIGH);
  menu();
}

void second() {
  menu();
}

void third() {
  menu();
}

void fourth() {
  menu();
}

void fifth() {
  digitalWrite(13, HIGH);
  delay(1000);
  digitalWrite(13, LOW);
  menu();
}

All seems to work apart from after about 10-20 presses of up/down buttons it hangs and needs resetting.
Anyone got any ideas as to why?

Also if anyone else has any scrolling menu programs they have written then I would be interested in seeing them.

Mowcius

I’m having a hard time following your code. As far as more menu examples, I recall seeing a few different menu libraries in one of the Arduino libraries pages.

while(digitalRead(up) == HIGH or digitalRead(down) == HIGH or digitalRead(select) == HIGH){};

Just out of interest, how/where is "or" defined"?

I'm having a hard time following your code. As far as more menu examples, I recall seeing a few different menu libraries in one of the Arduino libraries pages.

Yeah I'm not surprised and did you? Where? :)

Just out of interest, how/where is "or" defined"?

Aha! That is a good point. That might be the issue. I had forgotten that it's || not 'or'... I wonder why it didn't throw up an error for that one. :-?

Mowcius

Hmm. Changing that makes no difference... Any other ideas? Any links to these other menus?

Mowcius

hi everyone

I have added some serial debug lines and it appears to jump from 22a to 31 then to 38 and hang there…

void LCDclear(){
  LCDserial.print(0xFE, BYTE);       
  LCDserial.print(0x01, BYTE); 
}

void LCDfirst(){
  LCDserial.print(0xFE, BYTE);
  LCDserial.print(128, BYTE);
}
void LCDsecond(){
  LCDserial.print(0xFE, BYTE);
  LCDserial.print(192, BYTE);
}

void menu() {
  Serial.println(" 1");
  while(digitalRead(up) == HIGH or digitalRead(down) == HIGH or digitalRead(select) == HIGH){};
  Serial.println(" 2");
  delay(50);
  Serial.println(" 3");
  LCDclear();
  Serial.println(" 4");
  LCDfirst();
  Serial.println(" 5");
  if(prognumber > 1){
    Serial.println(" 6");    
  prognumber--;
  Serial.println(" 7");
  }
  else{
    Serial.println(" 8");
    prognumber == 1;
  Serial.println(" 9");
  }
  LCDmenudisplay();
  Serial.println(" 10");
  LCDsecond();
  Serial.println(" 11");

  prognumber++;
Serial.println("12 ");
  LCDmenudisplay();
  Serial.println("13 ");
  if(line == 1){
    Serial.println("14 ");
    LCDserial.print(0xFE, BYTE);
    Serial.println("15 ");
    LCDserial.print(143, BYTE);
    Serial.println(" 16");
    LCDserial.print("<");
    Serial.println("17 ");
  }
  else {
    Serial.println("18 ");
    LCDserial.print(0xFE, BYTE);
    Serial.println("19 ");
    LCDserial.print(207, BYTE);
    Serial.println("20 ");
    LCDserial.print("<");
    Serial.println(" 21");
  }
   Serial.println("22A ");
  while(digitalRead(up) == LOW && digitalRead(down) == LOW && digitalRead(select) == LOW){}
  Serial.println("22 ");
  delay(50);
  if(digitalRead(down) == HIGH){
    Serial.println(" 23");
  line++;
  Serial.println("24 ");
  if(line > 2){
    Serial.println("25 ");
  line = 2;
  Serial.println(" 26");
  prognumber++;
  Serial.println("27 ");
  }
  if(prognumber > 4){
    Serial.println("28 ");
  prognumber = 5;
Serial.println(" 29");
  }
  Serial.println(" 30");
  menu();
  Serial.println(" 31");
  }
  delay(50);
  if(digitalRead(up) == HIGH){
    Serial.println("32 ");
  line--;
  Serial.println("33 ");
  if(line < 1){
    Serial.println("34 ");
  line = 1;
  Serial.println("35 ");
  prognumber--;
  Serial.println("36 ");
  }
  Serial.println(" 37");
  menu();
  Serial.println("38 ");
  }
  delay(50);
  if(digitalRead(select) == HIGH){
    Serial.println("39 ");
  if(line == 1){
    Serial.println(" 40");
    prognumber--;
    Serial.println("41 ");
  }
  Serial.println("42 ");
  switch (prognumber) {                  
  case 1:                                
Serial.println("43 ");
    first(); 
    break;                               
  case 2:
  Serial.println("44 ");
    second();
    break;
  case 3:
  Serial.println("45 ");
    third();
    break;
  case 4:
  Serial.println("46 ");
    fourth();
    break;
  case 5:
  Serial.println("47");
    fifth();
    break;
   default:
    Serial.println("48");
    first();
      break;
  }
  }
}

void LCDmenudisplay() {
  switch (prognumber) {                  
  case 1:                                
    LCDserial.print("First");   
    break;                               
  case 2:
    LCDserial.print("Second");
    break;
  case 3:
    LCDserial.print("Third");
    break;
  case 4:
    LCDserial.print("Fourth");
    break;
  case 5:
    LCDserial.print("Fifth");
    break;
  default:
    LCDserial.print("First");
  }
  
}

void first() {
  digitalWrite(13, HIGH);
  menu();
}

void second() {
  menu();
}

void third() {
  menu();
}

void fourth() {
  menu();
}

void fifth() {
  digitalWrite(13, HIGH);
  delay(1000);
  digitalWrite(13, LOW);
  menu();
}

any ideas???

thanks heaps

ben

Hmm, intriguing...

You wanna add that code ] bracket back in? :)

Mowcius

oops fixed

Probably not the source of the problem but still worth fixing...

void menu() {
  while(digitalRead(up) == HIGH or digitalRead(down) == HIGH or digitalRead(select) == HIGH){};
  delay(50);
  LCDclear();
  LCDfirst();
  if(prognumber > 1){
  prognumber--;
  }
  else{
    prognumber [glow]=[/glow]= 1;  [glow]// Assignment?  Comparison?[/glow]
  }
  LCDmenudisplay();

Yes indeed. Another problem in my code… :frowning:

Mowcius

Looks like plenty of recursion going on :wink: You keep calling menu() - even within menu(). Unchecked recursion on a microcontroller == out of memory fast!

I just removed all calls to menu() other than in loop(). I haven’t tested it (but I have compiled it), so don’t yell at me!

#include <NewSoftSerial.h>

NewSoftSerial LCDserial(0, 2);

int prognumber = 1;
int line = 1;

int down = 8;
int select = 9;
int up = 10;

void menu();
void LCDclear();
void LCDfirst();
void LCDsecond();
void LCDmenudisplay();

void first();
void second();
void third();
void fourth();
void fifth();

void setup() {
  LCDserial.begin(9600);
}

void loop() {
  menu();
}

void LCDclear(){
  LCDserial.print(0xFE, BYTE);
  LCDserial.print(0x01, BYTE);
}

void LCDfirst(){
  LCDserial.print(0xFE, BYTE);
  LCDserial.print(128, BYTE);
}
void LCDsecond(){
  LCDserial.print(0xFE, BYTE);
  LCDserial.print(192, BYTE);
}

void menu() {
  while(digitalRead(up) == HIGH or digitalRead(down) == HIGH or digitalRead(select) == HIGH){};
  delay(50);
  LCDclear();
  LCDfirst();
  if(prognumber > 1){
    prognumber--;
  }
  else{
    prognumber = 1;
  }
  LCDmenudisplay();
  LCDsecond();
  prognumber++;
  LCDmenudisplay();
  if(line == 1){
    LCDserial.print(0xFE, BYTE);
    LCDserial.print(143, BYTE);
    LCDserial.print("<");
  }
  else {
    LCDserial.print(0xFE, BYTE);
    LCDserial.print(207, BYTE);
    LCDserial.print("<");
  }
  while(digitalRead(up) == LOW && digitalRead(down) == LOW && digitalRead(select) == LOW){}
  if(digitalRead(down) == HIGH){
    line++;
    if(line > 2){
      line = 2;
      prognumber++;
      if(prognumber > 4){
        prognumber = 5;
      }
    }
  }
  else if(digitalRead(up) == HIGH){
    line--;
    if(line < 1){
      line = 1;
      prognumber--;
    }
  }
  else if(digitalRead(select) == HIGH){
    if(line == 1){
      prognumber--;
    }
    switch (prognumber) {
    case 1:
      first();
      break;
    case 2:
      second();
      break;
    case 3:
      third();
      break;
    case 4:
      fourth();
      break;
    case 5:
      fifth();
      break;
    default:
      first();
    }
  }
}

void LCDmenudisplay() {
  switch (prognumber) {
  case 1:
    LCDserial.print("First");
    break;
  case 2:
    LCDserial.print("Second");
    break;
  case 3:
    LCDserial.print("Third");
    break;
  case 4:
    LCDserial.print("Fourth");
    break;
  case 5:
    LCDserial.print("Fifth");
    break;
  default:
    LCDserial.print("First");
  }

}

void first() {
  digitalWrite(13, HIGH);
}

void second() {
}

void third() {
}

void fourth() {
}

void fifth() {
  digitalWrite(13, HIGH);
  delay(1000);
  digitalWrite(13, LOW);
}

b

Brett comes to the rescue again :)

It works perfectly now. Well almost.

I am just playing with some delays for debounce but after that it seems good to go.

Mowcius

Latest code with a little delay to help with debouncing :slight_smile:

Seems to work perfectly now.

#include <NewSoftSerial.h>

NewSoftSerial LCDserial(0, 2);

int prognumber = 1;
int line = 1;

int down = 8;
int select = 9;
int up = 10;

void menu();
void LCDclear();
void LCDfirst();
void LCDsecond();
void LCDmenudisplay();

void first();
void second();
void third();
void fourth();
void fifth();

void setup() {
  LCDserial.begin(9600);
}

void loop() {
  menu();
}

void LCDclear(){
  LCDserial.print(0xFE, BYTE);
  LCDserial.print(0x01, BYTE);
}

void LCDfirst(){
  LCDserial.print(0xFE, BYTE);
  LCDserial.print(128, BYTE);
}
void LCDsecond(){
  LCDserial.print(0xFE, BYTE);
  LCDserial.print(192, BYTE);
}

void menu() {
  while(digitalRead(up) == HIGH or digitalRead(down) == HIGH or digitalRead(select) == HIGH){};
  LCDclear();
  LCDfirst();
  if(prognumber > 1){
    prognumber--;
  }
  else{
    prognumber = 1;
  }
  LCDmenudisplay();
  LCDsecond();
  prognumber++;
  LCDmenudisplay();
  if(line == 1){
    LCDserial.print(0xFE, BYTE);
    LCDserial.print(143, BYTE);
    LCDserial.print("<");
  }
  else {
    LCDserial.print(0xFE, BYTE);
    LCDserial.print(207, BYTE);
    LCDserial.print("<");
  }
  while(digitalRead(up) == LOW && digitalRead(down) == LOW && digitalRead(select) == LOW){}
  if(digitalRead(down) == HIGH){
    line++;
    if(line > 2){
      line = 2;
      prognumber++;
      if(prognumber > 4){
        prognumber = 5;
      }
    }
  }
  else if(digitalRead(up) == HIGH){
    line--;
    if(line < 1){
      line = 1;
      prognumber--;
    }
  }
  else if(digitalRead(select) == HIGH){
    if(line == 1){
      prognumber--;
    }
    switch (prognumber) {
    case 1:
      first();
      break;
    case 2:
      second();
      break;
    case 3:
      third();
      break;
    case 4:
      fourth();
      break;
    case 5:
      fifth();
      break;
    default:
      first();
    }
  }
  delay(50);
}

void LCDmenudisplay() {
  switch (prognumber) {
  case 1:
    LCDserial.print("First");
    break;
  case 2:
    LCDserial.print("Second");
    break;
  case 3:
    LCDserial.print("Third");
    break;
  case 4:
    LCDserial.print("Fourth");
    break;
  case 5:
    LCDserial.print("Fifth");
    break;
  default:
    LCDserial.print("First");
  }

}

void first() {
  digitalWrite(13, HIGH);
}

void second() {
  digitalWrite(13, HIGH);
  delay(1000);
  digitalWrite(13, LOW);
  delay(1000);
  digitalWrite(13, HIGH);
  delay(1000);
  digitalWrite(13, LOW);
}

void third() {
  digitalWrite(13, HIGH);
  delay(500);
  digitalWrite(13, LOW);
  delay(500);
  digitalWrite(13, HIGH);
  delay(500);
  digitalWrite(13, LOW);
}

void fourth() {
  digitalWrite(13, HIGH);
  delay(100);
  digitalWrite(13, LOW);
  delay(100);
  digitalWrite(13, HIGH);
  delay(100);
  digitalWrite(13, LOW);
}

void fifth() {
  digitalWrite(13, LOW);
}

Hi Mowcius & bhagman,

I would like to thank you both for all your help especially Mowcius!! and thanks to everyone else who contributed.

I love this community. ;D

thanks all

ben

It works without but I forgot to change this in the latest piece of code:

  while(digitalRead(up) == HIGH || digitalRead(down) == HIGH || digitalRead(select) == HIGH){};

Should be '||' not 'or'

Hi Mowcius & bhagman,

I would like to thank you both for all your help especially Mowcius!! and thanks to everyone else who contributed.

I love this community.

No problem! I love the community too :)

Mowcius

#include <NewSoftSerial.h>

NewSoftSerial LCDserial(0, 2);

int prognumber = 1;
int line = 1;

int down = 8;
int select = 9;
int up = 10;

void menu();
void LCDclear();
void LCDfirst();
void LCDsecond();
void LCDmenudisplay();

void first();
void second();
void third();
void fourth();
void fifth();

void setup() {
  LCDserial.begin(9600);
}

void loop() {
  menu();
}

void LCDclear(){
  LCDserial.print(0xFE, BYTE);
  LCDserial.print(0x01, BYTE);
}

void LCDfirst(){
  LCDserial.print(0xFE, BYTE);
  LCDserial.print(128, BYTE);
}
void LCDsecond(){
  LCDserial.print(0xFE, BYTE);
  LCDserial.print(192, BYTE);
}

void menu() {
  while(digitalRead(up) == HIGH || digitalRead(down) == HIGH || digitalRead(select) == HIGH){};
  LCDclear();
  LCDfirst();
  if(prognumber > 1){
    prognumber--;
  }
  else{
    prognumber = 1;
  }
  LCDmenudisplay();
  LCDsecond();
  prognumber++;
  LCDmenudisplay();
  if(line == 1){
    LCDserial.print(0xFE, BYTE);
    LCDserial.print(143, BYTE);
    LCDserial.print("<");
  }
  else {
    LCDserial.print(0xFE, BYTE);
    LCDserial.print(207, BYTE);
    LCDserial.print("<");
  }
  while(digitalRead(up) == LOW && digitalRead(down) == LOW && digitalRead(select) == LOW){}
  if(digitalRead(down) == HIGH){
    line++;
    if(line > 2){
      line = 2;
      prognumber++;
      if(prognumber > 4){
        prognumber = 5;
      }
    }
  }
  else if(digitalRead(up) == HIGH){
    line--;
    if(line < 1){
      line = 1;
      prognumber--;
    }
  }
  else if(digitalRead(select) == HIGH){
    if(line == 1){
      prognumber--;
    }
    switch (prognumber) {
    case 1:
      first();
      break;
    case 2:
      second();
      break;
    case 3:
      third();
      break;
    case 4:
      fourth();
      break;
    case 5:
      fifth();
      break;
    default:
      first();
    }
  }
  delay(50);
}

void LCDmenudisplay() {
  switch (prognumber) {
  case 1:
    LCDserial.print("First");
    break;
  case 2:
    LCDserial.print("Second");
    break;
  case 3:
    LCDserial.print("Third");
    break;
  case 4:
    LCDserial.print("Fourth");
    break;
  case 5:
    LCDserial.print("Fifth");
    break;
  default:
    LCDserial.print("First");
  }

}

void first() {
  digitalWrite(13, HIGH);
}

void second() {
  digitalWrite(13, HIGH);
  delay(1000);
  digitalWrite(13, LOW);
  delay(1000);
  digitalWrite(13, HIGH);
  delay(1000);
  digitalWrite(13, LOW);
}

void third() {
  digitalWrite(13, HIGH);
  delay(500);
  digitalWrite(13, LOW);
  delay(500);
  digitalWrite(13, HIGH);
  delay(500);
  digitalWrite(13, LOW);
}

void fourth() {
  digitalWrite(13, HIGH);
  delay(100);
  digitalWrite(13, LOW);
  delay(100);
  digitalWrite(13, HIGH);
  delay(100);
  digitalWrite(13, LOW);
}

void fifth() {
  digitalWrite(13, LOW);
}

As I never posted up the completely correct code before. :stuck_out_tongue:

I never used it, but here is a menu library:

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1240415211

May be could be useful to you.

Cheers,

I have seen that library but it did not do what I wanted it to ;)

So I wrote some code that did :D