MicroPython Driver for BMP180 Sensor
Contents
Introduction
This a MicroPython driver written specifically for the BBC micro:bit that will work with the BMP180 ambient temperature and barometric pressure sensor.
This driver is now in Version 2.00 which is a major rewrite of the original (Version 1.00)
The BMP180 sensor is discussed in some detail here.
The sensor is quite small and for projects using a breadboard its much easier to use a BMP180 breakout board. The breakout boards are quite inexpensive.
Even though the chip itself is no longer in production the breakout boards still appear to be readily available at time of writing (June 2025).
Connecting the BMP180
The BMP180 communicates via I2C. Hooking it up to the micro:bit is easy:
| micro:bit | BMP180 |
|---|---|
| 3.3V | VIN |
| GND | GND |
| Pin 20 | SDA |
| Pin 19 | SCL |
This utilises the standard I2C pins of the micro:bit.
Driver Overview
The BMP180 breakout board is easy to use. Even though the BMP180 chip has been replaced at point of manufacture by next generation sensors, these little breakout boards gave surprisingly good results during the development and testing of this MicroPython driver.
Driver codeThe driver code can be:
- Copied from this webpage onto the clipboard then pasted into the MicroPython editor e.g. the Mu Editor. It should be saved as fc_bmp180.py - OR -
- Download as a zip file using the link. Unzip the file and save it as fc_bmp180.py into the default directory where the MicroPython editor e.g. Mu Editor saves python code files.
After saving the fc_bmp180.py file to the computer it should be copied to the small filesystem on the micro:bit. The examples on this page will not work if this step is omitted. Any MicroPython editor that recognises the micro:bit will have an option to do this.
The Mu Editor is recommended for its simplicity. It provides a Files button on the toolbar for just this purpose.
I2C addressThe BMP180 has a point of manufacture fixed I2C address of 0x77.
Class constructorThe driver is implemented as a class. The first thing to do is call the constructor. This provides an instance of the class.
Syntax:
BMP180()
Example
from fc_bmp180 import *
# Declare a sensor object
sensor = BMP180()
This assumes that the file fc_bmp180.py has been successfully copied to the micro:bit's filesystem as described above.
Methods and PropertiesThe driver provides methods to:
- Set the sampling mode
- Perform a soft reset
- Perform some basic altitude calculations
The driver also provides properties to:
- Get the sampling mode
- Read temperature and pressure
- Return the sensor chip's ID
The driver implements all functions described in the product Datasheet.
Get & Set the Sampling Mode
This driver provides four different sampling modes. They follow the suggestions given in the product Datasheet.
Syntax:
SetMode(Mode=1)
Sets the sampling mode:
0 : Ultra low power, lowest resolution
1 : Standard (default)
2 : High resolution
3 : Highest resolution
GetMode
Property that returns the current mode.
Example:
from fc_bmp180 import *
# Declare sensor object
# with default sampling mode
sensor = BMP180()
print('Sensor sampling mode:', sensor.GetMode)
# Change sampling mode
print('Changing sampling mode...')
sensor.SetMode(2)
print('Sensor sampling mode:', sensor.GetMode)
Output:
Sensor sampling mode: 1
Changing sampling mode...
Sensor sampling mode: 2
Reading Temperature and Pressure
There are three properties and one function that return temperature and/or pressure readings.
Syntax:
Reading
Property that returns temperature
and pressure as a list.
• Temperature is in degrees Celsius.
• Pressure is in HPa (hectopascals)
Example:
from fc_bmp180 import *
sensor = BMP180()
reading = sensor.Reading
print('[Temperature, Pressure] :', reading)
Typical Output:
[Temperature, Pressure] : [20.92817, 981.4676]
Syntax:
CtoF(C, d = 2)
Function that converts Celsius to Fahrenheit
Where:
C : Celsius value to convert to Fahrenheit
d : Number of rounded decimals.
Example:
from fc_bmp180 import *
C = 11.98 # Degrees Celsius
F = CtoF(C) # Converted to Fahrenheit
print('11.98 C =', F, 'F')
Output:
11.98 C = 53.56 F
Syntax:
T
Property that returns the temperature.
Syntax:
P
Property that returns the pressure.
Example:
from fc_bmp180 import *
sensor = BMP180()
print('Temperature:', sensor.T)
print('Pressure:', sensor.P)
Sample Output:
Temperature: 20.31613
Pressure: 981.4107
Altitude Calculations
This driver provides three different altitude calculations.
Mean Sea Level PressureThe absolute barometric pressure measured with a sensor cannot be compared to absolute values from other weather stations unless they're all at the same altitude.
To get around this problem the accepted practice is to convert pressure readings to their sea level equivalents. These are the the pressure values that are published by meteorological services. The technical term is MSLP (Mean Sea Level Pressure).
This driver provides the MSLP() method to perform this calculation. However it can only be done if the BMP180's elevation above sea level is known with reasonable accuracy. This can be obtained from such sources as the local government authority, contour maps or, at a pinch, from GPS.
Syntax:
MSLP(Altitude)
This method returns the mean sea level
pressure given the altitude of the sensor
in metres.
Example:
# Demonstrates the MSLP calculation.
from fc_bmp180 import *
from microbit import *
sensor = BMP180()
altitude = 400 # metres
mslp = sensor.MSLP(altitude)
print('Altitude is ', altitude, 'metres')
print('Mean Sea Level Pressure is', mslp, 'hPa')
Typical Output:
Altitude is 400 metres
Mean Sea Level Pressure is 1028.537 hPa
Calculating the Altitude
If the mean sea level pressure is known than the altitude of the sensor can be calculated. The MSLP can be obtained from an official weather station if this station is at the same elevation as the sensor.
Syntax:
Altitude(MSLP)
This method returns the altitude if the
MSLP (in hPa) is known.
Example:
# Demonstrates calculation of altitude.
from fc_bmp180 import *
from microbit import *
sensor = BMP180()
mslp = 1028 # hPa
altitude = sensor.Altitude(mslp)
print('Mean Sea Level Pressure is', mslp, 'hPa')
print('Altitude is', altitude, 'metres')
Typical Output:
Mean Sea Level Pressure is 1028 hPa
Altitude is 390 metres
Calculating Difference in Altitude
If absolute barometric pressures are obtained from the sensor at two different altitudes it is possible to calculate the difference between the two altitudes.
Syntax:
AltDiff(P1, P2)
This method returns the difference in
altitude in metres if the absolute
pressure is known for both altitudes.
Example:
# Calculates the difference between
# two different altitudes given the
# absolute barometric pressures of
# the two altitudes.
from fc_bmp180 import *
from microbit import *
sensor = BMP180()
p1 = 975 # hPa
p2 = 974 # hPa
diff = sensor.AltDiff(p1, p2)
print('Absolute pressure at P1:', p1, 'hPa')
print('Absolute pressure at P2:', p2, 'hPa')
print('Altitude difference:', int(diff), 'M')
Output:
Absolute pressure at P1: 975 hPa
Absolute pressure at P2: 974 hPa
Altitude difference: 8 M
Getting the Chip ID
BMP180 chips have the ID value 0x55 written to read-only memory at point of manufacture . The ID property can be used to check that a BMP180 chip is connected to the microcontroller's I2C bus.
Syntax:
ID
Example:
from fc_bmp180 import *
sensor = BMP180()
print('BMP180 ID:', sensor.ID)
Output:
BMP180 ID: 0x55
BMP180 Soft Reset
The Reset() method causes the BMP180 to perform a soft reset. All power-on defaults are reloaded.
Most users might never use this method but it is presented here for completeness.
Syntax:
Reset()
Causes the BMP180 sensor to perform a soft reset.
Example:
from fc_bmp180 import *
sensor = BMP180()
sensor.Reset()
Enjoy!
BMP180 Driver Code for micro:bit
Download as zip file
'''
BMP180 Temperature and Barometric Pressure sensor
MicroPython driver for micro:bit
This is a major revision of Ver 1.00
EXAMPLE USAGE:
from fc_bmp180 import *
sensor = BMP180()
Temperature = sensor.T
Pressure = sensor.P
OSS Modes:
0 : Ultra low power
1 : Standard (default)
2 : High resolution
3 : Ultra high resolution
Temperature returned in Celsius.
Pressure returned in HPa.
AUTHOR: fredscave.com
DATE : 2025/06
VERSION : 2.00
'''
from microbit import i2c, sleep
from micropython import const
_ADDR = const(0x77)
_REG_OUT = const(0xF6)
_REG_MEASURE = const(0xF4)
_REG_RESET = const(0xE0)
_REG_ID = const(0xD0)
_CMD_READ_T = const(0x2E)
_CMD_READ_P = const(0x34)
_CMD_RESET = const(0xB6)
# Pressure conversion times (ms)
# for Modes 0 to 3
PCT = (6, 9, 15, 27)
# Convert Celsius to Fahrenheit
CtoF = lambda C, d=2: round((C * 9/5) +32, d)
class BMP180():
def __init__(self):
self._Load_Calibration_Data()
self.SetMode()
# Mode 0 : Ultra low power
# Mode 1 : Standard
# Mode 2 : High resolution
# Mode 3 : Ultra high resolution
def SetMode(self, Mode=1):
if Mode in range(0, 4):
self.OSS = Mode
else:
self.OSS = 1
# Soft reset, power-on defaults reloaded.
def Reset(self):
i2c.write(_ADDR, bytes([_REG_RESET, _CMD_RESET]))
sleep(10)
# *******************************************
# Properties
# *******************************************
# Trigger temperature and pressure measurements.
# Read uncompensated data and do the compensation
# calculations.
@property
def Reading(self):
# Get uncompensated temperature
i2c.write(_ADDR, bytes([_REG_MEASURE, _CMD_READ_T]))
sleep(6)
i2c.write(_ADDR, bytes([_REG_OUT]))
Buf = i2c.read(_ADDR, 2)
UT = Buf[0]*256 + Buf[1]
# Get uncompensated pressure
i2c.write(_ADDR, bytes([_REG_MEASURE,
_CMD_READ_P + (self.OSS << 6)]))
sleep(PCT[self.OSS])
i2c.write(_ADDR, bytes([_REG_OUT]))
Buf = i2c.read(_ADDR, 3)
UP = ((Buf[0] << 16) + (Buf[1] << 8) + Buf[2]) >> (8-self.OSS)
# Convert to actual temperature and pressure.
return self._Compensate(UT, UP)
# Returns temperature
@property
def T(self):
temp = self.Reading
return temp[0]
# Returns pressure
@property
def P(self):
pressure = self.Reading
return pressure[1]
# Return the chip's ID
@property
def ID(self):
i2c.write(_ADDR, bytes([_REG_ID]))
return hex(i2c.read(_ADDR, 1)[0])
# Returns Mode (0..3)
@property
def GetMode(self):
return self.OSS
# *******************************************
# Altitude Calculations
# *******************************************
# Calculate mean sea level pressure (MSLP)
# If the altitude of the sensor is known then
# the absolute pressure can be adjusted to its
# equivalent sea level pressure.
#
# This is the pressure that is reported by
# official weather services.
def MSLP(self, Altitude=None):
if Altitude == None:
return None
else:
P0 = 1013.25
a = 2.25577E-5
b = 5.25588
P = self.Reading[1]
PS = P0 * (1 - a * Altitude) ** b
offset = P0 - PS
return P + offset
# If pressure readings are taken at different
# altitudes then this method will calculate
# the difference between these two altitudes
# in meters.
def AltDiff(self, P1, P2):
a = 0.1157227
return (P1 - P2) / a
# If the Mean Sea Level pressure is known
# (usually obtained from the local weather service)
# then this method will calculate the altitude
# of the sensor in meters.
# The sensor is read to obtain the absolute
# pressure value.
def Altitude(self, MSLP=None):
if MSLP == None:
return None
else:
p = self.P
a = -2.25577E-5
b = 0.1902631
h = (((p/MSLP) ** b) - 1) / a
return int(round(h, 0))
# *******************************************
# Private Methods
# *******************************************
# Load all the calibration data from
# the chip's non-volatile memory (NVM).
def _Load_Calibration_Data(self):
self.AC1 = self._get(0xAA, 1)
self.AC2 = self._get(0xAC, 1)
self.AC3 = self._get(0xAE, 1)
self.AC4 = self._get(0xB0, 0)
self.AC5 = self._get(0xB2, 0)
self.AC6 = self._get(0xB4, 0)
self.B1 = self._get(0xB6, 1)
self.B2 = self._get(0xB8, 1)
self.MB = self._get(0xBA, 1)
self.MC = self._get(0xBC, 1)
self.MD = self._get(0xBE, 1)
# Used to retrieve calibration data
# which can be returned as either a
# signed integer or unsigned integer.
def _get(self, Reg, Signed):
i2c.write(_ADDR, bytes([Reg]))
buf = i2c.read(_ADDR, 2)
d = buf[0]*256 + buf[1]
if Signed == 1:
if d > 32767:
return d - 65536
else:
return d
else:
return d
# Convert uncompensated temperature and pressure
# to actual (compensated) values.
def _Compensate(self, UT, UP):
# Calculate actual temperature
X1 = (UT - self.AC6) * self.AC5/(1 << 15)
X2 = self.MC * (1 << 11) / (X1 + self.MD)
B5 = X1 + X2
T = (B5 + 8)/160
# Calculate actual pressure
B6 = B5 - 4000
X1 = (self.B2 * (B6*B6/(1 << 12))) / (1 << 11)
X2 = (self.AC2 * B6)/(1 << 11)
X3 = X1 + X2
B3 = ((int((self.AC1*4+X3)) << self.OSS) + 2)/4
X1 = self.AC3 * B6 / (1 << 13)
X2 = (self.B1 * (B6*B6/(1 << 12))) / (1 << 16)
X3 = (X1 + X2 + 2)/4
B4 = self.AC4 * (X3 + 32768)/(1 << 15)
B7 = (UP-B3) * (50000 >> self.OSS)
if B7 < 0x80000000:
p = (B7*2)/B4
else:
p = (B7/B4) * 2
X1 = (p/(1 << 8))*(p/(1 << 8))
X1 = (X1 * 3038)/(1 << 16)
X2 = (-7357*p)/(1 << 16)
P = p + (X1 + X2 + 3791)/16
return [T, P/100]
Using All Methods & Properties
The following example uses most of the methods and properties already described.
The Code:
from fc_bmp180 import *
# Create BMP180 sensor object.
sensor = BMP180()
sensor.SetMode(3)
altitude = 400
print('BMP180 sensor configuration:')
print('Mode is', sensor.GetMode, '; Ultra high resolution')
print('Height above sea level =', altitude, 'meters\n')
# Get temperature and pressure
# Test all properties
print('Get Temperature and Pressure measurements:')
print('Reading property:', sensor.Reading)
print('Temperature only property:', sensor.T)
print('Pressure only property:', sensor.P)
# Calculate Mean Sea Level Pressure (MSLP)
print('\nMean Sea Level Pressure:', sensor.MSLP(altitude))
# Reset the chip
# Test by getting ID, Mode and MSLP
print('\nResetting the sensor...')
sensor.Reset()
print('Chip ID:', sensor.ID)
print('Mode is', sensor.GetMode)
print('Mean Sea Level Pressure:', sensor.MSLP(altitude))
Typical Output:
BMP180 sensor configuration:
Mode is 3 ; Ultra high resolution
Height above sea level = 400 meters
Get Temperature and Pressure measurements:
Reading property: [21.71325, 981.4588]
Temperature only property: 21.72578
Pressure only property: 981.4178
Mean Sea Level Pressure: 1028.634
Resetting the sensor...
Chip ID: 0x55
Mode is 3
Mean Sea Level Pressure: 1028.631