<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Motion detector with temperature and barometer function]]></title><description><![CDATA[<p dir="auto">I have built an intrusion detector that also measures barometer pressure and indoor and outdoor temperatures.</p>
<p dir="auto">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.</p>
<p dir="auto">When movement is detected two red LEDs flash during 20 sec.</p>
<p dir="auto">Everything is built into a frightening wooden mask, bought in Indonesia. The LEDs poke out through the nostrils.</p>
<p dir="auto">Here is the sketch:</p>
<pre><code>/**
 * 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 &lt;henrik.ekblad@mysensors.org&gt;
 * 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 &lt;Adafruit_BMP280.h&gt;
#include &lt;Adafruit_Sensor.h&gt;
#include &lt;OneWire.h&gt;
#include &lt;DallasTemperature.h&gt;
#include &lt;SPI.h&gt;

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(&amp;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 &lt;MySensors.h&gt;

// 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&lt;numSensors &amp;&amp; i&lt;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 &lt; 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&lt;numSensors &amp;&amp; i&lt;MAX_ATTACHED_DS18B20; i++) {
  // Fetch and round temperature to one decimal
  float otemperature = static_cast&lt;float&gt;(static_cast&lt;int&gt;((sensors.getTempCByIndex(i)) * 10.)) / 10.;

  // Only send data if no error
    
  if (otemperature != -127.00 &amp;&amp; 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 &lt; 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 --&gt;  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 &gt; 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 &lt; 35 &amp;&amp; firstRound) //if time is less than 35 min on the first 3 hour interval.
  {
    forecast = UNKNOWN;
  }
  else if (dP_dt &lt; (-0.25))
  {
    forecast = THUNDERSTORM;
  }
  else if (dP_dt &gt; 0.25)
  {
    forecast = UNSTABLE;
  }
  else if ((dP_dt &gt; (-0.25)) &amp;&amp; (dP_dt &lt; (-0.05)))
  {
    forecast = CLOUDY;
  }
  else if ((dP_dt &gt; 0.05) &amp;&amp; (dP_dt &lt; 0.25))
  {
    forecast = SUNNY;
  }
  else if ((dP_dt &gt;(-0.05)) &amp;&amp; (dP_dt &lt; 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 --&gt; "));
  //Serial.println(weather[forecast]);

  return forecast;
}

</code></pre>
<p dir="auto">and here are a couple of photos, front and back:<br />
![alt text](<img src="/uploads/files/1487498681253-upload-7deee0a5-263a-42b0-989a-55d1aae32cf4.png" alt="0_1487498680609_upload-7deee0a5-263a-42b0-989a-55d1aae32cf4" class=" img-fluid img-markdown" /> image url)DSC_0669 (1).jpg<br />
![alt text](<img src="/uploads/files/1487498717616-upload-cd76f838-04f6-4fab-a4b8-e37823a7419c-resized.png" alt="0_1487498717047_upload-cd76f838-04f6-4fab-a4b8-e37823a7419c" class=" img-fluid img-markdown" /> image url)DSC_0668 (1).jpg</p>
]]></description><link>https://forum.mysensors.org/topic/6217/motion-detector-with-temperature-and-barometer-function</link><generator>RSS for Node</generator><lastBuildDate>Mon, 17 Aug 2026 07:51:00 GMT</lastBuildDate><atom:link href="https://forum.mysensors.org/topic/6217.rss" rel="self" type="application/rss+xml"/><pubDate>Sun, 19 Feb 2017 10:06:05 GMT</pubDate><ttl>60</ttl></channel></rss>