Translate

Showing posts with label temperature sensor. Show all posts
Showing posts with label temperature sensor. 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

}


Thursday, 12 June 2014

Room Management System - Full Sketch including the Menu

As promised, before adding the EEPROM usage to the program, again a complete working sketch.



///////////////////////////////////////////////////////////////////////////////////
////Room Management System Version 1.4.2///////////////////////////////////////////
////by Dieter Achtelstetter////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
////This program is free software: you can redistribute it and/or modify///////////
////it under the terms of the GNU General Public License as published by///////////
////the Free Software Foundation, either version 3 of the License, or   ///////////
////(at your option) any later version.                                 ///////////
///////////////////////////////////////////////////////////////////////////////////
////This program is distributed in the hope that it will be useful,     ///////////
////but WITHOUT ANY WARRANTY; without even the implied warranty of      ///////////
////MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the       ///////////
////GNU General Public License for more details.                        ///////////
///////////////////////////////////////////////////////////////////////////////////
////You should have received a copy of the GNU General Public License   ///////////
////along with this program.  If not, see <http://www.gnu.org/licenses/>.//////////
///////////////////////////////////////////////////////////////////////////////////


/////////////////////Includes/////////////////////////////
#include <DS1307RTC.h>
#include <Time.h>
#include <Wire.h>
#include <ShiftLCD.h>
#include <avr/pgmspace.h>


#define ON  1                        // (RRKM-01) The switch is in ON state
#define OFF 0                        // (RRKM-01) The switch is in OFF state


#define DS1307_ADDRESS 0x68
byte zero = 0x00;

//uncomment the lines below for debugging
//#define DA_DEBUG_serial //to enable Serial monitor
//#define DA_DEBUG_in //debug the input stage
//#define DA_DEBUG_btnReadings //check button readings
//#define DA_DEBUG_tmp //check temperatur readings
//#define DA_DEBUG_holtimers //debug the holiday timers
//#define DA_DEBUG_ac //Debug AC
//#define DA_DEBUG_AC_2 //Debug AC
//#define DA_DEBUG_out //debug the output stage
//#define DA_DEBUG_photo //debug control from photocell for holiday switching
/////////////////////Declaring the Variables/////////////////

///////////Timer and Sensitivity Settings to be changed to individual needs////////////////
unsigned int sensitivity = 300;    //should be between 200 and 1000 as
                                   //lower the number as more responsive 
                                   //the system will be
unsigned int photoCellCutOn = 320;  //var holding the switching limit for the photocell
unsigned int photoCellCutOff = 280; //var holding the value where the photocell cuts off
unsigned int photoOutsideOn = 220; //var holding the value which the photocell reading 
unsigned int photoOutsideOff = 260;
//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
/*int delayTime[16] = {dBed1, dBed2, dBed3, dLiving, dBath1, dBath2, dBath3,
                     dBath4, dKitchen, dCorridor, dAC1, dAC2, dAC3, dAC4,
                     dMaster, 0};*/
int delayTime[16] = {120, 120, 120, 600, 180, 180,
                     180, 180, 120, 120, 120, 120, 
                     120, 120, 240, 0};
                     
/*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*/

byte startDelay = 0;       //var to optional ac compressor start delay

byte acSwitchDelay = 2;    //ac puls delay for mode 3
byte ac_op_mode = 3;       //ac mode 1) read switches only
                           //ac mode 2) limited control using ac switch or auto restart of AC
                           //ac mode 3) limited control using ac momentary switch (push button)
byte ac_set_temp = 28;     //temperature at which the AC switches on
byte ac_periode[4][2] = {
                          {1, 5},     //time periode between January and May
                          {6, 9},     //time periode between June and September
                          {10, 10},   //October
                          {11, 12}    //time periode between November and December
};

byte ac_master_bypass[4] = {0};       //array holding values to bypass master relay


//////////////////////holiday and AC timer settings//////////////////////

byte 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
                    {2, 2, 2, 2},    //Dummy room 
                    {0, 1, 2, 2}     //outside lighting
};

//Timer Settings room, timer, hour on, minute on, hour off, minute off
byte 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 1 timer 1
                                 {19, 30, 20, 10},     //room 1 timer 2
                                 {0, 0, 0, 0},         //room 1 timer 3
                                 {0, 0, 0, 0}          //room 1 timer 4
                               },
                               {
                                 {5, 50, 6, 20},       //room 2 timer 1
                                 {18, 10, 18, 25},     //room 2 timer 2
                                 {19, 15, 19, 40},     //room 2 timer 3
                                 {23, 20, 23, 35}      //room 2 timer 4
                               },
                               {
                                 {0, 0, 0, 0},         //room 3 timer 1
                                 {17, 30, 23, 30},     //room 3 timer 2
                                 {0, 0, 0, 0},         //room 3 timer 3
                                 {0, 0, 0, 0}          //room 3 timer 4
                               },
                               {
                                 {5, 40, 5, 45},       //room 4 timer 1
                                 {19, 55, 20, 10},     //room 4 timer 2
                                 {0, 0, 0, 0},         //not used
                                 {0, 0, 0, 0}          //not used
                               },
                               {
                                 {6, 35, 6, 45},       //room 5 timer 1
                                 {19, 50, 20, 5},      //room 5 timer 2
                                 {0, 0, 0, 0},         //not used
                                 {0, 0, 0, 0}          //not used
                               },
                               {
                                 {6, 5, 6, 25},        //room 6 timer 1
                                 {22, 50, 23, 15},     //room 6 timer 2
                                 {0, 0, 0, 0},         //not used
                                 {0, 0, 0, 0}          //not used
                               },
                               {
                                 {0, 0, 0, 0},         //room 7 timer 1
                                 {22, 5, 22, 20},      //room 7 timer 2
                                 {0, 0, 0, 0},         //not used
                                 {0, 0, 0, 0}          //not used
                               },
                               {
                                 {5, 50, 6, 45},       //room 8 timer 1
                                 {17, 45, 18, 30},     //room 8 timer 2
                                 {0, 0, 0, 0},         //room 8 timer 3
                                 {0, 0, 0, 0}          //not used
                               },
                               {
                                 {0, 0, 0, 0},         //room 9 timer 1
                                 {0, 0, 0, 0},         //room 9 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
                               },
                               {
                                 {0, 0, 0, 0},           //Dummy timer not used
                                 {0, 0, 0, 0},       
                                 {0, 0, 0, 0},         
                                 {0, 0, 0, 0}           
                               },
                               {
                                 {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
                               }
};
 
byte ac_forced_on[4][2] = {
                            {19, 30},  //Switch on AC room 1
                            {19, 30},  //Switch on AC room 2
                            {22, 0},   //Switch on AC room 3
                            {16, 0}    //Switch on AC room 4
};
///////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////DO NOT MODIVY BELOW HERE///////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
////////////////////////////defining Arduino Pins/////////////////////////////
//////////////////////////////////////////////////////////////////////////////
ShiftLCD lcd(9, 11, 10);       //initializing the LCD adaptor pins

const byte latchPin = 2;        //5latch pin input connected to
                               //Arduino digital pin 2
const byte clockPin = 3;        //6clock pin input connected to
                               //Arduino digital pin 3
const byte dataPin = 4;         //7data pin input connected to 
                               //Arduino digital pin 4
                               
const byte latchPinOut = 5;     //2latch pin output shift register
                               //74HC595 connected to Arduino
                               //digital pin 5
const byte clockPinOut = 6;     //3clock pin output shift register
                               //74HC595 connected to Arduino
                               //digital pin 6
const byte dataPinOut = 7;      //4data pin output shift register
                               //74HC595 connected to Arduino
                               //digital pin 7

const byte lightSensor = 0;          //defining the input for the photocell

const byte doorMonitor = 8;           //Arduino pin for a monitor LED
const byte setupMode = 12;            //Arduino pin for switching to setup mode

const byte TMP01 = 2;                 //Arduino analog pin 2 - temperature sensor

/////////////////////////////////////////////////////////////////////////////
///////Variables to hold the data for each input shift register//////////////
/////////////////////////////////////////////////////////////////////////////

byte switchVar1 = 0;           //data for input shift register 1
byte switchVar2 = 0;           //data for input shift register 2
byte switchVar3 = 0;           //data for input shift register 3

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

////Sensor and timer variables
                     
byte temperatur1 = 0;                        //holding temperatur 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
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 
                                             
////////////////////////////////////////////////////////////////////////////////////////
//////////////////////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
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

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

unsigned long outputL = 0;                    //variable holding the output data

/////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////RTC and Holiday switch timers///////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
tmElements_t tm;               //initializing RTC

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 - Sa, 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";
prog_char weekday_3[] PROGMEM = "Wed";
prog_char weekday_4[] PROGMEM = "Thu";
prog_char weekday_5[] PROGMEM = "Fri";
prog_char weekday_6[] PROGMEM = "Sat";

PROGMEM const char *weekday_table[] = {
  weekday_0,
  weekday_1,
  weekday_2,
  weekday_3,
  weekday_4,
  weekday_5,
  weekday_6
};

char buffer[20];
///////////////////////////////////////////////////////////////////////////
///////////////////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
const byte menuOptions = 22;     //available menu options
byte submenu = 0;                //var to count current submenu option
const byte submenus = 9;         //available submenu options
byte acSetup = 0;                //var to count current ac setup menu options
const byte acSetups = 5;         //available ac setup menu options
byte acSubOption = 0;            //var to count current ac sub menu options
const byte acSubOptions = 10;    //available ac sub menu options


char buffer_M[20];               //var holding the menu strings retrieved from
                                 //the program memory

//Storing some menu messages in the program memory
prog_char msg_0[] PROGMEM = "Not Used";      
prog_char msg_1[] PROGMEM = "Saving....";
prog_char msg_2[] PROGMEM = "Setup mode";
prog_char msg_3[] PROGMEM = "Starting....";
prog_char msg_4[] PROGMEM = "RMU 1.4.2";
prog_char msg_5[] PROGMEM = "Weekday";
prog_char msg_6[] PROGMEM = "On  TIMER  Off";
prog_char msg_7[] PROGMEM = "Off   ";
prog_char msg_8[] PROGMEM = "Active";
prog_char msg_9[] PROGMEM = "PIR Delay R";
prog_char msg_10[] PROGMEM = "T1 On/Off R";
prog_char msg_11[] PROGMEM = "T2 On/Off R";
prog_char msg_12[] PROGMEM = "T3 On/Off R";
prog_char msg_13[] PROGMEM = "ADJ Hour On";
prog_char msg_14[] PROGMEM = "ADJ Minute On";
prog_char msg_15[] PROGMEM = "ADJ Hour Off";
prog_char msg_16[] PROGMEM = "ADJ Minute Off";
prog_char msg_17[] PROGMEM = "Set Sensitivity";
prog_char msg_18[] PROGMEM = "Set photocell R";
prog_char msg_19[] PROGMEM = "Set photocell O";
prog_char msg_20[] PROGMEM = "ADJ Time Minute";
prog_char msg_21[] PROGMEM = "ADJ Time Hour";
prog_char msg_22[] PROGMEM = "ADJ Date Day";
prog_char msg_23[] PROGMEM = "ADJ Date Month";
prog_char msg_24[] PROGMEM = "ADJ Date Year";
prog_char msg_25[] PROGMEM = "T4 On/Off R";
prog_char msg_26[] PROGMEM = "ADJ AC Mode";
prog_char msg_27[] PROGMEM = "AC Set Temp";
prog_char msg_28[] PROGMEM = "AC Switch Delay";
prog_char msg_29[] PROGMEM = "AC Seas 1 Start";
prog_char msg_30[] PROGMEM = "AC Seas 1 End";
prog_char msg_31[] PROGMEM = "AC Seas 2 Start";
prog_char msg_32[] PROGMEM = "AC Seas 2 End";
prog_char msg_33[] PROGMEM = "AC Seas 3 Start";
prog_char msg_34[] PROGMEM = "AC Seas 3 End";
prog_char msg_35[] PROGMEM = "AC Seas 4 Start";
prog_char msg_36[] PROGMEM = "AC Seas 4 End";
prog_char msg_37[] PROGMEM = "AC Off delay";
prog_char msg_38[] PROGMEM = "AC master byp";
prog_char msg_39[] PROGMEM = "AC Comp protect";


//Creating the table for the stored menu messages
PROGMEM const char *msg_table[] = {
  msg_0,
  msg_1,
  msg_2,
  msg_3,
  msg_4,
  msg_5,
  msg_6,
  msg_7,
  msg_8,
  msg_9,
  msg_10,
  msg_11,
  msg_12,
  msg_13,
  msg_14,
  msg_15,
  msg_16,
  msg_17,
  msg_18,
  msg_19,
  msg_20,
  msg_21,
  msg_22,
  msg_23,
  msg_24,
  msg_25,
  msg_26,
  msg_27,
  msg_28,
  msg_29,
  msg_30,
  msg_31,
  msg_32,
  msg_33,
  msg_34,
  msg_35,
  msg_36,
  msg_37,
  msg_38,
  msg_39
};

//storing some special char's in the program memory
const byte char_table[] PROGMEM = {
  B01111110,                          //Arrow right
  B01111111,                          //Arrow left
  B00110000,                          //0
  B00111010,                          //seperator
  B00101110,                          //dott
  B00110001,                          //1
  B00110010,                          //2
  B00110011,                          //3
  B00110100,                          //4
  B00110101,                          //5
  B00110110,                          //6
  B00110111,                          //7
  B00111000,                          //8
  B00111001                           //9
};

//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";
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,
  menu_21
};

//storing the sub menu points in the program memory
prog_char submenu_0[] PROGMEM = "PIR delay R";
prog_char submenu_1[] PROGMEM = "HT1 Active R";
prog_char submenu_2[] PROGMEM = "Timer 1 R";
prog_char submenu_3[] PROGMEM = "HT2 Active R";
prog_char submenu_4[] PROGMEM = "Timer 2 R";
prog_char submenu_5[] PROGMEM = "HT3 Active R";
prog_char submenu_6[] PROGMEM = "Timer 3 R";
prog_char submenu_7[] PROGMEM = "HT4 Active R";
prog_char submenu_8[] PROGMEM = "Timer 4 R";
prog_char submenu_9[] PROGMEM = "Off Delay R";

PROGMEM const char *submenu_table[] = {
  submenu_0,
  submenu_1,
  submenu_2,
  submenu_3,
  submenu_4,
  submenu_5,
  submenu_6,
  submenu_7,
  submenu_8,
  submenu_9
};

//storing the ac setup menu
prog_char ac_setup_0[] PROGMEM = "AC Mode";
prog_char ac_setup_1[] PROGMEM = "Set Temp";
prog_char ac_setup_2[] PROGMEM = "Seasons";
prog_char ac_setup_3[] PROGMEM = "Switch Delay";
prog_char ac_setup_4[] PROGMEM = "Start Delay";

PROGMEM const char *ac_setup_table[] = {
  ac_setup_0,
  ac_setup_1,
  ac_setup_2,
  ac_setup_3,
  ac_setup_4
};

//storing the AC sub menu
prog_char ac_sub_0[] PROGMEM = "AC off delay R";
prog_char ac_sub_1[] PROGMEM = "AC Master byp R";
prog_char ac_sub_2[] PROGMEM = "AC ST1 Active R";
prog_char ac_sub_3[] PROGMEM = "AC Timer 1 R";
prog_char ac_sub_4[] PROGMEM = "AC ST2 Active R";
prog_char ac_sub_5[] PROGMEM = "AC Timer 2 R";
prog_char ac_sub_6[] PROGMEM = "AC ST3 Active R";
prog_char ac_sub_7[] PROGMEM = "AC Timer 3 R";
prog_char ac_sub_8[] PROGMEM = "AC ST4 Active R";
prog_char ac_sub_9[] PROGMEM = "AC Timer 4 R";

PROGMEM const char *ac_sub_table[] = {
  ac_sub_0,
  ac_sub_1,
  ac_sub_2,
  ac_sub_3,
  ac_sub_4,
  ac_sub_5,
  ac_sub_6,
  ac_sub_7,
  ac_sub_8,
  ac_sub_9
};

prog_char error_0[] PROGMEM = "RTC ERR";
prog_char error_1[] PROGMEM = "RTC Read ERR";
  
PROGMEM const char *error_table[] = {
  error_0,
  error_1
};


void setup() {
   //////////////Start Serial for Debugging/////////////////////
   #ifdef DA_DEBUG_serial
     Serial.begin(9600);
   #endif
   
   //printing initialisation message
   lcd.begin(16, 2);
   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
   
   pinMode(setupMode, INPUT);           //setup switch to activate menu
   
   pinMode(latchPin, OUTPUT);  //setting the latch pin to output
   pinMode(clockPin, OUTPUT);  //setting the clock pin to output
   pinMode(dataPin, INPUT);  //setting the data pin to input
   
   pinMode(latchPinOut, OUTPUT);
   pinMode(clockPinOut, OUTPUT);
   pinMode(dataPinOut, OUTPUT);
   
}  

void loop() {
 
  ///////////////////checking the setup switch/////////////////////////
  while(digitalRead(setupMode) != 0){        //stay in here if activated
    lcd.clear();                             //clear display
    lcd.print(strcpy_P(buffer_M, (char*)pgm_read_word(&(msg_table[2]))));                 //print Setup mode
    delay(500);                              //small delay
    
    button_loop();                           //function call to monitore menu buttons
  }
   //////////////////////////////////////getting the input//////////////////////////////////////////////////
   
  
   //Serial.print("switchVar1 first: ");
   //Serial.println(switchVar1, BIN);
   //Serial.print("switchVar2 first: ");
   //Serial.println(switchVar2, BIN);
   //Serial.print("switchVar3 first: ");
   //Serial.println(switchVar3, BIN);
   
   //pulse the latch pin, set to high to collect serial data
   digitalWrite(latchPin, HIGH);
   //give it chance to collect the data
   delayMicroseconds(25);
   //set latch pin to low to transmit data serially
   digitalWrite(latchPin, LOW);

   //while in serial mode, collect data into a byte
   switchVar1 = shiftIn(dataPin, clockPin);
   switchVar2 = shiftIn(dataPin, clockPin);
   switchVar3 = shiftIn(dataPin, clockPin);
   
   /////////////do something with the collected Data/////////////////////
   //checks for debugging
   #ifdef DA_DEBUG_in
     Serial.println();                       //debug only
     Serial.print("Switch variable 1: ");    //debug only
     Serial.println(switchVar1, BIN);        //debug only
     Serial.println("-------------------");  //debug only
     Serial.println();                       //debug only
     Serial.print("Switch variable 2: ");    //debug only
     Serial.println(switchVar2, BIN);        //debug only
     Serial.println("-------------------");  //debug only
     Serial.println();                       //debug only
     Serial.print("Switch variable 3: ");    //debug only
     Serial.println(switchVar3, BIN);        //debug only
     Serial.println("-------------------");  //debug only
   #endif
   ////////////loop through the 8 input pins to check their status////////////
     // (RRKM-01) shift register 1
     switchState[0]  = IIFi((switchVar1 &      (1)), ON, OFF); //checking S1
     switchState[1]  = IIFi((switchVar1 & (1 << 1)), ON, OFF); //checking S2
     switchState[2]  = IIFi((switchVar1 & (1 << 2)), ON, OFF); //checking S3
     switchState[3]  = IIFi((switchVar1 & (1 << 3)), ON, OFF); //checking S4
    
     switchState[7]  = IIFi((switchVar1 & (1 << 4)), ON, OFF); //checking S5, notice bit locations!!!
     switchState[6]  = IIFi((switchVar1 & (1 << 5)), ON, OFF); //checking S6
     switchState[5]  = IIFi((switchVar1 & (1 << 6)), ON, OFF); //checking S7
     switchState[4]  = IIFi((switchVar1 & (1 << 7)), ON, OFF); //checking S8
  
     // (RRKM-01) shift register 2
     switchState[8]  = IIFi((switchVar2 &      (1)), ON, OFF); //checking S9
     switchState[9]  = IIFi((switchVar2 & (1 << 1)), ON, OFF); //checking S10
     switchState[10] = IIFi((switchVar2 & (1 << 2)), ON, OFF); //checking S11
     switchState[11] = IIFi((switchVar2 & (1 << 3)), ON, OFF); //checking S12
    
     switchState[15] = IIFi((switchVar2 & (1 << 4)), ON, OFF); //checking S13, same here!!!
     switchState[14] = IIFi((switchVar2 & (1 << 5)), ON, OFF); //checking S14
     switchState[13] = IIFi((switchVar2 & (1 << 6)), ON, OFF); //checking S15
     switchState[12] = IIFi((switchVar2 & (1 << 7)), ON, OFF); //checking S16
    
     // (RRKM-01) shift register 3
     switchState[16] = IIFi((switchVar3 &      (1)), ON, OFF); //checking S17
     switchState[17] = IIFi((switchVar3 & (1 << 1)), ON, OFF); //checking S18
     switchState[18] = IIFi((switchVar3 & (1 << 2)), ON, OFF); //checking S19
     switchState[19]  = IIFi((switchVar3 & (1 << 3)), ON, OFF); //checking S20
     
     switchState[20] = IIFi((switchVar3 & (1 << 4)), ON, OFF); //checking S21
     switchState[21] = IIFi((switchVar3 & (1 << 5)), ON, OFF); //checking S22
     switchState[22] = IIFi((switchVar3 & (1 << 6)), ON, OFF); //checking S23

   
  //////////////Debug Statements//////////////////////////////////
     #ifdef DA_DEBUG_in  // (RRKM-01) Only when debugging
       for(int x=0; x<23; x++) {
         Serial.println( "Status of Switch S" + String(x+1) + ": " +
                         IIFs((switchState[x] == ON), "ON", "OFF" )
                         );
       }
     #endif
   //////////////////checking the light status (photo cell)//////////////////////
  
    sensorValue = 0; 
    int reading = 0;                                  //the readings
     for(int i=0; i<15; i++){                         //take 15 readings
      reading += analogRead(lightSensor);
    }
    //average the readings
    sensorValue = reading / 15;
   //Serial.print("Sensor value: ");
   //Serial.println(sensorValue);
   
   ///////////////Checking the room temperature/////////////
    int temp1 = 0;               //var to take the readings
    for(int i=0; i<15; i++){     //take 15 readings for a stable output
      temp1 += map(analogRead(TMP01),0,410,-40,125);
    }
    temperatur1 = temp1/15;      //average the readings
    #ifdef DA_DEBUG_tmp          //check the output
      Serial.print("Current Temperatur: ");
      Serial.println(temperatur1);
    #endif
   
  
   //////////////////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 eg 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
    
    lcd.setCursor(0, 0);             //set the corsor 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 dott
    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 seperator
    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)
     
  }
  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;
  }
  //allowing the lights to switch on between 00:00 and 08:00 h
  else if(photocellSwitch == 1 && currentHour >= 0 && currentHour <= 8){
    for(int i=0; i<10; i++){
      lightLevel[i] = 1;
    }
    lightLevel[15] = 1;
  }
  //make sure the lights switch off on sunrise during morning hours
  else if(photocellSwitch == 0 && currentHour >= 5 && currentHour <= 8){
    for(int c=0; c<17; c++){
      lightLevel[c] = 0;
    }
  }
  
  #ifdef DA_DEBUG_photo
    Serial.print("Photo cell switch: ");
    Serial.println(photocellSwitch);
    for(int c=0; c<17; c++){
      Serial.print("Light level ");
      Serial.print(c);
      Serial.print(" :");
      Serial.println(lightLevel[c]);
    }
  #endif      
    
  //////////////Holiday lighting/////////////////////////
    
  if(switchState[20] == 1) {       //check if the holliday 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++){
      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;
        }
      }
    }
     
     #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 {
      
     ////////Outside lights////////////////////
     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;    
     }
     if(roomLight[15] == 1 && lightLevel[15] == 1){
         lightOutput[15] = outputValues[15];
     }
     else{
       lightOutput[15] = 0;
       lightLevel[15] = 0;
     }

     //////////////////room lights//////////////////////////////
         
      lightStatus[16] = check_master(0);                 //check if doorswitch was activated room 1 (bed1)
     
      lightOutput[0] = check_light_P(0, 1, 0, 1);        //check status room 1 (bed 1)
      delay(5);
      lightStatus[16] = check_master(2);                 //check if doorswitch was activated room 2 (bed 2)
     
      lightOutput[1] = check_light_P(2, 3, 1, 2);       //check status room 2 (bed 2)
      delay(5);
      lightStatus[16] = check_master(4);                 //check if doorswitch was activated room 3 (bed 3)
      
      lightOutput[2] = check_light_P(4, 5, 2, 4);       //check status room 3 (bed 3)
      delay(5);
      lightStatus[16] = check_master(6);                 //check if doorswitch was activated room 4 (living)
     
      lightOutput[3] = check_light_P(6, 7, 3, 8);       //check status room 4 (living)
      delay(5);
      lightStatus[16] = check_master(8);                 //check if doorswitch was activated room 5 (bath 1)
      
      lightOutput[4] = check_light_N(8, 4, 16);         //check status room 5 (bath 1)
      delay(5);
      lightStatus[16] = check_master(9);                 //check if door switch was activated room 6 (bath 2)
      
      lightOutput[5] = check_light_N(9, 5, 32);
      delay(5);
      lightStatus[16] = check_master(10);
    
      lightOutput[6] = check_light_N(10, 6, 64);
      delay(5);
      lightStatus[16] = check_master(11);  
      
      lightOutput[7] = check_light_N(11, 7, 128);
      delay(5);
      lightStatus[16] = check_master(12); 
      
      lightOutput[8] = check_light_N(12, 8, 256);
      delay(5);
      lightStatus[16] = check_master(13);
    
      lightOutput[9] = check_light_N(13, 9, 512);
  
  /////////////////////Ac Read Switches////////////////////////
    #ifdef DA_DEBUG_ac
      for(int i=10; i<14; i++){
        Serial.print("light output before ");
        Serial.print(i);
        Serial.print(": ");
        Serial.println(lightOutput[i]);
        Serial.print("output Value: ");
        Serial.println(outputValues[i]);
        Serial.print("Light Status before ");
        Serial.print(i);
        Serial.print(": ");
        Serial.println(lightStatus[i]);
      }
    #endif
     
    lightOutput[10] = ac_read(14, 10);
    delay(5);
    lightOutput[11] = ac_read(15, 11);
    delay(5);
    lightOutput[12] = ac_read(16, 12);
    delay(5);
    lightOutput[13] = ac_read(17, 13);

    #ifdef DA_DEBUG_ac
      for(int i=10; i<14; i++){
        Serial.print("light output after ");
        Serial.print(i);
        Serial.print(": ");
        Serial.println(lightOutput[i]);
        Serial.print("output Value: ");
        Serial.println(outputValues[i]);
        Serial.print("Light Status after ");
        Serial.print(i);
        Serial.print(": ");
        Serial.println(lightStatus[i]);
      }
    #endif
    
      /////////////Door switch control ////////////////////
    //Serial.print("switchState 18 :");
    //Serial.println(switchState[18]);
    //Serial.print("Switch state old: ");
    //Serial.println(masterSwitchStateOld);
    //Serial.print("Light status 16: ");
    //Serial.println(lightStatus[16]);
      
    if(switchState[18] != masterSwitchStateOld) {               //door switch check if the switch state
                                                                //has changed
      //Serial.println("Door switch was activated");              //debug only
      currentTime = millis()/1000;                                   //setting time reference
      lightStatus[16] = 1;                                      //setting light status
      digitalWrite(doorMonitor, HIGH);                          //setting the control LED
      for(int i=0; i<17; i++){                                  //looping through the timers
        roomTimer[i] = currentTime;                             //setting the timers
      }
    }
    else if(switchState[18] == masterSwitchStateOld && lightStatus[16] == 1){ //if the switch state
                                                                //has not changed and the lights are on
      //Serial.println("Checking off status");                    //debug only
      currentTime = millis()/1000;                                   //setting the time reference
      offTime = roomTimer[16] + delayTime[14];                  //setting the allowed delay time
      //Serial.print("off Time: ");
      //Serial.println(offTime);
      //Serial.print("current Time: ");
      //Serial.println(currentTime);
      if(currentTime >= offTime) {                              //comparing the times
        for(int c=0; c<17; c++) {                               //looping through the circuits
          if(roomTimer[c] != roomTimer[16]) {                   //comparing timers
            mainOff = 1;                                        //setting the switch off all command
            lightStatus[16] = 0;                                //switching off the master relay
          }
          else {
            mainOff = 0;                                        //if the timers match we set the 
                                                                //switch off all command to 0
            break;                                              //leaving the loop
          }
        }
      }
      //Serial.print("Main off: ");
      //Serial.println(mainOff);
      if(mainOff == 0) {                                        //master off command is 0
        //Serial.println("switching off everything and reset all"); //debug only
        for(int i=0; i<17; i++) {                               //looping through the circuits
          lightStatus[i] = 0;                                   //resetting all light status
          lightOutput[i] = 0;                                   //switching off all lights
          priorityStatus[i] = 0;                                //resetting all set priorities
          roomTimer[i] = 0;                                     //resetting all room timers
        }
        digitalWrite(doorMonitor, LOW);                         //resetting the control LED
        mainOff = 1;                                            //resetting master off command
      }
    }
    masterSwitchStateOld = switchState[18];                     //setting the switchState to old
  }  
  ///////////////////////////Output/////////////////////////////////////////////////
  
  for(int i=0; i<17; i++) {                                //loop through the light output array
    #ifdef DA_DEBUG_out
      Serial.print("Light Output ");                        //debug only
      Serial.print(i);                                      //debug only
      Serial.print(": ");                                   //debug only
      Serial.println(lightOutput[i]);                       //debug only
      Serial.print("Light status: ");                       //debug only
      Serial.println(lightStatus[i]);                       //debug only
      Serial.print("Room Timer: ");                         //debug only
      Serial.println(roomTimer[i]);                         //debug only
      delay(100);
    #endif
    outputL += lightOutput[i];                            //adding up the numbers
  }
  
  if(switchState[19] == 1) {              //if maintenance switch is active
    for(int i=0; i>17; i++){             //loop through all circuits
      lightStatus[i] = 1;                //setting the light status of everything
      roomTimer[i] = millis()/1000;           //setting all the room timers
    }
    outputL = 65535;                     //setting the output 
                                         //binary 1111111111111111
  }  
  
  lcd.setCursor(0,0);
  lcd.print(outputL, BIN);
  #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
  
}



////////////////Shift In Function for Input processing ////////////

byte shiftIn(int myDataPin, int myClockPin) {
  int i;
  int temp = 0;
  int pinState;
  byte myDataIn = 0;
  
  pinMode(myClockPin, OUTPUT);
  pinMode(myDataPin, INPUT);
  
  for(i=7; i>=0; i--) {
    digitalWrite(myClockPin, LOW);
    delayMicroseconds(2);
    temp = digitalRead(myDataPin);
    if(temp) {
      pinState = 1;
      myDataIn = myDataIn | (1 << i);
    }
    else {
      pinState = 0;
    }
    //Serial.print("PinState: ");    //debug only
    //Serial.print(pinState);        //debug only
    //Serial.print("        ");      //debug only
    //Serial.println(myDataIn, BIN); //debug only
    
    digitalWrite(myClockPin, HIGH);
  }
  //Serial.println();                //debug only
  //Serial.println(myDataIn, BIN);   //debug only
  return myDataIn;
}


////////////function to check timer/////////
byte checkOnTime(byte hourOn, byte minuteOn, byte hourOff, byte minuteOff){
  tmElements_t tm;
  byte onTime = 0;
  unsigned long timeNow = 0;
  unsigned long onTrigger = 0;
  unsigned long offTrigger = 0;
  
  if(RTC.read(tm)){ 
    
    timeNow = tmConvert_t(tmYearToCalendar(tm.Year), tm.Month, tm.Day, tm.Hour, tm.Minute, tm.Second);
    
    onTrigger = tmConvert_t(tmYearToCalendar(tm.Year), tm.Month, tm.Day, hourOn, minuteOn, 0);
    
    if(hourOff < hourOn) {
      offTrigger = tmConvert_t(tmYearToCalendar(tm.Year), tm.Month, tm.Day+1, hourOff, minuteOff, 0);
    }
    else {
      offTrigger = tmConvert_t(tmYearToCalendar(tm.Year), tm.Month, tm.Day, hourOff, minuteOff, 0);
    }
    if(timeNow >= onTrigger && timeNow < offTrigger) {
      onTime = 1;
    }
    else {
      onTime = 0;
    }
  }
  //Serial.print("   Time now: ");
  //Serial.println(timeNow);
  //Serial.print(" On trigger: ");
  //Serial.println(onTrigger);
  //Serial.print("Off Trigger: ");
  //Serial.println(offTrigger);
  return onTime;
}

/////function to convert real time to unix timne////////
time_t tmConvert_t(int YYYY, byte MM, byte DD, byte hh, byte mm, byte ss){
  tmElements_t tmSet;
  tmSet.Year = YYYY - 1970;
  tmSet.Month = MM;
  tmSet.Day = DD;
  tmSet.Hour = hh;
  tmSet.Minute = mm;
  tmSet.Second = ss;
  return makeTime(tmSet);         //convert to time_t
}

byte getSensorValue(int sensorReading, int switchValue, 
                    int switchLimit, byte switchStatus){
  byte onStatus = 0;
  
  if(switchStatus == 0){
    if(sensorReading <= switchValue){
      onStatus = 1;
    }
    else if(sensorReading > switchLimit){
      onStatus = 0;
    }
    else if(sensorReading > switchValue &&
            sensorReading <= switchLimit){
      onStatus = 0;
    }
  }
  else if(switchStatus == 1){
    if(sensorReading <= switchValue){
      onStatus = 1;
    }
    else if(sensorReading > switchValue &&
            sensorReading <= switchLimit){
      onStatus = 1;
    }
    else if(sensorReading > switchLimit){
      onStatus = 0;
    }
  }
  return onStatus;
} 

byte check_master(byte swNo){
  if(switchState[swNo] == 1 && lightStatus[16] == 1) {         //checking if PIR with switch Number  was
                                                               //activated (bed 1)
     lightStatus[16] = 0;                                      //resetting master off
     digitalWrite(doorMonitor, LOW);                           //resetting the door Monitor LED
  }
  //else {
    //lightStatus[16] = 1;
 // }
  return lightStatus[16];
}

boolean allTimer(unsigned long timeSet, unsigned int timeLimit){
  currentTime = millis()/1000;
  endTime = currentTime - timeSet;
  if(endTime >= timeLimit){
    return true;
  }
  else{
    return false;
  }
}

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
         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 yelay 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
           && 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];
}

unsigned long check_light_N(byte pir, byte room, unsigned long light){
  if(switchState[pir] == 1) {                                     //checking passed on PIR (byte pir)
                                                                  //of passed on room (byte room)
    //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 relay 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
    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];
}

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 && startDelay == 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;                                  //canceling ability to switch on the 
                                                                //AC
        lightStatus[room] = 0;                                  //resetting the light (AC) status
        roomTimer[room] = 0;   
      }
    }
    else if(switchState[readSw] == 1 && lightStatus[14] == 1 && startDelay == 0){
      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 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;                                     //canceling 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 && startDelay == 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 && startDelay == 1){   //if doors and windowa 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
        }
      }
      if(switchState[readSw] == 1 && lightStatus[14] == 1 && startDelay == 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){   
          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 if(switchState[readSw] == 1 && priorityStatus[room] == 1 && startDelay == 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){   
          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 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;                                   //canceling 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  && startDelay == 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] == 1  && startDelay == 0){ 
                    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 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;                            //canceling 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(startDelay == 1){
      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(startDelay == 0){
      if(roomLight[room] == 1){ //if a "on" command was given 
      
        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] == 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 swith 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;
}

//function to return the current time periode of the year
byte get_ac_periode(){
  int i = 0;             //declare the counter
  for(i=0; i<4; i++){    //loop through the array
    //and compare the settings with the current month
    //if the current month is found with in a defined 
    //limit break the loop and return the counter at the moment of breaking
    if(currentMonth >= ac_periode[i][0] && currentMonth <= ac_periode[i][1]) break;
  }
  return i;  //return the counter
}



int read_act_buttons(){
  act_key_in = analogRead(1);      //reading the sensor
  delay(250);                      //button debounce delay
  //Readings centered at 170 for menu
  //203 for search and 252 for select
  #ifdef DA_DEBUG_btnReadings
    Serial.print("Reading: ");
    Serial.println(act_key_in);
  #endif
  if(act_key_in < 160) return btnNone; //most likely result first
  //adding a range of +/- 10 to compensate for bouncing
  //readings
  if(act_key_in > 155 && act_key_in < 180) return btnMenu;  
  if(act_key_in > 191 && act_key_in < 220) return btnSearch;
  if(act_key_in > 239 && act_key_in < 270) return btnSelect;
  return btnNone;
}

//Checking for a pressed menu button
void button_loop(){
  //Serial.println("in button loop");
  byte button = read_act_buttons();   //function call to read the buttons
  if(button == btnMenu){              //if button menu was pressed
    selectMenu();                   //delay for readability
  }
}

void selectMenu(){
  //Serial.println("SelectMenu");
  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
      lcd.clear();                    //clear screen
      //retrieve and print the actal 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;
      }
    }
    
    
    if(button == btnSelect){ //if the select button is pressed
      if(menuOption == 1){   //amd menu option is 1
        adjust_date_time();  //go to ajdust date and time
        return;
      }
      if(menuOption == 2){   //and menu option is 2
        sensitivity = get_Timer(17, sensitivity, 0, 1000); //go to function 
        return;
      }
      if(menuOption == 3){   //and menu option is 3
        photoCellCutOff = get_Timer(18, photoCellCutOff, 0, 1024); //go to function
        return;
      }
      if(menuOption == 4) return; //and menu option is 4 return (not used)
      if(menuOption == 5){   //and menu option is 5     
        photoOutsideOff = get_Timer(19, photoOutsideOff, 0, 1024); //go to function
        return;
      }
      if(menuOption == 6) return; //and menu option is 6 return (not used)
      if(menuOption == 7){ //and menu option is 7 (room 1)
        get_submenu(0);
      }
      if(menuOption == 8){ //and menu option is 8 (room 2)
        get_submenu(1);
      } //submenu end
      if(menuOption == 9){ //and menu option is 9 (room 3)
        get_submenu(2);
      } //submenu end
      if(menuOption == 10){ //and menu option is 9 (room 4)
        get_submenu(3);
      }
      if(menuOption == 11){ //and menu option is 11 (room 5)
        get_submenu(4);
      }
      if(menuOption == 12){ //and menu option is 12 (room 6)
        get_submenu(5);
      } //submenu end
      if(menuOption == 13){ //and menu option is 13 (room 7)
        get_submenu(6);
      } //submenu end
      if(menuOption == 14){ //and menu option is 14 (room 8)
        get_submenu(7);
      } //submenu end
      if(menuOption == 15){ //and menu option is 15 (room 9)
        get_submenu(8);
      } //submenu end
      if(menuOption == 16){ //and menu option is 16 (room 10)
        get_submenu(9);
      } //submenu end
      if(menuOption == 17){ //and menu option is 17 (AC setup)
        get_ac_setup();
        //submenu end
      }
      if(menuOption == 18){ //and menu option is 18 (AC room 1)
        get_ac_sub(10);
        //submenu end
      }
      if(menuOption == 19){ //and menu option is 19 (AC room 2)
        get_ac_sub(11);
        //submenu end
      }
      if(menuOption == 20){ //and menu option is 20 (AC room 3)
        get_ac_sub(12);
        //submenu end
      }
      if(menuOption == 21){ //and menu option is 21 (AC room 4)
        get_ac_sub(13);
        //submenu end
      }
      if(menuOption == 22){ //and menu option is 16 (room 10)
        get_submenu(15);
      } //submenu end
    }   
  }
}

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
  if(room == 15){
    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
  }
  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
      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;
      }
    }
    if(subButton == btnSelect){   //if we pressed btnSelect
      if(submenu == 1){           //and submenu is 1
        //call the function get_delay() to change the setting
        if(room == 15) return;
        delayTime[room] = get_delay(9, room, delayTime[room]);
        return;
      }
      if(submenu == 2){           //and sub menu is 2
        //call the function get_offon to change the setting
        timer_active[room][0] = get_offon(10, room, timer_active[room][0]);
        return;
      }
      if(submenu == 3){           //and submenu is 3
        //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;
      }
      if(submenu == 4){           //and submenu is 4
        //call the function get_offon() to change the setting
        timer_active[room][1] = get_offon(11, room, timer_active[room][1]);
        return;
      }
      if(submenu == 5){           //and submenu is 5
        //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;
      }
      if(submenu == 6 && timer_active[room][2] != 2){   //and submenu is 6
        //call the function get_offon() to change the setting
        timer_active[room][2] = get_offon(12, room, timer_active[room][2]);
        return;
      }
      if(submenu == 7 && timer_active[room][2] != 2){          //and submenu == 7
        //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;
      }
      if(submenu == 8 && timer_active[room][3] != 2){           //and submenu is 6
        //call the function get_offon() to change the setting
        timer_active[room][3] = get_offon(25, room, timer_active[room][3]);
        return;
      }
      if(submenu == 9 && timer_active[room][3] != 2){          //and submenu == 7
        //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;
      }
    }
  }
} 

 

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;
      case 5:
        //call the function get_offon() tu update settings
        startDelay = get_offon(39, 0, startDelay);
        return;
      }
    }
  }
}



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;
      }
    }
  }
}

void adj_seasons(){
  byte subButton = 0;  //set button var to 0
  ac_periode[0][0] = get_Timer(29, ac_periode[0][0], 0, 13);  //get the first value
  if(ac_periode[0][0] >= 0 && ac_periode[0][0] <= 12){        //check if it is within range
    if(ac_periode[0][0] == 12){                               //predefine closing value
      ac_periode[0][1] = 1;
      ac_periode[0][1] = get_Timer(30, ac_periode[0][1], 1, 13);
    }
    else if(ac_periode[0][0] != 12){ 
      ac_periode[0][1] = ac_periode[0][0] + 1;
      ac_periode[0][1] = get_Timer(30, ac_periode[0][1], ac_periode[0][1], 13);
    }
    if(ac_periode[0][1] >= 0 && ac_periode[0][1] <= 12){
      ac_periode[1][0] = get_Timer(31, ac_periode[1][0], 0, 13);
      if(ac_periode[1][0] >= 0 && ac_periode[1][0] <= 12){
        if(ac_periode[1][0] == 12){
          ac_periode[1][1] = 1;
          ac_periode[1][1] = get_Timer(32, ac_periode[1][1], 1, 13);
        }
        else if(ac_periode[1][0] != 12){ 
          ac_periode[1][1] = ac_periode[1][0] + 1;
          ac_periode[1][1] = get_Timer(32, ac_periode[1][1], ac_periode[0][1], 13);
        }
        if(ac_periode[1][1] >= 0 && ac_periode[1][1] <= 12){
          ac_periode[2][0] = get_Timer(33, ac_periode[2][0], 0, 13);
          if(ac_periode[2][0] >= 0 && ac_periode[2][0] <= 12){
            if(ac_periode[2][0] == 12){
              ac_periode[2][1] = 1;
              ac_periode[2][1] = get_Timer(34, ac_periode[2][1], 1, 13);
            }
            else if(ac_periode[2][0] != 12){ 
              ac_periode[2][1] = ac_periode[2][0] + 1;
              ac_periode[2][1] = get_Timer(34, ac_periode[2][1], ac_periode[2][1], 13);
            }
            if(ac_periode[2][1] >= 0 && ac_periode[2][1] <= 12){
              ac_periode[3][0] = get_Timer(35, ac_periode[3][0], 0, 13);
              if(ac_periode[3][0] >= 0 && ac_periode[3][0] <= 12){
                if(ac_periode[3][0] == 12){
                  ac_periode[3][1] = 1;
                  ac_periode[3][1] = get_Timer(36, ac_periode[3][1], 1, 13);
                }
                else if(ac_periode[3][0] != 12){ 
                  ac_periode[3][1] = ac_periode[2][0] + 1;
                  ac_periode[3][1] = get_Timer(36, ac_periode[3][1], ac_periode[3][1], 13);
                }
                lcd.clear();
                if(ac_periode[0][0] < 10) lcd.write(pgm_read_byte(&char_table[2]));  //print 0
                lcd.print(ac_periode[0][0]);
                lcd.print(" | ");
                if(ac_periode[0][1] < 10) lcd.write(pgm_read_byte(&char_table[2]));  //print 0
                lcd.print(ac_periode[0][1]);
                lcd.print(" ");
                if(ac_periode[1][0] < 10) lcd.write(pgm_read_byte(&char_table[2]));  //print 0
                lcd.print(ac_periode[1][0]);
                lcd.print(" | ");
                if(ac_periode[1][1] < 10) lcd.write(pgm_read_byte(&char_table[2]));  //print 0
                lcd.print(ac_periode[1][1]);
                lcd.setCursor(0, 1);
                if(ac_periode[2][0] < 10) lcd.write(pgm_read_byte(&char_table[2]));  //print 0
                lcd.print(ac_periode[2][0]);
                lcd.print(" | ");
                if(ac_periode[2][1] < 10) lcd.write(pgm_read_byte(&char_table[2]));  //print 0
                lcd.print(ac_periode[2][1]);
                lcd.print(" ");
                if(ac_periode[3][0] < 10) lcd.write(pgm_read_byte(&char_table[2]));  //print 0
                lcd.print(ac_periode[3][0]);
                lcd.print(" | ");
                if(ac_periode[3][1] < 10) lcd.write(pgm_read_byte(&char_table[2]));  //print 0
                lcd.print(ac_periode[3][1]);
                while(subButton != btnSelect){
                  lcd.clear();
                  lcd.print(strcpy_P(buffer_M, (char*)pgm_read_word(&(msg_table[1]))));
                  delay(1000);
                  //save the values
                  return;
                }
              }
            }
          }
        }
      }
    }
  }
}
                
                
  
byte get_setTime( byte onTimeH, byte onTimeM, byte offTimeH,
                  byte offTimeM, byte room, byte timer){
  byte subButton = 0;
  onTimeH = get_Timer(13, onTimeH, 0, 23);
  if(onTimeH >= 0 && onTimeH < 24){
    onTimeM = get_Timer(14, onTimeM, 0, 59);
    if(onTimeM < 60){
      offTimeH = get_Timer(15, offTimeH, 0, 23);
      if(offTimeH >= 0 && offTimeH < 24){
        offTimeM = get_Timer(16, offTimeM, 0, 59);
        if(offTimeM < 60){
          lcd.clear();
          lcd.print(strcpy_P(buffer_M, (char*)pgm_read_word(&(msg_table[6]))));
          lcd.setCursor(0, 1);
          if(onTimeH < 10) lcd.write(pgm_read_byte(&char_table[2]));  //print 0
          lcd.print(onTimeH);
          lcd.write(pgm_read_byte(&char_table[3]));   //print seperator
          if(onTimeM < 10) lcd.write(pgm_read_byte(&char_table[2]));  //print 0
          lcd.print(onTimeM);
          lcd.setCursor(11, 1);
          if(offTimeH < 10) lcd.write(pgm_read_byte(&char_table[2]));  //print 0
          lcd.print(offTimeH);
          lcd.write(pgm_read_byte(&char_table[3]));   //print seperator
          if(offTimeM < 10) lcd.write(pgm_read_byte(&char_table[2]));  //print 0
          lcd.print(offTimeM);
          while(subButton != btnSelect){
            subButton = read_act_buttons();
            if(subButton == btnMenu) return 0;
            if(subButton == btnSelect){
              lcd.clear();
              lcd.print(strcpy_P(buffer_M, (char*)pgm_read_word(&(msg_table[1]))));
              delay(1000);
              room_timers[room][timer][0] = onTimeH;
              room_timers[room][timer][1] = onTimeM;
              room_timers[room][timer][2] = offTimeH;
              room_timers[room][timer][3] = offTimeM;
              return 0;
            }
          }
        }
      }
    }
  }
}
          

//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 if(room == 0){
    lcd.print("  ");
  }
  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;
}
  

//function to adjust the pir delay time
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;
}

void adjust_date_time(){
  byte button = 0; //set button var to 0
  //function call to adjust the minute part of the system time
  byte minuteT = get_Timer(20, tm.Minute, 0, 59); 
  if(minuteT >= 0 && minuteT < 60){ //check the returned result
    //function call to adjust the hour part of the system time
    byte hourT = get_Timer(21, tm.Hour, 0, 23);
    if(hourT >= 0 && hourT < 24){ //check the returned result
      //function call to adjust the day of the week
      byte weekDay = get_weekday();  
      if(weekDay > 0 && weekDay <= 7){ //check the returned result
        //function call to adjust the day of the month
        byte monthDay = get_Timer(22, tm.Day, 1, 31);
        if(monthDay >= 1 && monthDay <=31){  //check the returned result
          //function call to adjust the month
          byte monthT = get_Timer(23, tm.Month, 1, 12);
          if(monthT >= 1 && monthT <= 12){ //check returned result
            //function call to adjust the year
            byte yearT = get_Timer(24, tmYearToCalendar(tm.Year)-2000, 0, 99);
            if(yearT >= 0 && yearT <= 99){ //check the returned results
              byte value = weekDay;   //passing on the variable for calculations
              //the following lcd statements print the adjusted results 
              //on the LCD
              lcd.clear();
              if(hourT < 10) lcd.write(pgm_read_byte(&char_table[2]));    //print 0
              lcd.print(hourT);
              lcd.write(pgm_read_byte(&char_table[3]));   //print seperator
              if(minuteT < 10) lcd.write(pgm_read_byte(&char_table[2]));  //print 0
              lcd.print(minuteT);
              lcd.setCursor(0, 1);
              lcd.print(strcpy_P(buffer, (char*)pgm_read_word(&(weekday_table[value-1]))));
              lcd.print(" ");
              if(monthDay < 10) lcd.write(pgm_read_byte(&char_table[2]));  //print 0
              lcd.print(monthDay);
              lcd.write(pgm_read_byte(&char_table[4]));   //print dott
              if(monthT < 10) lcd.write(pgm_read_byte(&char_table[2]));    //print 0
              lcd.print(monthT);
              lcd.write(pgm_read_byte(&char_table[4]));   //print dott
              lcd.print(yearT);
              while(button != btnSelect){   //loop until button select is pressed
                button = read_act_buttons();
                if(button == btnMenu) return; //if button Menu is pressed return without saving
                if(button == btnSelect){ //if button select is pressed
                  lcd.clear();
                  lcd.print(strcpy_P(buffer_M, (char*)pgm_read_word(&(msg_table[1])))); //print saving
                  delay(1000);
                  //function call to save the adjusted values to RTC
                  save_time(minuteT, hourT, weekDay, monthDay, monthT, yearT);
                }
              }
              return;
            }
          }
        }
      }
    }
  }
}

void save_time(byte mi, byte hr, byte wkDay, byte da, byte mo, byte yr){
  Wire.beginTransmission(DS1307_ADDRESS);  //starting transmission to DS 1307 RTC
  Wire.write(zero);                        //needed leading zero byte
  
  Wire.write(decToBcd(0));       //set seconds to 0
  Wire.write(decToBcd(mi));      //set minutes to updated value
  Wire.write(decToBcd(hr));      //set hour to updated value
  Wire.write(decToBcd(wkDay));   //set weekday to updated value
  Wire.write(decToBcd(da));      //set month day to updated value
  Wire.write(decToBcd(mo));      //set month to updated value
  Wire.write(decToBcd(yr));      //set year to updated value
  
  Wire.write(zero);              //send finishing zero byte
  
  Wire.endTransmission();        //close transmission
}

byte decToBcd(byte val){
  return ((val/10*16) + (val%10));
}

int get_Timer(byte info, int reading, int startVal, int maxCount){
  byte button = 0;                 //reseting the button var
  lcd.clear();                     //clear the screen
  lcd.print(strcpy_P(buffer_M, (char*)pgm_read_word(&(msg_table[info]))));  //print the passed on info text
  lcd.setCursor(0, 1);             //set the cursor to second row first column
  lcd.print(reading);              //print the passed on value to be changed
  while(button != btnSelect){      //wait for a button to be pressed
    button = read_act_buttons();   //check if a button is pressed
    if(button == btnSearch){       //if btnSearch is pressed
      //if the reading is somewhere between the limit we add 1
      //to the value with every loop through while the btnSearch
      //is pressed
      if(reading >= startVal && reading < maxCount) reading++;
      if(reading >= maxCount)reading = startVal;   //reset the value to be changed to
                                                   //the lower limit
      lcd.setCursor(0, 1);      //setting the cursor to first column, second row
      lcd.print(reading);       //print the updating value
      lcd.print("    ");        //print 4 empty spaces to delete left overs
                                //if we the value changes from high to
                                //low limit
    }
  }
  return reading;               //return the value
}

byte get_weekday(){
  byte button = 0;              //reseting the button var
  byte value = currentDay;      //passing the global weekday variable to a
                                //local one for calculations
  //Serial.println(currentDay); //debug only
  lcd.clear();                  //clear the screen
  //print what we are updating (weekday)
  lcd.print(strcpy_P(buffer_M, (char*)pgm_read_word(&(msg_table[5])))); 
  lcd.setCursor(0, 1);          //set the cursor to second row, first column
  //print the current value for weekday
  lcd.print(strcpy_P(buffer, (char*)pgm_read_word(&(weekday_table[value]))));
  while(button != btnSelect){   //waite for a button to be pressed
    button = read_act_buttons(); //checking for a button pressed 
    if(button == btnSearch){     //if it was btnSearch
      if(value >= 0 && value < 7) value++; //checking between 0 and 6
      if(value >= 7) value = 0;    //setting the value back to 0 
      //Serial.print("Value: "); //debug only
      //Serial.println(value);   //debug only
      lcd.setCursor(0, 1);       //set cursor to second row, first column
      //printing the ubdating value
      lcd.print(strcpy_P(buffer, (char*)pgm_read_word(&(weekday_table[value]))));
    }
  }
  return value + 1; //return the value and add 1 to be stored in RTC memory 
}

void get_error(byte msg, byte row){
  lcd.setCursor(0, row);
  lcd.print(strcpy_P(buffer_M, (char*)pgm_read_word(&(error_table[msg])))); 
}


///////////////////some easy inline logical functions////////////////////////////////////
int IIFi( boolean iLogicalValue, int iWhenTrue, int iWhenFalse ) {
  if (iLogicalValue) return iWhenTrue;
  else               return iWhenFalse;
}

String IIFs( boolean iLogicalValue, String iWhenTrue, String iWhenFalse ) {
  if (iLogicalValue) return iWhenTrue;
  else               return iWhenFalse;
}