Skip to content
  • MySensors
  • OpenHardware.io
  • Categories
  • Recent
  • Tags
  • Popular
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo
  1. Home
  2. My Project
  3. Motion detector with temperature and barometer function

Motion detector with temperature and barometer function

Scheduled Pinned Locked Moved My Project
temperaturepressuremotion sensor
1 Posts 1 Posters 1.4k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • bgunnarbB Offline
    bgunnarbB Offline
    bgunnarb
    wrote on last edited by
    #1

    I have built an intrusion detector that also measures barometer pressure and indoor and outdoor temperatures.

    The pressure and indoor temperature is measured by a BMP280 and a number of DS18B20 sensors can be connected to measure the temperature in remote locations.

    When movement is detected two red LEDs flash during 20 sec.

    Everything is built into a frightening wooden mask, bought in Indonesia. The LEDs poke out through the nostrils.

    Here is the sketch:

    /**
     * File name: MotionSensor_LED_2_temp_baro_280
     * 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
     * Version 2.1 - Gunnar Blockmar includes PMB280 temp/baro sensor and DS18B20 temp sensor
     * 
     * DESCRIPTION
     * Motion Sensor example using HC-SR501 
     * http://www.mysensors.org/build/motion
     *
     * Now with 1 fading LEDs when sensor is triggered
     * Measuring temp and pressure with BMP 280. Local pressure
     * Measuring remote temp via DS18B20
     */
    
    #include <Adafruit_BMP280.h>
    #include <Adafruit_Sensor.h>
    #include <OneWire.h>
    #include <DallasTemperature.h>
    #include <SPI.h>
    
    unsigned long SLEEP_TIME = 60000; // Sleep time between reports (in milliseconds)
    
    #define MY_DEBUG
    #define DIGITAL_INPUT_SENSOR 3   // 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 CHILD_ID_MOT 0   // Id of the motion sensor child
    #define CHILD_ID_ITEMP 1  // Id of indoor temperature sensor
    #define CHILD_ID_BARO 2  // Id of pressure sensor
    #define CHILD_ID_OTEMP 3  // Id of outdoor temperature sensor 
    #define RED_LED 5    // Pin for LED
    #define RED_LED2 6  // Pin for LED2
    #define DELAY 40     // Wait for brightness change
    int fadeAmount = 5;   // brightness change per step
    #define ONE_WIRE_BUS 2 // Pin where dallas sensor is connected 
    #define MAX_ATTACHED_DS18B20 16
    OneWire oneWire(ONE_WIRE_BUS); // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
    DallasTemperature sensors(&oneWire); // Pass the oneWire reference to Dallas Temperature. 
    int numSensors=0;
    bool receivedConfig = false;
    
    
    const char *weather[] = { "Stabilt", "Bättre", "Sämre", "Ostadigt", "Åska!", "Okänt" };
    enum FORECAST
    {
      STABLE = 0,     // "Stable Weather Pattern"
      SUNNY = 1,      // "Slowly rising Good Weather", "Clear/Sunny "
      CLOUDY = 2,     // "Slowly falling L-Pressure ", "Cloudy/Rain "
      UNSTABLE = 3,   // "Quickly rising H-Press",     "Not Stable"
      THUNDERSTORM = 4, // "Quickly falling L-Press",    "Thunderstorm"
      UNKNOWN = 5     // "Unknown (More Time needed)
    };
    
    Adafruit_BMP280 bmp;      // Digital Pressure Sensor
    
    float lastPressure = -1;
    float lastTemp = -1;
    int lastForecast = -1;
    
    const int LAST_SAMPLES_COUNT = 5;
    float lastPressureSamples[LAST_SAMPLES_COUNT];
    
    // this CONVERSION_FACTOR is used to convert from Pa to kPa in forecast algorithm
    // get kPa/h by dividing hPa by 10 
    #define CONVERSION_FACTOR (1.0/10.0)
    
    int minuteCount = 0;
    bool firstRound = true;
    // average value is used in forecast algorithm.
    float pressureAvg;
    // average after 2 hours is used as reference value for the next iteration.
    float pressureAvg2;
    float dP_dt;
    
    
    
    // Enable debug prints to serial monitor
    // #define MY_DEBUG 
    
    // Enables and select radio type (if attached)
    #define MY_RADIO_NRF24
    //#define MY_RADIO_RFM69
    
    #define MY_NODE_ID 41
    
    #include <MySensors.h>
    
    // Initialize motion message
    MyMessage msgm(CHILD_ID_MOT, V_TRIPPED);
    // Initialize temp baro and forecast messages
    MyMessage msgit(CHILD_ID_ITEMP, V_TEMP);
    MyMessage msgp(CHILD_ID_BARO, V_PRESSURE);
    MyMessage forecastMsg(CHILD_ID_BARO, V_FORECAST);
    MyMessage msgot(0, V_TEMP);
    
    bool metric = true;
    void before()
    {
      // Startup up the OneWire library
      sensors.begin();
    }
    
    
    void setup()  
    {  
      pinMode(DIGITAL_INPUT_SENSOR, INPUT);      // sets the motion sensor digital pin as input
      pinMode(RED_LED, OUTPUT);   // sets the pin for the LEDs as output
      pinMode(RED_LED2, OUTPUT);
      analogWrite(RED_LED, 0);    // make sure LEDs are OFF
      analogWrite(RED_LED2, 0);
      bmp.begin();
      if (!bmp.begin()) 
      {
        Serial.println("Could not find a valid BMP280 sensor, check wiring!");
        while (1) {}
      }
      // requestTemperatures() will not block current thread
      sensors.setWaitForConversion(false);
    }
    
    void presentation()
    {
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo("M. Sens_LED_2t/b/f 280", "2.2");
    
      // Fetch the number of attached temperature sensors  
      numSensors = sensors.getDeviceCount();
      
      // Register all sensors to gw (they will be created as child devices)
      present(CHILD_ID_MOT, S_MOTION);
      present(CHILD_ID_ITEMP, S_TEMP);
      present(CHILD_ID_BARO, S_BARO);
      for (int i=0; i<numSensors && i<MAX_ATTACHED_DS18B20; i++) {   
         present(i+CHILD_ID_OTEMP, S_TEMP);
      }   
    }
    
    void loop()     
    {     
      
      // Read digital motion value
      boolean tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH; 
            
        
      Serial.println(tripped);
      send(msgm.set(tripped?"1":"0"));  // Send tripped value to gw
       
    
      if (tripped) {
       int brightness = 0;   // brightness of LED
       int count = 0;  // number of half cycles to fade LED
       while (count < 12) {    // run 6 full fade cycles
          analogWrite(RED_LED, brightness);
          analogWrite(RED_LED2, brightness);
          brightness = brightness + fadeAmount;
          if (brightness == 0 || brightness == 255) {
            fadeAmount = -fadeAmount;  // change direction of fade
            count ++;
          }
          wait (DELAY);  //wait to see brightness change
        }
        analogWrite(RED_LED, 0);  // turn off LEDs
        analogWrite(RED_LED2, 0);
      }
    
      int long pressure = bmp.readPressure() / 100;
      float temperature = bmp.readTemperature();
      int forecast = sample(pressure);
    
      send(msgit.set(temperature, 1));
      send(msgp.set(pressure, 0));
      send(forecastMsg.set(weather[forecast]));
    
      // Fetch temperatures from Dallas sensors
      sensors.requestTemperatures();
    
      sleep (750);
    
      // Read temperatures and send them to controller 
      for (int i=0; i<numSensors && i<MAX_ATTACHED_DS18B20; i++) {
      // Fetch and round temperature to one decimal
      float otemperature = static_cast<float>(static_cast<int>((sensors.getTempCByIndex(i)) * 10.)) / 10.;
    
      // Only send data if no error
        
      if (otemperature != -127.00 && otemperature != 85.00) {
      // Send in the new temperature
          send(msgot.setSensor(i+CHILD_ID_OTEMP).set(otemperature,1));
      }  
    }
    
      
     
      // Sleep until interrupt comes in on motion sensor but send update every minute. 
      tripped = false;  //reset tripped
      sleep(INTERRUPT,CHANGE, SLEEP_TIME);
    }
    
    float getLastPressureSamplesAverage()
    {
      float lastPressureSamplesAverage = 0;
      for (int i = 0; i < LAST_SAMPLES_COUNT; i++)
      {
        lastPressureSamplesAverage += lastPressureSamples[i];
      }
      lastPressureSamplesAverage /= LAST_SAMPLES_COUNT;
    
      return lastPressureSamplesAverage;
    }
    
    // Algorithm found here
    // http://www.freescale.com/files/sensors/doc/app_note/AN3914.pdf
    // Pressure in hPa -->  forecast done by calculating kPa/h
    int sample(float pressure)
    {
      // Calculate the average of the last n minutes.
      int index = minuteCount % LAST_SAMPLES_COUNT;
      lastPressureSamples[index] = pressure;
    
      minuteCount++;
      if (minuteCount > 185)
      {
        minuteCount = 6;
      }
    
      if (minuteCount == 5)
      {
        pressureAvg = getLastPressureSamplesAverage();
      }
      else if (minuteCount == 35)
      {
        float lastPressureAvg = getLastPressureSamplesAverage();
        float change = (lastPressureAvg - pressureAvg) * CONVERSION_FACTOR;
        if (firstRound) // first time initial 3 hour
        {
          dP_dt = change * 2; // note this is for t = 0.5hour
        }
        else
        {
          dP_dt = change / 1.5; // divide by 1.5 as this is the difference in time from 0 value.
        }
      }
      else if (minuteCount == 65)
      {
        float lastPressureAvg = getLastPressureSamplesAverage();
        float change = (lastPressureAvg - pressureAvg) * CONVERSION_FACTOR;
        if (firstRound) //first time initial 3 hour
        {
          dP_dt = change; //note this is for t = 1 hour
        }
        else
        {
          dP_dt = change / 2; //divide by 2 as this is the difference in time from 0 value
        }
      }
      else if (minuteCount == 95)
      {
        float lastPressureAvg = getLastPressureSamplesAverage();
        float change = (lastPressureAvg - pressureAvg) * CONVERSION_FACTOR;
        if (firstRound) // first time initial 3 hour
        {
          dP_dt = change / 1.5; // note this is for t = 1.5 hour
        }
        else
        {
          dP_dt = change / 2.5; // divide by 2.5 as this is the difference in time from 0 value
        }
      }
      else if (minuteCount == 125)
      {
        float lastPressureAvg = getLastPressureSamplesAverage();
        pressureAvg2 = lastPressureAvg; // store for later use.
        float change = (lastPressureAvg - pressureAvg) * CONVERSION_FACTOR;
        if (firstRound) // first time initial 3 hour
        {
          dP_dt = change / 2; // note this is for t = 2 hour
        }
        else
        {
          dP_dt = change / 3; // divide by 3 as this is the difference in time from 0 value
        }
      }
      else if (minuteCount == 155)
      {
        float lastPressureAvg = getLastPressureSamplesAverage();
        float change = (lastPressureAvg - pressureAvg) * CONVERSION_FACTOR;
        if (firstRound) // first time initial 3 hour
        {
          dP_dt = change / 2.5; // note this is for t = 2.5 hour
        }
        else
        {
          dP_dt = change / 3.5; // divide by 3.5 as this is the difference in time from 0 value
        }
      }
      else if (minuteCount == 185)
      {
        float lastPressureAvg = getLastPressureSamplesAverage();
        float change = (lastPressureAvg - pressureAvg) * CONVERSION_FACTOR;
        if (firstRound) // first time initial 3 hour
        {
          dP_dt = change / 3; // note this is for t = 3 hour
        }
        else
        {
          dP_dt = change / 4; // divide by 4 as this is the difference in time from 0 value
        }
        pressureAvg = pressureAvg2; // Equating the pressure at 0 to the pressure at 2 hour after 3 hours have past.
        firstRound = false; // flag to let you know that this is on the past 3 hour mark. Initialized to 0 outside main loop.
      }
    
      int forecast = UNKNOWN;
      if (minuteCount < 35 && firstRound) //if time is less than 35 min on the first 3 hour interval.
      {
        forecast = UNKNOWN;
      }
      else if (dP_dt < (-0.25))
      {
        forecast = THUNDERSTORM;
      }
      else if (dP_dt > 0.25)
      {
        forecast = UNSTABLE;
      }
      else if ((dP_dt > (-0.25)) && (dP_dt < (-0.05)))
      {
        forecast = CLOUDY;
      }
      else if ((dP_dt > 0.05) && (dP_dt < 0.25))
      {
        forecast = SUNNY;
      }
      else if ((dP_dt >(-0.05)) && (dP_dt < 0.05))
      {
        forecast = STABLE;
      }
      else
      {
        forecast = UNKNOWN;
      }
    
      // uncomment when debugging
      //Serial.print(F("Forecast at minute "));
      //Serial.print(minuteCount);
      //Serial.print(F(" dP/dt = "));
      //Serial.print(dP_dt);
      //Serial.print(F("kPa/h --> "));
      //Serial.println(weather[forecast]);
    
      return forecast;
    }
    
    

    and here are a couple of photos, front and back:
    ![alt text](0_1487498680609_upload-7deee0a5-263a-42b0-989a-55d1aae32cf4 image url)DSC_0669 (1).jpg
    ![alt text](0_1487498717047_upload-cd76f838-04f6-4fab-a4b8-e37823a7419c image url)DSC_0668 (1).jpg

    I have never been so busy since I retired!

    1 Reply Last reply
    1
    Reply
    • Reply as topic
    Log in to reply
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes


    15

    Online

    11.7k

    Users

    11.2k

    Topics

    113.1k

    Posts


    Copyright 2025 TBD   |   Forum Guidelines   |   Privacy Policy   |   Terms of Service
    • Login

    • Don't have an account? Register

    • Login or register to search.
    • First post
      Last post
    0
    • MySensors
    • OpenHardware.io
    • Categories
    • Recent
    • Tags
    • Popular