Pages: [1]   Go Down
Author Topic: Program causing Arduino to reset?  (Read 435 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Full Member
***
Karma: 0
Posts: 112
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
/*******************************************************************************************************
/  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();  
}
« Last Edit: June 12, 2009, 12:45:23 pm by ajb » Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 112
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

0
Offline Offline
Full Member
***
Karma: 0
Posts: 112
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
   SensorScreen(char desc[], MenuItem *par ) {
      parent = par;
      strcpy(descript, desc);
      currentDatum=0;
      lastPoll=0;
      refresh=true;
    }
to this:
Code:
   SensorScreen(char desc[], MenuItem *par ) {
      strcpy(descript, desc);
      currentDatum=0;
      lastPoll=0;
      refresh=true;
      parent = par;
    }
« Last Edit: June 12, 2009, 03:04:19 pm by ajb » Logged

0
Offline Offline
Faraday Member
**
Karma: 16
Posts: 2855
ruggedcircuits.com
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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"
Logged

Pages: [1]   Go Up
Jump to: