PIR sensor and false positives



  • After building my first combined sensor (not battery powered) i got enthusiastic about the MySensors project. This project as you can see was based on Arduino Nano and is working like a charm
    0_1509653376359_2017-06-16 19.10.58.jpg

    So i wanted to add more off these combined sensor nodes to my smart house. This time i wanted to try a battery powered sensor based on Pro Mini (5v version) and built the following sensor:
    0_1509653752643_2017-10-31 21.42.55.jpg

    Both project use the same PIR & BH1750 sensor and are running the same sketch (the second without the temperature sensor), but the second project (even if project is not powered by the battery) gives a lot of (and i mean a lot of) false positives.

    I already checked the following things:

    • tested the PIR also on breadboard with a Nano and there it is working fine

    • the project with only the lux sensor is working fine (only removed the PIR in the sketch)

    Can anyone confirm if i can rule out the difference between the boards i used (Nano and Pro mini)? Or perhaps does anyone can point me in the right direction how i can solve this?


  • Mod

    The pir sensor is known to give false positives due to power fluctuations and EM interference. Try to put sensors as far as possible from radio module and add a decent size capacitor as close as possible to vcc pin of the the pir sensor.


  • Mod

    @Mister_ik I had lots of false triggers on an esp8266 node. Almost every time the esp sent data, the pir was triggered. Since the nrf uses the same frequencies, you might be experiencing the same problem.

    I glued aluminium foil to a piece of regular printer paper to create a shield around the pir module. I connected the foil to gnd.

    That eliminated all false triggers.


  • Hero Member

    @mfalkvidd said in PIR sensor and false positives:

    I glued aluminium foil to a piece of regular printer paper to create a shield around the pir module. I connected the foil to gnd.

    Do you have a photo of that?


  • Hardware Contributor

    Just a small sidenote... the 9v battery are a poor choise in some tests I have made (and google searches) to power the board because of their high cost / mah and also current draw capacity. Using a AA pack is a better solution. Even if you got it to work with 9v its very expensive in the long run.

    The main issue i guess is that the pir needs 5v unless you do some hacks, but with some time put into it - that works (i have two running on 3.3v)


  • Mod

    @Mister_ik try to design your sensor to be directly powered by batteries, without step up/down conversion. The converters in general introduce a lot of noise, which the pir is very sensitive to.
    I power my pir sensors from 3xAA battery (remove the regulator from the pir module) and a 3.3v pro mini from 2xAA (same battery pack, just branch power after 2 batteries instead of whole pack)
    Works flawlessly with many years of battery lifetime.



  • @NeverDie @mfalkvidd I am also curious how you have done that. I picture would be nice!


  • Mod

    Sorry, I didn't take any pictures.

    All I did was cut a piece of aluminum foil (stolen from the kitchen) to the size of a A4 paper (I guess Americans would use the "letter" size) and glue it to the paper. The paper doesn't conduct, so I didn't need to worry about shorting things.


  • Hero Member

    It sounds as though Yveaux didn't need the paper-metal shroud for some reason.


  • Mod

    @NeverDie yup, no aluminum foil in my builds 😉
    I do keep the radio away as far as possible from the PIR though.
    This thread contains a picture: https://forum.mysensors.org/topic/3756/multisensor-pir-based-on-ikea-molgan/61



  • Finally i got some time this weekend to try out all of you tips. So thanks for those tips. Indeed the problem was solved when i moved the PIR away from the rest. But what i also noticed is that the PIR also have false positives (much less when it was near to radio, but still there where false positives) when it is close to the Arduino board and away from the radio. Therefore i decided to alter the setup and not to make the sensor a battery powered sensor, but use some ethernet cable to connect the sensors to the mainboard with the arduino and the radio. The cable is long enough to reach a wall outlet, so i can run the arduino and radio on normal power.
    0_1511817845568_PIR.jpg
    Because i had now all the space in the sensor module i added a DHT sensor. Now some new challenges arise. The sensor is working fine, but when the PIR is going off, it loops the sketch a lot of times (exactly 50 times) before it sleeps again. Perhaps someone can give me a hint which is causing this. My programming skills are not that good, so I have combined some different sample sketches. I am using currently the following sketch:

    /**
     * The MySensors Arduino library handles the wireless radio link and protocol
     * between your home built sensors/actuators and HA controller of choice.
     * The sensors forms a self healing radio network with optional repeaters. Each
     * repeater and gateway builds a routing tables in EEPROM which keeps track of the
     * network topology allowing messages to be routed to nodes.
     *
     * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
     * Copyright (C) 2013-2015 Sensnology AB
     * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
     *
     * Documentation: http://www.mysensors.org
     * Support Forum: http://forum.mysensors.org
     *
     * This program is free software; you can redistribute it and/or
     * modify it under the terms of the GNU General Public License
     * version 2 as published by the Free Software Foundation.
     *
     *******************************
     *
     * REVISION HISTORY
     * Version 1.0 - Henrik Ekblad
     *
     * DESCRIPTION
     * Motion Sensor example using HC-SR501
     * http://www.mysensors.org/build/motion
     *
     */
    
    // Enable debug prints
    #define MY_DEBUG
    
    // Enable and select radio type attached
    #define MY_RADIO_NRF24
    #define MY_NODE_ID 130
    
    #include <SPI.h>
    #include <MySensors.h>
    #include <BH1750.h>
    #include <wire.h>
    #include <DHT.h>
    
    #define CHILD_ID_MOTION 131              // Id of the motion sensor child
    #define CHILD_ID_LIGHT  133              // Id of the Light sensor child
    #define CHILD_ID_HUM    134              // Id of Hum sensor child
    #define CHILD_ID_TEMP   135              // Id of temp sensor child
    
    #define DIGITAL_INPUT_SENSOR 2           // The digital input you attached your motion sensor.  (Only 2 and 3 generates interrupt!)
    #define INTERRUPT DIGITAL_INPUT_SENSOR-2 // Usually the interrupt = pin -2 (on uno/nano anyway)
    #define DHT_DATA_PIN 4                   // The digital input you attached your DHT sensor. 
    #define SENSOR_TEMP_OFFSET 0             // Set this offset if the sensor has a permanent small offset to the real temperatures
    
    // Sleep time between sensor updates (in milliseconds).  Must be >1000ms for DHT22 and >2000ms for DHT11
    static const uint64_t UPDATE_INTERVAL = 300000;
    //unsigned long SLEEP_TIME = 300000;       // Sleep time between reports (in milliseconds)
    
    // Force sending an update of the temperature after n sensor reads, so a controller showing the
    // timestamp of the last update doesn't show something like 3 hours in the unlikely case, that
    // the value didn't change since;
    // i.e. the sensor would force sending an update every UPDATE_INTERVAL*FORCE_UPDATE_N_READS [ms]
    static const uint8_t FORCE_UPDATE_N_READS = 10;
    
    float    lastTemp;
    float    lastHum;
    float    lasttripped;
    uint16_t lastlux;
    uint8_t  nNoUpdatesTemp;
    uint8_t  nNoUpdatesHum;
    uint16_t teller;
    bool     metric = true;
    
    BH1750 lightSensor;
    DHT dht;
    
    // Initialize motion message
    MyMessage msgmotion(CHILD_ID_MOTION, V_TRIPPED);
    MyMessage msglux(CHILD_ID_LIGHT, V_LEVEL);  
    MyMessage msgHum(CHILD_ID_HUM, V_HUM);
    MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
    
    
    // -------------------------------------------------------------------------//
    //  setup
    // -------------------------------------------------------------------------//
    void setup()
    {
      // setup of Lux sensor
      lightSensor.begin();
      pinMode(DIGITAL_INPUT_SENSOR, INPUT);      // sets the motion sensor digital pin as input
    
      // setup of DHT sensor
      dht.setup(DHT_DATA_PIN);                   // set data pin of DHT sensor
      if (UPDATE_INTERVAL <= dht.getMinimumSamplingPeriod()) {
        Serial.println("Warning: UPDATE_INTERVAL is smaller than supported by the sensor!");
      }
      // Sleep for the time of the minimum sampling period to give the sensor time to power up
      // (otherwise, timeout errors might occure for the first reading)
      sleep(dht.getMinimumSamplingPeriod());
    }
    // -------------------------------------------------------------------------//
    //  presentation
    // -------------------------------------------------------------------------//
    void presentation()
    {
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo("Motion + Lux + DHT", "1.0");
    
      // Register all sensors to gw (they will be created as child devices)
      present(CHILD_ID_LIGHT, S_LIGHT_LEVEL);
      present(CHILD_ID_MOTION, S_MOTION);
      present(CHILD_ID_HUM, S_HUM);
      present(CHILD_ID_TEMP, S_TEMP);
      
      // Bepalen nodeID
      uint8_t getNodeId();
      Serial.println();
      Serial.print("NodeID : "); 
      Serial.println(getNodeId());
      Serial.println();
    
      teller = 0;
      metric = getControllerConfig().isMetric;
    }
    
    // -------------------------------------------------------------------------//
    //  loop
    // -------------------------------------------------------------------------//
    void loop() {    
      //---------------------------------- 
      // **** BH1750 Lux sensor
      //----------------------------------
      Serial.println("------------------------------");
      Serial.println("Requesting Light level...");
      uint16_t lux = lightSensor.readLightLevel();// Get Lux value
      Serial.print("lux : "); 
      Serial.println(lux);
      if (lux != lastlux) {
         send(msglux.set(lux));
         lastlux = lux;
      }
      else {
         Serial.println("lux is nog hetzelfde : ");
      }
    
      //----------------------------------
      // Read digital motion value
      //----------------------------------
      Serial.println("------------------------------");
      Serial.println("Requesting motion...");
      bool tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH; 
      Serial.print("Beweging sensor : ");
      Serial.println(tripped);
      if (tripped != lasttripped) {
         send(msgmotion.set(tripped?"1":"0"));  // Send tripped value to gw 
         lasttripped = tripped;
      }
      else {
         Serial.println("Motion is nog hetzelfde : ");
      }
    
    
      // Force reading sensor, so it works also after sleep()
      dht.readSensor(true);
      //delay(dht.getMinimumSamplingPeriod());
      //----------------------------------
      // Get temperature from DHT library
      //----------------------------------
      Serial.println("------------------------------");
      Serial.print("Requesting Temperature...");
      float temperature = dht.getTemperature();
      Serial.println("DONE");
      if (isnan(temperature)) 
      {
        Serial.println("Failed reading temperature from DHT!");
      } 
      else if (temperature != lastTemp) {
        #ifdef MY_DEBUG
          Serial.print("OLD Temperature : ");
          Serial.println(lastTemp);
          Serial.print("NEW Temperature : ");
          Serial.println(temperature);
        #endif
        
        // Only send temperature if it changed since the last measurement or if we didn't send an update for n times
        lastTemp = temperature;
        if (!metric) {
          temperature = dht.toFahrenheit(temperature);
        }
        send(msgTemp.set(temperature, 1));
      }
    
      //----------------------------------
      // Get humidity from DHT library
      //----------------------------------
      Serial.println();
      Serial.print("Requesting Humidity...");
      float humidity = dht.getHumidity();
      Serial.println("DONE");
      if (isnan(humidity)) 
      {
        Serial.println("Failed reading humidity from DHT");
      } 
      else if (humidity != lastHum ) {
        #ifdef MY_DEBUG
          Serial.print("OLD Humidity : ");
          Serial.println(lastHum);
          Serial.print("NEW Humidity : ");
          Serial.println(humidity);
        #endif
        // Only send humidity if it changed since the last measurement or if we didn't send an update for n times
        lastHum = humidity;
        send(msgHum.set(humidity, 0));  
      }
      
      //----------------------------------
      // Sleep
      //----------------------------------
      teller++;
      Serial.println("------------------------------");
      // Sleep for a while to save energys
      Serial.print("teller...: "); 
      Serial.println(teller) ;
      sleep(INTERRUPT, CHANGE, UPDATE_INTERVAL); 
      Serial.println();
    }
    // -------------------------------------------------------------------------//
    // END : einde script
    // -------------------------------------------------------------------------//
    

  • Mod

    Did you try to put a short delay or sleep before the real sleep? Or you could also try some caps on the pir vcc


  • Mod

    @Mister_ik make sure you're using mySensors 2.2.x development branch, as it contains some fixes for sleeping with interrupts.


 

290
Online

7.6k
Users

8.5k
Topics

91.2k
Posts