Monitor a motion sensor coming with a NC switch

Hello all,

I would like my arduino monitoring a motion sensor and counting how many time it has been trigerred. This sensor has a "normally closed" switch. As my project will be extended soon with more sensors I have combined an interrupt pin with a regular one and have added the sensors expected to come in the future.

It seems to work but I'd like to make sure I'm not wrong with the pin mode, their state and the pull down resistor..

Can you please take look and let me know how my code looks in regards to my breadboard sketch ?

Here is the code :

const int LED=13;
volatile int NBROFDETECTIONS=0;
int t=0;

const int inter=2;
const int button1=3;
const int button2=4;
const int button3=5;
 
volatile unsigned long button_time = 0;
volatile int trigger = 0;
int debounce = 250
; // debounce latency in ms
int total = 0;
int inta = 0;
int intb = 0;
int intc = 0;

void setup() {
    initPins();
    attachInterrupt(0, detect, RISING);
}

void loop() {
    // Blink LED with NBROFDETECTIONS-BEGIN
    t=0;
    delay(2000);
    for (t=0;t<NBROFDETECTIONS;t=t+1)
    {
      digitalWrite(LED,HIGH);
      delay(500);
      digitalWrite(LED,LOW);
      delay(500); 
      }
   // Blink LED with NBROFDETECTIONS-END 
}

void detect(){
 if (button_time > millis()) return;
 delayMicroseconds(32000);
 if (digitalRead(button1)) trigger=1;
 if (digitalRead(button2)) trigger=2;
 if (digitalRead(button3)) trigger=3;
 button_time = millis() + debounce;
 NBROFDETECTIONS=NBROFDETECTIONS+1;
}

void initPins(){
 pinMode(button1, INPUT);
 pinMode(button2, INPUT);
 pinMode(button3, INPUT);
 pinMode(inter, INPUT);
 digitalWrite(button1, HIGH);
 digitalWrite(button2, HIGH);
 digitalWrite(button3, HIGH);
 digitalWrite(inter, HIGH);
 pinMode(LED,OUTPUT);
 digitalWrite(LED, LOW);
 }

Thanks in advance !! :slight_smile:

Christophe

Sketch 1_bb.pdf (687 KB)

The preferred method of using a switch is to connect between input and Gnd, while using a pull up R. This can be 10k or use the internal pull up to save connecting another component. This reduces the possibility of shorting out the supply.

You would also reverse your logic to sense high or low.

Weedpharma

As my sensors have NC switches only I thought It could make sense to have them between the GND and the input with of course a pull down resistor. That way, in normal situation the pin are at LOW level and when one of the sensors is trigerred it become HIGH.

Hence, should I set the PINs on INPUT or OUTPUT mode ? and also, in case of INPUT mode, do I need to set them to HIGH (which will enable the internal pull-up resistor...) ?

am I right or wrong in the way I coded ?

finally I succeed in attaching my breadboard sketch :wink: please take a look on it :wink:

Thanks,
Christophe

CSA75:
As my sensors have NC switches only I thought It could make sense to have them between the GND and the input with of course a pull down resistor. That way, in normal situation the pin are at LOW level and when one of the sensors is trigerred it become HIGH.

If you connect the sensor output between the pin and ground, and also use a pulldown resistor, the pin will stay LOW forever. There will be nothing to ever pull it HIGH. You would use a pullup resistor. See the next part of my reply.

Hence, should I set the PINs on INPUT or OUTPUT mode ? and also, in case of INPUT mode, do I need to set them to HIGH (which will enable the internal pull-up resistor...) ?

If you're using a pin as an input, (which you are in this case), ALWAYS set it as an input. Never as an output, or you can damage the microcontroller.

As Wawa said, connect the NC sensor output between the input pin and ground, then set the pin as input with the internal pullup resistor enabled. Don't do it by making the pin INPUT then writing HIGH to it though. (That's the old way, from early versions of the IDE.)
The correct way is to set the pin to INPUT_PULLUP in 'setup()' like this:-

pinMode(pin, INPUT_PULLUP);

Edit: When writing the code, since the sensor output is NC, the pin will be "active-high", (it will go HIGH when triggered), so write the code accordingly.

am I right or wrong in the way I coded ?

You shouldn't need to use an interrupt for this. Instead get rid of all instances of 'delay()', and use 'millis()'-based timing instead. Check out the "BlinkWithoutDelay" example provided with the IDE, and also Demonstration code for several things at the same time

Yes I will try to modify my code accordingly but at the moment my problem is more on how to get a reliable detection of state change of my NC switch and above all avoid false positive. Today my system is not that much reliable...detections occurs randomly without any action on the switch :confused:

OldSteve:
As Wawa said, ....

?.. Didn't say anything yet :slight_smile:

CSA75:
but at the moment my problem is more on how to get a reliable detection of state change of my NC switch and above all avoid false positive. Today my system is not that much reliable...detections occurs randomly without any action on the switch

How long/messy is the wiring between Arduino and sensor/switch.
It might act as an antenna, and still trigger the port.
Try a 100n ceramic cap from Arduino pin to ground.
Post a full diagram of the setup if that doesn't help.
Leo..

Just looked at you diagram. Why are you switching the positive side of the switch?

You should have a pull-up R to the input, and switch to Gnd. If you switch the 5v, you do not have a fixed input reference so the input floats and acts as an aerial causing random signals.

Weedpharma

Wawa:
?.. Didn't say anything yet :slight_smile:

Oh @#$%, it was weedpharma, not you. I got the 'w' right at least.
(That's what I get for not scrolling back and checking when I post. :smiley: )

Sorry @weedpharma.

Hello,

Following your message, I made a schematic view of my wiring. I (maybe) found out something wrong with my code...I guess the pinmode is wrong...shoudl I use output for pin 2 ? Then when the button is close pin will be LOW and when oppened they will become HIGH ?

Please take a look at the attached file..

Thanks :slight_smile:

PS:At the moment I'm trying to get it working on the breadboard only, there is no long wiring :wink:

NC_Button.pdf (171 KB)

I don't get what you're trying to do, why you're using two input pins and why you're using interrupts at all. For detecting a PIR detector, or a button press, there's no need for interrupts - polling in 'loop()' is more than adequate for the purpose.

If you plan to connect multiple PIR detectors in future, but want separate actions for each, they'll need to be on separate pins, which you'd poll in sequence then take appropriate action. The 'loop()' function cycles very quickly, so you'll never miss a triggering.
If you want the same action for all of them, and they all have NC relay contacts, wire the contacts of them all in series. If any of the contacts open, the pin will go HIGH.

Then all you need is to connect the PIR detector output(s) between the input pin and ground. No other connections are necessary if you use INPUT_PULLUP, unless you have noise problems, in which case you could add an external pullup resistor instead of using INPUT_PULLUP.

And as I already mentioned in reply #3, to enable internal pullup resistors, instead of setting the pin as INPUT, then writing HIGH to it, just use INPUT_PULLUP in your 'pinMode()' statement:-pinMode(pin, INPUT_PULLUP);
Also, as a general rule, you shouldn't handle your 'millis()' calculations like this:-

if (button_time > millis())
.
.

button_time = millis() + debounce;

You should always use subtraction, to avoid 'millis()' rollover problems:-

if((millis() - buttonTime) >= debounce)
{
    buttonTime = millis();
    // Other code here

}

Again, I realize that giving the global picture would have been better for understanting of everybody...
So let's rewind !

This system is expected to work as a kind of a alarm system. 4 sensors will be connected to it. If one them is trigerred a SMS will be sent with the sensor number. Today, I'm trying to validate the working principle first.

The reason why I use interrupt instead of polling in 'loop' is because sending SMS take almost 3 sec (there is 5 phone numbers to send SMS to) and I don't want to miss a trigerring during that time.

Once that said, does-it make sense now to use interrupt ? or is there any other solution (without having to use a "slave" arduino dedicated to send SMS :wink: ) ?
if interrupt is the right solution, how should I wire and configure the pins please ? I'm a bit confused..

thanks for your help

Yes, more info might have been useful.
If sending the SMS messages really completely blocks the 'loop()' function for 3 seconds, then an interrupt isn't a bad idea. I'm not familiar with GSM and sending an SMS, so I have to take your word for that.

The N.C. contacts add a level of complexity. N.O. would be so much easier to work with in this situation, because you wouldn't need to add any external resistors. Then when a set of contacts closed, they could easily overpower the pullup resistors.
Are you sure that you don't also have N.O. contacts on the PIR detectors? It would make life far easier.

With NC contacts, added resistors are needed to overpower the pullup on the INT pin. Either way, you need one diode per PIR detector, for it's input pin to trigger the interrupt.

Your circuit has two faults.
First, the resistor isn't needed and stops the pin pulling close to ground when the contacts are closed.
Second, and more critical, once you add extra PIR detectors in parallel, they all have to trigger at the same time before the INT pin can go high. (Any closed contacts will hold the INT pin low.)

This is about the simplest layout I could think of:-
4 N.C. PIR with INT.JPG

As noted on the schematic, the interrupt will need to be triggered on the falling edge, and the PIR input pins are active-low. Also the internal pullup on the interrupt pin must be enabled, but not the pullups on the PIR input pins.

Everything would have been much simpler if sending the SMS messages didn't block for 3 seconds, or even if the PIR detectors had N.O. contacts. :frowning:

(It's the middle of the night here and I'm very tired, but I don't think I made any mistakes. I'm sure that someone will point it out if I did. :smiley: )

Edit: Just a little more info. Allowing for a worst-case scenario of the internal pullup resistor being as low in value as 20K, when a set of PIR contacts open, the INT pin will be pulled down to 1.43V, and the PIR input pin will be pulled down to 0.8V, so both should trigger fine. In reality, the internal pullup will probably be higher in value, so the voltage at each pin will be even lower.
The INT pin is close to the line, (it needs to be below 1.5V to reliably trigger), but should be fine. For a higher safety margin, 3K9 or 3K3 resistors could be used instead of 4K7, but I don't think that's absolutely necessary, especially since it's unlikely that the pullup resistor value will be as low as 20K.
For even more reliable results, you could use a 33K or 47K external pullup resistor on the INT pin, and ignore the internal pullup. That way, you'd be working with a known value.