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