Motion Sensor debounce

  • Hello,

    I am not sure how this can be done.
    Basically, I have a Panasonic PIR on Moteino with RFM69W working just fine. The problem is that it is spamming GW with messages.
    I need to introduce a delay - if PIR triggered, no more messages to GW for 30 secs or so. My issue is that the node is sleeping:

    sleep(digitalPinToInterrupt(MOTION_INPUT_PIN), CHANGE, SLEEP_TIME)

    and millis() are not working during sleeping.

    My question is this: How do I introduce a delay, say 30 sec, in order not to spam my GW/Controller with "Security Lighting" (this is how it is recognised in Domoticz). Such delay must work with the sleep function above.

    Appreciate if you could share your ideas


  • Mod

    @alexsh1 how about adding


    just before

    sleep(digitalPinToInterrupt(MOTION_INPUT_PIN), CHANGE, SLEEP_TIME)

    perhaps with an if statement that only invokes sleep(30*1000) if the sensor was triggered.

    An alternative could be to add an if-statement that only sends a message if the value was changed from last time.

    Edit: added *1000 to convert the seconds to milliseconds

  • @mfalkvidd, you mean

    define DEBOUNCE 30000 // 

    This just delays it ANYWAY regardless whether the PIR was triggered or not.

    When it comes to "if", during one trigger, my PIR is changing the status from 0 to 1 and back to 0. Unfortunately, I cannot count millis() when sleeping. How can use count 30 secs from the last even when the PIR was triggered please? Very much appreciate your suggestion.

  • Mod

    @alexsh1 hard to say without knowing what else your node does. If it does nothing, the sleep 30000 will be enough. You could connect a RTC, but that might also affect what else the node does.

  • @mfalkvidd The node is a PIR + reporting baro+temp+hum (BME280) every 5 minutes as well as battery voltage.

  • Mod

    @alexsh1 save the return value from your existing sleep into a variable. Add an if statement that does sleep(30000) only if your node was waken up by interrupt.

    Documentation for the return value is available at

  • @mfalkvidd That's got be the last nail in the coffin - thanks for your help!

  • I think the final product would be looking like this:

    #define DUPLICATE_INTERVAL 30000
    if (sleep(digitalPinToInterrupt(MOTION_INPUT_PIN), CHANGE, SLEEP_TIME)) {
          motionDetected = true;

    Testing now

  • Mod

    @alexsh1 I think you need to test för >= 0. The If statement will return true for anything non-zero so the current test will fail. Except that, the code looks great.

  • @mfalkvidd

    This worked well for me, for a vibration sensor:

    if (sleep(digitalPinToInterrupt(MOTION_INPUT_PIN), CHANGE, SLEEP_TIME) != -1) {
    // Interrupt occurred, do whatever is needed and then
    // clear any "floating" interrupts before going on.
    while (sleep(digitalPinToInterrupt(MOTION_INPUT_PIN),CHANGE,1000) != -1 ) {
    Serial.println("Clearing interrupts");

Log in to reply

Suggested Topics

  • 3
  • 5
  • 2
  • 2
  • 3
  • 15