In this tutorial we are going to design a Barometric Pressure Measuring System using BMP180 and ARDUINO. First of all for interfacing BMP180 to ARDUINO, we need to download a library specifically designed for BMP180. This library is available at: https://github.com/adafruit/Adafruit-BMP085-Library After attaching that library, we can call special functions which will ease working with BMP180 sensor.
This pressure sensor is a BMP-180 based digital barometric pressure sensor module and is functional compatible with older BMP-085 digital pressure sensor with less power consumption smaller in size and more accurate. BMP180 combines barometric pressure, temperature and altitude. The I2C allows easy interface with any microcontroller. On board 3.3V LDO regulator makes this board fully 5V supply compatible. BMP-180 can measure pressure range from 300 to 1100hPa (+9000m to -500m relating to sea level) with an accuracy down to 0.02hPa (0.17m) in advance resolution mode. BMP-180 is an improved replacement for BMP-085 sensor. BMP-180 uses piezo-resistive technology for high accuracy, linearity, EMC robustness and stability for a longer period of time.
Features:
Specifications:
The BMP180 consists of a piezo-resistive sensor, an analog to digital converter and a control unit with E2PROM and a serial I2C interface. The BMP180 delivers the uncompensated value of pressure and temperature.The microcontroller sends a start sequence to start a pressure or temperature measurement. After converting time, the result value (pressure or temperature respectively) can be read via the I2C interface. For calculating temperature in °C and pressure in hPa, the calibration data has to be used. These constants can be read out from the BMP180 E2PROM via the I2C interface at software initialization.The sampling rate can be increased up to 128 samples per second (standard mode) for dynamic measurement. In this case, it is sufficient to measure the temperature only once per second and to use this value for all pressure measurements during the same period.
You can use any method you like to make your connections to the board. For this example, we’ll solder on a five-pin length of male-male header strip, and use male/female jumper wires to connect the BMP180 to your Arduino.
Solder a 5-pin length of male-male header to the board. You can solder it to either side; the bottom is more useful for breadboards, and the top is more useful for jumper wires.
Note that the BMP180 is sensitive to moisture. When you’re done soldering, do not clean off the flux by rinsing the board in water or other fluids.
In the following sections, we can see how to interface the breakout board with Osoyoo UNO. The breakout board has 5 pins which are mentioned below. The board has 3.3V regulator. So you can use either 5V or 3.3V as supply voltage.
SDA | I2C data | Any pin labeled SDA, or:
|
||||||
SCL | I2C clock | Any pin labeled SCL, or:
|
||||||
GND | ground | GND | ||||||
VCC | 3.3V/5V power supply | 3.3V/5V | ||||||
3.3V | 3.3V | 3.3V |
The BMP180 was designed to accurately measure atmospheric pressure. Atmospheric pressure varies with both weather and altitude; you can measure both of these using this sensor. Here’s how:
The definition of pressure is a force “pressing” on an area. A common unit of pressure is pounds per square inch (psi). One pound, pressing on one square inch, equals one psi. The SI unit is newtons per square meter, which are called pascals (Pa).
There are lots of situations in which pressure can be measured (gravity, pull, etc.), but right now we’re interested in atmospheric pressure, which is the force that the air around you is exerting on everything. The weight of the gasses in the atmosphere creates atmospheric pressure. One doesn’t normally notice that air weighs anything, but if you took a one inch wide column of air from sea level to the top of the atmosphere, it would weigh about 14.7 pounds. (A 1 cm wide column of air would weigh about 1 kg.) This weight, pressing down on the footprint of that column, creates the atmospheric pressure that we can measure with sensors like the BMP180.
Because that inch-wide column of air weighs about 14.7 pounds, and is pressing on one square inch, it follows that the average sea level pressure is about 14.7 pounds per square inch (psi), or 101325 pascals. This will drop about 4% for each 1000 feet (or 300 meters) you ascend. The higher you get, the less pressure you’ll see, because the column to the top of the atmosphere is that much shorter and therefore weighs less. This is useful to know, because by measuring the pressure and doing some math, you can determine your altitude.
Fun fact: The air pressure at 12,500 feet (3810 meters) is only half of that at sea level. In other words, half of the mass of the atmosphere is below 12,500 feet, and the air at 12,500 feet is half as dense as that at sea level. No wonder you have a harder time breathing up there.
The BMP180 outputs absolute pressure in pascals (Pa). One pascal is a very small amount of pressure, approximately the amount that a sheet of paper will exert resting on a table. You will more often see measurements in hectopascals (1 hPa = 100 Pa) or kilopascals (1 kPa = 1000 Pa). The Arduino library we’ve provided outputs floating-point values in hPa, which also happens to equal one millibar (mbar).
Here are some conversions to other pressure units:
1 hPa = 100 Pa = 1 mbar = 0.001 bar
1 hPa = 0.75006168 Torr
1 hPa = 0.01450377 psi (pounds per square inch)
1 hPa = 0.02953337 inHg (inches of mercury)
1 hpa = 0.00098692 atm (standard atmospheres)
Because temperature affects the density of a gas, and density affects the mass of a gas, and mass affects the pressure (whew), atmospheric pressure will change dramatically with temperature. Pilots know this as “density altitude”, which makes it easier to take off on a cold day than a hot one because the air is more dense and has a greater aerodynamic effect.
To compensate for temperature, the BMP180 includes a rather good temperature sensor as well as a pressure sensor. To perform a pressure reading, you first take a temperature reading, then combine that with a raw pressure reading to come up with a final temperature-compensated pressure measurement. (Don’t worry, the Arduino library makes all of this very easy.)
As we just mentioned, if your application requires measuring absolute pressure, all you have to do is get a temperature reading, then perform a pressure reading (see the example sketch for details). The final pressure reading will be in hPa = mbar. If you wish, you can convert this to a different unit using the above conversion factors.
Note that the absolute pressure of the atmosphere will vary with both your altitude and the current weather patterns, both of which are useful things to measure.
The atmospheric pressure at any given location on earth (or anywhere with an atmosphere) isn’t constant. The complex interaction between the earth’s spin, axis tilt, and many other factors result in moving areas of higher and lower pressure, which in turn cause the variations in weather we see every day. By watching for changes in pressure, you can predict short-term changes in the weather. For example, dropping pressure usually means wet weather or a storm is approaching (a low-pressure system is moving in). Rising pressure usually means that clear weather is approaching (a high-pressure system is moving through).
But remember that atmospheric pressure also varies with altitude. The absolute pressure in Denver (altitude 5280′) will always be lower than the absolute pressure in San Francisco (altitude 52′). If weather stations just reported their absolute pressure, it would be difficult to directly compare pressure measurements from one location to another (and large-scale weather predictions depend on measurements from as many stations as possible).
To solve this problem, weather stations always remove the effects of altitude from their reported pressure readings by mathematically adding the equivalent fixed pressure to make it appear as if the reading was taken at sea level. When you do this, a higher reading in San Francisco than Denver will always be because of weather patterns, and not because of altitude.
To do this, there is a function in the library called seaLevel(P,A)
. This takes absolute pressure (P) in hPa, and the station’s current altitude (A) in meters, and removes the effects of the altitude from the pressure. You can use the output of this function to directly compare your weather readings to other stations around the world.
For more information, here is a good Wikipedia article on mean sea level pressure.
Since pressure varies with altitude, you can use a pressure sensor to measure altitude (with a few caveats).
The average pressure of the atmosphere at sea level is 1013.25 hPa (or mbar). This drops off to zero as you climb towards the vacuum of space. Because the curve of this drop-off is well understood, you can compute the altitude difference between two pressure measurements (p and p0) by using this equation:
There are two ways you can take advantage of this.
There’s a function in the library called altitude(P,P0)
that lets you accomplish both of these things. If you give it the sea level pressure (1013.25 hPa) for p0, and your local pressure for p, it will give you your altitude above sea level. If you use a local pressure measurement for p0, subsequent p pressure readings will give you your change in altitude from the baseline.
Now for the caveats:
Accuracy: How accurate is this? The theoretical noise level at the BMP180s highest resolution is 0.25m (about 10 inches), though in practice we see noise on the order of 1m (40 inches). You can improve the accuracy by taking a large number of readings and averaging them, although this will slow down your sample rate and response time.
Weather: You should also remember that pressure changes due to weather will affect your altitude readings. The best accuracy will be obtained if you take a “fresh” p0 when you need it and don’t rely on it to be accurate for extended periods due to changes in the weather.
Maximum altitude: The BMP180 can’t measure all the way down to vacuum (or up to space). It’s advertised lower limit is about 300 hPa (or mbar), which corresponds to an altitude of about 3000m or 30,000 feet. People have flown these to higher altitudes and gotten useful results, but this isn’t guaranteed or likely to be accurate. (You might consider using GPS for high-altitude measurements).
Minimum altitude: Similarly, this sensor isn’t suited for large pressures either. The advertised upper limit is 1100 hPa=mbar (or 16 psi), which is about 500 feet below sea level (that’s in air – the BMP180 isn’t submersible in water). This sensor isn’t a good choice for submersible or compressed-gas measurements.
Here are some important recommendations for making correct measurements and protecting the BMP180.
Each device has an I2C address that it uses to accept commands or send messages. For Uno board, this address usually is 0x27. But sometimes the address might be changed 0x37,0x24 …., So let’s go and look for the one on your device.
Download ic2_scanner sketch zip file , then unzip and load it into Arduino IDE. By opening up the serial monitor in the upright corner, Arduino will scan the address range looking for a reply. Most Arduino board will show 0x27, however it be other number.
Write down the Address that you have found, you may need it in the next step.
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.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
|
/*********************************************************************
BMP180 /BMP085 sensor
Test program without external library
www.projetsdiy.fr
From original version of Leo Nutz, www.ALTDuino.de
**********************************************************/
#include
#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
}
|
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.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
#include
#include
/***************************************************
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);
}
|
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.
DownLoad Url osoyoo.com