Since I had a few days now calculating
and playing around with the program memory I found out, that it will
be close to squeeze everything on the Atmega 328. The first step to
get it done is to do a little “house keeping”. Since I started
the project with just a simple task, making lights go on and off
using PIR's and time delays it was growing quite a bit, adding the
RTC, the automatic switch mode while the house is vacant and now we
try to build a menu on top. Before we start, with the final task, we
need to free up some memory, both, program memory and RAM.
First we have a closer look at our
sketch where we check the various PIR's and priority switches to
determine if a light is to be on or off and we find, that we repeat
the same code for every room. That's a call for packing it into a
function.
There for we go into the main loop of
the sketch and find the part where it says
“
//////////////////room lights//////////////////////////////” In my
sketch it's currently line 885 but that may vary depending on your
commenting and the amount of Serial.print statements for debugging.
Here we find the following code:
if(switchState[0] == 1 &&
lightStatus[16] == 1) { //checking if PIR in Room 1 was
//activated (bed 1)
lightStatus[16] = 0;
//resetting master off
digitalWrite(doorMonitor,
LOW); //resetting the door Monitor LED
}
and replace it with:
check_master(0);
Resetting the master timer which we do
for every set of PIR's no goes into the function called
check_master(switch Number) from switchState[switch Number].
Now we go down to the far end of the
sketch and write the function:
void check_master(byte swNo){
if(switchState[swNo] == 1 &&
lightStatus[16] == 1) { //checking if PIR with swNo was
//activated
lightStatus[16] = 0;
//resetting master off
digitalWrite(doorMonitor, LOW);
//resetting the door Monitor LED
}
}
We find the same peace of code for the
next room :
if(switchState[2] == 1 &&
lightStatus[16] == 1) { //checking if PIR in Room 2 was
//activated (bed 2)
lightStatus[14] = 0;
//resetting master off
digitalWrite(doorMonitor, LOW);
//resetting the door Monitor LED
}
and replace it with:
check_master(2);
We do the same thing with all the
rooms. Please make sure, that the numbers switchState[switch Number]
and the function call check_master[switch Number] match and you use
the “switch Number” from the switchState[] you are replacing and
not the one from the following code. The following statement in the
first 4 rooms is checking the priority switch and not the PIR's.
That wasn't so hard I guess. Now since
we got into changing things again, we come to the more difficult
part. We put the whole statement where we determine if a light has to
be switched on or not into a function.
There for we need to find the part in
our sketch where it says:
&& outsideOnTime == 1){
lightOutput[15] = 32768;
//switching on the lights
}
else {
lightOutput[15] = 0;
//no matches, they switch off
}
//////////////////room
lights//////////////////////////////
check_master(0);
//check if door switch was activated room 1 (bed1)
//Starting from here, the whole part
until “switchState1Old = switchState[1]; “ has to go – but
stop, //don't delete it right away cause we use it again to build our
function.
if(switchState[1] == 0 &&
sensorValue <= photoCellCutOff) { //checking if S2 priority off
was
//set bed 1
if(switchState[0] == 1 &&
priorityStatus[0] == 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[0] = 1;
//switching on the lights – binary
//000000000000000000000001
lightStatus[0] = 1;
//setting the light status for bed 1
lightOutput[14] = 16384;
//make sure the master relay
//stays on
lightStatus[14] = 1;
//setting the master relay status
roomTimer[0] = millis();
//setting the timer
}
else if(switchState[0] == 0 &&
lightStatus[0] == 1) { //the PIR not activated but the
//lights are on
//Serial.println("We
are checking the timer"); //Debug only
currentTime = millis();
//setting time reference
endTime = currentTime -
roomTimer[0]; //calculating the inactive time
if(endTime >=
delayTime[0]) { //comparing inactive time
with
//allowed delay time
//Serial.println("Time
is up switching off the lights"); //Debug only
lightOutput[0] = 0;
//switching off the lights
lightStatus[0] = 0;
//resetting the light status
roomTimer[0] = 0;
//resetting the room timer
}
}
}
else if(switchState[1] == 1 &&
lightStatus[0] == 1
&& switchState1Old
!= 1) { //if priority is activated and the
//lights are on
//Serial.println("Priority
switch activated switching off the lights"); //Debug only
lightOutput[0] = 0;
//switching off the lights
lightStatus[0] = 0;
//resetting the light status
roomTimer[0] = 0;
//resetting the room timer
priorityStatus[0] = 1;
//setting the priority status bed 1
}
else if(switchState[1] == 1 &&
lightStatus[0] == 0
&& switchState1Old
!= 1) { //if priority was activated and
the
//lights are off
//Serial.println("Priority
switch deactivated switching on the lights"); //Debug only
lightOutput[0] =1;
//switching on the lights
lightStatus[0] = 1;
//setting the light status
roomTimer[0] = millis();
//setting the room timer
priorityStatus[0] = 0;
//setting the priority for bed 1 back
//to 0
}
switchState1Old = switchState[1];
//passing on the switch state
The whole mentioned part we replace
with:
check_light_P(0, 1, 0, 1);
//check status room 1 (bed 1)
check_light_P() is our function call.
Don't worry about yet, we will build the function in a minute. The
first number we are passing to the function is the place in the
switchState[] - array holding the variable assigned to the pir switch
state for that room. (0 for room bed 1, 2 for bed 2, 4 for bed 3, 6
for living, 8 for bath 1, 9 for bath 2, 10 for bath 3 and so on. The
second number is the place in the switchState[] - array holding the
variable assigned to the priority switch for that room (1 for
priority bed 1, 3 for priority bed 2, 5 for priority bed 3 and 5 for
priority living. The third number is the place in various arrays
holding variables direct assigned to the room like light status, room
timer etc. (0 = room 1, 1 = room 2, 2 = room 3, …) and the last
number is the light output command for the particular room
representing the integer of a binary controlling the output shift
register.
Now we take the part we just cut and go
all the way down again, right to the end of our sketch and build the
function. First thing we paste the replaced part at the very end of
the sketch.
First we add:
void check_light_P(byte pir, byte prio,
byte room, unsigned long light){ //adding the function entry
//before we do anything else, we go to
the bottom of the sketch and close the function with a “}”.
//The variable pir is the place holder
of the space in the switchState array for the room we want
// to process. Now careful because the
first 4 rooms have to switchState variables, one for the
// PIR's and one for the priority
switch. The first is the one for the PIR the second for the priority
//switch. The first one is “0”.
Where ever it reads switchState[0] in the function, we replace the 0
//with pir so it reads
switchState[pir]. The second switchState variable we are using is
//switchState[1]. Where ever in the
function we find switchState[1] we replace the “1” with prio so
//it reads switchState[prio]. The next
variable addresses everything in arrays related direct to the
//room like lightOutput[0],
lightStatus[0], roomTimer[0] etc. There we replace the “0” with
room so
//it reads lightOutput[room],
lightStatus[room], roomTimer[room]...
//The last thing we need to change is
the lightOutput. After you made all the other changes, you will //find
two statements lightOutput[room] = 1;. This two statements have to
change to //lightOutput[room] = light;
if(switchState[1] == 0 &&
sensorValue <= photoCellCutOff) { //checking if S2 priority off
was
//set bed 1
if(switchState[0] == 1 &&
priorityStatus[0] == 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[0] = 1;
//switching on the lights – binary
//000000000000000000000001
lightStatus[0] = 1;
//setting the light status for bed 1
lightOutput[14] = 16384;
//make sure the master relay
//stays on
lightStatus[14] = 1;
//setting the master relay status
roomTimer[0] = millis(); //setting the timer
}
else if(switchState[0] == 0 &&
lightStatus[0] == 1) { //the PIR not activated but the
//lights are on
//Serial.println("We
are checking the timer"); //Debug only
currentTime = millis();
//setting time reference
endTime = currentTime -
roomTimer[0]; //calculating the inactive time
if(endTime >=
delayTime[0]) { //comparing inactive time
with
//allowed delay time
//Serial.println("Time
is up switching off the lights"); //Debug only
lightOutput[0] = 0; //switching off the lights
lightStatus[0] = 0;
//resetting the light status
roomTimer[0] = 0;
//resetting the room timer
}
}
}
else if(switchState[1] == 1 &&
lightStatus[0] == 1
&& switchState1Old
!= 1) { //if priority is activated and the
//lights are on
//Serial.println("Priority
switch activated switching off the lights"); //Debug only
lightOutput[0] = 0;
//switching off the lights
lightStatus[0] = 0; //resetting the light status
roomTimer[0] = 0; //resetting the room timer
priorityStatus[0] = 1;
//setting the priority status bed 1
}
else if(switchState[1] == 1 &&
lightStatus[0] == 0
&& switchState1Old
!= 1) { //if priority was activated and
the
//lights are off
//Serial.println("Priority
switch deactivated switching on the lights"); //Debug only
lightOutput[0] =1;
//switching on the lights
lightStatus[0] = 1; //setting the light status
roomTimer[0] = millis();
//setting the room timer
priorityStatus[0] = 0;
//setting the priority for bed 1 back
//to 0
}
switchState1Old = switchState[1];
} //closing the
function
You found everything, - great, to
confirm, below you have the complete function with all the changes.
void check_light_P(byte pir, byte prio,
byte room, unsigned long light){
if(switchState[prio] == 0 &&
sensorValue <= photoCellCutOff) { //checking if S2 priority off
was
//set bed 1
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
//000000000000000000000001
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 relay status
roomTimer[room] = millis();
//setting the timer
}
else if(switchState[pir] == 0 &&
lightStatus[room] == 1) { //the PIR not activated but the
//lights are on
//Serial.println("We are
checking the timer"); //Debug only
currentTime = millis();
//setting time reference
endTime = currentTime -
roomTimer[room]; //calculating the inactive time
if(endTime >=
delayTime[room]) { //comparing inactive
time with
//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
&& switchState1Old
!= 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
&& switchState1Old
!= 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();
//setting the room timer
priorityStatus[room] = 0;
//setting the priority for bed 1 back
//to 0
}
switchState1Old = switchState[prio];
//passing on the switch state
}
And we are back up in the main loop
where it says:
//////////////////room
lights//////////////////////////////
check_master(0);
//check if door switch was activated room 1 (bed1)
check_light_P(0, 1, 0, 1);
//check status room 1 (bed 1)
check_master(2);
//check if door switch was activated room 2 (bed 2)
//Next we replace the following part
including switchState3Old = switchState[3]; with
//check_light_P(2, 3, 1, 2);
//check status room 2 (bed 2)
if(switchState[3] == 0 &&
sensorValue <= photoCellCutOff){ //checking if S4 priority off
was
//set bed 2
if(switchState[2] == 1 &&
priorityStatus[1] == 0){ //check if the PIR in bed 2 was
//activated (S3)
//Serial.println("We
switch on the lights"); //debug only
lightOutput[1] = 2; //switch on the lights
//Binary 0000000000000010
lightStatus[1] = 1;
//setting the light status
lightOutput[14] = 16384;
//make sure the master relay
//stays on
lightStatus[14] = 1;
//setting the master relay status
roomTimer[1] = millis();
//setting the timer
}
else if(switchState[2] == 0 &&
lightStatus[1] == 1) { //the PIR not activated but the
//the lights are on
//Serial.println("We are
checking the timer"); //debug only
currentTime = millis();
//setting time reference
endTime = currentTime -
roomTimer[1]; //calculating the inactive time
if(endTime >= delayTime[1])
{ //comparing inactive time with
//Serial.println("Time
is up we switch the lights off"); //debug only
lightOutput[1] = 0;
//switching off the lights
lightStatus[1] = 0;
//resetting the light status
roomTimer[1] = 0;
//resetting the room timer
}
}
}
else if(switchState[3] == 1 &&
lightStatus[1] == 1
&& switchState3Old
!= 1) { //if priority is activated and the
//lights are on
//Serial.println("Priority
switch activated, switching off the lights"); //debug only
lightOutput[1] = 0;
//switching off the lights
lightStatus[1] = 0;
//resetting the light status
roomTimer[1] = 0;
//resetting the room timer
priorityStatus[1] = 1;
//setting the priority status for
//bed 2
}
else if(switchState[3] == 1 &&
lightStatus[1] == 0
&& switchState3Old
!= 1) { //if priority is activated and the
//lights are off
//Serial.println("Priority
switch off, switching the light back to normal"); //debug only
lightOutput[1] = 2;
//switching ion the lights
lightStatus[1] = 1;
//setting the light status
roomTimer[1] = millis();
//setting the room timer
priorityStatus[1] = 0;
//resetting the priority status
}
switchState3Old = switchState[3];
The same we do with the next two rooms
including the living room, so the part below reads like:
//////////////////room
lights//////////////////////////////
check_master(0);
//check if door switch was activated room 1 (bed1)
check_light_P(0, 1, 0, 1);
//check status room 1 (bed 1)
check_master(2);
//check if door switch was activated room 2 (bed 2)
check_light_P(2, 3, 1, 2);
//check status room 2 (bed 2)
check_master(4);
//check if door switch was activated room 3 (bed 3)
check_light_P(4, 5, 2, 4);
//check status room 3 (bed 3)
check_master(6);
//check if door switch was activated room 4 (living)
check_light_P(6, 7, 3, 8);
//check status room 4 (living)
check_master(8);
//check if door switch was activated room 5 (bath 1)
if(switchState[8] == 1) {
//checking S9 PIR of bathroom 1
//(room 5)
//Serial.println("We switch
on the lights"); //Debug only
lightOutput[4] = 16;
//switching on the lights
lightStatus[4] = 1;
//setting the light status
lightOutput[14] = 16384;
//make sure the master relay
//stays on
lightStatus[14] = 1;
//setting the master relay status
roomTimer[4] = millis();
//setting the room timer
}
If you didn't catch up with everything
don't worry to much. There will be quite a few changes now and before
we start building the menu, I prepare and post a full code again with
all valid changes.