Library 37- BMP180 pressure sensor for STM32F4
BMP180 is a digital pressure sensor, with builtin temperature sensor. Its range is between 300 and 1100 hPa (0.3 to 1.1Bar). In relating to the sea level, this is +9000 to -500 meters.
Sensor works with I2C communication at 100kHz.
If you want sensor from ebay, here is one link.
Sensor is quite bad created, because if you want to read pressure, you first need to read current temperature for pressure calculation. To read temperature you have to wait at least 4.5ms. After that, you first have to read temperature and then you can start with pressure measurement. Time for pressure measurement depends on mode you select. After pressure is measured, you can read uncompensated data from device. This is because device has one register for control temperature and pressure, and also one register for data. So both, temperature and pressure can not be measured at same time.
This takes about at least 10ms for every stuff to be done. At the end a lot of calculations are needed to get valid pressure from device.
Because veeery long time for STM32F4, I split things into several functions, to start temp, read temp, start pressure, read pressure, etc.
I have also added possibility, that you calculate pressure right above the sea from known pressure at known altitude.
Sequency for reading useful data is:
- Start temperature measurement
- Wait 4.5ms at least
- Read temperature
- Start pressure measurement
- Delay depends on measurement mode you select
- Read pressure
- Use pressure data
Library
Features
- Read BMP180 temperature sensor
- Read BMP180 pressure sensor
- Calculate sea level pressure at from given know pressure and altitude
- If you are at ex 1000meters and there si pressure 98000Pascals, then you can calculate pressure at sea level from this values
Dependencies
- CMSIS
- STM32F4xx
- STM32F4xx RCC
- STM32F4xx GPIO
- STM32F4xx I2C
- TM
- TM I2C
- defines.h
- TM I2C
BMP180 | STM32F4 | Description |
---|---|---|
SCL | PA8 | I2C3 Serial clock |
SDA | PC9 | I2C3 Serial data |
You can change I2C settings. Open defines.h file, copy lines below and edit them.
1 2 3 |
/* Select custom I2C */ #define BMP180_I2C I2C3 #define BMP180_I2C_PINSPACK TM_I2C_PinsPack_1 |
Like I said on beginning, different modes for reading pressure can be used. Modes differ in number of samples, conversion time and noise. You select your mode each time you start pressure measurement. For temperature, there is no possible to select mode.
Mode | Internal number of samples | Conversion time [us] | RMS noise [Pascals] | RMS noise [meters] |
---|---|---|---|---|
Ultra Low Power | 1 | 4500 | 6 | 0.5 |
Standard | 2 | 7500 | 5 | 0.4 |
High Resolution | 4 | 13500 | 4 | 0.3 |
Ultra High Resolution | 8 | 25500 | 3 | 0.25 |
Functions and enumerations
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 |
/** * BMP180 result typedef enumerations * Used for result from functions * * Parameters: * - TM_BMP180_Result_Ok: * Everything is OK * - TM_BMP180_Result_DeviceNotConnected: * Device is not connected to I2C * - TM_BMP180_Result_LibraryNotInitialized * Library is not initialized */ typedef enum { TM_BMP180_Result_Ok = 0x00, TM_BMP180_Result_DeviceNotConnected, TM_BMP180_Result_LibraryNotInitialized } TM_BMP180_Result_t; /** * Select pressure oversampling. * This settings differs in samples for one result * and sample time for one result * * Parameters: * - TM_BMP180_Oversampling_UltraLowPower: * 1 sample for result * - TM_BMP180_Oversampling_Standard: * 2 samples for result * - TM_BMP180_Oversampling_HighResolution: * 4 samples for result * - TM_BMP180_Oversampling_UltraHighResolution: * 8 samples for result */ typedef enum { TM_BMP180_Oversampling_UltraLowPower = 0, TM_BMP180_Oversampling_Standard = 1, TM_BMP180_Oversampling_HighResolution = 2, TM_BMP180_Oversampling_UltraHighResolution = 3 } TM_BMP180_Oversampling_t; /** * BMP180 working struct * * Parameters: * - float Altitude: * Calculated altitude at given read pressure * - uint32_t Pressure: * Pressure in pascals * - float Temperature: * Temperature in degrees * - uint16_t Delay: * Number of microseconds, that sensor needs to calculate data that you request to * - TM_BMP180_Oversampling_t Oversampling: * Oversampling for pressure calculation */ typedef struct { float Altitude; uint32_t Pressure; float Temperature; uint16_t Delay; TM_BMP180_Oversampling_t Oversampling; } TM_BMP180_t; /** * Initialize BMP180 pressure sensor * * Parameters: * - TM_BMP180_t* BMP180_Data: * Pointer to TM_BMP180_t structure * * Member of TM_BMP180_Result_t is returned */ extern TM_BMP180_Result_t TM_BMP180_Init(TM_BMP180_t* BMP180_Data); /** * Start temperature sensor on BMP180 * * Parameters: * - TM_BMP180_t* BMP180_Data: * Pointer to TM_BMP180_t structure * * Member of TM_BMP180_Result_t is returned */ extern TM_BMP180_Result_t TM_BMP180_StartTemperature(TM_BMP180_t* BMP180_Data); /** * Read temperature from BMP180 sensor * Temperature has 0.1°C degrees resolution * * Parameters: * - TM_BMP180_t* BMP180_Data: * Pointer to TM_BMP180_t structure * * Member of TM_BMP180_Result_t is returned */ extern TM_BMP180_Result_t TM_BMP180_ReadTemperature(TM_BMP180_t* BMP180_Data); /** * Start pressure measurement on BMP180 sensor * * Parameters: * - TM_BMP180_t* BMP180_Data: * Pointer to TM_BMP180_t structure * - TM_BMP180_Oversampling_t Oversampling: * Oversampling settings. Different settings have different measurement time * * Member of TM_BMP180_Result_t is returned */ extern TM_BMP180_Result_t TM_BMP180_StartPressure(TM_BMP180_t* BMP180_Data, TM_BMP180_Oversampling_t Oversampling); /** * Read pressure from BMP180 sensor and calculate it * * Parameters: * - TM_BMP180_t* BMP180_Data: * Pointer to TM_BMP180_t structure * * Member of TM_BMP180_Result_t is returned */ extern TM_BMP180_Result_t TM_BMP180_ReadPressure(TM_BMP180_t* BMP180_Data); /** * Calculate pressure above sea level in pascals * * This is good, if you read pressure from sensor at known altitude, not altitude provided from sensor. * Altitude from sensor is calculated in fact, that pressure above the sea is 101325 Pascals. * So, if you know your pressure, and you use calculated altitude, you will not get real pressure above the sea. * * You need calculated pressure from sensor, and known altitude (from other sensor or GPS data, or whatever) * and then you are able to calculate pressure above the sea level. * * Parameters: * - uint32_t pressure * Pressure at known altitude in pascals * - float altitude * Known altitude in meters. Do not use altitude from sensor, because then your result is inefficient * * Pressure above the sea is returned in pascals unit */ extern uint32_t TM_BMP180_GetPressureAtSeaLevel(uint32_t pressure, float altitude); |
Example
Example below takes measurements from device and sends data to USART1, TX pin on PB6 at 115200 bauds. You should get result something like on image below.
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 |
/** * Keil project for BMP180 pressure sensor * * Before you start, select your target, on the right of the "Load" button * * @author Tilen Majerle * @email tilen@majerle.eu * @website http://stm32f4-discovery.net * @ide Keil uVision 5 */ /* Include core modules */ #include "stm32f4xx.h" /* Include my libraries here */ #include "defines.h" #include "tm_stm32f4_delay.h" #include "tm_stm32f4_bmp180.h" #include "tm_stm32f4_usart.h" #include <stdio.h> int main(void) { char buffer[50]; /* Working structure */ TM_BMP180_t BMP180_Data; /* Initialize system */ SystemInit(); /* Initialize delay */ TM_DELAY_Init(); /* Initialize USART1, 11500baud, TX: PB6 */ TM_USART_Init(USART1, TM_USART_PinsPack_2, 115200); /* Initialize BMP180 pressure sensor */ if (TM_BMP180_Init(&BMP180_Data) == TM_BMP180_Result_Ok) { /* Init OK */ TM_USART_Puts(USART1, "BMP180 configured and ready to use\n\n"); } else { /* Device error */ TM_USART_Puts(USART1, "BMP180 error\n\n"); while (1); } /* Imagine, we are at 1000 meters above the sea */ /* And we read pressure of 95000 pascals */ /* Pressure right on the sea is */ sprintf(buffer, "Pressure right above the sea: %d pascals\n", TM_BMP180_GetPressureAtSeaLevel(95000, 1000)); TM_USART_Puts(USART1, buffer); sprintf(buffer, "Data were calculated from pressure %d pascals at know altitude %d meters\n\n\n", 95000, 1000); TM_USART_Puts(USART1, buffer); while (1) { /* Start temperature conversion */ TM_BMP180_StartTemperature(&BMP180_Data); /* Wait delay in microseconds */ /* You can do other things here instead of delay */ Delay(BMP180_Data.Delay); /* Read temperature first */ TM_BMP180_ReadTemperature(&BMP180_Data); /* Start pressure conversion at ultra high resolution */ TM_BMP180_StartPressure(&BMP180_Data, TM_BMP180_Oversampling_UltraHighResolution); /* Wait delay in microseconds */ /* You can do other things here instead of delay */ Delay(BMP180_Data.Delay); /* Read pressure value */ TM_BMP180_ReadPressure(&BMP180_Data); /* Format data and print to USART */ sprintf(buffer, "Temp: %2.3f degrees\nPressure: %6d Pascals\nAltitude at current pressure: %3.2f meters\n\n", BMP180_Data.Temperature, BMP180_Data.Pressure, BMP180_Data.Altitude ); /* Send to USART */ TM_USART_Puts(USART1, buffer); /* Some delay */ Delayms(1000); } } |
Project is available at my Github account.
Recent comments