Tags:
create new tag
view all tags

Exercise 12:

The BMP180 temperature and barometric pressure sensor

Goal:

The BMP180 is an I2C chip allowing to measure temperature to a precision of 0.1 °C and atmospheric (or barometric) pressure to 1 Pa. During this exercise we learn to understand the data sheet of a rather complex device which does not only incorporate 2 sensors but also includes individual calibration data on EEPROM on the chip. The temperature and air pressure values are read in raw binary form from the sensor and must be converted into physical units using the on-chip calibration data through an algorithm described in the data sheet.

Bosch, the supplier of the BMP180 chip provides access routines that must be adapted by the user to his own I2C access procedure. Here we learn to understand code written by professionals and adapt their code to our requirements. The access routines implement a bmp180_t structure describing the device and routines to convert raw temperature and pressure values to physical units.

Exercise 1: Preliminary checks

Read the data sheet and understand which registers are readable and which ones are writable. Understand the use of each of the registers.

Connect the device to the Raspberry Pi and use i2cdetect to find the BMP180 I2C address.

In oder to find out if you can correctly talk to the device read the device ID (fixed to 0x55). If you can read this then you know that your device access routines work fine.

Exercise2: Read the calibration data

The access library provided by Bosch, which we will use later in these exercises describes the BMP180 through the following structure of type bmp180_t:

struct bmp180_t {
struct bmp180_calib_param_t calib_param;/**<calibration data*/
u8 mode;/**<power mode*/
u8 chip_id; /**<chip id*/
u8 ml_version;/**<ml version*/
u8 al_version;/**<al version*/
u8 dev_addr;/**<device address*/
u8 sensortype;/**< sensor type*/

s32 param_b5;/**<pram*/
s32 number_of_samples;/**<sample calculation*/
s16 oversamp_setting;/**<oversampling setting*/
s16 sw_oversamp;/**<software oversampling*/

BMP180_WR_FUNC_PTR;/**< bus write function pointer*/
BMP180_RD_FUNC_PTR;/**< bus read function pointer*/
void (*delay_msec)(BMP180_MDELAY_DATA_TYPE);/**< delay function pointer*/
};

where bmp180_calib_param_t has this layout:

struct bmp180_calib_param_t {
s16 ac1;/**<calibration ac1 data*/
s16 ac2;/**<calibration ac2 data*/
s16 ac3;/**<calibration ac3 data*/
u16 ac4;/**<calibration ac4 data*/
u16 ac5;/**<calibration ac5 data*/
u16 ac6;/**<calibration ac6 data*/
s16 b1;/**<calibration b1 data*/
s16 b2;/**<calibration b2 data*/
s16 mb;/**<calibration mb data*/
s16 mc;/**<calibration mc data*/
s16 md;/**<calibration md data*/
};

Therefore we should create a structure of the same type as bmp180_calib_param_t and fill it with the information read from the BMP180 EEProm.

Exercise 3: Read the raw temperature and pressure values

Program the BMP180 such that it starts a temperature reading and analogue to digital conversion. How long do you have to wait for the conversion to finish? How can you check that the conversion is finished? How do you define the pressure resolution?

Exercise 4: Using the BOSCH driver code

In order to ease things for you I have modified the Bosch code in a way to include the access routines to the I2C bus implemented in the pigpiod daemon interface. This means the pigpiod must run in order to run your application. The code provided by Bosch has been converted into a shared library named libbpm180.so.

The first thing your code should do is to include bmp180.h which contains all definitions and function declarations you will need. Have a look at it!

The bmp180_t structure has been declared within the library and you can access to it by declaring it as external:

external bmp180_t bmp180;

Then you can access its elements e.g. as bmp180.chip_id etc. Write 2 functions:

  • void printBmp180Struct(void)

  • void printBmp180Calibration(void)

Up to you to guess what these functions will do.

Call I2C _routine() to fill bmp180 with initial values and print the result. Then initialize the chip by calling:

bmp180RetCode = bmp180_init(&bmp180)

This will also read all calibration values and fill the calibration table calib_param_t.
Then all you need to do is calling

  • rawTemp = bmp180_get_uncomp_temperature() /* gets the raw temperature value */

  • temperature =bmp180_get_temperature(rawTemp) /* converts it into °C */

  • rawPress = bmp180_get_uncomp_pressure(); /* reads the raw pressure value */

  • pressure = bmp180_get_pressure(rawPress); /* converts raw pressure to Pa */

You may define the resolution by setting bmp180.oversamp_setting to
  • BMP180_OVERSAMP_LOWPOWER

  • BMP180_OVERSAMP_STANDARD

  • BMP180_OVERSAMP_HIGH_RES

  • BMP180_OVERSAMP_SETTING_U8X /* ultra high resolution */

If you set bmp180.oversamp_setting to BMP180_OVERSAMP_SETTING_U8X and
bmp180.sw_oversamp to BMP180_SW_OVERSAMP_U8X then 3 pressure measurements will be made with ultra high resolution and the average of these 3 measurements will be returned.

-- Uli Raich - 2017-01-15

Comments

Topic revision: r1 - 2017-01-15 - uli
 
This site is powered by the TWiki collaboration platform Powered by PerlCopyright © 2008-2024 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback