False positives for HC-SR501 PIR battery node



  • I'm struggling with PIR sensor false positives on my sensor, meanwhile investigation is in progress, but maybe somebody already knows the solution?

    Latest investigation showed that PIR sees the motion each ~15min, which is the configured sleep time. So I guess that's somehow connected either to PIR settle time after sleep or some power instability right after waking up.

    Here is the part of my log for that node (all skipped except PIR):

    17-04-05 06:08:59 DEBUG (Thread-1) [homeassistant.components.mysensors] temp-hum-light-movement 10 1: value_type 16, value = 1
    17-04-05 06:09:41 DEBUG (Thread-5) [homeassistant.components.mysensors] temp-hum-light-movement 10 1: value_type 16, value = 0
    
    17-04-05 06:26:27 DEBUG (Thread-5) [homeassistant.components.mysensors] temp-hum-light-movement 10 1: value_type 16, value = 1
    17-04-05 06:27:09 DEBUG (Thread-1) [homeassistant.components.mysensors] temp-hum-light-movement 10 1: value_type 16, value = 0
    
    17-04-05 06:43:55 DEBUG (Thread-5) [homeassistant.components.mysensors] temp-hum-light-movement 10 1: value_type 16, value = 1
    17-04-05 06:44:37 DEBUG (Thread-8) [homeassistant.components.mysensors] temp-hum-light-movement 10 1: value_type 16, value = 0
    
    17-04-05 07:01:23 DEBUG (Thread-3) [homeassistant.components.mysensors] temp-hum-light-movement 10 1: value_type 16, value = 1
    17-04-05 07:02:05 DEBUG (Thread-6) [homeassistant.components.mysensors] temp-hum-light-movement 10 1: value_type 16, value = 0
    
    17-04-05 07:18:51 DEBUG (Thread-8) [homeassistant.components.mysensors] temp-hum-light-movement 10 1: value_type 16, value = 0
    17-04-05 07:18:51 DEBUG (Thread-1) [homeassistant.components.mysensors] temp-hum-light-movement 10 1: value_type 16, value = 1
    17-04-05 07:19:33 DEBUG (Thread-8) [homeassistant.components.mysensors] temp-hum-light-movement 10 1: value_type 16, value = 0
    
    17-04-05 07:36:19 DEBUG (Thread-6) [homeassistant.components.mysensors] temp-hum-light-movement 10 1: value_type 16, value = 1
    17-04-05 07:37:01 DEBUG (Thread-5) [homeassistant.components.mysensors] temp-hum-light-movement 10 1: value_type 16, value = 0
    
    17-04-05 07:53:47 DEBUG (Thread-7) [homeassistant.components.mysensors] temp-hum-light-movement 10 1: value_type 16, value = 1
    17-04-05 07:54:29 DEBUG (Thread-8) [homeassistant.components.mysensors] temp-hum-light-movement 10 1: value_type 16, value = 0
    
    17-04-05 08:11:15 DEBUG (Thread-4) [homeassistant.components.mysensors] temp-hum-light-movement 10 1: value_type 16, value = 1
    17-04-05 08:11:57 DEBUG (Thread-6) [homeassistant.components.mysensors] temp-hum-light-movement 10 1: value_type 16, value = 0
    
    17-04-05 08:28:43 DEBUG (Thread-9) [homeassistant.components.mysensors] temp-hum-light-movement 10 1: value_type 16, value = 1
    17-04-05 08:29:25 DEBUG (Thread-12) [homeassistant.components.mysensors] temp-hum-light-movement 10 1: value_type 16, value = 0
    
    17-04-05 08:46:11 DEBUG (Thread-7) [homeassistant.components.mysensors] temp-hum-light-movement 10 1: value_type 16, value = 1
    17-04-05 08:46:53 DEBUG (Thread-8) [homeassistant.components.mysensors] temp-hum-light-movement 10 1: value_type 16, value = 0
    

    PIR is HC-SR501, powered with 3.3v thru "H-pad" solution:
    0_1491383103220_FullSizeRender 2.jpg

    Wiring:
    0_1491383123974_temp-hum-light-movement_bb.png

    Code:

    
    
    /*
    *  Multisensor MySensors node (temperature, humidity, light, motion)
    *
    *  MCU:
    *   - Arduino Mini 3.3v
    *
    *  Integration type:
    *   - MySensors (Radio NRF24)
    *
    *  MySensors version:
    *   2.1.0
    *
    *  Modules:
    *   - nRF24L01: radio
    *   - HTU21 / GY-21: temperature/humidity
    *   - TBD: light
    *   - HC-SR501: motion
    *
    *   Wiring:
    *    Arduino       nRF24L01
    *      9  <------>  CE
    *     10  <------>  CSN/CS
    *     13  <------>  SCK
    *     11  <------>  MOSI
    *     12  <------>  MISO
    *    N/C  <------>  IRQ (not connected)
    *
    *     Arduino      HTU21
    *      A4  <----->  SCL
    *      A5  <----->  SDA
    *
    *     Arduino      Light (TBD)
    *
    *     Arduino      HC-SR501
    *       2  <------> Dout
    *
    *  Author:
    *   Vladimir Dobrikov <hedin.mail@gmail.com>
    */
    
    // Enable debug prints
    // #define MY_DEBUG
    
    #define SKETCH_NAME "temp-hum-light-movement"
    #define SKETCH_VERSION "1.1"
    
    // Enable and select radio type attached
    #define MY_RADIO_NRF24
    #define MY_RF24_PA_LEVEL RF24_PA_MIN // RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX
    
    //#define MY_NODE_ID 10
    
    // Keep MySensors.h below config definitions
    #include <Arduino.h>
    #include <MySensors.h>
    #include <SparkFunHTU21D.h>
    
    #define THRESHOLD_TEMP 2 // threshold to send update
    #define THRESHOLD_HUMD 2 // threshold to send update
    const unsigned long INIT_PIR_TIMEOUT_SEC = 5; // 3 sec to init PIR after poweron
    const unsigned long SLEEP_TIME_MIN = 15; // Sleep time between reports (in milliseconds)
    const byte BATT_WAKEUPS_MAX = 100; // Max wakeup times to send battery status
    const byte ENV_WAKEUPS_MAX = 10; // Max wakeup times to send temp/humidity status
    
    // #define DEBUG_OUPUT
    #if defined(DEBUG_OUPUT)
      #define DBGPRINT(str) Serial.print(str)
      #define DBGPRINTLN(str) Serial.println(str)
    #else
      #define DBGPRINT(str)
      #define DBGPRINTLN(str)
    #endif
    
    
    // Only 2 and 3 generates interrupt!
    #define PIN_MOTION 2
    #define PIN_LIGHT 3
    #define PIN_BATT A0
    
    // Child nodes IDs
    #define CHILD_ID_MOTION 1
    #define CHILD_ID_LIGHT 2
    #define CHILD_ID_TEMP 3
    #define CHILD_ID_HUMD 4
    
    // Initialize messages
    MyMessage msgMotion(CHILD_ID_MOTION, V_TRIPPED);
    MyMessage msgLight(CHILD_ID_LIGHT, V_TRIPPED);
    MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
    MyMessage msgHumd(CHILD_ID_HUMD, V_HUM);
    
    HTU21D sensorTempHumd;
    int8_t wakeupReason = -42;
    
    // Is there any convenient tool lib for that?
    bool prevMotion = false;
    bool motion = false;
    
    bool prevLight = false;
    bool light = false;
    
    float prevHumd = 0;
    float humd = 0;
    
    float prevTemp = 0;
    float temp = 0;
    
    int prevBattPcnt = 0;
    int battPcnt = 0;
    
    byte battWakeups = 0;
    byte envWakeups = 0;
    
    void setup()
    {
      analogReference(INTERNAL); // For batt measurement
      pinMode(PIN_MOTION, INPUT);
      pinMode(PIN_LIGHT, INPUT);
      sensorTempHumd.begin();
      sensorTempHumd.setResolution(USER_REGISTER_RESOLUTION_RH10_TEMP13);
    
      DBGPRINTLN(F("Sleep till PIR init"));
      sleep(INIT_PIR_TIMEOUT_SEC * 1000);
    }
    
    void presentation()
    {
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo(SKETCH_NAME, SKETCH_VERSION);
    
      // Register all sensors to gw (they will be created as child devices)
      present(CHILD_ID_MOTION, S_MOTION);
      present(CHILD_ID_LIGHT, S_CUSTOM);
      present(CHILD_ID_TEMP, S_TEMP);
      present(CHILD_ID_HUMD, S_HUM);
    }
    
    void loop()
    {
      // negative: timeout
      // 0: 1st interrupt
      // 1: 2nd interrupt
      DBGPRINTLN(F("---------------------------"));
      DBGPRINT(F("wakeupReason = "));DBGPRINTLN(wakeupReason < 0 ? "timeout" : wakeupReason == 0 ? "motion" : wakeupReason == 1 ? "light" : "unknown");
    
      battWakeups = battWakeups >= BATT_WAKEUPS_MAX ? 0 : battWakeups + 1;
      DBGPRINT(F("battWakeups = "));DBGPRINTLN(battWakeups);
    
      envWakeups = envWakeups >= ENV_WAKEUPS_MAX ? 0 : envWakeups + 1;
      DBGPRINT(F("envWakeups = "));DBGPRINTLN(envWakeups);
    
      if (battWakeups == 0) {
        battPcnt = getBattPcnt();
        DBGPRINT(F("battPcnt = "));DBGPRINTLN(battPcnt);
      }
    
      motion = digitalRead(PIN_MOTION) == HIGH;
      DBGPRINT(F("motion = "));DBGPRINTLN(motion);
    
      light = digitalRead(PIN_LIGHT) == LOW; // Reverse logic
      DBGPRINT(F("light = "));DBGPRINTLN(light);
    
      if (envWakeups == 0 || wakeupReason < 0) {
        humd = sensorTempHumd.readHumidity();
        DBGPRINT(F("humd = "));DBGPRINTLN(humd);
        humd = roundFloat(humd);
    
        temp = sensorTempHumd.readTemperature();
        DBGPRINT(F("temp = "));DBGPRINTLN(temp);
        temp = roundFloat(temp);
      }
    
      // Keep send action in the bottom close to each other to wakeup radio only
      // if needed and have it awake minimum time
      sendDataIfUpdate();
    
      // Sleep until interrupt comes in on motion or light sensor or sleep timeout.
      DBGPRINT(F("Going to sleep for (min): "));DBGPRINTLN(SLEEP_TIME_MIN);
      wakeupReason = sleep(digitalPinToInterrupt(PIN_MOTION), CHANGE, digitalPinToInterrupt(PIN_LIGHT), CHANGE, SLEEP_TIME_MIN * 60 * 1000);
    }
    
    void sendDataIfUpdate() {
      if (prevBattPcnt != battPcnt) {
        prevBattPcnt = battPcnt;
        DBGPRINT(F("  Sending batt: "));DBGPRINTLN(battPcnt);
        sendBatteryLevel(battPcnt);
      }
      if (prevMotion != motion) {
        prevMotion = motion;
        DBGPRINT(F("  Sending motion: "));DBGPRINTLN(motion);
    
        send(msgMotion.set(motion));
      }
      if (prevLight != light) {
        prevLight = light;
        DBGPRINT(F("  Sending light: "));DBGPRINTLN(light);
        send(msgLight.set(light));
      }
      if (abs(prevHumd - humd) >= THRESHOLD_HUMD) {
        prevHumd = humd;
        DBGPRINT(F("  Sending humd: "));DBGPRINTLN(humd);
        send(msgHumd.set(humd, 1));  // 1 means number of digits of fractional part
      }
      if (abs(prevTemp - temp) >= THRESHOLD_TEMP) {
        prevTemp = temp;
        DBGPRINT(F("  Sending temp: "));DBGPRINTLN(temp);
        send(msgTemp.set(temp, 1));  // 1 means number of digits of fractional part
      }
    }
    
    int getBattPcnt() {
      int rawBattVal = analogRead(PIN_BATT);
      DBGPRINT(F("rawBattVal = "));DBGPRINTLN(rawBattVal);
    
      return rawBattVal / 10;
    }
    
    // Round to 0.5
    float roundFloat(float val) {
      return round(val * 2) / 2;
    }
    
    

    Thanks in advance!


  • Hero Member

    @Vladimir-Dobrikov If you power the whole thing from batteries (2 AA, 3V) then for sure it is power related. The PIR is very sensitive to power fluctuations and unstable below 3v.
    You can try a large capacitor on the power lines but I doubt it...



  • @AWI do you think step-up to 3.3 + capacitor would help?


  • Hero Member

    @Vladimir-Dobrikov a step-up can be a cause of noise. I try to avoid these if possible. Three AA batteries or a lithium ion cell would be my choice.


  • Mod

    You can use 3 AA batteries for pir sensor and use 2 of them for the rest.



  • @gohan do you mean take 3 batteries and connect them to PIR thru 3.3v line like mentioned in pic above or thru regulator (regular 5v pin on PIR)? In case of 3.3 line, wouldn't it be risky to apply 4.5v?


  • Mod

    @Vladimir-Dobrikov do a search in the forum, but I remember someone suggested 3AA batteries to power PIR sensor with voltage regulator removed


  • Mod

    @gohan Guess that was me 😉

    @Vladimir-Dobrikov See my suggested setup in this thread.
    Also make sure you try the latest development version of MySensors, as I fixed a few nasty wake-from-sleep related bugs recently.


  • Mod

    @Yveaux yeah, could be. I have too many things to remember lately 😇



  • Thank you guys for quick help! Just bought some batteries to try with.. BTW I saw that this PIR supports 3..5v, so 4.5 is pretty safe.
    Will update once got results.



  • Just checked the solution: 9 hours of calm ghostless sleep. 🙂
    At lat I've got solid setup for PIR sensor. It was a headache for me last 6 months, when I tried it with ESP8266


Log in to reply
 

Suggested Topics

20
Online

11.2k
Users

11.1k
Topics

112.5k
Posts