Translate

Friday 6 June 2014

Room Management System – Menu part 12


Today we need to add the outside lights into the menu and make some changes to the selectMenu() and the sub menu functions.

Lets start with adding the outside lights as menu point. Therefore we go int the declaration part of our sketch and jump into the “menu and user interface section”. First we find the constant where we declare the amount of menu points and change it to 22.

///////////////////Menu and user interface/////////////////////////////////
///////////////////////////////////////////////////////////////////////////

const byte btnMenu = 1;          //defining the menu button – moves through the menu
const byte btnSearch = 2;        //defining the search button – moves through values 
const byte btnSelect = 3;        //defining the select button – selects a menu or a value
const byte btnNone = 0;          //defining the non button pressed var
int act_key_in = 0;              //var holding the key related sensor reading

byte menuOption = 0;             //var to count current menu option
//>>>>>>>>>>>>The line below change from  menuOptions = 21 to  menuOptions = 22 <<<<<<<<<<<<<
const byte menuOptions = 22;     //available menu options
byte submenu = 0;                //var to count current submenu option
const byte submenus = 10;        //available submenu options
byte acSetup = 0;                //var to count current ac setup menu options
const byte acSetups = 4;         //available ac setup menu options

Than we move down just a bit and add the menu point to the menu_table:

//storing the main menu points in the program memory

prog_char menu_0[] PROGMEM = "Date/Time";

prog_char menu_1[] PROGMEM = "Sensitivity";

prog_char menu_2[] PROGMEM = "Room photo cut";

prog_char menu_3[] PROGMEM = "Room photo limit";

prog_char menu_4[] PROGMEM = "OS photo cut";

prog_char menu_5[] PROGMEM = "OS photo limit";

prog_char menu_6[] PROGMEM = "Room 1";

prog_char menu_7[] PROGMEM = "Room 2";

prog_char menu_8[] PROGMEM = "Room 3";

prog_char menu_9[] PROGMEM = "Room 4";

prog_char menu_10[] PROGMEM = "Room 5";

prog_char menu_11[] PROGMEM = "Room 6";

prog_char menu_12[] PROGMEM = "Room 7";

prog_char menu_13[] PROGMEM = "Room 8";

prog_char menu_14[] PROGMEM = "Room 9";

prog_char menu_15[] PROGMEM = "Room 10";

prog_char menu_16[] PROGMEM = "AC Setup";

prog_char menu_17[] PROGMEM = "AC 1";

prog_char menu_18[] PROGMEM = "AC 2";

prog_char menu_19[] PROGMEM = "AC 3";

prog_char menu_20[] PROGMEM = "AC 4";

//>>>>>>>>>>>>>ADD the line below<<<<<<<<<<<<<<

prog_char menu_21[] PROGMEM = "Outside Lights";

PROGMEM const char *menu_table[] = {

menu_0,

menu_1,

menu_2,

menu_3,

menu_4,

menu_5,

menu_6,

menu_7,

menu_8,

menu_9,

menu_10,

menu_11,

menu_12,

menu_13,

menu_14,

menu_15,

menu_16,

menu_17,

menu_18,

menu_19,

menu_20, //<<<<<<<<<<<<<don't forget to add ','

//>>>>>>>>>>>>>ADD the line below<<<<<<<<<<<<<<

menu_21

};

Now we move down to the selectMenu() function and change the if-statements going through the menu points into a switch – statement:

OK, lets move down into the selectMenu() function and change it to:

