Today we are programming mode 3 of the
AC control sequence and I have a couple of changes in the rest of the
ac_read() function.
As usual, we start at the top of the
sketch in the declaration part. Since we have added quite a bit of
functionality since we started and the processor has to go through
quite a bit of code, we make the unit a little more responsive again
and reduce the default sensitivity value from 400 to 300.
/////////////////////Declaring the Variables///////////////// ///////////Timer and Sensitivity Settings to be changed to individual needs//////////////// //>>>>>>>>>>>>>CHANGE the sensitivity value to 300<<<<<<<<<<<<< unsigned int sensitivity = 300; //should be between 0 and 500 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;
After that, we stay in the same section
and move just a little down where we have to add the time value we
want to pulse the momentary switch of the AC.
int dAC3 = 120; //delay time in seconds for AC 3 (bed3) int dAC4 = 120; //delay time in seconds for AC 4 (living) int dMaster = 240; //delay time in seconds for Master Off //>>>>>>>>>>>>>ADD the line below<<<<<<<<<<<<<< byte acSwitchDelay = 3; //ac pulse 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//////////////////////
Now we move down to the “All the
other Variables” section and add the output values for the AC to
the outputValues[] array. We also need to alter the reserved spaces
in the roomLight[] array from roomLight[10] = {0}; to roomLight[14]
= {0};
byte lightLevel[17] ={0}; //array holding the switch state //checking timer and photocell (0, 1) byte roomLight[14] = {0}; //array holding the switch on command in holiday lighting //and in AC operating mode 3 //>>>>>>>>>>>>>REPLACE the existing outputValues[10] with the line below<<<<<<<<<<<<< unsigned int outputValues[14] = {1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192}; 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
Now we move down into the main loop to
the “AC read switches” section.
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//////////////////////// //>>>>>>>>>>>>To be replaced<<<<<<<<<<<<< lightOutput[10] = ac_read(14, 10, 1024); lightOutput[11] = ac_read(15, 11, 2048); lightOutput[12] = ac_read(16, 12, 4096); lightOutput[13] = ac_read(17, 13, 8192); //>>>>>>>>>>>>>Replacement ends here<<<<<<<<<<<< /////////////Door switch control //////////////////// //Serial.print("switchState 18 :");
The section above reads after
replacement:
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//////////////////////// lightOutput[10] = ac_read(14, 10); lightOutput[11] = ac_read(15, 11); lightOutput[12] = ac_read(16, 12); lightOutput[13] = ac_read(17, 13); /////////////Door switch control //////////////////// //Serial.print("switchState 18 :");
Since we added the output values to the
outputValues[] array, we don't need to pass them on into the
ac_read() function.
Time to jump down into the ac_read()
function. First, we remove the variable “unsigned long light” in
the functions initializing line. Second, we replace all the “light”
variables in the function with outputValues[room].
unsigned long ac_read(byte readSw, byte room, unsigned long light){ //<<<<<<<<<<REMOVE “unsigned long light” byte periode = get_ac_periode(); //function call to check time periode (season) //check if a forced switch on is defined 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){ //Checking if readswitches are activated //and the master relay is on AC room 1 (bed1) lightOutput[room] = light; //<<<<<<<<<<<<REPLACE all lightOutput[room] = light //statements with lightOutput[room] = outputValues[room]; //switch on the AC
Now we move down to the end of the
function and replace the end part:
lightStatus[room] = 0; //resetting the light (AC) status roomTimer[room] = 0; //resetting the timer } } } } else if(ac_op_mode == 3){ //still being worked on } return lightOutput[room]; }
with
lightStatus[room] = 0; //resetting the light (AC) status roomTimer[room] = 0; //resetting the timer } } } return lightOutput[room]; } else if(ac_op_mode == 3){ //AC operating mode 3 lightOutput[room] = 0; //Setting the lightOutput to 0 if(roomLight[room] == 1){ //if a "on" command was given currentTime = millis()/1000; //set timer for reference endTime = currentTime - roomTimer[room]; //compare reference with set time if(endTime >= acSwitchDelay){ //check if it matches allowed difference lightStatus[room] = 1; //set AC status to on roomLight[room] = 0; //cancel "on" command return 0; //return 0 } else{ return outputValues[room]; //pulse the switch while "on" command active } } if(roomLight[room] == 2){ //if an "off" command was given check delay timer currentTime = millis()/1000; //set time for reference endTime = currentTime - roomTimer[room]; //compare reference with set off delay if(endTime >= delayTime[room]){ //check if it matches allowed difference 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 currentTime = millis()/1000; //set time for reference endTime = currentTime - roomTimer[room]; //compare reference with set time if(endTime >= acSwitchDelay){ //check if it matches allowed difference lightStatus[room] = 0; //reset command status roomLight[room] = 0; //reset AC status 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; }
Let's have a quick look what's going on
in this part. Since we are switching the AC by using the AC's On/Off
button, we do not want a constant output throughout the running time.
We need to simulate the “button press”. Therefore we need to
check our events like is the switch on or switch off time reached,
is the master relay activated or not or is one of the corresponding
windows open and is the AC running. If one of the events is true,
depending on a switch on or switch off command, the system will
either got into the on sequence, giving the output value for a
predefined time or into the off sequence running through a
preprogrammed off delay and going again into the on sequence to
activate the “button” for a predefined time to switch the system
off.
In checking if the AC is running, we
have to be a little careful, since we do not have a feedback from the
AC itself what it's doing. We have to rely on the fact, that the user
is programming the AC's timers and thermostat to stay within the
programmed limits of this approach in the room management system. If
the AC is programmed differently from it's internal controls, it
might override the given on or off command from the room management
system. Maybe at a later state, I will check if it is possible to
check the AC's current draw to determine a off or on state off the AC
and implement a little check routine. But that is on my to do list
for further development.
Since we have done a few changes, here
the full code of our ac_read() function.
unsigned long check_light_N(byte pir, byte room, unsigned long light){ if(switchState[pir] == 1) { //checking S9 PIR of bathroom 1 //(room 5) //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 yelay 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 //Serial.println("We are checking the timer"); //Debug only currentTime = millis()/1000; //setting time reference endTime = currentTime - roomTimer[room]; //calculating the inactive time if(endTime >= delayTime[room]) { //comparing inactive time with //delay time //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){ //Checking if readswitches are activated //and the master relay is on AC room 1 (bed1) 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 } else if(switchState[readSw] == 0 && lightStatus[14] == 1){ //if a door is opened and the master //relay is on currentTime = millis()/1000; //setting time reference endTime = currentTime - roomTimer[room]; //calculating the inactive time if(endTime >= delayTime[room]){ //comparing inactive time with //delay time lightOutput[room] = 0; //canceling ability to switch on the //AC lightStatus[room] = 0; //resetting the light (AC) status roomTimer[room] = 0; //resetting the timer } } 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){ //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){ lightOutput[room] = outputValues[room]; //switch on the AC lightStatus[room] = 1; //setting the light (AC) status roomTimer[room] = millis()/1000; //setting the timer } } else if(switchState[readSw] == 1 && priorityStatus[room] == 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 lightOutput[room] = outputValues[room]; //switch on the AC lightStatus[room] = 1; //setting the light (AC) status roomTimer[room] = millis()/1000; //setting the timer } else{ lightOutput[room] = 0; //keep it off lightStatus[room] = 0; //setting the light (AC) status roomTimer[room] = 0; //resetting the room timer } } else if(switchState[readSw] == 0 && lightStatus[14] == 1){ //if a door is opened and the master //relay is on currentTime = millis()/1000; //setting time reference endTime = currentTime - roomTimer[room]; //calculating the inactive time if(endTime >= delayTime[room]){ //comparing inactive time with //delay time lightOutput[room] = 0; //canceling ability to switch on the //AC lightStatus[room] = 0; //resetting the light (AC) status roomTimer[room] = 0; //resetting the timer } } } else if(ac_master_bypass[room - 10] == 1){ //if master relay bypass is on if(switchState[readSw] == 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){ 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 } } else if(switchState[readSw] == 0){ //if a door is opened and the master //relay is on currentTime = millis()/1000; //setting time reference endTime = currentTime - roomTimer[room]; //calculating the inactive time if(endTime >= delayTime[room]){ //comparing inactive time with //delay time lightOutput[room] = 0; //canceling ability to switch on the //AC lightStatus[room] = 0; //resetting the light (AC) status roomTimer[room] = 0; //resetting the timer } } } return lightOutput[room]; } else if(ac_op_mode == 3){ //AC operating mode 3 lightOutput[room] = 0; //Setting the lightOutput to 0 if(roomLight[room] == 1){ //if a "on" command was given currentTime = millis()/1000; //set timer for reference endTime = currentTime - roomTimer[room]; //compare reference with set time if(endTime >= acSwitchDelay){ //check if it matches allowed difference lightStatus[room] = 1; //set AC status to on roomLight[room] = 0; //cancel "on" command return 0; //return 0 } else{ return outputValues[room]; //pulse the switch while "on" command active } } if(roomLight[room] == 2){ //if an "off" command was given check delay timer currentTime = millis()/1000; //set time for reference endTime = currentTime - roomTimer[room]; //compare reference with set off delay if(endTime >= delayTime[room]){ //check if it matches allowed difference 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 currentTime = millis()/1000; //set time for reference endTime = currentTime - roomTimer[room]; //compare reference with set time if(endTime >= acSwitchDelay){ //check if it matches allowed difference lightStatus[room] = 0; //reset command status roomLight[room] = 0; //reset AC status 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; }
Finally today a small description on
how to connect the AC control to your unit.
First a small warning:
You are dealing with domestic
electricity, 230 Volt in Europe and 110 Volt (US).
Before any attempt of opening your AC
unit even only to check for the ability of connecting it to the
room management system, always
disconnect it from the power supply. Failing to do so might cause
serious damage to the equipment or serious personnel insure or death.
If you are not sure what you are doing,
please ask for professional advise. Making wrong connections can
cause damage to your equipment or personal injury or death.
- Running it in Mode 1 – using only read switches to check if corresponding doors or windows are opened.That's usually easiest part. Please check at your AC's installation manual since at least the newer units are prepared for this feature. Instead of connecting all the read switches to the connection for it on the AC unit, you connect the for this unit designated relay from the room management system to it. If you have a to way relay, please connect the cables to the NO (normally open) part of the relay. The read switches are connected as usual in series as shown in a sample drawing here:http://arduinopraxis.blogspot.com/2014/03/room-management-system-putting-it.html
- Running it in Mode 2 – controlling the AC using the AC's auto restart abilityThe readswitches are connected as described in point 1. The relay from the room management system is controlling a contactor, which is able to switch the full AC's load. The AC's power supply is running through the contactor, so we actually cut the AC's power supply when switching it off. The AC recognizes it as power cut. If we want to switch the AC back on, we reactivate the contactor through the room management systems relay. The AC recognizes the power is coming back and reactivated the Unit to the last running conditions.Here we need to be a little careful with programming the unit it self. We have to make sure, that the program in the AC's internal controller is programmed within the programmed limits of the room management system.
- Running it in Mode 2 – replacing the AC – units switch with relay contacts controlled by our room managements system.That's most likely on older units still having an old fashion switch and being controlled through a wired thermostat. There we just need to take out the old switch and the connections go to the NO 9normally open) part of the room managements corresponding relay.
- Running it in Mode 3 – using the room managements system corresponding relay to simulate the AC's on/off button (push button). That's a little bit more difficult task, since it involves taking out a circuit board and solder a couple of wires to the push button pins, which again connect to the NO part of the corresponding relay of the room management system.In this case, great care has to be taken in programming the AC's controller and the room management system. The AC's controller has to be programmed to work within the limits of the room management system program. Other wise the AC controller and the room management system cancelling each other out in off and on commands which might result in uncontrolled AC-switching, which again might cause serious damage to the AC unit.
In the next post we start implementing
the AC control into the menu of the room management system.
No comments:
Post a Comment