Unable to detect third PIR sensor

Hi I am trying to eventually make an array of 16 PIR sensors triggering 16 relays at random. Right now I am trying to figure out how do it with 3 PIR sensors and a 8 relay module on an atmega2560. My sketch is able to see PIR sensors 1 and 2 but it is unable to detect 3.

Here is a video of the code in action:
https://vimeo.com/785091848

Here is the code:

const int pir1Pin = 2;
const int pir2Pin = 3;
const int pir3Pin = 4;
const int relay1Pin = 5;
const int relay2Pin = 6;
const int relay3Pin = 7;
const int relay4Pin = 8;
const int relay5Pin = 9;
const int relay6Pin = 10;
const int relay7Pin = 11;
const int relay8Pin = 12;

unsigned long lastPir1Time = 0;
unsigned long lastPir2Time = 0;
unsigned long lastPir3Time = 0;

int relayState[8] = {LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW};
unsigned long relayLastChangeTime[8] = {0, 0, 0, 0, 0, 0, 0, 0};

char relayString[4]; 

void setup() {
  pinMode(pir1Pin, INPUT);
  pinMode(pir2Pin, INPUT);
  pinMode(pir3Pin, INPUT);
  pinMode(relay1Pin, OUTPUT);
  pinMode(relay2Pin, OUTPUT);
  pinMode(relay3Pin, OUTPUT);
  pinMode(relay4Pin, OUTPUT);
  pinMode(relay5Pin, OUTPUT);
  pinMode(relay6Pin, OUTPUT);
  pinMode(relay7Pin, OUTPUT);
  pinMode(relay8Pin, OUTPUT);

  Serial.begin(9600);

  randomSeed(analogRead(A0));

  attachInterrupt(digitalPinToInterrupt(pir1Pin), handlePir1Interrupt, CHANGE);
  attachInterrupt(digitalPinToInterrupt(pir2Pin), handlePir2Interrupt, CHANGE);
  attachInterrupt(digitalPinToInterrupt(pir3Pin), handlePir3Interrupt, CHANGE);
}

void loop() {
  for (int i = 0; i < 8; i++) {
    if (millis() - relayLastChangeTime[i] > 1000) {
      digitalWrite(i + 5, LOW);
      relayState[i] = LOW; 
      relayLastChangeTime[i] = millis(); 
    }
  }
}

// Interrupt service routine for PIR 1
void handlePir1Interrupt() {
  if (digitalRead(pir1Pin) == HIGH) {
    int relayToTurnOn = random(8);
    digitalWrite(relayToTurnOn + 5, HIGH); 
    relayState[relayToTurnOn] = HIGH; 
    relayLastChangeTime[relayToTurnOn] = millis();
    
    sprintf(relayString, "%d", relayToTurnOn + 1);

    Serial.println("PIR 1 triggered, turning on relay " + String(relayString));
  }
}

// Interrupt service routine for PIR 2
void handlePir2Interrupt() {
  if (digitalRead(pir2Pin) == HIGH) {
    int relayToTurnOn = random(8); 
    digitalWrite(relayToTurnOn + 5, HIGH); 
    relayState[relayToTurnOn] = HIGH; 
    relayLastChangeTime[relayToTurnOn] = millis(); 
    
    sprintf(relayString, "%d", relayToTurnOn + 1);

    Serial.println("PIR 2 triggered, turning on relay " + String(relayString));
  }
}

// Interrupt service routine for PIR 3
void handlePir3Interrupt() {
  if (digitalRead(pir3Pin) == HIGH) {
    int relayToTurnOn = random(8); 
    digitalWrite(relayToTurnOn + 5, HIGH); 
    relayState[relayToTurnOn] = HIGH; 
    relayLastChangeTime[relayToTurnOn] = millis(); 

    sprintf(relayString, "%d", relayToTurnOn + 1);

    Serial.println("PIR 3 triggered, turning on relay " + String(relayString));
  }
}

Sketch of the schematic. PIR sensors are powered with an external power supply:

Your topic was MOVED to its current forum category which is more appropriate than the original as it has nothing to do with Installation and Troubleshooting of the IDE

Check on Arduino pages , but I think pin d4 does not support interrupts .

Your inputs from the sensor should not be open circuit when the sense is inactive , you need to Either use internal pull up. Or an external resistor .

Look here

Using interrupts will not work for 16 channels as an arduino Mega has only 6 interrupt pins.

But it is not nescessary to use interrupts in your application.
I guess the Pir-output changes state for minimum one second

So polling each PIR-sensor will work in every case
instead of using interrupts you write inside void loop()

if(digitalRead(pir3Pin == LOW) { // if relay is switched off
  if (digitalRead(pir3Pin) == HIGH) {
....

best regards Stefan

If that's a HC-SR501, then don't. Each PIR only draws about 70uA.
1000 PIR sensors could be powered from the 5volt pin without a problem.
Different story for the relays. They will need an external supply (75mA per active relay).

Don't use potentially problematic interrupts for PIR sensors.
There is absolutely no need for it. A PIR is a relative slow device for a processor.

Try to code without using delay(). Use millis() for timing.
Learn about arrays. It will make your code a lot shorter.
Strings are best left in the orchestra.
They don't play well with the small memory of an Arduino.
Leo..

1 Like

Hello 7lllao0

Do you have experience with programming in C++.

The task can easily be realised with an object.
A structured array contains all the information, such as the pin addresses for the I/O devices, as well as the information for the timing. A single service takes care of this information and initiates the intended action.
The structured array makes the sketch scalable until all I/O pins are used up without having to adapt the code for the service. It is cool stuff, isn´t it?

Have a nice day and enjoy coding in C++.

Interrupts would only be useful if this was a battery powered application and the MCU was in sleep mode most of the time, then would serve the purpose of waking the MCU. Otherwise, use polling as has been suggested. If you don't need to know which PIR sensor triggered, you could wire multiple sensors to the same pin, each via a small signal diode. For any sensors with an open collector/drain type output, you could even dispense with the diode.

I don't have specific experience with the SR-501 but some sensors such as the SR-505 are very prone to self triggering so you may have to design your code to stop listening to them before switching a load and until their "ON" time has expired. This is especially a problem when using multiple sensors as you are doing.

I have found the small AM312 PIR sensors much more stable, however, these have an unusually high 20K series resistor in their output path which has to be considered when designing the circuit.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.