Translate

Saturday, 24 May 2014

Room Management System – Adding a little more control to the AC's part 2


Today we are back at the breadboard. We add a LM 35 temperature sensor to our test circuit. If we look at the flat side of the sensor, the left pin connects to 5V supply voltage, the right pin to ground and the centre pin we connect to Atmega pin 25 (analogue pin 2).



Back to building the code. We start again adding a few more variables into the declaration part of our sketch. Staying pretty much in the beginning, we add:

#define DS1307_ADDRESS 0x68

byte zero = 0x00;

//uncomment the lines below for debugging

//#define DA_DEBUG_serial //to enable Serial monitor

//#define DA_DEBUG_in //debug the input stage

//>>>>>>>>>>>>>ADD the line below<<<<<<<<<<<<<<

//#define DA_DEBUG_tmp //check temperature readings

//#define DA_DEBUG_holtimers //debug the holiday timers

//#define DA_DEBUG_out //debug the output stage

//#define DA_DEBUG_photo //debug control from photocell for holiday switching

/////////////////////Declaring the Variables/////////////////

Now we go into the “Timer and Sensitivity Settings” section and add:

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

//>>>>>>>>>>>>>Addition starts here<<<<<<<<<<<<<

byte ac_op_mode = 2; //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

//>>>>>>>>>>>>>Addition ends here<<<<<<<<<<<<<

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//////////////////////

From her we go down just a little further and in the “Defining the Arduino pins” section we add:

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

Just a little further down in the “All the other variables” section we add:

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

///////////////////////////////////////////////////////////////////////////////

////Sensor and timer variables

int delayTime[16] = {dBed1, dBed2, dBed3, dLiving, dBath1, dBath2, dBath3,

dBath4, dKitchen, dCorridor, dAC1, dAC2, dAC3, dAC4,

dMaster, 0};

//>>>>>>>>>>>>>ADD the line below<<<<<<<<<<<<<

byte temperatur1 = 0; //holding temperature for room 1

int sensorValue = 0; //holding the indicated sensor value of the photocell

byte photocellSwitch = 0; //holding the switch command after 

Now we are going down in to the main loop and add after the “checking the light status” section the code for the temperature sensor:

//////////////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);

//>>>>>>>>>>>>>>Addition starts here<<<<<<<<<<<<<

///////////////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 Temperature: ");

Serial.println(temperatur1);

#endif

//>>>>>>>>>>>>>>Addition ends here<<<<<<<<<<<<<<

//////////////////processing the input/////////////////////

Lets have a quick look into the map statement “map(analogRead(TMP01),0,410,-40,125);”

map is a telling the system to convert a range of values into another range of values. I guess we can skip the analogRead part of it and go straight to the numbers. Our analogue input will read values between 0 and 1023 on a max. allowed input voltage range between 0 an 5 Volt. To convert the analogue reading into a voltage reading we would need to type in the command
map(analogRead(analogPin)0, 1023, 0, 5); This would convert the analogue Range between 0 and 1024 to our voltage range between 0 and 5.

I am using a TMP36 sensor, which is giving a output voltage from 100 to 2000 mV having a maximum operating range from -50 and 150 degrees Celsius. A lot of tutorials using the max values to map the range. I had a hell of a time to find out why the temperature value was always about 5 to 6 degrees above the actual temperature. If we look a little closer into the data sheet of the TMP36, we also find a line:
Scale Factor, TMP36 -40°C ≤ T + 125°C
This are the values we have to work with!
Going back to our map command. Since the analogue pin is set to measure up to 5 V by default, we have to tell the system, that we only have a voltage range from 100 mV (0,1 Volt set to 0) and 2000 mV (2 Volt).
I was taking it very simple and divided the max output value 1023 by 5 max default Voltage which gives us a result of 204.8. This multiplied by 2 Volt (max sensor output) comes up to 409.6 (set to 410).
This makes the first two numbers in the map command. The second two numbers are the range we are measuring, -40°C to 125°C.
There we are:

temp1 += map(analogRead(TMP01)0,410,-40,125).


Since we have implemented a temperature sensor and passed the reading to a variable so we can use it throughout the rest of the sketch, we go down to the ac_read() function and insert the temperature check. If you did pay attention at the beginning, when we added the variables, we also added one called “byte ac_op_mode = 2;”. If you remember the first post about implementing a little more control over the AC-units, we talked about 3 different ways of controlling it. The first on was using the AC's controller for general functions and use the Room Management System only to shut it of when a door or window is opened for more than a predefined time. The second option was to be able switching the AC's on and off according to timer and sensor settings outside the Controls using eider the AC's Auto restart ability or if the AC unit has a toggle switch to turn it of or on where we can plug in to. Option three was the same as option 2 but having a momentary switch (push button) to plug into. In this post we will take care of option 1 and 2 and as just mentioned above the implementation of temperature control. There fore we go down to the ac_read() function.

Th first thing we do, we rebuild the function above or below and start with:

unsigned long ac_read(byte readSw, byte room, unsigned long light){

}

Next, we cut and paste the line where we get the seasonal periode:

unsigned long ac_read(byte readSw, byte room, unsigned long light){

byte periode = get_ac_periode(); //function call to check time periode (season)

}

We do the same with the next if-statement where we check if a time is set to switch on the unit and add a statement checking for the temperature.

unsigned long ac_read(byte readSw, byte room, unsigned long light){

byte periode = get_ac_periode(); //function call to check time periode (season)

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){ //<<<<<<<<<<<<<NOTE the temperature check<<<<<<<<<<<<<

priorityStatus[room] = 1; //set priority status to 1 if yes

}

else{

priorityStatus[room] = 0; //set priority status to 0 if no

}

}

After that we add the mode structure:


unsigned long ac_read(byte readSw, byte room, unsigned long light){

byte periode = get_ac_periode(); //function call to check time periode (season)

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){ //<<<<<<<<<<<<<NOTE the temperature check<<<<<<<<<<<<<

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){

//add code for mode 1

}

else if(ac_op_mode == 2){

//add code for mode 2

}

else if(ac_op_mode == 3){

//add code for mode 3

}

}

Remember the code we had, just after we converted the the code for the AC units into a function, switching the AC's off soon as a window or a door is opened? If you still have it somewhere, just copy and paste it into the part where I made the note “//add code for mode 1. Second, cut the rest of the code from the previous ac_read() function and paste it in the one we just rebuild into the part where I wrote the note “add code for mode 2”:


unsigned long ac_read(byte readSw, byte room, unsigned long light){

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] = light; //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; //cancelling ability to switch on the

//AC

lightStatus[room] = 0; //resetting the light (AC) status

roomTimer[room] = 0; //resetting the timer

}

}

}

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] = light; //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 windows 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] = light; //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; //cancelling 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(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] = light; //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; //cancelling ability to switch on the

//AC

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

}

Please don't forget to delete what's left from the old ac_read() function or you will get a compiler error.
In the next post we take care of the possibility of the AC switch is a momentary switch (push button.

No comments:

Post a Comment