Translate

Sunday 1 June 2014

Room Management System – Add AC compressor protection and some other improvements


To stop the AC from switching on and off while having a jumping value in the temperature reading or a non corresponding timer adjustment in the ac - setup, we are adding a timer to lock the AC for 8 minutes after it last switched off. Before we start implementing that timer, we build a little timer function, since we have quite a few statements like:

currentTime = millis()/1000;

endTime = currentTime  presetTime;

if(endTime >= timeLimit){

doSomething;

}

To cut this scenario short, I packed it into a little function which we can place right after all the check_Light() and ac_read() functions:

boolean allTimer(unsigned long timeSet, unsigned int timeLimit){

currentTime = millis()/1000; //set the reference time

endTime = currentTime  timeSet; //calculate the reference time against a set time

if(endTime >= timeLimit){ //check if we are passed the limit

return true; //return true if yes

}

else{

return false;

}

}

This makes it easy for our function call.

if(allTimer(roomTimer[room], delayTime[room])) Do something;

That if – statement is only processed if the function returns true.

Now, did you place the function already? Good, than we have to change a few timer statements.
We jump right into the check_Light_P function:

unsigned long check_light_P(byte pir, byte prio, byte room, unsigned long light){

if(switchState[prio] == 0 && sensorValue <= photoCellCutOff) { //checking if S2 priority off was

//set bed 1

if(switchState[pir] == 1 && priorityStatus[room] == 0) { //check if the PIR in bed 1 was

//activated and no priority was set

//Serial.println("We switch in the lights in bedroom 1"); //Debug only

lightOutput[room] = light; //switching on the lights – binary

//000000000000000000000001

lightStatus[room] = 1; //setting the light status for bed 1

lightOutput[14] = 16384; //make sure the master relay

//stays on

lightStatus[14] = 1; //setting the master delay status

roomTimer[room] = millis()/1000; //setting the timer

}

else if(switchState[pir] == 0 && lightStatus[room] == 1) { //the PIR not activated but the

//lights are on

//>>>>>>>>>>>>>NOTE the change below<<<<<<<<<<<<<

if(allTimer(roomTimer[room], delayTime[room])){ // check allowed delay time

//Serial.println("Time is up switching off the lights"); //Debug only

lightOutput[room] = 0; //switching off the lights

lightStatus[room] = 0; //resetting the light status

roomTimer[room] = 0; //resetting the room timer

}

}

}

else if(switchState[prio] == 1 && lightStatus[room] == 1

&& switchState1Old != 1) { //if priority is activated and the

//lights are on

//Serial.println("Priority switch activated switching off the lights"); //Debug only

lightOutput[room] = 0; //switching off the lights

lightStatus[room] = 0; //resetting the light status

roomTimer[room] = 0; //resetting the room timer

priorityStatus[room] = 1; //setting the priority status bed 1

}

else if(switchState[prio] == 1 && lightStatus[room] == 0

&& switchState1Old != 1) { //if priority was activated and the

//lights are off

//Serial.println("Priority switch deactivated switching on the lights"); //Debug only

lightOutput[room] = light; //switching on the lights

lightStatus[room] = 1; //setting the light status

roomTimer[room] = millis()/1000; //setting the room timer

priorityStatus[room] = 0; //setting the priority for bed 1 back //to 0

}

switchState1Old = switchState[prio]; //passing on the switch state

return lightOutput[room];

}

Found the changes? Good, but don't worry to much, before I start storing some of the variables in the EEPROM memory, I post a full working code again. Now we move down to the next function, check_light_N and do the same there:

unsigned long check_light_N(byte pir, byte room, unsigned long light){

if(switchState[pir] == 1) { //checking S9 PIR of bathroom 1

//(room 5)

//Serial.println("We switch on the lights"); //Debug only

lightOutput[room] = light; //switching on the lights

lightStatus[room] = 1; //setting the light status

lightOutput[14] = 16384; //make sure the master relay

//stays on

lightStatus[14] = 1; //setting the master delay status

roomTimer[room] = millis()/1000; //setting the room timer

}

else if(switchState[pir] == 0 && lightStatus[room] == 1) { //if no PIR was activated and

//the lights are on

//>>>>>>>>>>>>>NOTE changes below<<<<<<<<<<<<<

if(allTimer(roomTimer[room], delayTime[room])){ //check if the time limit is reached

//Serial.println("We are switching off the lights"); //debug only

lightOutput[room] = 0; //switching off the lights

lightStatus[room] = 0; //resetting the light status

roomTimer[room] = 0; //resetting the room timer

}

}

return lightOutput[room];

}

Before we take care of the ac_read() function, we make a small d-tour and add a variable for the 8 minutes lock timer for the AC-units. There fore we go to the declaration part in to the “all the other variables section:

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

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

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

////Sensor and timer variables

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

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

dMaster, 0};

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

//>>>>>>>>>>>>Add the line below<<<<<<<<<<<<<<

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

from here we go down to the ac_read() function. We add the 8 minute lock timer and change the the general timers in to function calls in one go.
We are going to break it up a bit and start with AC operating mode 1:


unsigned long ac_read(byte readSw, byte room){

byte periode = get_ac_periode(); //function call to check time periode (season)

//check if a forced switch on is defined and the set temperature

if(ac_forced_on[room-10][0] != 99 && checkOnTime(room_timers[room][periode][0], room_timers[room][periode][1],

room_timers[room][periode][2], room_timers[room][periode][3]) == 1 &&

temperatur1 >= ac_set_temp){

priorityStatus[room] = 1; //set priority status to 1 if yes

}

else{

priorityStatus[room] = 0; //set priority status to 0 if no

}

if(ac_op_mode == 1){

if(switchState[readSw] == 1 && lightStatus[14] == 1){ //Checking if readswitches are activated //and the master relay is on AC room

//>>>>>>>>>>>>NOTE the Changes<<<<<<<<<<<<<

//we are packing the light (AC) output statements in a if -statement checking if the 8 minute lock

//time are passed

if(allTimer(lastRun[room - 10], 480)){ //check if 8 minute lock is passed since last run

lightOutput[room] = outputValues[room]; //providing the ability to

//switch on the AC

lightStatus[room] = 1; //setting the light (AC) status

roomTimer[room] = millis()/1000; //setting the timer

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

lastRun[room - 10] = 0; //setting the lock timer to 0

}

//We need to add the else statement to keep everything off if the lock time is not up yet

else{

lightOutput[room] = 0; //cancelling ability to switch on the

//AC

lightStatus[room] = 0; //resetting the light (AC) status

roomTimer[room] = 0;

}

}

else if(switchState[readSw] == 0 && lightStatus[14] == 1){ //if a door is opened and the master

//relay is on

if(allTimer(roomTimer[room], delayTime[room])){ //checking the time limit

lightOutput[room] = 0; //cancelling ability to switch on the

//AC

lightStatus[room] = 0; //resetting the light (AC) status

roomTimer[room] = 0; //resetting the timer

//And while we are switching off the units, we need to set the timer

//>>>>>>>>>>>>>Add the line below<<<<<<<<<<<<<

lastRun[room - 10] = millis()/1000;

}

}

return lightOutput[room];

}

else if(ac_op_mode == 2){

Please note, that operating mode 1 is not meant to switch on the AC. The room management systems relay is only replacing variable read switches and is meant to be connected according to your AC's installation instructions instead of the read switches on doors and windows. The read switches are connected to the corresponding input channel of the room management system. Sure, you can connect it to a contactor, cut the power supply and use the AC's auto restart ability to start your AC but this would put extra strain on the compressor and the AC's control system.

Lets move on to operating mode 2:
It is actually pretty simple, all statements where we switch on some lights, we need to a statement checking the 8 minute lock timer.
Everything looking like that:


if(checkOnTime(room_timers[room][periode][0], room_timers[room][periode][1], //checking if AC is allowed to run

room_timers[room][periode][2], room_timers[room][periode][3]) == 1){

lightOutput[room] = outputValues[room]; //switch on the AC

lightStatus[room] = 1; //setting the light (AC) status

roomTimer[room] = millis()/1000; //setting the timer

}

has to change to:

room_timers[room][periode][2], room_timers[room][periode][3]) == 1){

if(allTimer(lastRun[room - 10], 480)){ //check if 8 minute lock is passed since last run

lightOutput[room] = outputValues[room]; //switch on the AC

lightStatus[room] = 1; //setting the light (AC) status

roomTimer[room] = millis()/1000; //setting the timer

lastRun[room - 10] = 0;

}

else{

lightOutput[room] = 0; //keep it off

lightStatus[room] = 0;

}

The same goes for operating mode 3. To cut a long story short, here is the revised ac_read function with all the changes.

unsigned long ac_read(byte readSw, byte room){

byte periode = get_ac_periode(); //function call to check time periode (season)

//check if a forced switch on is defined and the set temperature

if(ac_forced_on[room-10][0] != 99 && checkOnTime(room_timers[room][periode][0], room_timers[room][periode][1],

room_timers[room][periode][2], room_timers[room][periode][3]) == 1 &&

temperatur1 >= ac_set_temp){

priorityStatus[room] = 1; //set priority status to 1 if yes

}

else{

priorityStatus[room] = 0; //set priority status to 0 if no

}

if(ac_op_mode == 1){

if(switchState[readSw] == 1 && lightStatus[14] == 1){ //Checking if readswitches are activated //and the master relay is on AC room 1 (bed1)

if(allTimer(lastRun[room - 10], 480)){ //check if 8 minute lock is passed since last run

lightOutput[room] = outputValues[room]; //providing the ability to

//switch on the AC

lightStatus[room] = 1; //setting the light (AC) status

roomTimer[room] = millis()/1000; //setting the timer

lastRun[room - 10] = 0;

}

else{

lightOutput[room] = 0; //cancelling ability to switch on the

//AC

lightStatus[room] = 0; //resetting the light (AC) status

roomTimer[room] = 0;

}

}

else if(switchState[readSw] == 0 && lightStatus[14] == 1){ //if a door is opened and the master

//relay is on

if(allTimer(roomTimer[room], delayTime[room])){ //checking the time limit

lightOutput[room] = 0; //cancelling ability to switch on the

//AC

lightStatus[room] = 0; //resetting the light (AC) status

roomTimer[room] = 0; //resetting the timer

lastRun[room - 10] = millis()/1000;

}

}

return lightOutput[room];

}

else if(ac_op_mode == 2){

if(ac_master_bypass[room - 10] == 0){ //check if the master bypass is set

if(switchState[readSw] == 1 && lightStatus[14] == 1){ //Checking if readswitches are activated

if(checkOnTime(room_timers[room][periode][0], room_timers[room][periode][1], //checking if AC is allowed to run

room_timers[room][periode][2], room_timers[room][periode][3]) == 1){

if(allTimer(lastRun[room - 10], 480)){ //check if 8 minute lock is passed since last run

lightOutput[room] = outputValues[room]; //switch on the AC

lightStatus[room] = 1; //setting the light (AC) status

roomTimer[room] = millis()/1000; //setting the timer

lastRun[room - 10] = 0;

}

else{

lightOutput[room] = 0; //keep it off

lightStatus[room] = 0;

}

}

}

else if(switchState[readSw] == 1 && priorityStatus[room] == 1){ //if doors and windows are closed and priority is set

if(currentHour >= ac_forced_on[room-10][0] && currentMinute >= ac_forced_on[room-10][1]){ //check if it's time to start

if(allTimer(lastRun[room - 10], 480)){ //check if 8 minute lock is passed since last run

lightOutput[room] = outputValues[room]; //switch on the AC

lightStatus[room] = 1; //setting the light (AC) status

roomTimer[room] = millis()/1000; //setting the timer

lastRun[room - 10] = 0;

}

else{

lightOutput[room] = 0; //keep it off

lightStatus[room] = 0;

}

}

else{

lightOutput[room] = 0; //keep it off

lightStatus[room] = 0; //setting the light (AC) status

roomTimer[room] = 0; //resetting the room timer

}

}

else if(switchState[readSw] == 0 && lightStatus[14] == 1){ //if a door is opened and the master

//relay is on

//delay time

if(allTimer(roomTimer[room], delayTime[room])){ //checking the time limit

lightOutput[room] = 0; //cancelling ability to switch on the

//AC

lightStatus[room] = 0; //resetting the light (AC) status

roomTimer[room] = 0; //resetting the timer

lastRun[room - 10] = millis()/1000;

}

}

}

else if(ac_master_bypass[room - 10] == 1){ //if master relay bypass is on

if(switchState[readSw] == 1){ //Checking if readswitches are activated

if(checkOnTime(room_timers[room][periode][0], room_timers[room][periode][1],

room_timers[room][periode][2], room_timers[room][periode][3]) == 1 &&

temperatur1 >= ac_set_temp){

if(allTimer(lastRun[room - 10], 480)){ //check if 8 minute lock is passed since last run

lightOutput[room] = outputValues[room]; //switch on the AC

lightStatus[room] = 1; //setting the light (AC) status

roomTimer[room] = millis()/1000; //setting the timer

lastRun[room - 10] = 0;

}

else{

lightOutput[room] = 0; //keep it off

lightStatus[room] = 0;

}

}

}

else if(switchState[readSw] == 0){ //if a door is opened and the master

//relay is on

//delay time

if(allTimer(roomTimer[room], delayTime[room])){ //checking the time limit

lightOutput[room] = 0; //cancelling ability to switch on the

//AC

lightStatus[room] = 0; //resetting the light (AC) status

roomTimer[room] = 0; //resetting the timer

lastRun[room - 10] = millis() / 1000;

}

}

}

return lightOutput[room];

}

else if(ac_op_mode == 3){ //AC operating mode 3

lightOutput[room] = 0; //Setting the lightOutput to 0

if(roomLight[room] == 1 && lastRun[room - 10] == 0){ //if a "on" command was given and the time since last run is more than 8 minutes

if(allTimer(roomTimer[room], acSwitchDelay)){

lightStatus[room] = 1; //set AC status to on

roomLight[room] = 0; //cancel "on" command

return 0; //return 0

}

else{

return outputValues[room]; //pulse the switch while "on" command active

}

}

if(roomLight[room] == 1 && lastRun[room - 10] != 0){ //if a "on" command was given and the time since last run is less than 8 minutes

/*currentTime = millis()/1000; //setting time for reference

endTime = currentTime - lastRun[room - 10]; //compare time with last switch off time

if(endTime >= 480) lastRun[room - 10] = 0; */ //if last switch off is 8 minutes ore longer

if(allTimer(lastRun[room - 10], 480)) lastRun[room - 10] = 0;

return 0; //return 0

}

if(roomLight[room] == 2){ //if an "off" command was given check delay timer

/*currentTime = millis()/1000; //set time for reference

endTime = currentTime - roomTimer[room]; //compare reference with set off delay

if(endTime >= delayTime[room]){ */ //check if it matches allowed difference

if(allTimer(roomTimer[room], delayTime[room])){

roomLight[room] = 3; //final command to switch off

return 0; //return 0

}

else{

roomLight[room] = 2; //keep the status

return 0; //return 0

}

}

if(roomLight[room] == 3){ //final off command given

if(allTimer(roomTimer[room], acSwitchDelay)){

lightStatus[room] = 0; //reset command status

roomLight[room] = 0; //reset AC status

lastRun[room - 10] = millis()/1000; //set switch off time

return 0; //return 0

}

else{

return outputValues[room]; //pulse the switch

}

}

if(ac_master_bypass[room-10] == 0){

if(lightStatus[room] == 0 && roomLight[room] == 0){

if(switchState[readSw] == 1 && lightStatus[14] == 1 &&

temperatur1 >= ac_set_temp && priorityStatus[room] == 0){

if(checkOnTime(room_timers[room][periode][0], room_timers[room][periode][1], //checking if AC is allowed to run

room_timers[room][periode][2], room_timers[room][periode][3]) == 1){

roomLight[room] = 1;

roomTimer[room] = millis()/1000;

return 0;

}

else {

return 0;

}

}

if(switchState[readSw] == 1 && priorityStatus[room] == 1 &&

temperatur1 >= ac_set_temp){

if(currentHour >= ac_forced_on[room-10][0] &&

currentMinute >= ac_forced_on[room-10][1]){ //check if it's time to start

roomLight[room] = 1;

roomTimer[room] = millis()/1000;

return 0;

}

else {

return 0;

}

}

}

if(lightStatus[room] == 1 && roomLight[room] == 0){

if(currentHour == room_timers[room][periode][2] && //if the allowed running limit is reached

currentMinute >= room_timers[room][periode][3]){

roomLight[room] = 2;

roomTimer[room] = millis()/1000;

return 0;

}

else{

return 0;

}

if(priorityStatus[room] == 1 && switchState[readSw] == 0){

roomLight[room] = 2;

roomTimer[room] = millis()/1000;

return 0;

}

else{

return 0;

}

if(priorityStatus[room] == 0){

if(switchState[readSw] == 0 | lightStatus[14] == 0){

roomLight[room] = 2;

roomTimer[room] = millis()/1000;

return 0;

}

else{

return 0;

}

}

}

}

}

return 0;

}

Since we got this straight, we need to do a few adjustments. Tu update the settings for the AC's, we are using most of the functions, we are also using for updating the light settings. Which is great, it saves us a lot of typing and memory space in the program. However, we need to do at least one ajustment. If we look at our arrays holding the variables for operating the light, they are nearly all proportional to the rooms array[0] corresponds with room 1, array[1] corresponds with room 2 and so on. Since we are using the same variables and arrays to control the AC units, we need to account for it in the functions. Let's have a quick look at the lightOutput[] array. As just explained, if we are referring to room 5, in the lightOutput[] array we need to look at place no 4 (lightOutput[4] to find the right value. Just remember, array counts start with 0 and not with 1 like we number the rooms. If I need to print a room number, since everything is linear, I can pass the corresponding array place to a function to find all needed variables and to print the room number on the screen, I just add 1 to the value and I have the actual room number and not the place holder in the array. But this works only until we come up to the AC's. The first AC unit in the first room is now placeholder 10 in the arrays and carrying on with the just mentioned system, that would make room 11 for the first AC unit...
Therefore, we need to change the part where we print the room number in the adjustment functions a little.

We currently are showing the assigned room no with lcd.print(room + 1). We need to change this to a little if-statement:

if(room >= 10 && room <= 13){ //calculating room for AC units

lcd.print(room - 9]; //AC room

}

else{

lcd.print(room + 1); //light room

The assigned place holders in the arrays for the AC-units are 10, 11, 12 and 13. We need to make sure, if 1 of this numbers is passed into the variable room, giving the right place holder in the arrays but we need to subtract 9 to get the right room no. Placeholder 10 stands for AC 1 in room 1 and so on.

Here the effected, updated functions:

  1. int get_delay(byte info, byte room, int reading){

//function to adjust the pir delay time and AC off - delay

int get_delay(byte info, byte room, int reading){

byte subButton = 0; //resetting the button value

byte value = reading / 60; //converting to Minutes

lcd.clear(); //clear screen

lcd.print(strcpy_P(buffer, (char*)pgm_read_word(&(msg_table[info])))); //print passed message

if(room >= 10 && room <= 13){ //calculating room for AC units

lcd.print(room - 9]; //AC room

}

else{

lcd.print(room + 1); //light room

}

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

if(value < 10) lcd.write(pgm_read_byte(&char_table[2])); //print 0

lcd.print(value); //print the passed value in minutes

lcd.setCursor(4, 1); //set cursor to second row, column 6

lcd.print("Min"); //just print Min.

while(subButton != btnSelect){ //wait for select btn

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

if(subButton == btnSearch){ //if btnSearch was pressed

if(value > 0 && value < 30){ //we are within allowed range

value++; //add 1 to value while btnSearch is pressed

}

if(value >= 30) value = 1; //if reaches upper limit set to lower limit

lcd.setCursor(0, 1); //setting the cursor

if(value < 10) lcd.write(pgm_read_byte(&char_table[2])); //print 0

lcd.print(value); //printing the updated value

}

}

return value*60;

}

  1. byte get_offon(byte info, byte room, byte reading){

//function to set a timer active / inactive

byte get_offon(byte info, byte room, byte reading){

byte subButton = 0; //resetting button value

lcd.clear(); //clear screen

lcd.print(strcpy_P(buffer, (char*)pgm_read_word(&(msg_table[info])))); //print passed info text

if(room >= 10 && room <= 13){ //calculating room for AC units

lcd.print(room - 9]; //AC room

}

else{

lcd.print(room + 1); //light room

}

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

if(reading != 1) lcd.print(strcpy_P(buffer, (char*)pgm_read_word(&(msg_table[7])))); //if value is not 1 timer is off

//print off

if(reading == 1) lcd.print(strcpy_P(buffer, (char*)pgm_read_word(&(msg_table[8])))); //if timer is 1, timer is active

//print active

while(subButton != btnSelect){ //waiting for btnSelect to be pressed

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

if(subButton == btnSearch){ //if btnSearch is pressed

if(reading == 1) reading = 0; //set to 0 if 1

else

if(reading == 0) reading = 1; //set to 1 if 0

}

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

if(reading != 1) lcd.print(strcpy_P(buffer, (char*)pgm_read_word(&(msg_table[7])))); //print off if not set to 1

if(reading == 1) lcd.print(strcpy_P(buffer, (char*)pgm_read_word(&(msg_table[8])))); //print Active if set to 1

}

return reading;

}

The last thing we take care of today is preparing the timers for the outside lighting to go also into the menu so we are able to adjust them to individual liking. I am sorry for making you jump around in the code but we need to start again at the top in the declaration part, “Timer and Sensitivity Settings” section. There we find the following two entries and delete them.


//>>>>>>>>>>>>>DELETE the following two variables<<<<<<<<<<<<<<

byte hourOutsideOff = 23; //var holding the time (full hours) in which the lights have

//to switch off

byte minuteOutsideOff = 30; //var holding the time (minutes) in which the lights

//have to switch off

Now e move down to the “/holiday and AC timer settings/” section:


byte timer_active[15][4] = { //<<<<<<<<<<<<< CHANGE timer_active[14][4] to timer_active[15][4]

{1, 1, 1, 0}, //room 0 timers 0 to 3

{1, 1, 0, 0}, //room 1 timers 0 to 3

{1, 1, 1, 1}, //room 2 timers 0 to 3

{0, 1, 0, 0}, //room 3 timers 0 to 3

{1, 1, 2, 2}, //room 4 timers 0 to 3

{1, 1, 2, 2}, //room 5 timers 0 to 3

{1, 1, 2, 2}, //room 6 timers 0 to 3

{1, 0, 2, 2}, //room 7 timers 0 to 3

{1, 1, 2, 2}, //room 8 timers 0 to 3

{0, 0, 2, 2}, //room 9 timers 0 to 3

{1, 1, 1, 0}, //room 0 AC timers 0 to 3

{1, 1, 1, 0}, //room 1 AC timers 0 to 3

{1, 1, 1, 0}, //room 2 AC timers 0 to 3

{1, 1, 2, 0}, //room 3 AC timers 0 to 3

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

{0, 1, 2, 2} //outside lighting

};

//Timer Settings room, timer, hour on, minute on, hour off, minute off

byte room_timers[15][4][4] = { //<<<<<<<<<<<<< CHANGE room_timers[14][4][4] to room_timers[15][4][4]

{

{5, 35, 6, 5}, //room 0 timer 0

{19, 35, 20, 15}, //room 0 timer 1

{21, 5, 21, 15}, //room 0 timer 2

{0, 0, 0, 0} //room 0 timer 3

},

{

{6, 30, 6, 50}, //room 2 timer 1

{19, 30, 20, 10}, //room 2 timer 2

{0, 0, 0, 0}, //room 2 timer 3

{0, 0, 0, 0} //room 2 timer 4

},

{

{5, 50, 6, 20}, //room 3 timer 1

{18, 10, 18, 25}, //room 3 timer 2

{19, 15, 19, 40}, //room 3 timer 3

{23, 20, 23, 35} //room 3 timer 4

},

{

{0, 0, 0, 0}, //room 4 timer 1

{17, 30, 23, 30}, //room 4 timer 2

{0, 0, 0, 0}, //room 4 timer 3

{0, 0, 0, 0} //room 4 timer 4

},

{

{5, 40, 5, 45}, //room 5 timer 1

{19, 55, 20, 10}, //room 5 timer 2

{0, 0, 0, 0}, //not used

{0, 0, 0, 0} //not used

},

{

{6, 35, 6, 45}, //room 6 timer 1

{19, 50, 20, 5}, //room 6 timer 2

{0, 0, 0, 0}, //not used

{0, 0, 0, 0} //not used

},

{

{6, 5, 6, 25}, //room 7 timer 1

{22, 50, 23, 15}, //room 7 timer 2

{0, 0, 0, 0}, //not used

{0, 0, 0, 0} //not used

},

{

{0, 0, 0, 0}, //room 8 timer 1

{22, 5, 22, 20}, //room 8 timer 2

{0, 0, 0, 0}, //not used

{0, 0, 0, 0} //not used

},

{

{5, 50, 6, 45}, //room 9 timer 1

{17, 45, 18, 30}, //room 9 timer 2

{0, 0, 0, 0}, //room 9 timer 3

{0, 0, 0, 0} //not used

},

{

{0, 0, 0, 0}, //room 10 timer 1

{0, 0, 0, 0}, //room 10 timer 2

{0, 0, 0, 0}, //not used

{0, 0, 0, 0} //not used

},

{

{19, 30, 22, 0}, //room 0 AC timer 1

{19, 30, 5, 30}, //room 0 AC timer 2

{19, 30, 22, 0}, //room 0 AC timer 3

{0, 0, 0, 0} //room 0 AC timer 4

},

{

{19, 30, 22, 0}, //room 1 AC timer 1

{19, 30, 5, 30}, //room 1 AC timer 2

{19, 30, 22, 0}, //room 1 AC timer 3

{0, 0, 0, 0} //room 1 AC timer 4

},

{

{21, 30, 1, 0}, //room 2 AC timer 1

{21, 30, 6, 0}, //room 2 AC timer 2

{21, 30, 1, 0}, //room 2 AC timer 3

{0, 0, 0, 0} //room 2 AC timer 4

},

{

{13, 0, 20, 0}, //room 3 AC timer 1

{5, 0, 23, 59}, //room 3 AC timer 2

{6, 0, 20, 0}, //room 3 AC timer 3

{0, 0, 0, 0} //room 3 AC timer 4

},

//>>>>>>>>>>>>>ADD from here<<<<<<<<<<<<<<

{

{0, 0, 0, 0}, //outside lights timer 1

{17, 0, 23, 59}, //outside lights timer 2

{0, 0, 0, 0}, //outside lights timer 3

{0, 0, 0, 0} //outside lights timer 4

}

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

};

We move down a little further into the “all the other variables” section and find:

unsigned int outputValues[14] = {1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192}

and change it to

unsigned int outputValues[15] = {1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,32768};

in the same section, just a little further down we delete:

//>>>>>>>>>>>>>>DELETE the line below<<<<<<<<<<<<<<<

unsigned int outsideOnTime = 0; //checking result if the time is within

//on or off time limits

Now we go down into the main loop into the “holiday lighting” section:

//////////////Holiday lighting/////////////////////////

if(switchState[20] == 1) { //check if the holiday switch

//is activated

lightOutput[14] = 0; //make sure the master relay is off

///////////////loop through all the lights///////////////

for(int x=0; x<16; x++){ //>>>>>>>>>>>>>CHANGE x<10; to x<16;

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

if(x >= 0 && x < 10 | x == 15){

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

if(timer_active[x][i] == 1 && currentHour >= room_timers[x][i][0] &&

currentHour <= (room_timers[x][i][2] + 1)){ //checking if we came passed

//the hour where the lights

//to be switched on

//checking the times

roomLight[x] = checkOnTime(room_timers[x][i][0], room_timers[x][i][1],

room_timers[x][i][2], room_timers[x][i][3]);

}

}

if(roomLight[x] == 1 && lightLevel[x] == 1){ //if with in the on time

lightOutput[x] = outputValues[x]; //switch on the lights

}

else {

lightOutput[x] = 0; //other keep them off

lightLevel[x] = 0;

}

} //>>>>>>>>>>>>>>ADD the closing braces for the new if – statement

}

We extend the loop to go through 16 “rooms” by changing x<10 to x<16 which we need cause the variables for the outside lighting are on place 15 in our arrays. Since the whole system was never planned to reach this dimensions when I started, there are a few thing which should be on a different place like the outside lights. They should be on place 10 to save a couple of lines of code. However, now it is as it is and maybe in the next complete revision I change it as it should be. For time being, we need to add the if – statement (if(x >= 0 && x < 10 | x == 15){) to exclude the places 10, 11, 12 and 13 (AC units) and place 14 (master relay) from the loop.

Since we have done this, we can delete the outside lighting part in the 'holiday lighting” section.

//>>>>>>>>>>>>>DELETE from here<<<<<<<<<<<<<<

////////Outside lights////////////////////

for(i=0; i<4; i++){

outsideOnTime = checkOnTime(17, 02, hourOutsideOff,

minuteOutsideOff); //function call to check time

if(outsideOnTime == 1 && lightLevel[15] == 1){

lightOutput[15] = 32768;

}

else {

lightOutput[15] = 0;

lightLevel[15] = 0;

}

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

#ifdef DA_DEBUG_holtimers

for(int x=0; x<16; x++){

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

Serial.print("Room ");

Serial.print(x);

Serial.print(": ");

Serial.println(timer_active[x][y]);

Serial.print("Room ");

Serial.print(x);

Serial.print(" Lights: ");

Serial.println(room1Light[x]);

}

}

#endif

}

else {

Right connecting to the holiday lighting part is the part where we check the lights in normal operational mode and the first part of it is again the outside lighting:

outsideOnTime = checkOnTime(17, 02, hourOutsideOff,

minuteOutsideOff); //function call to check time

if(outsideOnTime == 1 && lightLevel[15] == 1){

lightOutput[15] = 32768;

}

else {

lightOutput[15] = 0;

lightLevel[15] = 0;

}

//////////////////room lights//////////////////////////////

changes to:


////////Outside lights////////////////////

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

roomLight[15] = checkOnTime(room_timers[15][i][0], room_timers[15][i][1],

room_timers[15][i][2], room_timers[15][i][3]);

if(roomLight[15] == 1 && lightLevel[15] == 1){

lightOutput[15] = outputValues[15];

}

else {

lightOutput[15] = 0;

lightLevel[15] = 0;

}

}

//////////////////room lights//////////////////////////////

In the next post we implement the outside lights into the menu and we will have a look at saving around 100 lines of code in the selectMenu() function as suggested from Reuben.

No comments:

Post a Comment