I'm setting up a PIR activated relay (connected to some lights) using an Arduino Nano.
I have the PIR code working (obtained from a 3rd party site) but I'd like the option to override the PIR input based on an input from a push button switch. To add even more complexity, I'd like to have an LED lit up to let me know when the PIR is being manually overridden (relay always on).
The button is a simple push button.
By default, I want the unit to be in PIR mode. The relay is activated if motion is detected, and then after X seconds it switches off. If I press the button once, it's manually overridden and the relay is switched on (constantly) and the blue LED is activated to inform me that the unit is on constantly. If the button is pressed again, the unit switches back to PIR mode.
Here's the code I've got so far – but the LED and relay seem to be constantly active. The PIR is still reading (according to the serial monitor).
/*
* PIR sensor tester
*/
int PIR_override = 3; // the number of the switch pin
int overridestatus = 12; // the number of the led pin
int relaypin = 13; // choose the pin for the LED
int inputPin = 2; // choose the input pin (for PIR sensor)
int pirState = LOW; // we start, assuming no motion detected
int val = 0; // variable for reading the pin status
int DELVAR = 3000; // Delay in milliseconds
int override_state = LOW; // the current state of the output pin
// set states for PIR override switch
int state = LOW; // the current state of the output pin
int reading; // the current reading from the input pin
int previous = HIGH; // the previous reading from the input pin
///////////////////////////////////////////////////////
void setup() {
pinMode(relaypin, OUTPUT); // declare LED as output
pinMode(inputPin, INPUT); // declare sensor as input
Serial.begin(9600);
}
void loop()
{
digitalRead(PIR_override); // read input value of PIR override switch
if (val == LOW)
{ // check if the input is LOW
val = digitalRead(inputPin); // read input value
if (val == HIGH)
{ // check if the input is HIGH
digitalWrite(relaypin, HIGH); // turn LED ON
if (pirState == LOW)
{
// we have just turned on
Serial.println("Motion detected!");
// We only want to print on the output change, not state
pirState = HIGH;
delay(DELVAR); // maximum delay is 32776 millisecons,
// delay(DELVAR); // so add multiple delays together to get
// delay(DELVAR); // so add multiple delays together to get
}
}
else
{
digitalWrite(relaypin, LOW); // turn LED OFF
if (pirState == HIGH)
{
// we have just turned of
Serial.println("Motion ended!");
// We only want to print on the output change, not state
pirState = LOW;
}
else
{
digitalWrite(overridestatus, HIGH); // turn override status LED ON
digitalWrite(relaypin, HIGH); // turn relay ON
}
}
}
}
Here's the code I've got so far – but the LED and relay seem to be constantly active. The PIR is still reading (according to the serial monitor).
There's clearly something wrong with my if-else loop but I'm not entirely sure where I need to start looking.
I'm also including a basic breadboard image of the circuit (it's my first Fritz so be gentle!) Also, please ignore the pin in on the relay board. I am using an SRD-05VDC-SL-C but it's on a slightly different board with only 3 pins (IN, VCC, GND).
Best Answer
I think your main problem is that you aren't assigning a variable or using an
if
statement with yourdigitalRead(PIR_override);
, but even with that you may miss the button press in the loop. If it's a momentary switch then it goes high/low for only the time that it's pressed, so the processor would have to see this at the right time in the while loop. You could just hold the button down for about a second or you could connect the button to pin 2 or 3 and use an interrupt, which it looks like your button is connected to pin 3 according to your code. I think this is a better solution. In the embedded world interrupts are your friend.So, according to the documentation (https://www.arduino.cc/en/Reference/AttachInterrupt), you could do something like this:
Inside
Setup()
add:So now
motionOverride
will be called when the button is pressed. Just put what you want to happen inside this function. Something like this:Then inside your main
loop()
just look at the override flag (Note: I did not check any of your PIR motion detection logic, and hopefully I didn't mess up your brackets there):Try that out if you want. If there's a mistake I'll try and help with it.