/////////////////////////////////////////////////////////////////////////////////// ////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
Sunday, 22 June 2014
The current working sketch of the Room Management System
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment