DIY Projects

BMP180 (Arduino): how to create a numerical barometer sensor

bmp180 bmp085 arduino

The BMP180 is a sensor that can measure atmospheric pressure and temperature using your Arduino or Raspberry Pi very simply. BMP180 is the next generation Bosch BMP085 sensor. No changes have been made to the firmware level, which makes it possible to continue using existing libraries and examples. BMP180 returns the absolute atmospheric pressure in Pascal (Pa). It will take a small unit conversion to present the measured value or use the conversion functions available in some libraries. You can buy BMP180 less than €4.

Connecting the BMP180 to an Arduino

The easiest way is to get the BMP180 already soldered to a PCB with an I2C interface. In the I2C version, the wiring of the BMP180 is very simple. The following table summarizes the wiring according to some Arduino boards.

BMP180 Pin Pin function Arduino connexion
DA (or SDA) I2C Data Any Pin identified SDA or
Uno, Redboard, Pro / Pro mini A4
Mega, Due 20
Leonardo, Pro Micro 2
ESP8266 D2 , GPIO-4
CL (or SCL) I2C clock Any Pin identified SCL or
Uno, Redboard, Pro / Pro mini A5
mega, Due 21
Leonardo, Pro Micro 3
ESP8266 D1, GPIO-5
– or GND Ground GND
+ or VCC 3,3 Volts 3.3V

BMP180 Technical Specifications:

Important recommendations

Here are some important recommendations for making correct measurements and protecting the BMP180.

3 methods to read the temperature and atmospheric pressure on the BMP180

Without using external library

Create a new project and paste the code below originally developed by Leo Nutz. It does not use any external libraries to communicate and perform measurement conversions. Less practical but also a little more compact than an external library which can prove very useful in an Arduino project.

/*********************************************************************
  BMP180 /BMP085 sensor
  Test program without external library
  www.projetsdiy.fr
  
  From original version of Leo Nutz, www.ALTDuino.de       
 
 **********************************************************/

#include <Wire.h>

#define ADDRESS_SENSOR 0x77                 // Addresse du capteur

int16_t  ac1, ac2, ac3, b1, b2, mb, mc, md; // Store sensor PROM values from BMP180
uint16_t ac4, ac5, ac6;                     // Store sensor PROM values from BMP180
// Ultra Low Power       OSS = 0, OSD =  5ms
// Standard              OSS = 1, OSD =  8ms
// High                  OSS = 2, OSD = 14ms
// Ultra High Resolution OSS = 3, OSD = 26ms
const uint8_t oss = 3;                      // Set oversampling setting
const uint8_t osd = 26;                     // with corresponding oversampling delay 

float T, P;                                 // Variables globales pour la température et la pression

void setup()
{
  Serial.begin(9600);                       
  while(!Serial){;}                         // On attend que le port série soit disponible
  delay(5000);
  Wire.begin();                             // Active le bus I2C
    init_SENSOR();                          // Initialise les variables
  delay(100);
}

void loop()
{
  int32_t b5;
 
  b5 = temperature();                       // Lit et calcule la température (T) 

  Serial.print("Temperature: ");
  Serial.print(T, 2);
  Serial.print("*C, ");

  P = pressure(b5);                         // Lit et calcule la pressure (P) 

  Serial.print("Pression: ");
  Serial.print(P, 2);
  Serial.print(" mbar, ");
  Serial.print(P * 0.75006375541921, 2);
  Serial.println(" mmHg");
  Serial.println("");

  delay(1000);                               // Delai entre chaque mesure
  
}

/**********************************************
  Initialise les variables du capteur
 **********************************************/