void selectMenu(){

//Serial.println("Select Menu");

byte button = 0; //var holding the button value

byte subButton = 0; //var holding the subButton value

menuOption = 1; //current menu option

lcd.clear(); //clear screen

//print the retrieved string on lcd

lcd.print(strcpy_P(buffer_M, (char*)pgm_read_word(&(menu_table[0]))));

while(menuOption <= menuOptions){ //loop through menu options

button = read_act_buttons(); //check if button was pressed

if(button == btnMenu){ //if it was btn menu

menuOption++; //add 1 to menu option

//>>>>>>>>>>>>>Modification starts here<<<<<<<<<<<<<

lcd.clear(); //clear screen

//retrieve and print the actual menu point

lcd.print(strcpy_P(buffer_M, (char*)pgm_read_word(&(menu_table[menuOption -1]))));

switch(menuOption){

case 2: //only menu point no option

case 3: //only menu point no option

case 5: //only menu point no option

break;

case 4: //menu point with option not used

case 6: //menu point with option not used

lcd.setCursor(0,1); //set cursor column 0, row 1

//retrieve and print "not used"

lcd.print(strcpy_P(buffer_M, (char*)pgm_read_word(&(msg_table[0]))));

break;

case 7: //menu point with option arrow right

case 8: //menu point with option arrow right

case 9: //menu point with option arrow right

case 10: //menu point with option arrow right

case 11: //menu point with option arrow right

case 12: //menu point with option arrow right

case 13: //menu point with option arrow right

case 14: //menu point with option arrow right

case 15: //menu point with option arrow right

case 16: //menu point with option arrow right

case 17: //menu point with option arrow right

case 18: //menu point with option arrow right

case 19: //menu point with option arrow right

case 20: //menu point with option arrow right

case 21: //menu point with option arrow right

case 22: //menu point with option arrow right

lcd.setCursor(15,0); //set cursor column 15, row 0

//retrieve and print "arrow right"

lcd.write(pgm_read_byte(&char_table[0]));

break;

}

//>>>>>>>>>>>>>>Modification ends here<<<<<<<<<<<<<<

}

if(button == btnSelect){ //if the select button is pressed

if(menuOption == 1){ //and menu option is 1

adjust_date_time(); //go to adjust date and time

return;

}

What have we done here. First we placed another lcd.print statement right after
menuOption++
again, we retrieve the menu option and print it but as counter we the variable menuOption – 1.
  • 1 again cause of counting issues, arrays and tables start counting at 0...
lcd.print(strcpy_P(buffer_M, (char*)pgm_read_word(&(menu_table[menuOption  1]))));

And now comes the actual trick – Thank you Reuben – I didn't know you can group the cases in a switch command so nice.

Instead of going through all the single menu points we look at the ones printing out the same kind of message.
Option 2, 3 and 5 are printing only the plain menu point
which we are doing with

lcd.print(strcpy_P(buffer_M, (char*)pgm_read_word(&(menu_table[menuOption  1]))));

This and the needed lcd.clear() command is done right after menuOption++.

In that case we do not need to add anything into the switch cases. We group them together and finish the group with a break command.
The options 4 and 6 are implemented but not used yet. This 2 options are printing a additional informative message, that this menu point is not used. Now we group menu point 4 and 6 together and add the additional code after the last case in the group and close the group again with a break command like:

case 4: //menu point with option not used

case 6: //menu point with option not used

lcd.setCursor(0,1); //set cursor column 0, row 1

//retrieve and print "not used"

lcd.print(strcpy_P(buffer_M, (char*)pgm_read_word(&(msg_table[0]))));

break;

The menu points 7 to 22 also have one thing in common, they all print a right arrow after the menu point to indicate an existing sub menu for this point. Here again we group them together and add the code needed to print the arrow after the last case in the group, ending the group again with a break command:

case 7: //menu point with option arrow right

case 8: //menu point with option arrow right

case 9: //menu point with option arrow right

case 10: //menu point with option arrow right

case 11: //menu point with option arrow right

case 12: //menu point with option arrow right

case 13: //menu point with option arrow right

case 14: //menu point with option arrow right

case 15: //menu point with option arrow right

case 16: //menu point with option arrow right

case 17: //menu point with option arrow right

case 18: //menu point with option arrow right

case 19: //menu point with option arrow right

case 20: //menu point with option arrow right

case 21: //menu point with option arrow right

case 22: //menu point with option arrow right

lcd.setCursor(15,0); //set cursor column 15, row 0

//retrieve and print "arrow right"

lcd.write(pgm_read_byte(&char_table[0]));

break;

Now adding another menu point is easy and if you have a closer look, I already sneaked the menu point (case 22:) for the outside lights in.

But first, why we are at it, we change our sub menus the same way. We jump down to the get_submenu() function and change it like this:

void get_submenu(byte room){

byte subButton = 0; //resetting the button var

submenu = 1; //submenu counter

lcd.clear(); //clear screen

//retrieving and printing first sub menu point

lcd.print(strcpy_P(buffer, (char*)pgm_read_word(&(submenu_table[0]))));

lcd.print(room + 1); //printing assigned room number

while(submenu <= submenus){ //loop through the sub menu points

subButton = read_act_buttons(); //checking for pressed buttons

if(subButton == btnMenu){ //if button Menu was pressed

submenu++; //add 1 - move to the next sub menu point

//>>>>>>>>>>>>>CHANGES start here<<<<<<<<<<<<<

lcd.clear(); //clear screen

//retrieve and print menu options

lcd.print(strcpy_P(buffer, (char*)pgm_read_word(&(submenu_table[submenu -1]))));

lcd.print(room + 1); //printing assigned room number

switch(submenu){

case 2: //only sub menu point no option

case 3: //only sub menu point no option

case 4: //only sub menu point no option

case 5: //only sub menu point no option

break;

case 6: //menu point + checking timer 2 options

case 7: //menu point + checking timer 2 options

if(timer_active[room][2] == 2){ //if set to 2

lcd.setCursor(0, 1); //set cursor to column 0, row 1

//retrieve and print not used

lcd.print(strcpy_P(buffer, (char*)pgm_read_word(&(msg_table[0])))); //print not used

}

break;

case 8: //menu point + checking timer 3 options

case 9: //menu point + checking timer 3 options

if(timer_active[room][3] == 2){ //if set to 2

lcd.setCursor(0, 1); //set cursor to column 0, row 1

//retrieve and print not used

lcd.print(strcpy_P(buffer, (char*)pgm_read_word(&(msg_table[0])))); //print not used

}

break;

}

//>>>>>>>>>>>>>>CHANGES end here<<<<<<<<<<<<<<

}

if(subButton == btnSelect){ //if we pressed btnSelect

if(submenu == 1){ //and submenu is 1

//call the function get_delay() to change the setting

delayTime[room] = get_delay(9, room, delayTime[room]);

return;

}

Next we do the ac_get_setup() function. Since we don't have any changes in the menu point handling, we can deal with it a little different. Again a big thank you to Reuben for explaining. Here we replace the whole function as follows:

void get_ac_setup(){
  byte subButton = 0;
  acSetup = 1;                        //submenu counter (AC Mode)
  lcd.clear();                        //clear screen
  //retrieving and printing first sub menu point
  lcd.print(strcpy_P(buffer, (char*)pgm_read_word(&(ac_setup_table[0]))));
  while(acSetup <= acSetups){        //loop through the submenu points
    subButton = read_act_buttons();  //checking for pressed buttons
    if(subButton == btnMenu){        //if button menu was pressed
      acSetup++;                     //add 1 -  move to the next point
      lcd.clear();
      //printing and retrieving the menu points
      lcd.print(strcpy_P(buffer, (char*)pgm_read_word(&(ac_setup_table[acSetup - 1]))));
    }
    if(subButton == btnSelect){      //if btn select was pressed
      switch(acSetup){               //going right through the options
      case 1:
        //call the function get_timer() to update settings
        ac_op_mode = get_Timer(26, ac_op_mode, 1, 4);
        return;
      case 2:
        //call the function get_timer() to update settings
        ac_set_temp = get_Timer(27, ac_set_temp, 18, 32);
        return;
      case 3:
        adj_seasons();
        return;
      case 4:
        //call the function get_timer() to update settings
        acSwitchDelay = get_Timer(28, acSwitchDelay, 1, 5);
        return;
      }
    }
  }
}

and the ac_get_sub() function, we change the same way as the get_ac_setup() function:


void get_ac_sub(byte room){
  byte subButton = 0;               //resetting the button var
  acSubOption = 1;                  //submenu counter
  lcd.clear();                      //clear screen
  //retrieving and printing first submenu point
  lcd.print(strcpy_P(buffer, (char*)pgm_read_word(&(ac_sub_table[0]))));
  lcd.print(room - 9);              //printing assigned room number
  while(acSubOption <= acSubOptions){ //loop through the submenu points
    subButton = read_act_buttons();   //checking for pressed buttons
    if(subButton == btnMenu){         //if btn menu was pressed
      acSubOption++;                  // add 1 to move to the next sub menu point
      lcd.clear();
      //retrieving and printing the menu points
      lcd.print(strcpy_P(buffer, (char*)pgm_read_word(&(ac_sub_table[acSubOption - 1]))));
      lcd.print(room - 9);       //printing assigned room number
    }
    if(subButton == btnSelect){
      switch(acSubOption){
        case 1:               //only sub menu point no option
          //call the function get_delay() to change the setting
          delayTime[room] = get_delay(37, room, delayTime[room]);
          return;
        case 2:               //only sub menu point no option
          //call the function get_offon to change setting
          ac_master_bypass[room - 10] = get_offon(38, room, ac_master_bypass[room - 10]);
          return;
        case 3:               //only sub menu point no option
          //call the function get_offon to change setting
          timer_active[room][0] = get_offon(10, room, timer_active[room][0]);
          return;
        case 4:               //only sub menu point no option
          //call the function get_setTime() to change timer 1
          get_setTime(room_timers[room][0][0], room_timers[room][0][1],
                      room_timers[room][0][2], room_timers[room][0][3], 
                      room, 0);
          return;
        case 5:               //only sub menu point no option
          //call the function get_offon() to change the setting
          timer_active[room][1] = get_offon(11, room, timer_active[room][1]);
          return;
        case 6:               //only sub menu point no option
          //call the function get_setTime() to change timer 2
          get_setTime(room_timers[room][1][0], room_timers[room][1][1],
                      room_timers[room][1][2], room_timers[room][1][3], 
                      room, 1);
          return;
        case 7:               //only sub menu point no option
          //call the function get_offon() to change the setting
          timer_active[room][2] = get_offon(12, room, timer_active[room][2]);
          return;
        case 8:               //only sub menu point no option
          //call function get_setTime() to change timer 3
          get_setTime(room_timers[room][2][0], room_timers[room][2][1],
                      room_timers[room][2][2], room_timers[room][2][3], 
                      room, 2);
          return;
        case 9:               //only sub menu point no option
          //call the function get_offon() to change the setting
          timer_active[room][3] = get_offon(25, room, timer_active[room][3]);
          return;
        case 10:               //only sub menu point no option
          //call function get_setTime() to change timer 3
          get_setTime(room_timers[room][3][0], room_timers[room][3][1],
                      room_timers[room][3][2], room_timers[room][3][3], 
                      room, 3);
          return;
      }
    }
  }
}

Before we start building the submenu for the outside lights, lets try and make a little space again in our memory. We jump up into the declaration part again and remove all the single delay declarations since we are storing them in an array after anyway:

//>>>>>>>>>>>>>Add the delayTime – array with the actual delay times<<<<<<<<<<<<<

int delayTime[16] = {120, 120, 120, 600, 180, 180,

180, 180, 120, 120, 120, 120,

120, 120, 240, 0};

//The block below can actually be deleted. However, I left it commented out just to have

//a better few of what is what in the array

/*delayTime[0] = 120; //int dBed1 = 120; //delay time in seconds for bedroom 1

delayTime[1] = 120; //int dBed2 = 120; //delay time in seconds for bedroom 2

delayTime[2] = 120; //int dBed3 = 120; //delay time in seconds for bedroom 3

delayTime[3] = 600; //int dLiving = 600; //delay time in seconds for living area

delayTime[4] = 180; //int dBath1 = 180; //delay time in seconds for bathroom 1

delayTime[5] = 180; //int dBath2 = 180; //delay time in seconds for bathroom 2

delayTime[6] = 180; //int dBath3 = 180; //delay time in seconds for bathroom 3

delayTime[7] = 180; //int dBath4 = 180; //delay time in seconds for bathroom 4

delayTime[8] = 120; //int dKitchen = 120; //delay time in seconds for kitchen

delayTime[9] = 120; //int dCorridor = 60; //delay time in seconds for corridor

delayTime[10] = 120; //int dAC1 = 120; //delay time in seconds for AC 1 (bed1)

delayTime[11] = 120; //int dAC2 = 120; //delay time in seconds for AC 2 (bed2)

delayTime[12] = 120; //int dAC3 = 120; //delay time in seconds for AC 3 (bed3)

delayTime[13] = 120; //int dAC4 = 120; //delay time in seconds for AC 4 (living)

delayTime[14] = 240; //int dMaster = 240; //delay time in seconds for Master Off

delayTime[15] = 0; //free*/

Now we have to go down to the “/all the other variables/” section and delete the delayTime array residing there.


///////////////////////////all the other variables/////////////////////////////

///////////////////////////////////////////////////////////////////////////////

//////////////Sensor and timer variables//////////////

//>>>>>>>>>>>>>>DELETE the statement below<<<<<<<<<<<<<

int delayTime[16] = {dBed1, dBed2, dBed3, dLiving, dBath1, dBath2, dBath3,

dBath4, dKitchen, dCorridor, dAC1, dAC2, dAC3, dAC4,

dMaster, 0};

//>>>>>>>>>>>>>>Delete ends here<<<<<<<<<<<<<<

byte temperatur1 = 0; //holding temperature for room 1

unsigned int lastRun[4] = {0}; //var to hold var when ac was last running

int sensorValue = 0; //holding the indicated sensor value of the photocell

byte photocellSwitch = 0; //holding the switch command after 


No comments:

Post a Comment