/////////////////////////////////////////////////////////////////////////////////// ////Room Management System Version 1.4.5/////////////////////////////////////////// ////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. /////////// /////////////////////////////////////////////////////////////////////////////////// ////For details on the GNU General Public License please visit /////////// ////the website <http://www.gnu.org/licenses/>. /////////// /////////////////////////////////////////////////////////////////////////////////// //////////////////////////Credits////////////////////////////////////////////////// ////A very big thank you goes to my wife and my daughter for all /////////// ////their support and patience. /////////// ////To Rene, for helping in improofing the input stage and the way /////////// ////of debugging the code. And showing me a way of programming /////////// ////which will finde a definite place in future projects. /////////// ////To Reuben, who was a very great help in optimizing the /////////// ////menu part of the program. /////////// ////To all the guys in the ARDUINO Forum, answering all my /////////// ////quetions and also helping debugging some of the code. /////////// /////////////////////////////////////////////////////////////////////////////////// /////////////////////Includes///////////////////////////// #include <DS1307RTC.h> #include <Time.h> #include <Wire.h> #include <ShiftLCD.h> #include <avr/pgmspace.h> #include <EEPROM.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; //////////////DEBUGGING/////////////// //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///////////////// /////////////EEPROM Storage////////////// int eepromValue = 0; const byte EEPROM_ID = 111; const int ID_ADDR = 0; const byte Sensitivity_ADDR = 1; //2 byte value const byte photoCellCutOff_ADDR = 3; //2 byte value const byte photoOutsideOff_ADDR = 5; //2 byte value const int startDelay_ADDR = 374; //1 byte value const int acSwitchDelay_ADDR = 375; //1 byte value const int ac_op_mode_ADDR = 376; //1 byte value const int ac_set_temp_ADDR = 377; //1 byte value const byte delayTime_ADDR[15] PROGMEM = {7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35}; const byte timer_active_ADDR[16][4] PROGMEM = { {37, 38, 39, 40}, {41, 42, 43, 44}, {45, 46, 47, 48}, {49, 50, 51, 52}, {53, 54, 55, 56}, {57, 58, 59, 60}, {61, 62, 63, 64}, {65, 66, 67, 68}, {69, 70, 71, 72}, {73, 74, 75, 76}, {77, 78, 79, 80}, {81, 82, 83, 84}, {85, 86, 87, 88}, {89, 90, 91, 92}, {93, 94, 95, 96}, {97, 98, 99, 100} }; const int room_timers_ADDR[16][4][4] PROGMEM = { { {102, 103, 104, 105}, {106, 107, 108, 109}, {110, 111, 112, 113}, {114, 115, 116, 117} }, { {118, 119, 120, 121}, {122, 123, 124, 125}, {126, 127, 128, 129}, {130, 131, 132, 133} }, { {134, 135, 136, 137}, {138, 139, 140, 141}, {142, 143, 144, 145}, {146, 147, 148, 149} }, { {150, 151, 152, 153}, {154, 155, 156, 157}, {158, 159, 160, 161}, {162, 163, 164, 165} }, { {166, 167, 168, 169}, {170, 171, 172, 173}, {174, 175, 176, 177}, {178, 179, 180, 181} }, { {182, 183, 184, 185}, {186, 187, 188, 189}, {190, 191, 192, 193}, {194, 195, 196, 197} }, { {198, 199, 200, 201}, {202, 203, 204, 205}, {206, 207, 208, 209}, {210, 211, 212, 213} }, { {214, 215, 216, 217}, {218, 219, 220, 221}, {222, 223, 224, 225}, {226, 227, 228, 229} }, { {230, 231, 232, 233}, {234, 235, 236, 237}, {238, 239, 240, 241}, {242, 243, 244, 245} }, { {246, 247, 248, 249}, {250, 251, 252, 253}, {254, 255, 256, 257}, {258, 259, 260, 261} }, { {262, 263, 264, 265}, {266, 267, 268, 269}, {270, 271, 272, 273}, {274, 275, 276, 277} }, { {278, 279, 280, 281}, {282, 283, 284, 285}, {286, 287, 288, 289}, {290, 291, 292, 293} }, { {294, 295, 296, 297}, {298, 299, 300, 301}, {302, 303, 304, 305}, {306, 307, 308, 309} }, { {310, 311, 312, 313}, {314, 315, 316, 317}, {318, 319, 320, 321}, {322, 323, 324, 325} }, { {326, 327, 328, 329}, {330, 331, 332, 333}, {334, 335, 336, 337}, {338, 339, 340, 341} }, { {342, 343, 344, 345}, {346, 347, 348, 349}, {350, 351, 352, 353}, {354, 355, 356, 357} } }; const int ac_forced_on_ADDR[4][2] PROGMEM = { {358, 359}, {360, 361}, {363, 363}, {364, 365} }; const int ac_periode_ADDR[4][2] PROGMEM = { {366, 367}, {368, 369}, {370, 371}, {372, 373} }; const int ac_master_bypass_ADDR[4] PROGMEM = {378, 379, 380, 381}; ///////////Timer and Sensitivity Settings to be changed to individual needs//////////////// 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; /*int delayTime[16] = {dBed1, dBed2, dBed3, dLiving, dBath1, dBath2, dBath3, dBath4, dKitchen, dCorridor, dAC1, dAC2, dAC3, dAC4, dMaster, 0};*/ int delayTime[15] = {120, 120, 120, 600, 180, 180, //delay time in seconds to the above order 180, 180, 120, 120, 120, 120, 120, 120, 240}; 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 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 unsigned int displayTimeSet = millis()/1000; //variable needed for display exchange //////////////////////////////////////////////////////////////////////////////////////// //////////////////////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 switchStateOld[4] = {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 = 10; //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.5"; 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"; prog_char msg_40[] PROGMEM = "Initializing...."; prog_char msg_41[] PROGMEM = "Reading...."; //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, msg_40, msg_41 }; //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 }; ////////////////Error Handling///////////// prog_char error_0[] PROGMEM = "RTC ERR"; prog_char error_1[] PROGMEM = "RTC Read ERR"; prog_char error_2[] PROGMEM = "EEPROM empty!"; prog_char error_3[] PROGMEM = "EEP write error"; PROGMEM const char *error_table[] = { error_0, error_1, error_2, error_3 }; void setup() { //////////////Start Serial for Debugging///////////////////// #ifdef DA_DEBUG_serial Serial.begin(9600); #endif lcd.begin(16, 2); lcd.clear(); eepromValue = Mem_readByte(ID_ADDR); //check if the eeprom holds valid data if(eepromValue != EEPROM_ID){ get_error(2, 0); //if not, display an error delay(5000); //load default var values //work with default variables declared //in the declaration section above } else{ //read the values from the eeprom sensitivity = Mem_readInt(Sensitivity_ADDR); //sensitivity photoCellCutOff = Mem_readInt(photoCellCutOff_ADDR); //photocell cut off value for rooms photoOutsideOff = Mem_readInt(photoOutsideOff_ADDR); //photocell cut off value for outside for(int i=0; i<15; i++){ //PIR and AC cut off delay times delayTime[i] = Mem_readInt(pgm_read_byte(&(delayTime_ADDR[i]))); } for(int x=0; x<16; x++){ //holiday lighting and ac timers active settings for(int y=0; y<4; y++){ timer_active[x][y] = Mem_readByte(pgm_read_byte(&(timer_active_ADDR[x][y]))); } } for(int x=0; x<16; x++){ //holiday lighting and ac timer settings for(int y=0; y<4; y++){ for(int z=0; z<4; z++){ room_timers[x][y][z] = Mem_readByte(pgm_read_byte(&(room_timers_ADDR[x][y][z]))); } } } for(int x=0; x<4; x++){ //ac forced on setting for(int y=0; y<2; y++){ ac_forced_on[x][y] = Mem_readByte(pgm_read_byte(&(ac_forced_on_ADDR[x][y]))); } } for(int x=0; x<4; x++){ //seasonal settings for ac use for(int y=0; y<2; y++){ ac_periode[x][y] = Mem_readByte(pgm_read_byte(&(ac_periode_ADDR[x][y]))); } } startDelay = Mem_readByte(startDelay_ADDR); //ac start delay (compressor protection acSwitchDelay = Mem_readByte(acSwitchDelay_ADDR); //ac switch time for op mode 3 ac_op_mode = Mem_readByte(ac_op_mode_ADDR); //ac mode ac_set_temp = Mem_readByte(ac_set_temp_ADDR); //ac temperature setting for(int i=0; i<4; i++){ //ac master bypass ac_master_bypass[i] = Mem_readByte(pgm_read_byte(&(ac_master_bypass_ADDR[i]))); } } //printing initialisation message lcd.clear(); lcd.print(strcpy_P(buffer_M, (char*)pgm_read_word(&(msg_table[4])))); delay(1000); lcd.setCursor(0, 1); lcd.print(strcpy_P(buffer_M, (char*)pgm_read_word(&(msg_table[3])))); delay(2000); //////////////////defining pin modes//////////////////// pinMode(doorMonitor, OUTPUT); //setting the LED pin to output 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 } else { get_error(0, 1); } endTime = (millis()/1000) - displayTimeSet; if(endTime <= 15) displayDateTime(); if(endTime > (15) && endTime <= (30)) displayTemp(); if(endTime > 30) displayTimeSet = millis()/1000; 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); 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 //outputOld = outputL; outputL = 0; //setting the var holding the output //number back to 0 delay(sensitivity); //delay to adjust how responsive the //system will react } //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 } } } //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 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) lcd.print(" "); } //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 temerature 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 } ////////////////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 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 && 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]; } 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 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 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 //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 > 158 && act_key_in < 188) return btnMenu; if(act_key_in > 195 && act_key_in < 225) return btnSearch; if(act_key_in > 231 && 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 Mem_updateInt(Sensitivity_ADDR, sensitivity); return; } if(menuOption == 3){ //and menu option is 3 photoCellCutOff = get_Timer(18, photoCellCutOff, 0, 1024); //go to function Mem_updateInt(photoCellCutOff_ADDR, photoCellCutOff); 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 Mem_updateInt(photoOutsideOff_ADDR, photoOutsideOff); 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; case 10: 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]); Mem_updateInt(delayTime_ADDR[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]); Mem_updateByte(pgm_read_byte(&(timer_active_ADDR[room][0])), 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]); Mem_updateByte(pgm_read_byte(&(timer_active_ADDR[room][1])), 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]); Mem_updateByte(pgm_read_byte(&(timer_active_ADDR[room][2])), 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]); Mem_updateByte(pgm_read_byte(&(timer_active_ADDR[room][3])), 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; } if(submenu == 10) 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); Mem_updateByte(ac_op_mode_ADDR, ac_op_mode); return; case 2: //call the function get_timer() to update settings ac_set_temp = get_Timer(27, ac_set_temp, 18, 32); Mem_updateByte(ac_set_temp_ADDR, ac_set_temp); return; case 3: adj_seasons(); return; case 4: //call the function get_timer() to update settings acSwitchDelay = get_Timer(28, acSwitchDelay, 1, 5); Mem_updateByte(acSwitchDelay_ADDR, acSwitchDelay); return; case 5: //call the function get_offon() tu update settings startDelay = get_offon(39, 0, startDelay); Mem_updateByte(startDelay_ADDR, 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]); Mem_updateInt(pgm_read_byte(&(delayTime_ADDR[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]); Mem_updateByte(pgm_read_byte(&(ac_master_bypass_ADDR[room - 10])), 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]); Mem_updateByte(pgm_read_byte(&(timer_active_ADDR[room][0])), 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]); Mem_updateByte(pgm_read_byte(&(timer_active_ADDR[room][1])), 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]); Mem_updateByte(pgm_read_byte(&(timer_active_ADDR[room][2])), 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]); Mem_updateByte(pgm_read_byte(&(timer_active_ADDR[room][3])), 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])))); //save the values Mem_updateByte(pgm_read_byte(&(ac_periode_ADDR[0][0])), ac_periode[0][0]); Mem_updateByte(pgm_read_byte(&(ac_periode_ADDR[0][1])), ac_periode[0][1]); Mem_updateByte(pgm_read_byte(&(ac_periode_ADDR[1][0])), ac_periode[1][0]); Mem_updateByte(pgm_read_byte(&(ac_periode_ADDR[1][1])), ac_periode[1][1]); Mem_updateByte(pgm_read_byte(&(ac_periode_ADDR[2][0])), ac_periode[2][0]); Mem_updateByte(pgm_read_byte(&(ac_periode_ADDR[2][1])), ac_periode[2][1]); Mem_updateByte(pgm_read_byte(&(ac_periode_ADDR[3][0])), ac_periode[3][0]); Mem_updateByte(pgm_read_byte(&(ac_periode_ADDR[3][1])), ac_periode[3][1]); delay(1000); 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, 24); if(onTimeH >= 0 && onTimeH < 24){ onTimeM = get_Timer(14, onTimeM, 0, 60); if(onTimeM < 60){ offTimeH = get_Timer(15, offTimeH, 0, 24); if(offTimeH >= 0 && offTimeH < 24){ offTimeM = get_Timer(16, offTimeM, 0, 60); 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); Mem_updateByte(pgm_read_byte(&(room_timers_ADDR[room][timer][0])), onTimeH); room_timers[room][timer][0] = onTimeH; Mem_updateByte(pgm_read_byte(&(room_timers_ADDR[room][timer][1])), onTimeM); room_timers[room][timer][1] = onTimeM; Mem_updateByte(pgm_read_byte(&(room_timers_ADDR[room][timer][2])), offTimeH); room_timers[room][timer][2] = offTimeH; Mem_updateByte(pgm_read_byte(&(room_timers_ADDR[room][timer][3])), offTimeM); 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, 60); 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, 24); 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, 32); if(monthDay >= 1 && monthDay <=31){ //check the returned result //function call to adjust the month byte monthT = get_Timer(23, tm.Month, 1, 13); 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 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; } void Mem_writeByte(int address, byte value){ EEPROM.write(address, value); delay(5); byte reading = Mem_readByte(address); if(reading != value){ get_error(3, 1); delay(60000); } } // the writeBytes takes care of the delay.. void Mem_writeInt(int address, int value) { Mem_writeByte(address, highByte(value) ); Mem_writeByte(address+1, lowByte(value) ); } void Mem_updateByte(int address, byte value){ byte reading = EEPROM.read(address); if(reading != value) Mem_writeByte(address, value); } void Mem_updateInt(int address, int value){ Mem_updateByte(address, highByte(value)); //high byte Mem_updateByte(address+1, lowByte(value)); //low byte } byte Mem_readByte(int address){ byte value = EEPROM.read(address); return value; } int Mem_readInt(int address){ byte hiByte = EEPROM.read(address); byte loByte = EEPROM.read(address+1); int value = word(hiByte, loByte); return value; }
Translate
Showing posts with label light control. Show all posts
Showing posts with label light control. Show all posts
Sunday, 22 June 2014
The current working sketch of the Room Management System
Subscribe to:
Posts (Atom)