MicroPython Driver for BMP580, BMP581 & BMP585 Sensors
Contents
Introduction
This a MicroPython driver written specifically for the BBC micro:bit that will work with the BMP580, BMP581 and BMP585 ambient temperature and barometric pressure sensors.
The BMP580, BMP581 and BMP585 sensors are discussed in some detail here.
The BMP580 is the next generation replacements for the BMP3xx sensors. The BMP581/BMP585 (capacitive pressure technology) is the replacement for the BMP580 sensor (piezo-resistive technology).
FIG 1 - Three different styles of breakout boards: [Left] BMP580, Centre BMP581 and [Right] BMP585
The sensors are quite small and for projects using a breadboard its much easier to use a breakout board. The breakout boards are reasonably inexpensive.
Connecting the BMP580/BMP581/BMP585
These sensors communicate via I2C, I3C and SPI. This driver will only use I2C. Hooking them up to the micro:bit for I2C is easy:
| micro:bit | Sensor board |
|---|---|
| 3.3V | VCC |
| GND | GND |
| Pin 20 | SDA |
| Pin 19 | SCL |
This utilises the standard I2C pins of the micro:bit.
Optionally, a jumper wire can be placed between the GND pin and the SDO pin (if available) on the breakout board. This changes the default I2C address and is discussed below.
Driver Overview
This driver implements a fair amount of the BMP58x functionality as described in the product Datasheets.
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_bmp58x.py - OR -
- Download as a zip file using the link. Unzip the file and save it as fc_bmp58x.py into the default directory where the MicroPython editor e.g. Mu Editor saves python code files.
After saving the fc_bmp58x.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 addressAll three breakout boards have a default I2C address of 0x47. This can be changed to 0x46 if a jumper wire is connected between the GND pin and SDO pin (if this pin is available on the board).
Class constructorThe driver is implemented as a class.The first thing to do is call the constructor of the BMP58X class to obtain a sensor object.
Syntax:
BMP58X(ADDR=0x47)
Where:
ADDR : The I2C address.
Example
from fc_bmp58x import *
# Declare a BMP580 sensor object
# The I2C address is 0x46.
bmp580 = BMP58X(0x46)
# Declare a BMP585 sensor object
# The I2C address is 0x47 (default).
bmp585 = BMP58X()
This assumes that the file fc_bmp58x.py has been successfully copied to the micro:bit's filesystem as described above.
Methods and PropertiesThe driver provides methods and properties to:
- Set and get the sampling mode and associated parameters (Mode, ODR and IIR filtering).
- Read temperature and pressure.
- Operate the FIFO queue.
- Perform altitude calculations.
- Return Chip ID and Revision Number.
These sensor chips are quite complicated. This driver implements much of the functionality as described in the product Datasheet. The INT pin is not used. Reading and writing to the NVM (non-volatile memory) is not supported.
Sampling Modes
These sensors have such a plethora of possible settings that the user can become totally confused. Temperature and pressure have a multitude of oversampling possibilities. Additionally, there is a very useful IIR filter that counteracts pressure errors when in an environment with extraneous air movement.
The datasheets provide some suggestions with different oversampling and power mode combinations. This driver has taken up four of these suggested modes which allow the user to select a suitable compromise between lower power and higher resolution.
By restricting the user to these four sampling modes this driver gets around the problem that the user may configure combinations that make no sense and would otherwise return invalid temperature and pressure readings.
Mode
SetMode(Mode=1)
This method is used to set the sampling mode.
Mode can have a value of 0 to 3.
Mode 0 : Lowest power, lowest resolution
Mode 1 : Standard resolution (default)
Mode 2 : High resolution
Mode 3 : Highest resolution
GetMode
Property that returns the current
mode : 0 to 3.
ODR
SetODR(ODR=0x1C)
This method sets the Output Data Rate.
Valid ODR values can be found in the
datasheet on Page 60.
The ODR value is only applied in Modes 1 to 3.
Mode 0 has minimal oversampling applied.
In this mode the sampling is done on demand
and is very fast.
If the user attempts to apply an ODR that is
too fast for the selected resolution mode,
this driver will adjust the ODR to fastest
value possible.
GetODR
Property that returns the current
ODR value : 0x04 to 0x1F.
IIR Filtering
SetIIR(IIR=0)
Method that sets the level of IIR filtering.
Values from 0 (off) to 7 (highest filtering).
GetIIR
Property that returns the current
IIR filtering value : 0 to 7.
Example
from fc_bmp58x import *
sensor = BMP58X()
print('Default Mode, ODR and IIR filtering:')
print('Sampling mode:', sensor.GetMode)
print('ODR setting:', sensor.GetODR)
print('IIR Filter setting:', sensor.GetIIR)
print('\nChange to Mode = 3')
sensor.SetMode(3)
print('Set ODR to 0x1F (1 sample per 8 seconds)')
sensor.SetODR(0x1F)
print('Apply highest level of IIR filtering (7)')
sensor.SetIIR(7)
print('Sampling mode:', sensor.GetMode)
print('ODR setting:', sensor.GetODR)
print('IIR Filter setting:', sensor.GetIIR)
Output
Default Mode, ODR and IIR filtering:
Sampling mode: 1
ODR setting: 0x1c
IIR Filter setting: 0
Change to Mode = 3
Set ODR to 0x1F (1 sample per 8 seconds)
Apply highest level of IIR filtering (7)
Sampling mode: 3
ODR setting: 0x1f
IIR Filter setting: 7
Reading Temperature & Pressure
There are three properties that return temperature and/or pressure readings Reading, T and P.
The function CtoF is available to convert Celsius to Fahrenheit.
Syntax:
Reading
Returns temperature and pressure as a tuple.
The first element of the tuple is temperature.
The second element is pressure.
Temperature is in degrees Celsius.
Pressure is in hPa (hectopascals)
T
Returns only the temperature in Celsius.
P
Returns only the pressure in hPa.
CtoF(C, d = 1)
Function converts Celsius to Fahrenheit
C : Celsius value to convert to Fahrenheit
d : Number of decimals for rounding to.
Example:
# Read temperature and pressure.
from fc_bmp58x import *
from microbit import sleep
# Get instance of sensor
# with default settings.
sensor = BMP58X()
sleep(500)
print('Mode:', sensor.GetMode)
print('ODR:', sensor.GetODR)
print('IIR filter:', sensor.GetIIR)
print('Taking a reading...')
print('(temperature, Pressure):', sensor.Reading)
# Test the T and P properties.
sleep(500)
print('\nUsing T and P properties...')
t = sensor.T
f = CtoF(t, 5)
print('Temperature:', t, 'C')
print(t, 'C is', f, 'F')
print('Pressure:', sensor.P, 'hPa')
# Change to Mode 0.
# Take some very fast readings
print('\nChanging to Mode 0...')
sensor.SetMode(0)
print('Mode:', sensor.GetMode)
print('Taking 5 very quick readings...')
for __ in range(5):
print(sensor.Reading)
Typical Output:
Mode: 1
ODR: 0x1c
IIR filter: 0
Taking a reading...
(temperature, Pressure): (16.40552, 954.1312)
Using T and P properties...
Temperature: 16.39841 C
16.39841 C is 61.51713 F
Pressure: 954.1248 hPa
Changing to Mode 0...
Mode: 0
Taking 5 very quick readings...
(16.40592, 954.1116)
(16.41197, 954.1262)
(16.41206, 954.1099)
(16.42436, 954.1255)
(16.42339, 954.1245)
Output Data Rate (ODR) Configuration
In this driver's Mode 1, Mode 2 and Mode 3 the rate that new temperature and pressure readings become available is dependent on the configured ODR setting.
As explained above, the ODR is set using the SetODR() method. The table on pages 60-61 of the datasheets explain the settings and the resultant sampling rate.
Stale data will be returned if the user program requests temperature and pressure readings faster than the ODR setting allows. The following example illustrates this point.
Example:
# Demonstrate output of stale data
# if the BMP585 sensor is read for
# temperature and pressure faster
# than the ODR setting.
from fc_bmp58x import *
from microbit import sleep
sensor = BMP58X()
# Set ODR = 0x1D
# This will produce a new temperature
# and pressure sample every two
# seconds
sensor.SetODR(0x1D)
# Take seven temperature and pressure
# readings at a rate of one
# sample per second.
for __ in range(7):
sleep(1000)
print(sensor.Reading)
Typical Output:
(17.11963, 961.2056)
(17.10197, 961.1979)
(17.10197, 961.1979)
(17.10666, 961.2036)
(17.10666, 961.2036)
(17.1048, 961.2075)
(17.1048, 961.2075)
In the above example temperature and pressure readings are being made at twice the rate that the sensor is sampling. The result is that every second temperature & pressure reading will the same as the previous reading i.e stale.
The FIFO Queue
The BMP384/BMP388/BMP390 series were the first of these sensors to have a FIFO queue. It worked well but was rather complicated in practice.
The FIFO queue of the BMP58x series has been simplified. It can store a maximum of 32 temperature or pressure records. Alternatively it can store 16 temperature and pressure records. This driver uses the latter option i.e. stores both temperature and pressure records.
Commands written to registers configure options and kick off the storage process. It's important to note that while the sensor is storing data to the FIFO it is still possible for the user to read temperature and/or pressure with the Reading, T and P properties. This is demonstrated in an example below. Read the datasheet for full details.
FIFO storage can be initiated and stopped. Stopping the FIFO collecting process also flushes all buffer data.
There are properties that return the number of records in the queue and if the queue is full. Another property reads the entire FIFO in a burst read and converts all raw records found to actual temperatures and pressures.
Syntax:
FIFOStart()
This method starts the storage of records
to the FIFO.
FIFOStop()
This method stops the storage of records
to the FIFO and flushes all data.
IsFIFOFull
This property returns True if the queue is
full. When full no more records are stored
till the queue is either read or flushed.
FIFOLength
This property returns the number of records
in the FIFO queue.
FIFORead
A burst read of the FIFO is done to retrieve
all raw temperature and pressure
records. This property performs the conversion
of the raw values to actual
temperatures and pressures.
A list of tuples is returned. The first
element of each tuple is temperature.
The second tuple element is pressure.
Records read from the FIFO are also deleted
from the queue.
Example:
# Program to test the FIFO queue
# on the BMP58x sensor.
from fc_bmp58x import *
from microbit import sleep
bmp585 = BMP58X()
bmp585.SetMode(0)
print('Reading from sensor:', bmp585.Reading)
sleep(2000)
# Start FIFO record storage
print('\nStarting FIFO...')
bmp585.FIFOStart()
ReadData = []
# Data Collection Section
# Wait for FIFO to fill up
while not bmp585.IsFIFOFull:
# Manual reading for comparison purposes.
ReadData.append(bmp585.Reading)
sleep(1000)
print('FIFO is now full')
print('FIFO records:', bmp585.FIFOLength)
# Convert raw records
FIFOData = bmp585.FIFORead
# Report Section
print('\nComparing first five records...')
# Compare FIFO values with manual values.
print('Manual Readings FIFO Readings')
for i in range(5):
print(ReadData[i], ' ', FIFOData[i])
Typical Output:
Reading from sensor: (17.55772, 964.5356)
Starting FIFO...
FIFO is now full
FIFO records: 16
Comparing first five records...
Manual Readings FIFO Readings
(17.55644, 964.5432) (17.56026, 964.5408)
(17.56133, 964.5366) (17.56133, 964.5366)
(17.57634, 964.5437) (17.57634, 964.5437)
(17.55675, 964.5422) (17.55675, 964.5422)
(17.56513, 964.5366) (17.56513, 964.5366)
The above example demonstrates the use of all FIFO methods and properties.
The FIFO process is turned on. At the same time manual readings are taken using the Reading property. A loop monitors the queue till it is full. The queue is then read and the raw temperature and pressure values are converted to Celsius and hPa values.
The first five records from the FIFO are compared to the manually obtained readings. As shown in the Typical Output the manual and queue values (except for the very first record) match.
Altitude Calculation
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 BMP580/581/585'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_bmp58x import *
sensor = BMP58X()
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 999.3567 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_bmp58x import *
sensor = BMP58X()
mslp = 999 # hPa
altitude = sensor.Altitude(mslp)
print('Mean Sea Level Pressure is', mslp, 'hPa')
print('Altitude is ', altitude, 'metres')
Output:
Mean Sea Level Pressure is 999 hPa
Altitude is 403 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_bmp58x import *
sensor = BMP58X()
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
Chip ID
Since the second generation BMP180 sensor all Bosch BMPxxx barometric pressure sensors have had an 8-bit model-specific ID number written to NVM (non-volatile memory) during manufacture. The specific chip ID's for BMP580, BMP581 and BMP585 are:
- BMP580 : (0x50)
- BMP581 : (0x50)
- BMP585 : (0x51)
These sensors also have an 8-bit REV_ID number, all with a value of 0x32.
Syntax:
ID
This property returns the sensor's ID number.
RevID
This property returns the REV_ID number of
the BMP580/581/585 sensor.
Example:
# The following I2C addresses are assumed:
# BMP580 : 0x46
# BMP585 : 0x47
from fc_bmp58x import *
bmp585 = BMP58X()
bmp580 = BMP58X(0x46)
print('BMP580 ID:', bmp580.ID)
print('BMP580 REV_ID:', bmp580.RevID)
print('\nBMP585 ID:', bmp585.ID)
print('BMP585 REV_ID:', bmp585.RevID)
Output:
BMP580 ID: 0x50
BMP580 REV_ID: 0x32
BMP585 ID: 0x51
BMP585 REV_ID: 0x32
The above example was run using the setup from the Comparing BMP580 with BMP585 example.
Enjoy!
BMP580, BMP581 & BMP585 Driver Code for micro:bit
Download as zip file
'''
BMP580, BMP581 and BMP585 Temperature and
Barometric Pressure sensors
MicroPython driver for micro:bit
EXAMPLE USAGE:
from fc_bmp58x import *
sensor = BMP58X()
Temperature = sensor.T
Pressure = sensor.P
4 x Sampling Modes as defined in datasheets:
0 : Lowest power
1 : Standard resolution (default)
2 : High resolution
3 : Highest resolution
Temperature returned in Celsius.
Pressure returned in hPa.
AUTHOR: fredscave.com
DATE : 2025/07
VERSION : 1.00
'''
from microbit import *
from micropython import const
_REG_CHIP_ID = const(0x01)
_REG_REV_ID = const(0x02)
_REG_MEASURE = const(0x1D)
_REG_DSP_IIR = const(0x31)
_REG_OSR_CONFIG = const(0x36)
_REG_ODR_CONFIG = const(0x37)
_REG_OSR_REF = const(0x38)
_REG_CMD = const(0x7E)
_REG_INT_SOURCE = const(0x15)
_REG_FIFO_CONFIG = const(0x16)
_REG_FIFO_LENGTH = const(0x17)
_REG_FIFO_SELECT = const(0x18)
_REG_FIFO_DATA = const(0x29)
_REG_INT_STATUS = const(0x27)
# Store temperature & pressure
_FIFO_SELECT = const(0x03)
_FIFO_STOP = const(0x00)
# Stop when FIFO is full.
_FIFO_MODE = const(0x20)
# FIFO full interrupt
_FIFO_FULL_INT = const(0x02)
_FIFO_EMPTY_FRAME = const(0x7F)
STANDBY = const(0)
NORMAL = const(1)
FORCED = const(2)
CONTINUOUS = const(3)
_CMD_PWR_MODE = (0, 1, 2, 3)
# OVERSAMPLE RATE configurations
# for Modes 0, 1, 2 and 3.
# As per datasheet page 20.
_MODE_OSR = (0x40, 0x50, 0x60, 0x7B)
# *** OUTPUT DATA RATE ***
# Mode = 0
# Sensor can be sampled every 4ms.
# Mode = 1, 2 or 3
# Default set to once per sec.
# This can be changed by setting
# another ODR value from table in
# datasheet on page 60.
_DEFAULT_ODR = const(0x1C)
_MIN_ODR = (0, 0x04, 0x0D, 0x17)
# Forced power mode sampling time.
_ADCT_FORCED = 2
# IIR Filter Coefficient applied to pressure.
# There are eight levels (0 to 7) from bypass (off)
# through to maximum filtering level.
# Default is no filtering.
_IIR_COEFF = (0x00, 0x08, 0x10, 0x18,
0x20, 0x28, 0x30, 0x38)
# Convert Celsius to Fahrenheit
CtoF = lambda C, d=1: round((C * 9/5) +32, d)
class BMP58X():
def __init__(self, ADDR=0x47):
self.ADDR = ADDR
self.ODR = _DEFAULT_ODR
self.IIR = 0
# Enable FIFO full interrupt.
self._writeReg([_REG_INT_SOURCE, _FIFO_FULL_INT])
self.SetMode()
# Mode 0 : Forced power mode
# Mode 1 to 3 : Normal power mode
# Higher modes use more power
# but return higher resolution.
def SetMode(self, Mode=1):
if Mode in (0, 1, 2, 3):
self.Mode = Mode
else:
self.Mode = 1
self._writeReg([_REG_OSR_CONFIG, _MODE_OSR[Mode]])
if Mode != 0:
# Turn on Normal power mode
self.SetODR(self.ODR)
self._setPowerMode(NORMAL)
# Sets the Output Data Rate (ODR).
# This setting is only used in NORMAL
# power mode. (Mode = 1, 2 or 3)
# If the user attempts to set an ODR that
# is too fast then this method adjusts
# rate to highest possible that works.
# Valid values are 0x04 .. 0x1F.
def SetODR(self, ODR=_DEFAULT_ODR):
if ODR < _MIN_ODR[self.Mode]:
odr = _MIN_ODR[self.Mode]
else:
odr = ODR
buf = self._readReg(_REG_ODR_CONFIG, 1)
reg = buf[0]
reg = reg & 0b10000011
reg = reg | (odr << 2)
self._writeReg([_REG_ODR_CONFIG, reg])
self.ODR = odr
# Sets the IIR filtering level.
# Valid value is 0..7
# 0 = filter off, 7 = max filtering.
def SetIIR(self, IIR=0):
if IIR in range(8):
self.IIR = IIR
else:
self.IIR = 0
# Stop conversions
self._setPowerMode(STANDBY)
# Write filter setting
self._writeReg([_REG_DSP_IIR, _IIR_COEFF[self.IIR]])
# Turn on sampling
self.SetMode(self.Mode)
# *******************************************
# Properties
# *******************************************
# Trigger and return both temperature
# and pressure measurements.
@property
def Reading(self):
# Read unconverted temperature and pressure.
if self.Mode == 0:
self._setPowerMode(FORCED)
sleep(_ADCT_FORCED)
buf = self._readReg(_REG_MEASURE, 6)
temperature = (buf[2] << 16) + (buf[1] << 8) + buf[0]
pressure = (buf[5] << 16) + (buf[4] << 8) + buf[3]
# Convert to actual values
return self._convert(temperature, pressure)
# Returns temperature only
@property
def T(self):
return self.Reading[0]
# Returns pressure only
@property
def P(self):
return self.Reading[1]
# Returns the chip's ID
@property
def ID(self):
id = self._readReg(_REG_CHIP_ID, 1)
return hex(id[0])
# Chip revision number
@property
def RevID(self):
id = self._readReg(_REG_REV_ID, 1)
return hex(id[0])
# Returns Mode where:
# 0 : Forced power mode.
# 1..3 : Normal power mode.
@property
def GetMode(self):
return self.Mode
# Returns odr_set parameter.
# This value determines the sampling period
# when the sensor is in Mode 1 i.e Normal
@property
def GetODR(self):
return hex(self.ODR)
# Returns the IIR filter setting.
# Value is in 0..7
@property
def GetIIR(self):
return self.IIR
# *******************************************
# FIFO Methods and Properties
# *******************************************
# Starts writing temperature and pressure
# unconverted values to the FIFO queue.
def FIFOStart(self):
# Ensure Normal sampling mode is on.
if self.Mode == 0:
self.SetMode(1)
# Must be in STANDBY power mode to config.
self._setPowerMode(STANDBY)
self._writeReg([_REG_FIFO_CONFIG, _FIFO_MODE])
self._writeReg([_REG_FIFO_SELECT, _FIFO_SELECT])
# Turn on sampling & FIFO
self.SetMode(self.Mode)
# Stops writing to the FIFO queue.
# The FIFO is flushed.
def FIFOStop(self):
# Must be in STANDBY power mode.
self._setPowerMode(STANDBY)
self._writeReg([_REG_FIFO_SELECT, _FIFO_STOP])
sleep(3)
# Turn on sampling
self.SetMode(self.Mode)
# Returns the number of records in the FIFO queue.
@property
def FIFOLength(self):
buf = self._readReg(_REG_FIFO_LENGTH, 1)
return buf[0]
# Reads all bytes in the FIFO queue.
# Sensor data frames are parsed to retrieve
# all stored raw temperature and
# pressure values. They are converted and
# returned as a list of tuples of actual values.
@property
def FIFORead(self):
length = self.FIFOLength
buf = self._readReg(_REG_FIFO_DATA, length*6)
i = 0
data = []
while i < length:
count = i * 6
if buf[count] == _FIFO_EMPTY_FRAME:
break
else:
temperature = (buf[count+2] << 16) + (buf[count+1] << 8) + buf[count]
pressure = (buf[count+5] << 16) + (buf[count+4] << 8) + buf[count+3]
i += 1
data.append(self._convert(temperature, pressure))
return data
# Returns True if the FIFO queue is full.
@property
def IsFIFOFull(self):
buf = self._readReg(_REG_INT_STATUS, 1)
return (buf[0] & 0b10) == 0b10
# *******************************************
# 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
# *******************************************
# Sets the power mode. One of:
# STANDBY, NORMAL, FORCED, CONTINUOUS.
def _setPowerMode(self, PwrMode):
buf = self._readReg(_REG_ODR_CONFIG, 1)
reg = buf[0]
reg = (reg >> 2) << 2
reg = reg | _CMD_PWR_MODE[PwrMode]
self._writeReg([_REG_ODR_CONFIG, reg])
# Convert raw temperature and pressure
# to Celsius and hectopascals.
def _convert(self, temperature, pressure):
if temperature > 8388607:
temp = temperature - 16777216
else:
temp = temperature
return (temp / 65536, pressure / 6400)
# Writes one or more bytes to register.
# Bytes is expected to be a list.
# First element is the register address.
def _writeReg(self, Bytes):
i2c.write(self.ADDR, bytes(Bytes))
# Read a given number of bytes from
# a register.
def _readReg(self, Reg, Num):
self._writeReg([Reg])
buf = i2c.read(self.ADDR, Num)
return buf
Comparing BMP580 with BMP585
It's easy to use a BMP580 and BMP585 simultaneously on the same I2C bus on the micro:bit.
Hookup guideMake the following connections:
- micro:bit 3.3V to VCC pins on both boards.
- micro:bit GND to GND pins on both boards.
- micro:bit Pin 19 to SCL pins on both boards.
- micro:bit pin 20 to SDA pins on both board.
- On the BMP580 board, connect the GND pin to the SDO pin. This is the white wire in the image below. This ensures the alternative I2C address of 0x46.
The fc_bmp58x.py driver file must also be on the micro:bit's file system.
# Compare temperature & pressure readings
# from BMP580 and BMP585 sensors.
# A BMP580 sensor and a BMP585 sensor
# will be used on the same I2C bus.
# BMP580:
# Address = 0x46
# SDO is tied to GND.
# BMP585:
# Address = 0x47
from fc_bmp58x import *
# Create BMP580 and BMP585 sensor objects.
bmp580 = BMP58X(0x46)
bmp585 = BMP58X()
# Read temperature and pressure
# from both sensors.
# Both sensors are at an altitude of 400m.
T1, P1 = bmp580.T, bmp580.P
MSLP1 = bmp580.MSLP(400)
T2, P2 = bmp585.T, bmp585.P
MSLP2 = bmp585.MSLP(400)
# Report
print(' T P MSLP')
print('BMP580 ', T1, ' ', P1, ' ', MSLP1)
print('BMP585 ', T2, ' ', P2, ' ', MSLP2)
Typical Output:
T P MSLP
BMP580 19.36885 964.0552 1011.194
BMP585 19.52124 963.3584 1010.497
This program was run with micro:bit and sensors at an altitude of 400 metres. If you know your altitude above seal level then you can change the line in the above code where the MSLP is calculated.
The local weather service's published barometric pressure observation was 1010 hPa. The BMP580 sensor and BMP585 sensor gave fairly close results for temperature and pressure.