Atmospheric Pressure Sensor

created by hek , updated

The BMP085 senses both pressure and temperature conditions. In the example sketch we've also implemented a simple weather forecast algorithm that could be useful if you decide to build a weather station.

This sensor has a very low power consumption (5μA in standard mode) and uses the I2C interface when communicating with the Arduino.

Wiring Things Up

Start by connecting the radio module.

Sensor Arduino Comment
GND GND Marked black
3V3 or +5V 3.3V or 5V Marked red
SCL A5 (analog input) Marked blue
SDA A4 (analog input) Marked green

Select 3.3V or 5V depending upon your Arduino model's output voltage.

Example

This example uses the external BMP085 library found here. Please install it and restart the Arduino IDE before trying to compile.

/mysensors/MySensorsArduinoExamples/examples/PressureSensor/PressureSensor.ino
Last updated by mfalkvidd, 6 Aug 2016, "Use bool instead of boolean in examples"

/**
 * 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 <[email protected]>
 * 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
 * Pressure sensor example using BMP085 module  
 * http://www.mysensors.org/build/pressure
 *
 */

// Enable debug prints to serial monitor
#define MY_DEBUG 

// Enable and select radio type attached
#define MY_RADIO_NRF24
//#define MY_RADIO_RFM69

#include <SPI.h>
#include <MySensors.h>  
#include <Wire.h>
#include <Adafruit_BMP085.h>

#define BARO_CHILD 0
#define TEMP_CHILD 1

const float ALTITUDE = 688; // <-- adapt this value to your own location's altitude.

// Sleep time between reads (in seconds). Do not change this value as the forecast algorithm needs a sample every minute.
const unsigned long SLEEP_TIME = 60000; 

const char *weather[] = { "stable", "sunny", "cloudy", "unstable", "thunderstorm", "unknown" };
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_BMP085 bmp = Adafruit_BMP085();      // 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 be 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;
bool metric;
MyMessage tempMsg(TEMP_CHILD, V_TEMP);
MyMessage pressureMsg(BARO_CHILD, V_PRESSURE);
MyMessage forecastMsg(BARO_CHILD, V_FORECAST);


void setup() 
{
    if (!bmp.begin()) 
    {
        Serial.println("Could not find a valid BMP085 sensor, check wiring!");
        while (1) {}
    }
    metric = getConfig().isMetric;
}

void presentation()  {
  // Send the sketch version information to the gateway and Controller
  sendSketchInfo("Pressure Sensor", "1.1");

  // Register sensors to gw (they will be created as child devices)
  present(BARO_CHILD, S_BARO);
  present(TEMP_CHILD, S_TEMP);
}

void loop() 
{
    float pressure = bmp.readSealevelPressure(ALTITUDE) / 100.0;
    float temperature = bmp.readTemperature();

    if (!metric) 
    {
        // Convert to fahrenheit
        temperature = temperature * 9.0 / 5.0 + 32.0;
    }

    int forecast = sample(pressure);

    Serial.print("Temperature = ");
    Serial.print(temperature);
    Serial.println(metric ? " *C" : " *F");
    Serial.print("Pressure = ");
    Serial.print(pressure);
    Serial.println(" hPa");
    Serial.print("Forecast = ");
    Serial.println(weather[forecast]);


    if (temperature != lastTemp) 
    {
        send(tempMsg.set(temperature, 1));
        lastTemp = temperature;
    }

    if (pressure != lastPressure) 
    {
        send(pressureMsg.set(pressure, 0));
        lastPressure = pressure;
    }

    if (forecast != lastForecast)
    {
        send(forecastMsg.set(weather[forecast]));
        lastForecast = forecast;
    }

    sleep(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;
}

Datasheets

NameSize# Downloads
BST-BMP085-DS000-05.pdf638.5 kB120

Shopping Guide

BMP180 Barometric Pressure Sensor
Barometric Digital Pressure Sensor (replaces the old BMP085). Also measures temperature.
2625 available - $2.44   Buy
In stock - $2.20   Buy

Comments