/////////////////////////////////////////////////////////////////////////////////// ////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; }
Translate
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.
Labels:
AC control,
arduino,
atmega,
binary,
coding,
home automation,
intelligent lighting,
LCD,
light control,
menu,
photocell,
PIR,
progmem,
real time,
room management,
RTC,
shift register,
submenu,
temperature sensor
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment