Go Down

Topic: Program causing Arduino to reset? (Read 549 times) previous topic - next topic

ajb

Jun 12, 2009, 07:42 pm Last Edit: Jun 12, 2009, 07:45 pm by ajb Reason: 1
I'm working on a menu system for a project, and for some reason hitting the "back" button which causes a menu screen handler to return a reference to a parent menu causes the Arduino to jump back to the setup function.  I'm not sure if it's doing a full reset because when I added an LED that's turned on right before the return statement, that LED stays on until I actually hit the reset button.  I've pretty much ruled out a hardware issue with the button, so I must be missing something in software.

Any insight is appreciated.

The problem occurs at the indicated line at the end of DataScreen.maintain()

Code: [Select]
/*******************************************************************************************************
/  CLASS MenuItem
/  base class for all of the various menu screens so that the currentItem pointer may point to any
/  of the sketch's menus.
/
/******************************************************************************************************/

class MenuItem {
 public:
   char descript[16];
   MenuItem* parent;
   virtual void display(){};
   virtual MenuItem* handleButton( int button ){};
   virtual MenuItem* maintain(){}; //do any required maintenance, ie-poll sensors to update screen data
};

/*******************************************************************************************************
/  CLASS DataScreen
/  for displaying sensor data
/
/******************************************************************************************************/

class SensorScreen : public MenuItem {
 protected:
   unsigned int currentDatum; //current datum that should be displayed
   unsigned long lastPoll; //time of last sensor data update
   boolean refresh; // flag indicates if screen needs to be refreshed
 
 public:
   SensorScreen(char desc[], MenuItem *par ) {
     parent = par;
     strcpy(descript, desc);
     currentDatum=0;
     lastPoll=0;
     refresh=true;
   }
    void display() {
      Serial.println("display");
     lcd.clear();
     lcd.home();
     lcd.print(valueNames[currentDatum]);
     lcd.setCursor(0,1);
     lcd.print(currentDatum);
     lcd.print(":");
     lcd.print(sensorData[currentDatum]);
   }
   MenuItem* maintain() {
      //Serial.println("maintain");
     if( millis() - lastPoll > pollInterval ) {
       //poll sensors again;
     }
     if( up.changed && up.pressed ) {
       currentDatum = ( currentDatum < 66 ? currentDatum + 1 : 0 );
       refresh=true;
     }
     if( dn.changed && dn.pressed ) {
       currentDatum = ( currentDatum > 0 ? currentDatum - 1 : 66 );
       refresh=true;
     }

     if( back.changed && back.pressed ) {
       digitalWrite(12, HIGH); //troubleshooting LED
       return parent; //this is where things go bad
     }
     else {
       if(refresh){
         display();
         refresh=false;
       }
       return this;
     }
   }
};

/*******************************************************************************************************
/  CLASS SelectScreen
/  base class for all of the various menu screens so that the currentItem pointer may point to any
/  of the sketch's menus.
/
/******************************************************************************************************/

class SelectScreen : public MenuItem {
 protected:
   int currentSelection;
   boolean refresh;
 public:
   MenuItem *options[1];
   SelectScreen( char desc[] ) {
     strcpy(descript, desc);
     currentSelection=0;
     refresh=true;
     parent = this;
   }
   void display() {
     lcd.clear();
     lcd.print(options[currentSelection]->descript);
   }
   MenuItem * maintain() {
     if( enter.changed && enter.pressed ) {
       return options[currentSelection];
     }
     else return this;
   }
};


MenuItem *currentItem;
SelectScreen mainMenu("Main Menu");

SensorScreen sensorScreen("View sensor data", &mainMenu);

void setup() {
 mainMenu.options[0] = &sensorScreen ;
 Serial.begin(9600);
 lcd.clear();
 lcd.print("hello!");
 currentItem = &mainMenu;
 delay(1000);
 currentItem->display();
 pinMode(12, OUTPUT);

}

void loop(){
 up.refresh();
 dn.refresh();
 back.refresh();
 enter.refresh();
 
 currentItem = currentItem->maintain();  
}

ajb

I added another derived class ModeScreen similar to DataScreen, and ModeScreen.maintain() does exactly what I want it to!  DataScreen.maintain() still fails.  I changed the way the value gets returned (changed "return parent;" to "return parent->display(); to ensure the new screen is displayed properly) as well.

Code: [Select]
/*******************************************************************************************************
/  CLASS MenuItem
/  base class for all of the various menu screens so that the currentItem pointer may point to any
/  of the sketch's menus.
/
/******************************************************************************************************/

class MenuItem {
 public:
   char descript[16];
   MenuItem* parent;
   virtual MenuItem* display(){};
   virtual MenuItem* maintain(){}; //do any required maintenance, ie-poll sensors to update screen data
};

/*******************************************************************************************************
/  CLASS DataScreen
/  for displaying sensor data
/
/******************************************************************************************************/

class SensorScreen : public MenuItem {
 protected:
   unsigned int currentDatum; //current datum that should be displayed
   unsigned long lastPoll; //time of last sensor data update
   boolean refresh; // flag indicates if screen needs to be refreshed
 
 public:
   SensorScreen(char desc[], MenuItem *par ) {
     parent = par;
     strcpy(descript, desc);
     currentDatum=0;
     lastPoll=0;
     refresh=true;
   }
   MenuItem * display() {
      Serial.println("display");
     lcd.clear();
     lcd.home();
     lcd.print(valueNames[currentDatum]);
     lcd.setCursor(0,1);
     lcd.print(currentDatum);
     lcd.print(":");
     lcd.print(sensorData[currentDatum]);
     return this;
   }
   MenuItem* maintain() {
      //Serial.println("maintain");
     if( millis() - lastPoll > pollInterval ) {
       //poll sensors again;
     }
     if( up.changed && up.pressed ) {
       currentDatum = ( currentDatum < 66 ? currentDatum + 1 : 0 );
       refresh=true;
     }
     if( dn.changed && dn.pressed ) {
       currentDatum = ( currentDatum > 0 ? currentDatum - 1 : 66 );
       refresh=true;
     }

     if( back.changed && back.pressed ) {
       digitalWrite(12, HIGH); //troubleshooting LED
       return parent->display(); //this is where things go bad
     }
     else {
       if(refresh){
         display();
         refresh=false;
       }
       return this;
     }
   }
};

/*******************************************************************************************************
/  CLASS SelectScreen
/  base class for all of the various menu screens so that the currentItem pointer may point to any
/  of the sketch's menus.
/
/******************************************************************************************************/

class SelectScreen : public MenuItem {
 protected:
   int currentSelection;
   boolean refresh;
 public:
   MenuItem *options[2];
   SelectScreen( char desc[] ) {
     strcpy(descript, desc);
     currentSelection=0;
     refresh=true;
     parent = this;
   }
   MenuItem * display() {
     lcd.clear();
     lcd.print(options[currentSelection]->descript);
     return this;
   }
   MenuItem * maintain() {
     if( up.changed && up.pressed ) {
       currentSelection = ( currentSelection < 1 ? currentSelection + 1 : 0 );
       refresh=true;
     }
     if( dn.changed && dn.pressed ) {
       currentSelection = ( currentSelection > 0 ? currentSelection - 1 : 1 );
       refresh=true;
     }
     if( enter.changed && enter.pressed ) {
       return options[currentSelection]->display();
     }
     else {
       if(refresh){
         display();
         refresh=false;
       }
       return this;
     }
   }
};


/*******************************************************************************************************
/  CLASS ModeScreen
/  issue mode to ECU
/
/******************************************************************************************************/

class ModeScreen : public MenuItem {
 protected:
   int currentSelection;
   boolean refresh;
   unsigned int modes;
     
     
 public:
   ModeScreen( char desc[], MenuItem *par ) {
     strcpy(descript, desc);
     currentSelection=0;
     refresh=true;
     parent = par;
     modes=9;

   }
   MenuItem * display() {
     lcd.clear();
     lcd.print(modeDesc[currentSelection][0]);
     lcd.setCursor(0,1);
     lcd.print(modeDesc[currentSelection][1]);
     return this;
   }
   MenuItem * maintain() {
     if( up.changed && up.pressed ) {
       currentSelection = ( currentSelection < 8 ? currentSelection + 1 : 0 );
       refresh=true;
     }
     if( dn.changed && dn.pressed ) {
       currentSelection = ( currentSelection > 0 ? currentSelection - 1 : 8 );
       refresh=true;
     }

     if( back.changed && back.pressed ) {
       return parent->display(); //And this one works fine?!?!
     }
     else {
       if(refresh){
         display();
         refresh=false;
       }
       return this;
     }
   }
};

MenuItem *currentItem;
SelectScreen mainMenu("Main Menu");

SensorScreen sensorScreen("View sensor data", &mainMenu);
ModeScreen modeScreen("Issue Mode", &mainMenu);

void setup() {
 mainMenu.options[0] = &sensorScreen;
 mainMenu.options[1] = &modeScreen;
 Serial.begin(9600);
 lcd.clear();
 lcd.print("hello!");
 currentItem = &mainMenu;
 delay(1000);
 currentItem->display();
 pinMode(12, OUTPUT);

}

void loop(){
 up.refresh();
 dn.refresh();
 back.refresh();
 enter.refresh();
 
 currentItem = currentItem->maintain();  
}

ajb

#2
Jun 12, 2009, 10:03 pm Last Edit: Jun 12, 2009, 10:04 pm by ajb Reason: 1
Problem resolved, although I don't understand why.

I moved the parent pointer assignment further down in the constructor for the SensorScreen class, and now it works  :confused

Basically changed this:

Code: [Select]
   SensorScreen(char desc[], MenuItem *par ) {
     parent = par;
     strcpy(descript, desc);
     currentDatum=0;
     lastPoll=0;
     refresh=true;
   }

to this:
Code: [Select]
   SensorScreen(char desc[], MenuItem *par ) {
     strcpy(descript, desc);
     currentDatum=0;
     lastPoll=0;
     refresh=true;
     parent = par;
   }

RuggedCircuits

char descript[16] isn't long enough. You need an extra byte to store the terminating 0 at the end of the string "View sensor data"

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy