Translate

Showing posts with label correction. Show all posts
Showing posts with label correction. Show all posts

Sunday, 22 June 2014

Room Management System – Some final bug fixes and improvements


Being so focused on saving memory space and optimizing the code so everything fits on a Atmega 328 chip or a Arduino Uno board, I missed something. I just realized, that with the current code, the priority switches which we are using to stop the light from coming on in bed room while asleep are working but we have again the effect, that the light keeps on switching on and off while the button is pressed for a longer periode of time. But we want the light only to switch once per button press no matter for how long the button is pressed.
Let's go down in the declaration part of the sketch and find the section “/PIR and Room switch related var's/”

//////////////////////PIR and Room switch related var's/////////////////////////////////

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

byte mainOff = 1; //variable for master relay control

unsigned int offTime = 0; //var needed to calculate delay for master off

byte masterSwitchStateOld = 0; //var holding the previous door switch state

byte switchState[25] = {0}; //array holding the state of each switch

unsigned long lightOutput[17] = {0}; //array holding a integer which converted to binary

//will trigger the relay to switch in our output code

byte lightStatus[17] = {0}; //array holding the switch status of each room on/off

byte priorityStatus[17] = {0}; //array holding the priority status of each room on/off

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

byte switchState1Old = 0; //var to check if the priority switch state has changed

byte switchState3Old = 0; //var to check if the priority switch state has changed

byte switchState5Old = 0; //var to check if the priority switch state has changed

byte switchState7Old = 0; //var to check if the priority switch state has changed

//>>>>>>>>>>>>>DELETE ends here<<<<<<<<<<<<<<

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

byte switchStateOld[4] = {0}; //var to check if the priority switch state has changed

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

///////////////////////////Output/////////////////////////////////////////////

The 4 variables which where checking if the switchState of the priority switches in the 3 bedrooms and the living room have changed don't work any more since we have banned this part of the code into a function and the function is not handling only 1 room, its handling all four rooms having a priority switch. Since it's the first four rooms it's easy, we just replace the the for variables with a 4 spaces containing array. To make it work we have to go down to our function check_light_P() and where ever we find a variable called “switchState1Old”, we replace it with switchStateOld[room]. Below you find the already updated 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

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

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 relay 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

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

&& switchStateOld[room] != 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

&& switchStateOld[room] != 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

}

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

return lightOutput[room];

}

Here comes a small upgrade. In our lcd display, in row 0 , where we display the status of the shift register, displaying 1 or 0 to show if a output is activated or not I would like to keep a 16 digit display, so I can see straight away which room should be on or off. Currently we are loosing 1 digit every time the outside lighting goes off and if we are in the holiday timer option at some points of the day the display in row 0 isn't showing anything and that is because binary numbers drop there upper most digits soon as they turn 0.
The number 4 in a 16 bit binary would be:
0000000000000100
But the display would only show
100
since all the upper most digits turning to 0 are dropped.

This we do with help of a little function, which we place at the end of the main loop. Since we are currently displaying the output status in the first row and date and time in the second row of our display but having a bit more information to show, I made a little routine to change the display in the second row a little to show date and time in an interval exchanging with temperature and photocell reading.

We start again in the declaration part and there we go into the “all the other variables” section.

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

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

////Sensor and timer variables

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

unsigned long 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

//checking sensor readings (0, 1)

byte photocellSwitchOld = 0; //switch command from the previous pass

byte lightLevel[17] ={0}; //array holding the switch state

//checking timer and photocell (0, 1)

byte roomLight[15] = {0}; //array holding the switch on command in holiday lighting

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

unsigned int roomTimer[17] = {0}; //array holding the time when the PIR was last activated

unsigned int currentTime = 0; //var to hold a reference time to calculate the up time

//against the preprogrammed delay time

unsigned int endTime = 0; //var to hold a temp result to calculate the up time

//against the preprogrammed delay time

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

unsigned int displayTimeSet = millis()/1000; //variable needed for display exchange

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

//////////////////////PIR and Room switch related var's/////////////////////////////////

from here we go down into the main loop in to the section where it says “processing the input”

//////////////////processing the input/////////////////////

if(RTC.read(tm)) { //Reading the clock

currentHour = tm.Hour; //passing the time into a var

currentMinute = tm.Minute; //passing the time into a var

currentDay = tm.Wday - 1; //passing Weekday

//(Mon - Sun e.g. 1-7) into var

currentDoM = tm.Day; //passing day in to var (1-31)

currentMonth = tm.Month; //passing month into var (1-12)

currentYear = tmYearToCalendar(tm.Year); //passing year to var

//>>>>>>>>>>>>>DELETE the part marked<<<<<<<<<<<<<<

lcd.setCursor(0, 0); //set the cursor to line 1 pos 1

lcd.print(" "); //print 15 blanks to delete all

//prior statements

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

lcd.print(strcpy_P(buffer, (char*)pgm_read_word(&(weekday_table[currentDay]))));

lcd.print(" ");

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

lcd.print(currentDoM);

lcd.write(pgm_read_byte(&char_table[4])); //print dot

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

lcd.print(currentMonth);

lcd.print(" ");

if(currentHour < 10) lcd.write(pgm_read_byte(&char_table[2]));

//if the hour is less than 10

//we print a 0 to keep 2 digits

lcd.print(currentHour); //print current time (hour)

lcd.write(pgm_read_byte(&char_table[3])); //print separator

if(currentMinute < 10) lcd.write(pgm_read_byte(&char_table[2]));

//if the minute is less than

//10 print 0 to keep 2 digits

lcd.print(currentMinute); //print current time (minutes)

//>>>>>>>>>>>>>DELETE ends here<<<<<<<<<<<<<

}

else {

get_error(0, 1);

}

photocellSwitch = getSensorValue(sensorValue, photoCellCutOff,

photoCellCutOn, photocellSwitchOld);

photocellSwitchOld = photocellSwitch;

//allowing the lights to switch on between 17:00 and 23:00 h

if(photocellSwitch == 1 && currentHour >= 17 && currentHour <= 23) {

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

lightLevel[i] = 1;

}

lightLevel[15] = 1;

There fore we add:

if(RTC.read(tm)) { //Reading the clock

currentHour = tm.Hour; //passing the time into a var

currentMinute = tm.Minute; //passing the time into a var

currentDay = tm.Wday - 1; //passing Weekday

//(Mon - Sun e.g. 1-7) into var

currentDoM = tm.Day; //passing day in to var (1-31)

currentMonth = tm.Month; //passing month into var (1-12)

currentYear = tmYearToCalendar(tm.Year); //passing year to var

}

else {

get_error(0, 1);

}

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

endTime = (millis()/1000)  displayTimeSet; //set time reference

if(endTime <= 15) displayDateTime(); //display time for 15 seconds

if(endTime > (15) && endTime <= (30)) displayTemp(); //display temp and photocell reading for 15 sec.

if(endTime > 30) displayTimeSet = millis()/1000; //reset the timer

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

photocellSwitch = getSensorValue(sensorValue, photoCellCutOff,

photoCellCutOn, photocellSwitchOld);

photocellSwitchOld = photocellSwitch;

//allowing the lights to switch on between 17:00 and 23:00 h

if(photocellSwitch == 1 && currentHour >= 17 && currentHour <= 23) {

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

lightLevel[i] = 1;

}

lightLevel[15] = 1;

now we go down to the end of the main loop:

outputL = 65535; //setting the output

//binary 1111111111111111

}

lcd.setCursor(0,0);

//>>>>>>>>>>>>>REPLACE the line below<<<<<<<<<<<<<<

lcd.print(outputL, BIN);

//>>>>>>>>>>>>>>>>>>>WITH this line <<<<<<<<<<<<<<<<<<<

printBinary16(outputL);

#ifdef DA_DEBUG_out

Serial.print("Output value: ");

Serial.print(outputL);

Serial.print(" ");

Serial.println(outputL, BIN);

#endif

digitalWrite(latchPinOut, LOW); //setting the latch pin to low to

//be able to send the data

shiftOut(dataPinOut, clockPinOut, MSBFIRST, (outputL >> 8)); //sending the date for the

//second shift register

shiftOut(dataPinOut, clockPinOut, MSBFIRST, outputL); //sending the data for the

//first shift register

digitalWrite(latchPinOut, HIGH); //setting the latch pin back to

//high to finish the data transmission

outputL = 0; //setting the var holding the output

//number back to 0

delay(sensitivity); //delay to adjust how responsive the

//system will react

}

Time to build the three functions needed right at the end of the main loop:
The first function is the one keeping a 16 bit (digit) display. In praxis we can mark above the display what every digit is for. In our case from right to left it would be

bed room 1
bed room 2
bed room 3
Living
Bath room 1
Bath room 2
Bath room 3
Bath room 4
Kitchen
Corridor
AC bed 1
AC bed 2
AC bed 3
AC bed 4
Master relay
Outside lights

Having it setup this way might help in a later state trouble shooting since we no if a corresponding relay should be activated or not. If the corresponding digit indicates a 1 and a light does not come on you got to check if the relay itself is working and if it does than the problem is some where in the external part of the system. If the corresponding digit shows 0 while you jumping in front of the indicating PIR, than you might have to have a look at the PIR first and if you are sure that the PIR is working you have a more serious electronic problem.

//function to keep a 16 digit (bit) display

void printBinary16(unsigned int iIn) {

// 0b1234567812345678

for (unsigned int mask = 0b1000000000000000; mask; mask >>= 1) { //create a bit mask

if (mask & iIn) { //add the incoming data

lcd.print('1'); //print if active

}

else {

lcd.print('0'); //if empty, still print the 0

}

}

}

Next is the function to display the time and date. If you deleted the part of code in the main loop which was displaying it you are fine. If you have been lazy like I was and just copied the part into a function, please delete the firs three lines:

  lcd.setCursor(0, 0);            //set the cursor to line 1 pos
  lcd.print("               ");   //print 15 blanks to delete all
                                  //prior statements

This part was responsible for a unsteady (blinking) first row on the LCD, which I was looking for to fix it for nearly a week!

//function to display date and time

void displayDateTime(){

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

lcd.print(strcpy_P(buffer, (char*)pgm_read_word(&(weekday_table[currentDay]))));

lcd.print(" ");

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

lcd.print(currentDoM);

lcd.write(pgm_read_byte(&char_table[4])); //print dot

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

lcd.print(currentMonth);

lcd.print(" ");

if(currentHour < 10) lcd.write(pgm_read_byte(&char_table[2]));

//if the hour is less than 10

//we print a 0 to keep 2 digits

lcd.print(currentHour); //print current time (hour)

lcd.write(pgm_read_byte(&char_table[3])); //print separator

if(currentMinute < 10) lcd.write(pgm_read_byte(&char_table[2]));

//if the minute is less than

//10 print 0 to keep 2 digits

lcd.print(currentMinute); //print current time (minutes)

lcd.print(" ");

}

The last function is the one printing the temperature and light reading. The temperature reading we use direct since it returns the directly the temperature in degrees Celsius. OK, got the point. I put an option in to change it to Fahrenheit. The photocell reading is converted to output the value in lux from 0 (all dark) to 100000 (direct bright sunlight).

//function to display temperature and light reading

void displayTemp() {

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

lcd.print("T "); //print T for temperature

lcd.print(temperatur1); //print the reading

lcd.print(" C"); //print C for Celsius

lcd.print(" "); //print a space

lcd.print("L "); //print L for light

lcd.print(map(sensorValue, 0, 1023, 0, 100000)); //convert the photocell reading to lux

if(map(sensorValue, 0, 1023, 0, 100000) < 10000) lcd.print(" "); //print a space if below 10000

lcd.print(" L"); //print L for Lux

}


Tuesday, 3 June 2014

Room Management System – Bug fix to outside lighting


Since I added the single variables controlling the outside lights into the array holding all the on and off times for the lights, the outside lights wouldn't come on any more. Banging my head on the desk for a day and I finally found the reason. I know, I should take a couple of extra lessons in maths. It's the 0, which caught me again. In all the place holders the number 14 in the arrays is the control for the master relay and the master relay is not addressed in any light controls so I always forget about it. The outside lights are no 15 and that's again my number. Looking into the timer_active array and the room_timers array there is no space for the master relay since we do not address it in general room lighting. Simply, the space 14 was missing and the timers for the outside lights became the 15 space in the array which is again the no 14 because arrays start counting with 0. To cut an ongoing story short, there is a simple solution for this problem:

Lets go to the timer_active array pretty much at the beginning of the declaration part:


byte timer_active[16][4] = { //<<<<<<<<<<<timer_active[15 ][4] changes to timer_active[16][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

//>>>>>>>>>>>>Insert the line below<<<<<<<<<<<<<

{2, 2, 2, 2}, //Dummy timer

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

};

Here we have to update the numbers in the initialisation and I just added a set and set it to 2 for not used not to effect the operation of the master relay.

Now we insert a dummy timer into the room_timers array in place 15, placeholder [14].


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

byte room_timers[16][4][4] = { //<<<<<<room_timers[15][4][4] changes to room_timers[16][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

},

//>>>>>>>>>>>>>Addition starts here<<<<<<<<<<<<<

{

{0, 0, 0, 0}, //Dummy timer not used

{0, 0, 0, 0},

{0, 0, 0, 0},

{0, 0, 0, 0}

},

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

{

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

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

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

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

}

};

Now we move down int the main loop into the outside lights section. There we have to add a break command in the loop soon as the on time check returns a 1 not to overwrite the on command with a following 0:


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

if(timer_active[15][i] == 1){

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) break; //<<<<<<<<<<<<<ADD the break if a 1 is returned

}

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

lightOutput[15] = outputValues[15];

}

else{

lightOutput[15] = 0;

lightLevel[15] = 0;

}

Wednesday, 21 May 2014

Room Management System – Improvements part 3


Cause we are still at it, I do have some more improvements to optimize and minimize the sketch. Today we start with adding a couple of loops to the “holiday lighting” section. Let's jump straight down to the beginning of the “holiday lighting” section in the main loop. There we have a closer look at the first room:

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

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

//is activated

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

///////Room 1 (Bed 1) /////////////

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

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

//the hour where the lights

//to be switched on

//checking the times

room1Lights = checkOnTime(room_timers[0][0][0], room_timers[0][0][1],

room_timers[0][0][2], room_timers[0][0][3]);

}

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

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

//the hour where the lights

//to be switched on

//checking the times

room1Lights = checkOnTime(room_timers[0][1][0], room_timers[0][1][1],

room_timers[0][1][2], room_timers[0][1][3]);

}

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

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

//the hour where the lights

//to be switched on

//checking the times

room1Lights = checkOnTime(room_timers[0][2][0], room_timers[0][2][1],

room_timers[0][2][2], room_timers[0][2][3]);

}

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

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

//the hour where the lights

//to be switched on

//checking the times

room1Lights = checkOnTime(room_timers[0][3][0], room_timers[0][3][1],

room_timers[0][3][2], room_timers[0][3][3]);

}

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

lightOutput[0] =1; //switch on the lights

}

else {

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

lightLevel[0] = 0;

}

We are going through 4 timers for every room, the same bit of code 4 times. That's again calling for some improvement. Lets shorten it a bit and run it through a for loop. If we are looking at room_timers[x][y][z] and timer_active[x][y], the place holder x is corresponding with the room number which we use a little later for further improvement. For now we look at the place holder y which is in correspondents with the timers. Having 4 timers for each room makes it again easy to do the change. We take the first part of the code

//and add

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

//now we replace the second place holder with “i”

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

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

//the hour where the lights

//to be switched on

//checking the times

room1Lights = checkOnTime(room_timers[0][i][0], room_timers[0][i][1],

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

}

//and we have to end the loop with a }

}

And now what the revised code for room 1 looks like:

///////Room 1 (Bed 1) /////////////

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

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

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

//the hour where the lights

//to be switched on

//checking the times

room1Lights = checkOnTime(room_timers[0][i][0], room_timers[0][i][1],

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

}

}

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

lightOutput[0] =1; //switch on the lights

}

else {

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

lightLevel[0] = 0;

}

OK so far? If you expected the code coming up for the rest of the room, I got to disappoint you. We go further and add a couple of variables to the declaration part in the “/all the other variables/” where it says “////Sensor and timer variables////”

////Sensor and timer variables

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

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

dMaster, 0};

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

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

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

//checking sensor readings (0, 1)

byte photocellSwitchOld = 0; //switch command from the previous pass

byte lightLevel[17] ={0}; //array holding the switch state

//checking timer and photocell (0, 1)

//>>>>>>>>>>>>>ADD the two lines below<<<<<<<<<<<<<

byte roomLight[10] = {0}; //array holding the switch on command in holiday lighting

int outputValues[10] = {1,2,4,8,16,32,64,128,256,564};

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

unsigned int roomTimer[17] = {0}; //array holding the time when the PIR was last activated

unsigned int currentTime = 0; //var to hold a reference time to calculate the up time 

We go down a little further to the “//RTC and Holiday switch timers/” section and delete the following block of variables:

tmElements_t tm; //initializing RTC

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

byte room1Lights = 0; //var to hold the on command for room light

byte room2Lights = 0; //var to hold the on command for room light

byte room3Lights = 0; //var to hold the on command for room light

byte room4Lights = 0; //var to hold the on command for room light

byte room5Lights = 0; //var to hold the on command for room light

byte room6Lights = 0; //var to hold the on command for room light

byte room7Lights = 0; //var to hold the on command for room light

byte room8Lights = 0; //var to hold the on command for room light

byte room9Lights = 0; //var to hold the on command for room light

byte room10Lights = 0;

//>>>>>>>>>>>>>DELETE ends here<<<<<<<<<<<<<

byte currentHour = 0; //var holding the time (hour 0-23)

byte currentMinute = 0; //var holding the time (minute 0-59)

byte currentDay = 0; //var holding the date (day 1-31)

byte currentDoM = 0; //var holding the weekday (Sun - Sat, 1-7)

byte currentMonth = 0; //var holding the date (month 1-12)

int currentYear = 0; //var holding the year (based on Unix time)

//Array holding the day names to replace the weekday index

prog_char weekday_0[] PROGMEM = "Sun";

prog_char weekday_1[] PROGMEM = "Mon";

prog_char weekday_2[] PROGMEM = "Tue";

Now we go back down to the “Holiday lighting” section to room 1 where we just left off:

for(int x=0; x<10; x++){ //<<<<<<<<<<<<<ADD another for loop

//replace all the first place holders in the arrays with “x”

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

//replace room1Lights with roomLight[x]

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

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

}

}

//again replace room1Lights with roomLight[x]

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

//replace 1 with outputValues[x]

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

}

else {

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

lightLevel[x] = 0;

}

}//<<<<<<<<<<<<<ADD closing braces to end the loop

Now we loop through the 10 rooms and the 4 timers at the same time. Having done this, we can delete the following statements for the next 9 rooms and the new “holiday lighting section read like this:

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

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

//is activated

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

///////Room 1 (Bed 1) /////////////

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

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;

}

}

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

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;

}

#ifdef DA_DEBUG_holtimers

for(int x=0; x<10; 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 1 Lights: ");

Serial.println(room1Lights);

Serial.print("Room 2 Lights: ");

Serial.println(room2Lights);

Serial.print("Room 3 Lights: ");

Serial.println(room3Lights);

Serial.print("Room 4 Lights: ");

Serial.println(room4Lights);

Serial.print("Room 5 Lights: ");

Serial.println(room5Lights);

Serial.print("Room 6 Lights: ");

Serial.println(room6Lights);

Serial.print("Room 7 Lights: ");

Serial.println(room7Lights);

Serial.print("Room 8 Lights: ");

Serial.println(room8Lights);

Serial.print("Room 9 Lights: ");

Serial.println(room9Lights);

Serial.print("Room 10 Lights: ");

Serial.println(room10Lights);

#endif

}

else {

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

In preparation of the planned expansion of the AC functionality we d a little more optimization. First we pack the existing code where we check the read switches into a function. This is one of the operations which are needed in daily operation. So we put the function right behind the ones where we check the room light operations unsigned long check_light_N(). Right after this one we add:

unsigned long ac_read(byte readSw, byte room, unsigned long light){

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

//and the master relay is on AC

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

//switch on the AC

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

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

}

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

//relay is on

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

endTime = currentTime - roomTimer[room]; //calculating the inactive time

if(endTime >= delayTime[room]){ //comparing inactive time with

//delay time

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

//AC

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

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

}

}

return lightOutput[room];

}

It looks pretty familiar. I have done pretty much the same as with the lights, use the existing code, put it into a function and pass the variables for switch number, room number and the light output value. Now going back up into the main loop into the “////////AC read switches///////” section. There we replace the hole section with:


/////////////////////Ac Read Switches////////////////////////

lightOutput[10] = ac_read(14, 10, 1024);

lightOutput[11] = ac_read(15, 11, 2048);

lightOutput[12] = ac_read(16, 12, 4096);

lightOutput[13] = ac_read(17, 13, 8192);

/////////////Door switch control ////////////////////

In the next post, we start with extending the AC control a little.