void init_SENSOR()
{
  ac1 = read_2_bytes(0xAA);
  ac2 = read_2_bytes(0xAC);
  ac3 = read_2_bytes(0xAE);
  ac4 = read_2_bytes(0xB0);
  ac5 = read_2_bytes(0xB2);
  ac6 = read_2_bytes(0xB4);
  b1  = read_2_bytes(0xB6);
  b2  = read_2_bytes(0xB8);
  mb  = read_2_bytes(0xBA);
  mc  = read_2_bytes(0xBC);
  md  = read_2_bytes(0xBE);

  Serial.println("");
  Serial.println("Données de calibration du capteur :");
  Serial.print(F("AC1 = ")); Serial.println(ac1);
  Serial.print(F("AC2 = ")); Serial.println(ac2);
  Serial.print(F("AC3 = ")); Serial.println(ac3);
  Serial.print(F("AC4 = ")); Serial.println(ac4);
  Serial.print(F("AC5 = ")); Serial.println(ac5);
  Serial.print(F("AC6 = ")); Serial.println(ac6);
  Serial.print(F("B1 = "));  Serial.println(b1);
  Serial.print(F("B2 = "));  Serial.println(b2);
  Serial.print(F("MB = "));  Serial.println(mb);
  Serial.print(F("MC = "));  Serial.println(mc);
  Serial.print(F("MD = "));  Serial.println(md);
  Serial.println("");
}

/**********************************************
  Calcul de la pressure
 **********************************************/
float pressure(int32_t b5)
{
  int32_t x1, x2, x3, b3, b6, p, UP;
  uint32_t b4, b7; 

  UP = read_pressure();                         // Lecture de la pression renvoyée par le capteur

  b6 = b5 - 4000;
  x1 = (b2 * (b6 * b6 >> 12)) >> 11; 
  x2 = ac2 * b6 >> 11;
  x3 = x1 + x2;
  b3 = (((ac1 * 4 + x3) << oss) + 2) >> 2;
  x1 = ac3 * b6 >> 13;
  x2 = (b1 * (b6 * b6 >> 12)) >> 16;
  x3 = ((x1 + x2) + 2) >> 2;
  b4 = (ac4 * (uint32_t)(x3 + 32768)) >> 15;
  b7 = ((uint32_t)UP - b3) * (50000 >> oss);
  if(b7 < 0x80000000) { p = (b7 << 1) / b4; } else { p = (b7 / b4) << 1; } // ou p = b7 < 0x80000000 ? (b7 * 2) / b4 : (b7 / b4) * 2;
  x1 = (p >> 8) * (p >> 8);
  x1 = (x1 * 3038) >> 16;
  x2 = (-7357 * p) >> 16;
  return (p + ((x1 + x2 + 3791) >> 4)) / 100.0f; // Retourne la pression en mbar
}

/**********************************************
  Lecture de la température (non compensée)
 **********************************************/
int32_t temperature()
{
  int32_t x1, x2, b5, UT;

  Wire.beginTransmission(ADDRESS_SENSOR); // Début de transmission avec l'Arduino 
  Wire.write(0xf4);                       // Envoi l'adresse de registre
  Wire.write(0x2e);                       // Ecrit la donnée
  Wire.endTransmission();                 // Fin de transmission
  delay(5);                               
  
  UT = read_2_bytes(0xf6);                // Lecture de la valeur de la TEMPERATURE 

  // Calcule la vrai température
  x1 = (UT - (int32_t)ac6) * (int32_t)ac5 >> 15;
  x2 = ((int32_t)mc << 11) / (x1 + (int32_t)md);
  b5 = x1 + x2;
  T  = (b5 + 8) >> 4;
  T = T / 10.0;                           // Retourne la température in celsius 
  return b5;  
}

/**********************************************
  Lecture de la pression 
 **********************************************/
int32_t read_pressure()
{
  int32_t value; 
  Wire.beginTransmission(ADDRESS_SENSOR);   // Début de transmission avec l'Arduino 
  Wire.write(0xf4);                         // Envoi l'adresse de registre
  Wire.write(0x34 + (oss << 6));            // Ecrit la donnée
  Wire.endTransmission();                   // Fin de transmission
  delay(osd);                               
  Wire.beginTransmission(ADDRESS_SENSOR);
  Wire.write(0xf6);                         
  Wire.endTransmission();
  Wire.requestFrom(ADDRESS_SENSOR, 3);      
  if(Wire.available() >= 3)
  {
    value = (((int32_t)Wire.read() << 16) | ((int32_t)Wire.read() << 8) | ((int32_t)Wire.read())) >> (8 - oss);
  }
  return value;                             // Renvoie la valeur
}

/**********************************************
  Lecture d'un byte sur la capteur BMP 
 **********************************************/
uint8_t read_1_byte(uint8_t code)
{
  uint8_t value;
  Wire.beginTransmission(ADDRESS_SENSOR);         
  Wire.write(code);                               
  Wire.endTransmission();                         
  Wire.requestFrom(ADDRESS_SENSOR, 1);            
  if(Wire.available() >= 1)
  {
    value = Wire.read();                          
  }
  return value;                                   
}

/**********************************************
  Lecture de 2 bytes sur la capteur BMP 
 **********************************************/
uint16_t read_2_bytes(uint8_t code)
{
  uint16_t value;
  Wire.beginTransmission(ADDRESS_SENSOR);         
  Wire.write(code);                               
  Wire.endTransmission();                         
  Wire.requestFrom(ADDRESS_SENSOR, 2);            
  if(Wire.available() >= 2)
  {
    value = (Wire.read() << 8) | Wire.read();     // Récupère 2 bytes de données
  }
  return value;                                   // Renvoie la valeur
}

With the Adafruit_BMP085 library

The Adafruit library (Adafruit_BMP085) has not been updated. It is still based on the BMP085. Unlike the Sparkfun bookshop, the altitude estimate is (almost) correct.

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

/*************************************************** 
  This is an example for the BMP085 Barometric Pressure & Temp Sensor

  Designed specifically to work with the Adafruit BMP085 Breakout 
  ----> https://www.adafruit.com/products/391

  These displays use I2C to communicate, 2 pins are required to  
  interface
  Adafruit invests time and resources providing this open source code, 
  please support Adafruit and open-source hardware by purchasing 
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.  
  BSD license, all text above must be included in any redistribution
 ****************************************************/

// Connect VCC of the BMP085 sensor to 3.3V (NOT 5.0V!)
// Connect GND to Ground
// Connect SCL to i2c clock - on '168/'328 Arduino Uno/Duemilanove/etc thats Analog 5
// Connect SDA to i2c data - on '168/'328 Arduino Uno/Duemilanove/etc thats Analog 4
// EOC is not used, it signifies an end of conversion
// XCLR is a reset pin, also not used here

Adafruit_BMP085 bmp;
  
void setup() {
  Serial.begin(9600);
  if (!bmp.begin()) {
    Serial.println("Could not find a valid BMP085 sensor, check wiring!");
    while (1) {}
  }
}
  
void loop() {
    Serial.print("Temperature = ");
    Serial.print(bmp.readTemperature());
    Serial.println(" *C");
    
    Serial.print("Pressure = ");
    Serial.print(bmp.readPressure());
    Serial.println(" Pa");
    
    // Calculate altitude assuming 'standard' barometric
    // pressure of 1013.25 millibar = 101325 Pascal
    Serial.print("Altitude = ");
    Serial.print(bmp.readAltitude());
    Serial.println(" meters");

  // you can get a more precise measurement of altitude
  // if you know the current sea level pressure which will
  // vary with weather and such. If it is 1015 millibars
  // that is equal to 101500 Pascals.
    Serial.print("Real altitude = ");
    Serial.print(bmp.readAltitude(101500));
    Serial.println(" meters");
    
    Serial.println();
    delay(500);
}

With the Sparfun library

The Sparkfun library is available here. Two examples are provided, one of which incorporates an estimate of the altitude according to the formula described below.

For further

Here is a small help file from wikipedia for unit conversions

Knowing the atmospheric pressure, it is possible to determine approximately the altitude thanks to this relation (some libraries integrate this function).

Click to rate this post!
[Total: 0 Average: 0]
Exit mobile version