I'm looking to automate some light fittings in my home, however before I delve into the world of Arduino (never done anything like this before) I wanted to make sure it is capable of doing what I need it to do.
I want the board to control (with a relay) 3 separate lights with 3 separate motion sensors that are totally independent of each other. They will be required to turn on when motion is detected and turn off after 20 seconds of no motion. They will also be able to all be on at the same time although have separate 20 second countdown timers.
Can anyone tell me if the following code would work (Bear in mind I have not coded the light sensor yet as this will just wrap the motion sensor code, so to keep focus on the lights for now I have left it out, and I've only included two light and sensor pairs as it's etc...)
const int relay1 = 7; // the number of the light on relay 1
const int relay2 = 8; // the number of the light on relay 2
const int motion1 = 2; // the number of the motion sensor for light 1
const int motion2 = 3; // the number of the motion sensor for light 2
long timeLeft1 = 0;
long timeLeft2 = 0;
long timeSince1 = 0;
long timeSince2 = 0;
long timeOff = 20000;
void setup() {
pinMode(relay1, OUTPUT);
pinMode(relay2, OUTPUT);
pinMode(motion1, INPUT);
pinMode(motion2, INPUT);
}
void loop()
{
unsigned long timeNow = millis();
if(digitalRead(motion1) == HIGH){
digitalWrite(relay1,HIGH); //turn lights on
timeSince1 = millis(); //record time relay1 was set
timeLeft1 = timeOff; //reset timer
} else {
if (timeLeft1 <= 0){
digitalWrite(relay1, LOW);
} else {
timeLeft1 = timeleft1 - (timeNow - timeSince1); //take current time from the time the light was turned on and set this as the time left until off
}
}
if(digitalRead(motion2) == HIGH){
digitalWrite(relay2,HIGH); //turn lights on
timeSince2 = millis(); //record time relay2 was set
timeLeft2 = timeOff; //reset timer
} else {
if (timeLeft2 <= 0){
digitalWrite(relay2, LOW);
} else {
timeLeft2 = timeleft2 - (timeNow - timeSince2); //take current time from the time the light was turned on and set this as the time left until off
}
}
}
I can only presume it's because I'm new to this. Does this mean the code won't work until I use arrays?
Edit:
I've just looked up arrays and whilst I understand the concept I'm still unsure how it will be useful to me. I best had explain the set-up a little more.
Light positions 2, 3 and 4 are used during the day and are controlled separate from each other. Each has its own motion sensor.
When it is dark, the system reverts to a master motion sensor and includes another light fitting and turns them all on at the same time.
Here is the full code
const int relay1 = 7; // the number of the light on relay 1
const int relay2 = 8; // the number of the light on relay 2
const int relay3 = 9; // the number of the light on relay 3
const int relay4 = 10; // the number of the light on relay 4
const int motion1 = 2; // the number of the motion sensor for light 1
const int motion2 = 3; // the number of the motion sensor for light 2
const int motion3 = 4; // the number of the motion sensor for light 3
const int motion4 = 5; // the number of the motion sensor for light 4
const int light = 6; // the number of the light sensor
long timeLeft1 = 0;
long timeLeft2 = 0;
long timeLeft3 = 0;
long timeLeft4 = 0;
long timeSince1 = 0;
long timeSince2 = 0;
long timeSince3 = 0;
long timeSince4 = 0;
long timeOff = 20000;
int lightThreshold = 250;
void setup() {
pinMode(relay1, OUTPUT);
pinMode(relay2, OUTPUT);
pinMode(relay3, OUTPUT);
pinMode(relay4, OUTPUT);
pinMode(motion1, INPUT);
pinMode(motion2, INPUT);
pinMode(motion3, INPUT);
pinMode(motion4, INPUT);
pinMode(light, INPUT);
}
void loop()
{
unsigned long timeNow = millis();
if(digitalRead(light) < lightThreshold) {
if(digitalRead(motion1) == HIGH){
digitalWrite(relay1,HIGH); //turn lights on
digitalWrite(relay2,HIGH); //turn lights on
digitalWrite(relay3,HIGH); //turn lights on
digitalWrite(relay4,HIGH); //turn lights on
timeSince1 = millis(); //record time relays were set
timeLeft1 = timeOff; //reset timer
} else {
if (timeLeft1 <= 0){
digitalWrite(relay1, LOW);
digitalWrite(relay2, LOW);
digitalWrite(relay3, LOW);
digitalWrite(relay4, LOW);
} else {
timeLeft1 = timeLeft1 - (timeNow - timeSince1); //take current time from the time the lights were turned on and set this as the time left until off
}
}
} else {
if(digitalRead(motion2) == HIGH){
digitalWrite(relay2,HIGH); //turn lights on
timeSince2 = millis(); //record time relay1 was set
timeLeft2 = timeOff; //reset timer
} else {
if (timeLeft2 <= 0){
digitalWrite(relay2, LOW);
} else {
timeLeft2 = timeLeft2 - (timeNow - timeSince2); //take current time from the time the light was turned on and set this as the time left until off
}
}
if(digitalRead(motion3) == HIGH){
digitalWrite(relay3,HIGH); //turn lights on
timeSince3 = millis(); //record time relay2 was set
timeLeft3 = timeOff; //reset timer
} else {
if (timeLeft3 <= 0){
digitalWrite(relay3, LOW);
} else {
timeLeft3 = timeLeft3 - (timeNow - timeSince3); //take current time from the time the light was turned on and set this as the time left until off
}
}
if(digitalRead(motion4) == HIGH){
digitalWrite(relay4,HIGH); //turn lights on
timeSince4 = millis(); //record time relay2 was set
timeLeft4 = timeOff; //reset timer
} else {
if (timeLeft4 <= 0){
digitalWrite(relay4, LOW);
} else {
timeLeft4 = timeLeft4 - (timeNow - timeSince4); //take current time from the time the light was turned on and set this as the time left until off
}
}
}
}
Does this mean the code won't work until I use arrays?
No, but it means you will have three times as much code as you need (or four, or five if you add more sensors and relays). Evey time you duplicate code, you increase the chances of not changing every needed in the copy, screwing up something that was working.
const int light = 6; // the number of the light sensor
...
int lightThreshold = 250;
...
pinMode(light, INPUT);
...
if(digitalRead(light) < lightThreshold) {
So you've defined light to be digital pin 6, and are reading it with a digitalRead. digitalRead returns either HIGH or LOW which numerically are 1 and 0. Both 1 and 0 are below 250, so that if statement will always be true. Typically, light sensors are hooked up to analogPins and read with an analogRead. How come you haven't done that?
So you've defined light to be digital pin 6, and are reading it with a digitalRead. digitalRead returns either HIGH or LOW which numerically are 1 and 0. Both 1 and 0 are below 250, so that if statement will always be true. Typically, light sensors are hooked up to analogPins and read with an analogRead. How come you haven't done that?
Along with what this guy said, you need to do an analogRead() on either an Analog pin, or one of the PWM Digital pins (these are, as PaulS corrected, not Analog pins, but I'm pretty sure you can use them similar to the Analog pins for basic tasks such as this). Once you have that value, you will probably need to use constrain() or map() depending on what you want.
Ah, silly mistake. I've changed it to the following, presuming that I understand correctly that 14 is analogue 1
const int light = 14; // the number of the light sensor
...
int lightThreshold = 250;
...
pinMode(light, INPUT);
...
if(analogRead(light) < lightThreshold) {
14 is the value of the digital pin that shares space with analog pin 0, on some Arduinos. Why not just use 0? The analogRead() function will have to subtract 14 from the value you specify, if you specify a pin number that is out of range, so save it the trouble and use correct pin numbers.
14 is the value of the digital pin that shares space with analog pin 0, on some Arduinos. Why not just use 0? The analogRead() function will have to subtract 14 from the value you specify, if you specify a pin number that is out of range, so save it the trouble and use correct pin numbers.
Brilliant, thank you very much, I got a bit confused over A0, 0 and 14.
if(digitalRead(motion1) == HIGH){
digitalWrite(relay1,HIGH); //turn lights on
timeSince1 = millis(); //record time relay1 was set
timeLeft1 = timeOff; //reset timer
} else {
if (timeLeft1 <= 0){
digitalWrite(relay1, LOW);
} else {
timeLeft1 = timeleft1 - (timeNow - timeSince1); //take current time from the time the light was turned on and set this as the time left until off
}
}
If this even works, it's a very bizarre way of doing it. If the motion sensor pin is HIGH, turn the relay on and set the appropriate time:
The array is optional. I wouldn't worry about it until after you have it working, and then if you want to make it more elegant, feel free.
However, I really like how Arrch did the time stamp. Although timeSince1 and timeSinceLastHigh are probably a not quite accurately named. Maybe timeOfLastHigh or timeStampOfLastHigh would be more intuitive.
TanHadron:
The array is optional. I wouldn't worry about it until after you have it working, and then if you want to make it more elegant, feel free.
However, I really like how Arrch did the time stamp. Although timeSince1 and timeSinceLastHigh are probably a not quite accurately named. Maybe timeOfLastHigh or timeStampOfLastHigh would be more intuitive.
I too like the time change suggested. I did begin to create the array but quickly got stuck with motion sensor 1 only being active when it was dark and controlling all of the lights.
Thank you for the StampOfLastHigh suggestion, I've been playing with a new name for it all day.