Translate

Sunday 15 June 2014

Room Management system – The Menu part 15 – with EEPROM


All variables safe uploaded to the EEPROM? - Good, than we can modify the main program to use the variables from it. While compiling the sketch for the variable upload, you might have noticed how memory consuming the whole thing is. To deal with the heavy impact on RAM usage, we write the arrays containing the addresses for the variables stored in the EEPROM in to the program memory.

Lets start with bringing the address declarations to the main program. In our room management sketch, right under “Declaring the variables”, we start a new section and name it “/////////////EEPROM storage//////////////”. Than we copy all the variables / arrays, holding the eeprom addresses right under the new section:

/////////////////////Declaring the Variables/////////////////

/////////////EEPROM Storage//////////////

int eepromValue = 0;

const byte EEPROM_ID = 0x99;

const int ID_ADDR = 0;

const byte Sensitivity_ADDR = 1; //2 byte value

const byte photoCellCutOff_ADDR = 3; //2 byte value

const byte photoOutsideOff_ADDR = 5; //2 byte value

const int startDelay_ADDR = 374; //1 byte value

const int acSwitchDelay_ADDR = 375; //1 byte value

const int ac_op_mode_ADDR = 376; //1 byte value

const int ac_set_temp_ADDR = 377; //1 byte value

const byte delayTime_ADDR[15] PROGMEM = {7, 9, 11, 13, 15, 17,

19, 21, 23, 25, 27, 29,

31, 33, 35};

const byte timer_active_ADDR[16][4] PROGMEM = {

{37, 38, 39, 40},

{41, 42, 43, 44},

{45, 46, 47, 48},

{49, 50, 51, 52},

{53, 54, 55, 56},

{57, 58, 59, 60},

{61, 62, 63, 64},

{65, 66, 67, 68},

{69, 70, 71, 72},

{73, 74, 75, 76},

{77, 78, 79, 80},

{81, 82, 83, 84},

{85, 86, 87, 88},

{89, 90, 91, 92},

{93, 94, 95, 96},

{97, 98, 99, 100}

};

const int room_timers_ADDR[16][4][4] PROGMEM = {

{

{102, 103, 104, 105},

{106, 107, 108, 109},

{110, 111, 112, 113},

{114, 115, 116, 117}

},

{

{118, 119, 120, 121},

{122, 123, 124, 125},

{126, 127, 128, 129},

{130, 131, 132, 133}

},

{

{134, 135, 136, 137},

{138, 139, 140, 141},

{142, 143, 144, 145},

{146, 147, 148, 149}

},

{

{150, 151, 152, 153},

{154, 155, 156, 157},

{158, 159, 160, 161},

{162, 163, 164, 165}

},

{

{166, 167, 168, 169},

{170, 171, 172, 173},

{174, 175, 176, 177},

{178, 179, 180, 181}

},

{

{182, 183, 184, 185},

{186, 187, 188, 189},

{190, 191, 192, 193},

{194, 195, 196, 197}

},

{

{198, 199, 200, 201},

{202, 203, 204, 205},

{206, 207, 208, 209},

{210, 211, 212, 213}

},

{

{214, 215, 216, 217},

{218, 219, 220, 221},

{222, 223, 224, 225},

{226, 227, 228, 229}

},

{

{230, 231, 232, 233},

{234, 235, 236, 237},

{238, 239, 240, 241},

{242, 243, 244, 245}

},

{

{246, 247, 248, 249},

{250, 251, 252, 253},

{254, 255, 256, 257},

{258, 259, 260, 261}

},

{

{262, 263, 264, 265},

{266, 267, 268, 269},

{270, 271, 272, 273},

{274, 275, 276, 277}

},

{

{278, 279, 280, 281},

{282, 283, 284, 285},

{286, 287, 288, 289},

{290, 291, 292, 293}

},

{

{294, 295, 296, 297},

{298, 299, 300, 301},

{302, 303, 304, 305},

{306, 307, 308, 309}

},

{

{310, 311, 312, 313},

{314, 315, 316, 317},

{318, 319, 320, 321},

{322, 323, 324, 325}

},

{

{326, 327, 328, 329},

{330, 331, 332, 333},

{334, 335, 336, 337},

{338, 339, 340, 341}

},

{

{342, 343, 344, 345},

{346, 347, 348, 349},

{350, 351, 352, 353},

{354, 355, 356, 357}

}

};

const int ac_forced_on_ADDR[4][2] PROGMEM = {

{358, 359},

{360, 361},

{363, 363},

{364, 365}

};

const int ac_periode_ADDR[4][2] PROGMEM = {

{366, 367},

{368, 369},

{370, 371},

{372, 373}

};

const int ac_master_bypass_ADDR[4] PROGMEM = {378, 379, 380, 381};

///////////Timer and Sensitivity Settings to be changed to individual needs////////////////

You might have noticed right away that I have changed something already. To store the addresses into the program memory I added PROGMEM to the array declarations:

const byte delayTime_ADDR[15] = {7, 9,
becomes
const byte delayTime_ADDR[15] PROGMEM = {7, 9,

and

const byte timer_active_ADDR[16][4] = {
becomes
const byte timer_active_ADDR[16][4] PROGMEM = {

As simple is that to store a multidimensional array into the program memory and keep the structure of the originating array. We change all the arrays containing EEPROM addresses like described on the two examples.
Now we have to move down in the declaration part into the menu and user interface section. Right above the last table being saved to the program memory before the setup loop we add a new section “//////////////Error handling/////////////”. And at the last table, where we have already a couple of error messages we add a couple of things.

ac_sub_8,

ac_sub_9

};

////////////////Error Handling/////////////

prog_char error_0[] PROGMEM = "RTC ERR";

prog_char error_1[] PROGMEM = "RTC Read ERR";

//>>>>>>>>>>>>>>ADDITION starts here<<<<<<<<<<<<<

prog_char error_2[] PROGMEM = "EEPROM empty!";

prog_char error_3[] PROGMEM = "EEP write error";

//>>>>>>>>>>>>>>Addition ends here<<<<<<<<<<<<<<

PROGMEM const char *error_table[] = {

error_0,

error_1,

//>>>>>>>>>>>>>ADDITION starts here<<<<<<<<<<<<<

error_2,

error_3

//>>>>>>>>>>>>>Addition ends here<<<<<<<<<<<<<<

};

void setup() {

//////////////Start Serial for Debugging/////////////////////

#ifdef DA_DEBUG_serial

Serial.begin(9600);

#endif

lcd.begin(16, 2);

Now we move down to the setup loop and add:

void setup() {

//////////////Start Serial for Debugging/////////////////////

#ifdef DA_DEBUG_serial

Serial.begin(9600);

#endif

lcd.begin(16, 2);

//>>>>>>>>>>>>>ADDITION starts here<<<<<<<<<<<<<

lcd.clear();

eepromValue = Mem_readByte(ID_ADDR); //check if the eeprom holds valid data

if(eepromValue != EEPROM_ID){

get_error(2, 0); //if not, display an error

delay(5000);

//load default var values //work with default variables declared

//in the declaration section above

}

else{ //read the values from the eeprom

sensitivity = Mem_readInt(Sensitivity_ADDR); //sensitivity

photoCellCutOff = Mem_readInt(photoCellCutOff_ADDR); //photocell cut off value for rooms

photoOutsideOff = Mem_readInt(photoOutsideOff_ADDR); //photocell cut off value for outside

for(int i=0; i<15; i++){ //PIR and AC cut off delay times

delayTime[i] = Mem_readInt(pgm_read_byte(&(delayTime_ADDR[i])));

}

for(int x=0; x<16; x++){ //holiday lighting and ac timers active settings

for(int y=0; y<4; y++){

timer_active[x][y] = Mem_readByte(pgm_read_byte(&(timer_active_ADDR[x][y])));

}

}

for(int x=0; x<16; x++){ //holiday lighting and ac timer settings

for(int y=0; y<4; y++){

for(int z=0; z<4; z++){

room_timers[x][y][z] = Mem_readByte(pgm_read_byte(&(room_timers_ADDR[x][y][z])));

}

}

}

for(int x=0; x<4; x++){ //ac forced on setting

for(int y=0; y<2; y++){

ac_forced_on[x][y] = Mem_readByte(pgm_read_byte(&(ac_forced_on_ADDR[x][y])));

}

}

for(int x=0; x<4; x++){ //seasonal settings for ac use

for(int y=0; y<2; y++){

ac_periode[x][y] = Mem_readByte(pgm_read_byte(&(ac_periode_ADDR[x][y])));

}

}

startDelay = Mem_readByte(startDelay_ADDR); //ac start delay (compressor protection

acSwitchDelay = Mem_readByte(acSwitchDelay_ADDR); //ac switch time for op mode 3

ac_op_mode = Mem_readByte(ac_op_mode_ADDR); //ac mode

ac_set_temp = Mem_readByte(ac_set_temp_ADDR); //ac temperature setting

for(int i=0; i<4; i++){ //ac master bypass

ac_master_bypass[i] = Mem_readByte(pgm_read_byte(&(ac_master_bypass_ADDR[i])));

}

}

//>>>>>>>>>>>>>ADDITION ends here<<<<<<<<<<<<<

//printing initialisation message

lcd.clear();

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

delay(1000);

lcd.setCursor(0, 1);

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

delay(2000);

//////////////////defining pin modes////////////////////

pinMode(doorMonitor, OUTPUT); //setting the LED pin to output

If you remember from the last post the system to write the values to the eeprom having the same array structure for the values and the address.
To get the right value from the eeprom, we only need to take the corresponding address array with the corresponding counter values and we read back the values. Looking at the delayTime() array, we take the first counter setting of our for loop which would be delayTime[0] and if we look it up from the default declaration part, the first value is 120. Now we overwrite this value with the value we read from the eeprom.


for(int i=0; i<15; i++){ //PIR and AC cut off delay times

delayTime[i] = Mem_readInt(pgm_read_byte(&(delayTime_ADDR[i])));

}


We call the function Mem_readInt(address). Since we have stored all the addresses again in the program memory, we need to retrieve them form there with “pgm_read_byte(&(table_name or array_name)). We stored the arrays in the program memory keeping the whole structure, so the array name is just the same as we declared it and in this example delayTime_ADDR[0], which gives us the address “7”. If we now go back to the sketch we wrote to upload the eeprom values, and check the values for delayTime_ADDR[0] and delayTime[0], we recall what value the default delayTime[0] value will be overwritten with and used by the program. In our case it is 300. It's not difficult. The only thing you have to take care of is that the array counters for the values match with the array counters of the address arrays.

To make it work, we copy the functions we wrote in the upload sketch to the bottom of the Room Management sketch, right on the end of everything.




No comments:

Post a Comment