Chain reaction with PIR sensors

Hello all, I have a very strange occurrence happening on my arduino. I have 3 PIR sensors which are connected to 3 corresponding LEDs. The hardware is simple and here is my code.

int pir_1 = 2; //digital 2
int pir_2 = 7;
int pir_3 = 8;
int led_1 = 13;
int led_2 = 12;
int led_3 = 11;
int val_1 = 0;
int val_2 = 0;
int val_3 = 0;



void setup(){
 Serial.begin(9600);       // for diagnostics
 pinMode(pir_1, INPUT);
 pinMode(pir_2, INPUT);
 pinMode(pir_3, INPUT);
 pinMode (led_1, OUTPUT);
 pinMode (led_2, OUTPUT);
 pinMode (led_3, OUTPUT);
 Serial.println("testing all leds");
 digitalWrite (led_1, HIGH);
 delay(500);
 digitalWrite (led_1, LOW);
 delay(500);
 digitalWrite (led_2, HIGH);
 delay(500);
 digitalWrite (led_2, LOW);
 delay(500);
 digitalWrite (led_3, HIGH);
 delay(500);
 digitalWrite (led_3, LOW);
 delay(3000);
 Serial.println("begin motion detection");
}


void loop(){
  int val_1 = digitalRead(pir_1);
  int val_2 = digitalRead(pir_2);
  int val_3 = digitalRead(pir_3);

  if(val_1 == LOW && val_2 == HIGH && val_3 == HIGH) //was motion detected
    {
     digitalWrite (led_1, HIGH);
     delay (500);
     digitalWrite (led_1, LOW);
     delay (500);
     Serial.println("PIR 1 is LIVE");
    }
   else if (val_1 == HIGH && val_2 == LOW && val_3 == HIGH)
   {
     digitalWrite (led_2, HIGH);
     delay (500);
     digitalWrite (led_2, LOW);
     delay (500);
     Serial.println("PIR 2 is LIVE");
   }
   else if (val_1 == HIGH && val_2 == HIGH && val_3 == LOW)
   {
     digitalWrite (led_3, HIGH);
     delay (500);
     digitalWrite (led_3, LOW);
     delay (500);
     Serial.println("PIR 3 is LIVE");
   }
   else if (val_1 == LOW && val_2 == LOW && val_3 == HIGH)
   {
     digitalWrite (led_1, HIGH);
     digitalWrite (led_2, HIGH);
     delay (500);
     digitalWrite (led_1, LOW);
     digitalWrite (led_2, LOW);
     delay (500);
     Serial.println("PIR 1 and PIR 2 are LIVE");
   }
   else if (val_1 == LOW && val_2 == HIGH && val_3 == LOW)
   {
     digitalWrite (led_1, HIGH);
     digitalWrite (led_3, HIGH);
     delay (500);
     digitalWrite (led_1, LOW);
     digitalWrite (led_3, LOW);
     delay (500);
     Serial.println("PIR 1 and PIR 3 are LIVE");
   }
   else if (val_1 == HIGH && val_2 == LOW && val_3 == LOW)
   {
     digitalWrite (led_2, HIGH);
     digitalWrite (led_3, HIGH);
     delay (500);
     digitalWrite (led_2, LOW);
     digitalWrite (led_3, LOW);
     delay (500);
     Serial.println("PIR 2 and PIR 3 are LIVE");
   }
   else if (val_1 == LOW && val_2 == LOW && val_3 == LOW)
   {
     digitalWrite (led_1, HIGH);
     digitalWrite (led_2, HIGH);
     digitalWrite (led_3, HIGH);
     delay (500);
     digitalWrite (led_1, LOW);
     digitalWrite (led_2, LOW);
     digitalWrite (led_3, LOW);
     delay (500);
     Serial.println("ALL PIRs are LIVE");
   }
   
}

Granted this is very bad code discipline, I will implement them into functions later. However, here is the strange thing. When I set off sensor 1, there is a pattern where led2 and 3 also light up a couple of times. This only happens when LED 1 is triggered. When LED 2 or 3 are triggered there is no other result except the corresponding led lighting up. Could this be an issue with the sensitivity/ range of the sensors? (I have the sensors sitting inside cardboard boxes aimed in different directions). Do I need to attenuate the signals by either changing the physical barriers or changing the gain?

Cheers, V

Before setting any LEDs, clear ALL leds. You code never establishes a reference (all off) except during Setup() and the all-on conditional.

Just put this near the top of the loop() before you Test...

     digitalWrite (led_1, HIGH);
     digitalWrite (led_2, HIGH);
     digitalWrite (led_3, HIGH);

then you never need to turn off any leds in the subsequent tests, just turn on what you need. The loop runs so fast you will not notice the blinking... get rid of all those delay(500)'s .... you really only need one delay(1000) before the loop repeats.

Ray

When I set off sensor 1, there is a pattern where led2 and 3 also light up a couple of times

Could this be down to floating inputs? How are the PIRs wired?

This is a shortened version of you loop() routine. Does this show the same problems?

void loop(){
  int val_1 = digitalRead(pir_1);
  int val_2 = digitalRead(pir_2);
  int val_3 = digitalRead(pir_3);
  digitalWrite(led_1,  ! val_1);
  digitalWrite(led_2,  ! val_2);
  digitalWrite(led_3,  ! val_3);
  delay(500);
  digitalWrite(led_1, LOW);
  digitalWrite(led_2, LOW);
  digitalWrite(led_3, LOW);
}

Ray, Thank you for your suggestion. Nevertheless, I still have the same problem. Your solution turned all the LEDs on at the beginning of the loop and it off everytime motion is detected (the opposite of what it has been doing so far). However, the chain reaction still exists. The lights continue to blink up to 2 seconds after the trigger.

Warm Regards, V

Haha! Thank you pylon for simplifying it so elegantly :slight_smile: I feel a bit stupid now.

@AWOL, The wiring is as such for all leds:
Pin—>Led—>resistor—>GND

The thing that bothers me is that it works for PIR 2 and 3 but not one.

Warm Regards,
v

@Pylon- Yes it still has the same problem after implementing your suggestion. In fact, now there is a chain reaction for PIR2 and 3 as well.

Warm Regards, V

I didn't ask about the wiring of the LEDs.

My bad, PIRs are connected directly to the input pins along with V+ and GND.

Warm Regards, V

visal: My bad, PIRs are connected directly to the input pins along with V+ and GND.

With a pullup or pulldown resistor? Even better would be to enable internal pullups and connect one leg to the digital pin, and the other to ground.

Okay, I tried to add a internal pull up resistor but I am not sure if I am doing it right. This is what I have now:

pinMode (pin_ref, INPUT);
digitalWrite (pin_ref, HIGH);

Yes, everything is initialized and all the +V connections are now connected to digital pin (pin_ref).
Here is a schematic of what my circuit resembles however, the new change is that <pin_ref> is replacing the +5V

There is still no change. In fact, I know something is wrong because none of the LEDs light up when I add the internal ref.

Warm Regards,
V

Please post a link to the PIRs you're using.

https://www.sparkfun.com/products/8630

So connect 5V to 5V, GND to GND and the AL(ARM) signal to the digital input you configure with internal pull-ups. Then it should work.

Yes, That is exactly what I have done. Each PIR is independent, as is each LED. This however doesnt stop the chain reaction. Please look at the youtube video attached below if you can: http://www.youtube.com/watch?v=k1bQz77lpw4&feature=youtu.be

The problem still persists. I am using a multi meter to identify if there are any floating voltages but I cant find any.

Warm Regards, V

Have you tried to use another pin for led_1? On pin 13 there is already an LED on the board. Maybe that double load let the USB voltage drop a bit and the PIR sensors react on that?

Let me try that and report the results...

Okay, there is no change, I altered all the pins. Rewired the whole circuit on a different bread board ( I assumed there may be something wrong with it) but the nothing has changed. Why would a HIGH signal on one pin result in other pins mimicking the same? I have tried isolating each PIR by it self and it works fine. However, when connected in tandem to sense 3 different directions it all goes haywire.

Warm Regards, V

You're going to make yourself crazy...

We (all) need to clear our heads and think about what you are doing. - 3 PIR sensors. These act like switches, On and Off - 3 LEDs. These are indicators.

Our goal is to turn on a LED for each PIR... therefore, the four states are: 1) NO LEDS 2) #1 LED On 3) #2 LED On 4) #3 LED On

Note: All three can be on at the SAME time.

When movement is no longer detected on a PIR, that PIR should turn off the associated LED. With movement, the PIR should turn on the associated LED.

Now, LEDs can be connected in two ways to an I/O pin. If one side of the LED is Gnd and the other is a resistor to the uC, that configuration is called "Sourcing" as related to the Arduino. Conversely, if one end of the LED is on +5 Volts (through a resistor OR not) and the other end of the LED is to the Arduino I/O pin (through a resistor OR not) then the configuration is called "Sinking" as related to the Arduino. NOTE: Somewhere there needs to be a resistor to limit the LED current.

Now: IN a tight-loop such as you have, you do NOT need to have a complex IF statement. Using a simple IF, the code would appear:

a) Turn OFF all LEDs b) IF PIR #1, then turn ON LED #1 c) IF PIR #2, then turn ON LED #2 d) IF PIR #3, then turn ON LED #3 e) Go to a (or in Arduino terminology, just "}" the loop() function.

This is not a state machine... we are only monitoring and displaying in a very, very fast loop. There is no need for a pause/delay/wait (BUT if you want to see the LED at full brightness, then put a delay() as the last statement before the loop repeats.) Were we to extend our design to include other functions to control other things from within the loop(), we may wish to capture the PIR states in a variable. For example, With 3 PIRs, we could control 2^3 states... or in numeric terms 0 - 7 which we could then check in a switch (var) statement. You have done pin-state capture in your original code with your val_1, val_2, val_3 which is great.

.....
void loop() {
// Turn OFF all LEDs in a current sourcing arrangement - requires 3 separate resistors for current limiting
     digitalWrite (led_1, LOW);
     digitalWrite (led_2, LOW);
     digitalWrite (led_3, LOW);

     if (digitalRead(pir_1)) digitalWrite(led_1, HIGH);
     if (digitalRead(pir_2)) digitalWrite(led_2, HIGH);
     if (digitalRead(pir_3)) digitalWrite(led_3, HIGH);
}

You can extend the above to the concept of using variables as states. Compound logic is only required if you require more than 3 ON states, one per LED.

PERSONALLY, I always wire the uC as a current sink... that is, the LEDs are always tied to +5 through a resistor and the cathode of the LED goes to the I/O pin of the Arduino. If done my way, the statement: digitalWrite (led_1, LOW); would turn ON a LED... hence my original communication. My bad for not studying your code deeper.