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

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:

  • BMP180BMP180Dimension of PCB: 10 x 12 x 2 mm (11mm height with straight connector welded)
  • Power supply: 3 to 5 Volts
  • Low power consumption: 5 μA for 1 measurement per second
  • Measurement range of atmospheric pressure: from 300-1100 hPa (up to 9000m above sea level)
  • Measurement accuracy: 0.03hPa – 0.25m altitude
  • Operation: -40 ° C to + 85 ° C
  • The complete technical data sheet is available here

Important recommendations

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

  • The BMP180 must be in contact with the ambient air to carry out the measurements. If you need to integrate the sensor into a housing, do not forget to provide holes for air circulation.
  • Do not expose the BMP180 excessively to the airflow of a fan, as this may result in erroneous or very fluctuating measurements.
  • The measurement of the atmospheric pressure depends on the temperature. Avoid placing the BMP180 in front of a source of heat, still less in front of a source producing rapid changes (heating, window in full sun …).
  • The BMP180 is sensitive to moisture and is not intended for direct contact with water.
  • It is also sensitive to light. It should be protected as much as possible from ambient light. Do not place the sensor in front of the ventilation hole of your case, for example.
  • The BMP180 accepts a supply voltage between 1.8 and 3.6 Volts. The best way is to use the 3.3V output of your Arduino without ever exceeding 3.6V (according to Sparkfun).

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

  • 1 hPa = 100 Pa = 1 mbar = 0.001 bar
  • 1 hPa = 0.75006168 Torr
  • 1 hPa = 0.01450377 psi (imperial measurement, pounds per square inch)
  • 1 hPa = 0.75006375541921 mmHg (millimeters of mercury)
  • 1 hpa = 0.00098692 atm (atmosphere)

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

Estimation de l'altitude en fonction de la pression atmosphérique

Subscribe to the weekly newsletter

No spam and no other use will be made of your email. You can unsubscribe anytime.

Tags:

We will be happy to hear your thoughts

Leave a Reply

DIY Projects
%d bloggers like this: