Skip to main content

Barometric Pressure (BMP180)

This should already be your first sensor!

If you're following the Getting Started guide, then you'll already have this sensor set up and working. This page only exists here for the sake of users who want a bit more technical information on this sensor, or a more brief rundown of how to set it up quickly. You can read the First Sensor guide for a much less technical version of this page.

Wiring

tip

Source files for this diagram are available here.

What if I already have something connected there on the Pi?

If you have something already connected to SCL and SDA on your Pi, don't panic! You can just connect to the same two pins for all I2C sensors, as I2C uses a method to communicate that allows it to use only two pins to communicate with many devices on the same "bus".

bmp180 wiring diagram

Note that this sensor may be unsoldered in your kit, but comes with Molex-style headers. You can also solder wires directly to it if neccesary. If you need help with solering, reach out on the Discord.

Code

Aerospace Jam rolls its own library for the BMP180. The source code is available, but it comes pre-installed in the SDK, so you don't really have to worry about it. Usage is relatively simple:

from bmp180 import BMP180

bmp = BMP180() # you can specify an I2C bus number with `bus_number=*`, but it defaults to 1, which is correct for the above wiring

temperature = bmp.get_temperature()
pressure = bmp.get_pressure()
altitude = bmp.get_altitude()

print(f"Temperature: {temperature} °C")
print(f"Pressure: {pressure / 100.0} hPa") # Convert Pa to hPa, which is directly equivalent to mbar
print(f"Altitude: approximately {altitude} m above sea level")

If run, this code will print the temperature, pressure, and estimated altitude that you're at. Easy peasy!

Troubleshooting

The BMP180 is an I2C sensor, and therefore, the disclaimer regarding I2C in the Appendix remains relevant. If you're still stuck, try giving the First Sensor guide a read, which goes into setting up this sensor in much more simple terms, and has a more in-depth troubleshooting section.


Advanced: How Altitude is Calculated

The BMP180 does not measure altitude directly. It measures pressure, and the library then calculates an estimated altitude based on that pressure reading. This is done using the barometric formula, which relates the change in atmospheric pressure to a change in altitude.

The key thing to understand is that this calculation requires a reference point: the pressure at sea level (P0P_0).

Altitude=44330(1(CurrentPressureSeaLevelPressure)0.1903)Altitude = 44330 * (1 - (\frac{CurrentPressure}{SeaLevelPressure}) ^{0.1903})

The bmp.get_altitude() function uses a standard, internationally agreed-upon value for sea level pressure: 101325101325 Pascals. This is why the output is an "approximate" altitude. The actual local sea level pressure changes with the weather, so the altitude reading can fluctuate from day to day even if the sensor doesn't move.

Improving Accuracy for Relative Changes

While the absolute altitude reading may be off, the sensor is excellent for measuring changes in altitude. For example, if you want to measure how high your vehicle has climbed, you can improve accuracy significantly:

  1. Before launch, take a pressure reading on the ground. This will be your local reference pressure.
  2. Then, use it as your sea level: the library's get_altitude() function has an optional parameter where you can provide your own sea-level pressure. By passing your ground-level pressure reading to this function, you are effectively setting "zero altitude" to be your starting point.
# Before launch
ground_pressure = bmp.get_pressure()
print(f"Ground pressure set to: {ground_pressure} Pa")

# ... some time later, in the air ...
current_altitude = bmp.get_altitude(sea_level_pressure=ground_pressure)

# This will now give you a much more accurate height above your launch point.
print(f"Altitude above ground: {current_altitude} m")

Advanced: Reading Pressure Manually

This section is for teams who are not using the SDK or who want to write their own sensor library in a different language. The following steps outline the I2C communication and the mathematical formulas required to get a pressure reading directly from the BMP180, based on the logic in our library. If you need more reference code, try reading it yourself, too!

For Experts Only

These calculations are complex and based on the official Bosch datasheet. The process requires careful implementation of I2C read/write commands and specific integer arithmetic. For the ultimate source of truth, please refer to the Bosch BMP180 datasheet.

The process can be broken down into four main steps:

  1. Read the factory calibration data (only needs to be done once at startup).
  2. Read the uncompensated (raw) temperature value.
  3. Read the uncompensated (raw) pressure value.
  4. Use the calibration data and raw values to calculate the true temperature and pressure.

Step 1: Read Calibration Data

At startup, you must read 11 calibration values from the sensor's EEPROM. These are unique to each sensor.

Variable NameRegister AddressData Type
AC10xAAsigned 16-bit
AC20xACsigned 16-bit
AC30xAEsigned 16-bit
AC40xB0unsigned 16-bit
AC50xB2unsigned 16-bit
AC60xB4unsigned 16-bit
B10xB6signed 16-bit
B20xB8signed 16-bit
MB0xBAsigned 16-bit
MC0xBCsigned 16-bit
MD0xBEsigned 16-bit

Store these values in variables to be used in the final calculations.

Step 2: Read Uncompensated Temperature (UT)

  1. Write the value 0x2E to the control register 0xF4.
  2. Wait for at least 5 ms.
  3. Read 2 bytes (an unsigned 16-bit integer) from the data register 0xF6. This is your UT value.

Step 3: Read Uncompensated Pressure (UP)

  1. Choose an oversampling setting (oss), which determines the balance between accuracy and measurement time:
    oss ValueControl Register ValueMin. Wait Time
    0 (ultra low power)0x345 ms
    1 (standard)0x748 ms
    2 (high resolution)0xB414 ms
    3 (ultra high res)0xF426 ms
  2. Write the corresponding "Control Register Value" from the table above to register 0xF4.
  3. Wait for the "Min. Wait Time".
  4. Read 3 bytes from register 0xF6 (MSB), 0xF7 (LSB), and 0xF8 (XLSB).
  5. Combine them to get the raw pressure value UP using the formula: UP = ((MSB << 16) + (LSB << 8) + XLSB) >> (8 - oss)

Step 4: Calculate True Temperature and Pressure

Now, use the stored calibration data and the raw UT and UP values to get the final readings. These calculations rely only on optimizable, fast integer arithmetic, but works in a small unit that can be turned back into a float later.

A. Calculate True Temperature

  1. X1 = (UT - AC6) * AC5 / 2^15
  2. X2 = (MC * 2^11) / (X1 + MD)
  3. B5 = X1 + X2
  4. TrueTemperature = (B5 + 8) / 2^4

The TrueTemperature result is in units of 0.1 °C. Divide by 10 to get degrees Celsius. The B5 value is also needed for the pressure calculation.

B. Calculate True Pressure

  1. B6 = B5 - 4000
  2. X1 = (B2 * (B6 * B6 / 2^12)) / 2^11
  3. X2 = AC2 * B6 / 2^11
  4. X3 = X1 + X2
  5. B3 = (((AC1 * 4 + X3) << oss) + 2) / 4
  6. X1 = AC3 * B6 / 2^13
  7. X2 = (B1 * (B6 * B6 / 2^12)) / 2^16
  8. X3 = ((X1 + X2) + 2) / 4
  9. B4 = AC4 * (unsigned long)(X3 + 32768) / 2^15
  10. B7 = ((unsigned long)UP - B3) * (50000 >> oss)
  11. if (B7 < 0x80000000): p = (B7 * 2) / B4
  12. else: p = (B7 / B4) * 2
  13. X1 = (p / 2^8) * (p / 2^8)
  14. X1 = (X1 * 3038) / 2^16
  15. X2 = (-7357 * p) / 2^16
  16. TruePressure = p + (X1 + X2 + 3791) / 2^4

The final TruePressure value is in Pascals (Pa). You can now use this value for altitude calculations or other purposes.