**Interface BMP180 with STM32**

**Description**

The BMP180 is a very **‘simple to use’** **Pressure** sensor, which senses the atmospheric Pressure. This Pressure can be used to calculate the **Altitude **from the sea level. BMP180 also have an integrated Temperature Sensor. It uses the **I2C** for the communication, and delivers the uncompensated values of pressure and temperature. For more information on the sensor, please read it’s datasheet.

The **measurement Flow chart** is given below

**Connection**

Connecting BMP180 is very simple. Just connect the **SCL to SCL** and **SDA to SDA** and you are good to go.

The **I2C address** of BMP180 is **0xEE** as per it’s datasheet. It is shown below

**How to actually do the measurement**

Well the answer for every “How to interface this” is in the device datasheet. If you look at **page number 15** of the BMP180 Datasheet, there is an algorithm given to do all the necessary calculations. Below is the picture.

Here, first of all we need to read the** calibration values **from the EEPROM with starting address from 0xAA.

Every value i.e. AC1, AC2, AC3 etc is 16 bit in size. These values varies for every BMP180 sensor, but there are some defaults given in the datasheet.

Whatever calibration values you have, they should be somewhat around these default values.

They are as shown below

- Once the Calibration is read, we will
**start the reading for UT**(Uncompensated Temperature). To do so, we need to read the Registers**0xF6, and 0xF7.** - Next in line is
**UP (Uncompensated Pressure)**. To read the UP, we need to read**0xF6, 0xF7 and 0xF8 registers**. - And finally we do the calculations as per the datasheet to get the Temperature and the Pressure.

## Some Insight into the CODE

**Read Calibration:-**

void read_calliberation_data (void) { uint8_t Callib_Data[22] = {0}; uint16_t Callib_Start = 0xAA; HAL_I2C_Mem_Read(BMP180_I2C, BMP180_ADDRESS, Callib_Start, 1, Callib_Data,22, HAL_MAX_DELAY); AC1 = ((Callib_Data[0] << 8) | Callib_Data[1]); AC2 = ((Callib_Data[2] << 8) | Callib_Data[3]); AC3 = ((Callib_Data[4] << 8) | Callib_Data[5]); AC4 = ((Callib_Data[6] << 8) | Callib_Data[7]); AC5 = ((Callib_Data[8] << 8) | Callib_Data[9]); AC6 = ((Callib_Data[10] << 8) | Callib_Data[11]); B1 = ((Callib_Data[12] << 8) | Callib_Data[13]); B2 = ((Callib_Data[14] << 8) | Callib_Data[15]); MB = ((Callib_Data[16] << 8) | Callib_Data[17]); MC = ((Callib_Data[18] << 8) | Callib_Data[19]); MD = ((Callib_Data[20] << 8) | Callib_Data[21]); }

- As per the instructions in the datasheet, we will
**read the calibrations**data first. - The start address for the data to be read is 0xAA
- We need to read 22 Bytes totally
- The values for 16 bit AC1, AC2 etc.. are calculated by shifting the 8 bit values that we read
- HAL_I2C_Mem_Read function reads the entered number of registers from the given start address

**Temp Calculation:-**

// Get uncompensated Temp uint16_t Get_UTemp (void) { uint8_t datatowrite = 0x2E; uint8_t Temp_RAW[2] = {0}; HAL_I2C_Mem_Write(BMP180_I2C, BMP180_ADDRESS, 0xF4, 1, &datatowrite, 1, 1000); HAL_Delay (5); // wait 4.5 ms HAL_I2C_Mem_Read(BMP180_I2C, BMP180_ADDRESS, 0xF6, 1, Temp_RAW, 2, 1000); return ((Temp_RAW[0]<<8) + Temp_RAW[1]); } float BMP180_GetTemp (void) { UT = Get_UTemp(); X1 = ((UT-AC6) * (AC5/(pow(2,15)))); X2 = ((MC*(pow(2,11))) / (X1+MD)); B5 = X1+X2; Temp = (B5+8)/(pow(2,4)); return Temp/10.0; }

In order to calculate the Temperature, we need to get the UT (Uncompensated Temperature) first. To do so, the following are the steps

- Write
**0x2E (DATA)**in the**0xF4 (Address)** - Now read the
**2 Bytes**of Data from the address 0xF4. - convert these 2 Bytes into a single 16 bit value, and that will be the
**UT value** - Using this UT value, we will do the calculation for the
**Temperature**as shown in the above code - The formulas used are provided in the datasheet

**Pressure Calculation:-**

// Get uncompensated Pressure uint32_t Get_UPress (int oss) // oversampling setting 0,1,2,3 { uint8_t datatowrite = 0x34+(oss<<6); uint8_t Press_RAW[3] = {0}; HAL_I2C_Mem_Write(BMP180_I2C, BMP180_ADDRESS, 0xF4, 1, &datatowrite, 1, 1000); switch (oss) { case (0): HAL_Delay (5); break; case (1): HAL_Delay (8); break; case (2): HAL_Delay (14); break; case (3): HAL_Delay (26); break; } HAL_I2C_Mem_Read(BMP180_I2C, BMP180_ADDRESS, 0xF6, 1, Press_RAW, 3, 1000); return (((Press_RAW[0]<<16)+(Press_RAW[1]<<8)+Press_RAW[2]) >> (8-oss)); } float BMP180_GetPress (int oss) { UP = Get_UPress(oss); X1 = ((UT-AC6) * (AC5/(pow(2,15)))); X2 = ((MC*(pow(2,11))) / (X1+MD)); B5 = X1+X2; B6 = B5-4000; X1 = (B2 * (B6*B6/(pow(2,12))))/(pow(2,11)); X2 = AC2*B6/(pow(2,11)); X3 = X1+X2; B3 = (((AC1*4+X3)<<oss)+2)/4; X1 = AC3*B6/pow(2,13); X2 = (B1 * (B6*B6/(pow(2,12))))/(pow(2,16)); X3 = ((X1+X2)+2)/pow(2,2); B4 = AC4*(unsigned long)(X3+32768)/(pow(2,15)); B7 = ((unsigned long)UP-B3)*(50000>>oss); if (B7<0x80000000) Press = (B7*2)/B4; else Press = (B7/B4)*2; X1 = (Press/(pow(2,8)))*(Press/(pow(2,8))); X1 = (X1*3038)/(pow(2,16)); X2 = (-7357*Press)/(pow(2,16)); Press = Press + (X1+X2+3791)/(pow(2,4)); return Press; }

In this part we will calculate the Pressure. The steps are mentioned below

- Just like Temperature, here also we need to calculate the value of UP (Uncompensated Pressure) first
- Write
**0x34+(oss<<6)**into the Register**0xF4**. Here oss is**OverSampling Setting**, you can read about it in the datasheet. - Now we need to wait depending on what oss value you choose. I have used the
**oss as 0**in this code - Then read
**3 bytes**of data starting from**0xF6** - Rearranging these Bytes gives the
**UP value** - Using the UP from the first function, we will calculate the
**Pressure** - The calculation shown above is as provided in the BMP180 datasheet.

**Altitude Calculation:-**

#define atmPress 101325 //Pa float BMP180_GetAlt (int oss) { BMP180_GetPress (oss); return 44330*(1-(pow(((float)Press/(float)atmPress), 0.19029495718))); }

Here we need to define the **Standard Atmospheric Pressure** first, as it will be needed in the calculation

The **Altitude **can be calculated from the Pressure using the formula as shown below

## Result

Let’s take a look the **Calibration variables** first

As you can see in the picture above, that the calibration results are almost the same as the default ones. I have too much variation in AC1 and AC2 but that’s okay.

you can see above the rest of the variables values and based on these values, the Pressure, Temperature and Altitude is calculated.

**Check out the**

**VIDEO**

**Below**

### Recent Posts

- STM32 Ethernet #1. Connection July 17, 2021
- How to Setup DMA using Registers June 26, 2021
- How to Setup UART using Registers in STM32 June 24, 2021
- UART DMA with IDLE Line Detection June 19, 2021
- Incremental ENCODER and STM32 June 5, 2021
- DMA with ADC using Registers in STM32 May 30, 2021