PIR sensor starts to trigger constantly after some time


  • Hardware Contributor

    I recently updated my nodes to MySensors 2.0 and shortly after that my motion sensor started to behave strangely. It uses a mini PIR (linked in the mysensors store). It works for the first ~10-120 minutes and then starts to trigger constantly (without motion). I am using one of my minisensors boards (see here for pictures).

    The code I am using is based on the slim node pir from this forum, but converted to mysensors 2.

    /**
     * Based on the sketch of m26872 here https://forum.mysensors.org/topic/2715/slim-node-as-a-mini-2aa-battery-pir-motion-sensor
     * Documentation: http://forum.mysensors.org...
     *
     * Version 1 06.09.2016 basesketch
     * Version 2 12.11.2016 update to mysensors 2
     */
     
    // library settings
    #define MY_RADIO_NRF24
    #define MY_DEBUG    // Enables debug messages in the serial log
    //#define MY_DEBUG_VERBOSE_SIGNING //!< Enable signing related debug prints to serial monitor
    #define MY_BAUD_RATE  9600 // Sets the serial baud rate for console and serial gateway
    //#define MY_SIGNING_SOFT // Enables software signing
    //#define MY_SIGNING_REQUEST_SIGNATURES // Always request signing from gateway//
    //#define MY_SIGNING_SOFT_RANDOMSEED_PIN 7 // floating pin for randomness
    //#define MY_SIGNING_NODE_WHITELISTING {{.nodeId = GATEWAY_ADDRESS,.serial = {0x5B,0x96,0x29,0xDD,0x0F,0x80,0x80,0xC5,0x1B}}} // gateway address
    //#define MY_NODE_ID 7
    
    #include <SPI.h>
    #include <MyConfig.h>
    #include <MySensors.h>
    #include <Vcc.h>
    
    // program settings
    #define CHILD_ID 1
    #define CHILD_ID_BATTERY 2
    #define MOTION_INPUT_PIN 3
    #define BATTERY_REPORT_DAY 1   // Desired heartbeat(battery report) interval when inactive. 
    #define BATTERY_REPORT_BY_IRT_CYCLE 30 // Make a battery report after this many trips. Maximum report interval will also be equal to this number of days.
    #define ONE_DAY_SLEEP_TIME 86400000
    #define VCC_MIN 1.8
    #define VCC_MAX 3.3
    
    int dayCounter = BATTERY_REPORT_DAY;
    int irtCounter = 0;
    
    bool interruptReturn = false; // "false" will make the first loop disregard high output from HV-505 (from start-up) and make a battery report instead.
     
    Vcc vcc(1.0);
    MyMessage msg(CHILD_ID, V_TRIPPED);
    MyMessage voltage_msg(CHILD_ID_BATTERY, V_VOLTAGE);
    
    
    void before() {
      pinMode(MOTION_INPUT_PIN, INPUT);
      digitalWrite(MOTION_INPUT_PIN, LOW);    // Disable internal pull-ups
    }
    
    void presentation()  
    {  
      sendSketchInfo("Motion sensor", "12112016 v2.0");
      present(CHILD_ID, S_MOTION);
      present(CHILD_ID_BATTERY, S_MULTIMETER);
    
      sleep(20000); // Wait until HC-505 warmed-up and output returned low.
    }
    
    void loop() 
    {
      if (interruptReturn) {    // Woke up by rising pin
        send(msg.set("1"));  // Just send trip (set) commands to controller.
        wait(50);
        send(msg.set("0"));  // Send the off command right after
        irtCounter++;
        if (irtCounter >= BATTERY_REPORT_BY_IRT_CYCLE) {
            irtCounter=0;
            sendBatteryReport();
        }
      }
      else { // Woke up by timer  (or it's the first run)
        dayCounter++; 
        if (dayCounter >= BATTERY_REPORT_DAY) {
              dayCounter = 0;
              sendBatteryReport();
        }
      }
      
      sleep(3000);  // Make sure everything is stable before start to sleep with interrupts. (don't use "wait()" here). Tests shows false trip ~2s after battery report otherwise.
    
      // Sleep until interrupt comes in on motion sensor or sleep time passed.
      interruptReturn = sleep(MOTION_INPUT_PIN-2, RISING, ONE_DAY_SLEEP_TIME);
    } 
    
    void sendBatteryReport() {
      float p = vcc.Read_Perc(VCC_MIN, VCC_MAX, true);
      float v = vcc.Read_Volts();
      int batteryPcnt = static_cast<int>(p);
      sendBatteryLevel(batteryPcnt);
      send(voltage_msg.set(v,3));
    }
    

    Signing is disabled for now as I had some problems with that.

    I am not sure if this has anything to do with the update but it worked before. Any idea how to fix this? Perhaps some kind of pulldown/up resistor or another capacitor?
    Thanks for your help!


  • Mod

    @LastSamurai you could try with the development branch as I fixed some wake from interrupt issues there; it might solve your issues.
    However, I have a comparable experience with cheap pir sensors. Sometimes they trigger when the arduino wakes, probably due to power variation (any other ideas are welcome).
    I can imagine that due to changes in amount/order/speed of messages sent in 2.0 this might trigger this strange behavior of the pir sensor.


  • Hardware Contributor

    @Yveaux Thanks for the help, but it seems like the problem got only worse with the development branch. I guess its some kind of hardware problem then. Hopefully my pcb for the ikea motion sensor will arrive soon, then I will try them out.



  • Try with a fresh battery! Do you have any step-up converter for the PIR? I've also had the same problem recently, and I think (still need to test a bit more) that it was caused by the battery getting a bit discharged (after an OTA update).

    It usually triggers the PIR when the radio sends something. I think it is because the radio makes the voltage fluctuate when it sends.
    A simple workaround is to wait 3 seconds (the time my PIR takes to reset/settle after triggering) after sending data, and only then check if it has triggered. But I only wait if the previous state was zero (no motion), since I want it to fire instantaneously when motion is detected. So:

    • Get state;
    • Send state data;
    • If state was 1, sleep 3 secs;
    • Send new state if it changed from 0 to 1 (during 3 secs sleep);
    • Sleep with interrupt;

  • Hardware Contributor

    @abmantis Thanks for the answer. I think I got most of this. I modified some code from another pir post in this forum.
    Here is the code. Is that what you did too?

    // library settings
    #define MY_RADIO_NRF24
    #define MY_DEBUG    // Enables debug messages in the serial log
    //#define MY_DEBUG_VERBOSE_SIGNING //!< Enable signing related debug prints to serial monitor
    #define MY_BAUD_RATE  9600 // Sets the serial baud rate for console and serial gateway
    #define MY_SIGNING_SOFT // Enables software signing
    //#define MY_SIGNING_REQUEST_SIGNATURES // Always request signing from gateway
    #define MY_SIGNING_SOFT_RANDOMSEED_PIN 7 // floatingpin  for randomness
    #define MY_NODE_ID 12
    
    #include <SPI.h>
    #include <MyConfig.h>
    #include <MySensors.h>
    #include <Vcc.h>
    
    // program settings
    #define CHILD_ID 1
    #define CHILD_ID_BATTERY 2
    #define MOTION_INPUT_PIN 3
    #define BATTERY_REPORT_DAY 1   // Desired heartbeat(battery report) interval when inactive. 
    #define BATTERY_REPORT_BY_IRT_CYCLE 30 // Make a battery report after this many trips. Maximum report interval will also be equal to this number of days.
    #define ONE_DAY_SLEEP_TIME 86400000
    #define VCC_MIN 1.8
    #define VCC_MAX 3.3
    
    int dayCounter = BATTERY_REPORT_DAY;
    int irtCounter = 0;
    
    bool interruptReturn = false; // "false" will make the first loop disregard high output from HV-505 (from start-up) and make a battery report instead.
     
    Vcc vcc(1.0);
    MyMessage msg(CHILD_ID, V_TRIPPED);
    MyMessage voltage_msg(CHILD_ID_BATTERY, V_VOLTAGE);
    
    
    void before() {
      pinMode(MOTION_INPUT_PIN, INPUT);
      digitalWrite(MOTION_INPUT_PIN, LOW);    // Disable internal pull-ups
    }
    
    void presentation()  
    {  
      sendSketchInfo("Motion sensor", "12112016 v2.0");
      present(CHILD_ID, S_MOTION);
      present(CHILD_ID_BATTERY, S_MULTIMETER);
    
      sleep(20000); // Wait until HC-505 warmed-up and output returned low.
    }
    
    void loop() 
    {
      if (interruptReturn) {    // Woke up by rising pin
        send(msg.set("1"));  // Just send trip (set) commands to controller.
        wait(50);
        send(msg.set("0"));  // Send the off command right after
        irtCounter++;
        if (irtCounter >= BATTERY_REPORT_BY_IRT_CYCLE) {
            irtCounter=0;
            sendBatteryReport();
        }
      }
      else { // Woke up by timer  (or it's the first run)
        dayCounter++; 
        if (dayCounter >= BATTERY_REPORT_DAY) {
              dayCounter = 0;
              sendBatteryReport();
        }
      }
      
      sleep(3000);  // Make sure everything is stable before start to sleep with interrupts. (don't use "wait()" here). Tests shows false trip ~2s after battery report otherwise.
    
      // Sleep until interrupt comes in on motion sensor or sleep time passed.
      interruptReturn = sleep(MOTION_INPUT_PIN-2, RISING, ONE_DAY_SLEEP_TIME);
    } 
    
    void sendBatteryReport() {
      wait(50);
      float p = vcc.Read_Perc(VCC_MIN, VCC_MAX, true);
      float v = vcc.Read_Volts();
      int batteryPcnt = static_cast<int>(p);
      sendBatteryLevel(batteryPcnt);
      send(voltage_msg.set(v,3));
    }
    


  • My code is a little different, since I only send 0 when the PIR reports 0, instead of sending it right after 1.

    If you want I may post the code later.


  • Hardware Contributor

    @abmantis Yes, I did that earlier too, but like this it was easier too use with my controller. Would be great if you could post your code too. Then I could test that too. Really want to get my pir up and working again ;)


  • Mod

    @LastSamurai a quick test would be to introduce a blind time after triggering by issuing a sleep for a fixed amount of time (e.g 30 secs) without wake from Interrupt.
    After this sleep you start another sleep which will wake when the sensor triggers.
    I added this to my pir sensors and it works great!


  • Hardware Contributor

    @Yveaux Isn't the "sleep(3000)" already this blind time? But, sure an increase would be good start.


  • Mod

    @m26872 yup, you're right :smirk: I didn't look at the sketch.
    It should indeed wait longer than 3 seconds.



  • @LastSamurai Here is the code for my PIR and Light sensore node:
    https://github.com/abmantis/MySensors-Sketches/blob/master/MotionLightSensor/MotionLightSensor.ino

    It is a bit complex, sorry. Also, ignore the temperature parts since that is a WIP and is untested.


Log in to reply
 

Looks like your connection to MySensors Forum was lost, please wait while we try to reconnect.