-
-
Save ggirjau/369d1520a21c7cf41413b00352446d61 to your computer and use it in GitHub Desktop.
| /* | |
| * bmp180.c | |
| * | |
| * Created on: 27 feb. 2019 | |
| * Author: gheorghe.ghirjev | |
| */ | |
| #include <string.h> | |
| #include <math.h> | |
| #include "bmp180.h" | |
| #include "stm32f7xx_hal.h" | |
| // global struct to store all BMP180 main data. | |
| bmp_t bmp; | |
| extern I2C_HandleTypeDef hi2c1; | |
| /*! | |
| * @brief: - Read and check bmp chip ID.This value is fixed to 0x55, | |
| * and can be used to check whether communication is functioning. | |
| * @param[in] - NONE. | |
| * @return - NO_ERR if chip_id is equal to 0x55, otherwise CHIP_ID_INVALID_ERR. | |
| */ | |
| static bmp_err_t read_chip_id (void) | |
| { | |
| uint8_t out_buff = 0; | |
| uint8_t ret_val = NO_ERR; | |
| HAL_I2C_Mem_Read(&hi2c1, BMP_READ_ADDR, BMP_CHIP_ID_REG, 1, &out_buff, 1, BMP_I2C_TIMEOUT); | |
| if (BMP_CHIP_ID_VAL != out_buff) | |
| { | |
| ret_val = CHIP_ID_INVALID_ERR; | |
| } | |
| return ret_val; | |
| } | |
| /*! | |
| * @brief: - Write oversampling settings to the Control register. | |
| * @param[in] - struct of type oss_t | |
| * @param[in] - enum of type oss_ratio_t | |
| * @return - None | |
| */ | |
| static void set_oss (oss_t * oss, oss_ratio_t ratio) | |
| { | |
| uint8_t in_buff[2] = {0}; | |
| switch (ratio) | |
| { | |
| case ULTRA_LOW_PWR_MODE: | |
| { | |
| oss->wait_time = BMP_OSS0_CONV_TIME; | |
| break; | |
| } | |
| case STANDARD_MODE: | |
| { | |
| oss->wait_time = BMP_OSS1_CONV_TIME; | |
| break; | |
| } | |
| case HIGH: | |
| { | |
| oss->wait_time = BMP_OSS2_CONV_TIME; | |
| break; | |
| } | |
| case ULTRA_HIGH_RESOLUTION: | |
| { | |
| oss->wait_time = BMP_OSS3_CONV_TIME; | |
| break; | |
| } | |
| default: | |
| { | |
| oss->wait_time = BMP_OSS1_CONV_TIME; | |
| break; | |
| } | |
| } | |
| oss->ratio = ratio; | |
| BMP_SET_I2CRW_REG (in_buff[1], BMP_CTRL_OSS_MASK(ratio)); | |
| HAL_I2C_Mem_Write( &hi2c1, BMP_WRITE_ADDR, BMP_CTRL_REG, 1, in_buff, 2, BMP_I2C_TIMEOUT ); | |
| } | |
| /*! | |
| * @brief: - Read calibration BMP data. The E2PROM has stored 176 bit of individual calibration data. | |
| * This is used to compensate offset, temperature dependence and other parameters of the sensor. | |
| * @param[in] - struct of type bmp_calib_param_t | |
| * @return - NO_ERR if read calibration data are valid otherwise READ_CALIB_ERR. | |
| */ | |
| static bmp_err_t read_calib_data (short * calib_data) | |
| { | |
| bmp_err_t ret_val = NO_ERR; | |
| uint8_t out_buff[BMP_CALIB_DATA_SIZE] = {0}; | |
| uint8_t i = 0; | |
| uint8_t j = 1; | |
| HAL_I2C_Mem_Read(&hi2c1, BMP_READ_ADDR, BMP_CALIB_ADDR, 1, out_buff, BMP_CALIB_DATA_SIZE, BMP_I2C_TIMEOUT); | |
| // Store read calib data to bmp_calib struct. | |
| for (i = 0; i <= BMP_CALIB_DATA_SIZE / 2; i++, j+2) | |
| { | |
| calib_data[i] = (out_buff[i * 2] << 8) | out_buff[j]; | |
| // checking that none of the words has the value 0 or 0xFFFF. | |
| if ((0 == calib_data[i]) | (-1 == calib_data[i])) | |
| { | |
| ret_val = GET_CALIB_ERR; | |
| } | |
| } | |
| return ret_val; | |
| } | |
| /*! | |
| * @brief: - Performe initial sequence of BMP sensor | |
| * @param[in] - pointer to struct of type bmp_calib_param_t | |
| * @return - None. | |
| */ | |
| void bmp_init (bmp_t * bmp) | |
| { | |
| memset(bmp, 0x00, sizeof(&bmp)); // clear bmp strut; | |
| bmp->err = read_chip_id (); // check chip validity and I2C communication. | |
| bmp->err = read_calib_data ((short *)&bmp->calib); | |
| set_oss (&bmp->oss, HIGH); // set oversampling settings | |
| } | |
| /*! | |
| * @brief: - Get uncompensated temperature value. UT = temperature data (16 bit) | |
| * @param[in] - None. | |
| * @return - uncompensated temp. | |
| */ | |
| int32_t get_ut (void) | |
| { | |
| uint8_t out_buff[2]; | |
| BMP_SET_I2CRW_REG (out_buff[0], BMP_SET_TEMP_CONV); | |
| HAL_I2C_Mem_Write( &hi2c1, BMP_WRITE_ADDR, BMP_CTRL_REG, 1, out_buff, 1, BMP_I2C_TIMEOUT ); | |
| HAL_Delay (BMP_TEMP_CONV_TIME); | |
| HAL_I2C_Mem_Read ( &hi2c1, BMP_READ_ADDR, BMP_DATA_MSB_ADDR, 1, out_buff, 2, BMP_I2C_TIMEOUT ); | |
| return (out_buff[0] << BYTE_SHIFT) | out_buff[1]; | |
| } | |
| /*! | |
| * @brief: - Calc true temperature. | |
| * @param[in] - pointer to struct of type bmp_t | |
| * @return - true temp. | |
| */ | |
| float get_temp(bmp_t * bmp) | |
| { | |
| int32_t X1 = 0; | |
| int32_t X2 = 0; | |
| float temp = 0; | |
| X1 = (((int32_t)bmp->uncomp.temp - bmp->calib.AC6) * bmp->calib.AC5) >> 15; | |
| X2 = (bmp->calib.MC << 11) / (X1 + bmp->calib.MD); | |
| bmp->data.B5 = X1 + X2; | |
| temp = ((bmp->data.B5 + 8) >> 4) * 0.1f; | |
| if ((temp <= BMP_MIN_TEMP_THRESHOLD) || (temp >= BMP_MAX_TEMP_THRESHOLD)) | |
| { | |
| bmp->err = GET_TEMP_ERR; | |
| } | |
| return temp; | |
| } | |
| /*! | |
| * @brief: - Get uncompensated pressure value. UP = pressure data (16 to 19 bit) | |
| * @param[in] - struct of type oss_t | |
| * @return - uncompensated pressure. | |
| */ | |
| int32_t get_up (oss_t oss) | |
| { | |
| uint8_t out_buff[3] = {0}; | |
| long up = 0; | |
| BMP_SET_I2CRW_REG (out_buff[0], BMP_SET_PRESS_CONV); | |
| HAL_I2C_Mem_Write ( &hi2c1, BMP_WRITE_ADDR, BMP_CTRL_REG, 1, out_buff, 1, BMP_I2C_TIMEOUT ); | |
| HAL_Delay (oss.wait_time); | |
| HAL_I2C_Mem_Read(&hi2c1, BMP_READ_ADDR, BMP_DATA_MSB_ADDR, 1, out_buff, 3, BMP_I2C_TIMEOUT); | |
| up = ((out_buff[0] << SHORT_SHIFT) + (out_buff[1] << BYTE_SHIFT) + out_buff[2]) >> (8 - oss.ratio); | |
| return up; | |
| } | |
| /*! | |
| * @brief: - Calc true pressure. | |
| * @param[in] - struct of type bmp_t | |
| * @return - true pressure in Pa. | |
| */ | |
| int32_t get_pressure(bmp_t bmp) | |
| { | |
| int32_t X1, X2, X3, B3, B6, p = 0; | |
| uint32_t B4, B7 = 0; | |
| B6 = bmp.data.B5 - 4000; | |
| X1 = (bmp.calib.B2 * (B6 * B6 / 0x1000)) / 0x800; | |
| X2 = bmp.calib.AC2 * B6 / 0x800; | |
| X3 = X1 + X2; | |
| B3 = (((bmp.calib.AC1 * 4 + X3) << bmp.oss.ratio) +2) / 4; | |
| X1 = bmp.calib.AC3 * B6 / 0x2000; | |
| X2 = (bmp.calib.B1 * (B6 * B6 / 0x1000)) / 0x10000; | |
| X3 = ((X1 + X2) + 2) / 0x4; | |
| B4 = bmp.calib.AC4 * (unsigned long)(X3 + 32768) / 0x8000; | |
| B7 = ((unsigned long)bmp.uncomp.press - B3) * (50000 >> bmp.oss.ratio); | |
| if (B7 < 0x80000000) | |
| { | |
| p = (B7 * 2) / B4; | |
| } | |
| else | |
| { | |
| p = (B7 / B4) * 2; | |
| } | |
| X1 = (p / 0x100 * (p / 0x100)); | |
| X1 = (X1 * 3038) / 0x10000; | |
| X2 = (-7357 * p) / 0x10000; | |
| p = p + (X1 + X2 + 3791) / 0x10; | |
| return p; | |
| } | |
| /*! | |
| * @brief: - Calc true altitude. | |
| * @param[in] - struct of type bmp_t | |
| * @return - true pressure. | |
| */ | |
| float get_altitude (bmp_t * bmp) | |
| { | |
| float altitude = 0; | |
| altitude = BMP_PRESS_CONST_COEFICIENT * (1.0f - pow((bmp->data.press / BMP_PRESS_CONST_SEA_LEVEL), (1/5.255))); | |
| if ((altitude <= BMP_MIN_ALT_THRESHOLD) || (altitude >= BMP_MAX_ALT_THRESHOLD)) | |
| { | |
| bmp->err = GET_ALTITUDE_ERR; | |
| } | |
| return altitude; | |
| } | |
| /* | |
| * bmp180.h | |
| * | |
| * Created on: 27 feb. 2019 | |
| * Author: gheorghe.ghirjev | |
| */ | |
| #ifndef BMP180_H_ | |
| #define BMP180_H_ | |
| #include "stdint.h" | |
| // Data type definitions: | |
| #define BYTE_SHIFT (8U) | |
| #define SHORT_SHIFT (16U) | |
| /* Chip-id [R/O] (register D0h): This value is fixed to 0x55, | |
| * and can be used to check whether communication is functioning. */ | |
| #define BMP_CHIP_ID_REG (0xD0) | |
| #define BMP_CHIP_ID_VAL (0x55) | |
| /* Measurement control [R/W] (register F4h): | |
| * <4:0> - Controls measurements. | |
| * <5> - SCO : Start of conversion. The value of this bit stays “1” during conversion, | |
| * and is reset to “0” after conversion is complete | |
| * <7:6> - OSS : Controls the oversampling ratio of the pressure measurement | |
| */ | |
| #define BMP_CTRL_REG (0xF4) | |
| #define BMP_CTRL_SCO_BIT(reg) ((reg & 0x20) >> 5) | |
| #define BMP_CTRL_OSS_MASK(oss) (oss = (oss & 0x3) << 6) | |
| #define BMP_OSS0_CONV_TIME (5U) | |
| #define BMP_OSS1_CONV_TIME (8U) | |
| #define BMP_OSS2_CONV_TIME (14U) | |
| #define BMP_OSS3_CONV_TIME (26U) | |
| /* Soft reset [W/O] (register E0h): | |
| * If set to 0xB6, will perform the same sequence as power on reset. */ | |
| #define BMP_SOFT_RST_REG (0xE0) | |
| #define BMP_SOFT_RST_VAL (0xB6) | |
| // Calibration data [R/O] (register AAh up to BFh): | |
| #define BMP_CALIB_ADDR (0xAA) | |
| #define BMP_CALIB_DATA_SIZE (22U) | |
| // Device I2C addr register [R/O]: write EEh, read EFh: | |
| #define BMP_READ_ADDR (0xEF) | |
| #define BMP_WRITE_ADDR (0xEE) | |
| #define BMP_I2C_TIMEOUT (50U) | |
| #define BMP_SET_I2CRW_REG(i2c_buff, reg) (i2c_buff = reg) | |
| // BMP measurmenet regs | |
| #define BMP_DATA_MSB_ADDR (0xF6) | |
| #define BMP_DATA_LSB_ADDR (0xF7) | |
| #define BMP_DATA_XLSB_ADDR (0xF8) | |
| // Temp. measurement : | |
| #define BMP_SET_TEMP_CONV (0x2E) | |
| #define BMP_TEMP_CONV_TIME (5U) | |
| #define BMP_MIN_TEMP_THRESHOLD (-40) | |
| #define BMP_MAX_TEMP_THRESHOLD (85U) | |
| // Pressure measurment : | |
| #define BMP_SET_PRESS_CONV (0x34) | |
| #define BMP_PRESS_CONST_SEA_LEVEL (101325.0f) // pressure in Pa | |
| #define BMP_PRESS_CONST_COEFICIENT (44330.0f) | |
| // Altitude measurment : | |
| #define BMP_MIN_ALT_THRESHOLD (-500) // m. relating to sea level) | |
| #define BMP_MAX_ALT_THRESHOLD (9000U) // m. relating to sea level) | |
| struct bmp_calib_param_t | |
| { | |
| int16_t AC1; | |
| int16_t AC2; | |
| int16_t AC3; | |
| uint16_t AC4; | |
| uint16_t AC5; | |
| uint16_t AC6; | |
| int16_t B1; | |
| int16_t B2; | |
| int16_t MB; | |
| int16_t MC; | |
| int16_t MD; | |
| }; | |
| struct measure_data_t | |
| { | |
| float temp; | |
| int32_t press; | |
| /* for uncompensated values do not use below fields: */ | |
| int32_t B5; | |
| float altitude; | |
| }; | |
| typedef enum | |
| { | |
| ULTRA_LOW_PWR_MODE = 0, | |
| STANDARD_MODE, | |
| HIGH, | |
| ULTRA_HIGH_RESOLUTION | |
| } oss_ratio_t; | |
| typedef struct | |
| { | |
| oss_ratio_t ratio; | |
| uint8_t wait_time; | |
| }oss_t; | |
| typedef enum | |
| { | |
| NO_ERR = 0, | |
| CHIP_ID_INVALID_ERR, | |
| GET_CALIB_ERR, | |
| GET_TEMP_ERR, | |
| GET_PRESSURE_ERR, | |
| GET_ALTITUDE_ERR | |
| } bmp_err_t; | |
| typedef struct | |
| { | |
| struct bmp_calib_param_t calib; | |
| struct measure_data_t uncomp; // uncompensated values | |
| struct measure_data_t data; | |
| oss_t oss; | |
| bmp_err_t err; | |
| }bmp_t; | |
| /*! | |
| * @brief: - Performe initial sequence of BMP180 sensor. | |
| * @param[in] - pointer to struct of type bmp_calib_param_t | |
| * @return - None. | |
| */ | |
| void bmp_init (bmp_t * bmp); | |
| /*! | |
| * @brief: - Read oversampling settings from CTRL reg F4h. | |
| * Oss (register F4h <7:6>): controls the oversampling ratio of the pressure measurement | |
| * (00b: single, 01b: 2 times, 10b: 4 times, 11b: 8 times). | |
| * @param[in] - None. | |
| * @return - None. | |
| */ | |
| static void set_oss (oss_t * oss, oss_ratio_t ratio); | |
| /*! | |
| * @brief: - Get uncompensated temperature value. | |
| * @param[in] - None. | |
| * @return - uncompensated temp. | |
| */ | |
| int32_t get_ut (void); | |
| /*! | |
| * @brief: - Calc true temperature. | |
| * @param[in] - pointer to struct of type bmp_t | |
| * @return - true temp. | |
| */ | |
| float get_temp(bmp_t * bmp); | |
| /*! | |
| * @brief: - Get uncompensated pressure value. | |
| * @param[in] - oss - conversion time. | |
| * @return - uncompensated pressure. | |
| */ | |
| int32_t get_up (oss_t oss); | |
| /*! | |
| * @brief: - Calc true pressure. | |
| * @param[in] - struct of type bmp_t | |
| * @return - true pressure in Pa. | |
| */ | |
| int32_t get_pressure(bmp_t bmp); | |
| /*! | |
| * @brief: - Calc true altitude. | |
| * @param[in] - struct of type bmp_t | |
| * @return - altitude in meters. | |
| */ | |
| float get_altitude (bmp_t * bmp); | |
| #endif /* BMP180_H_ */ |
Hello, I'm grateful for the library that was created,
but after I compailer an error occurred.
error lies when I initialize
bmp_init (& bmp);
'bmp' undeclared (first use in this function); did you mean 'bmp_t'?
Hello.
First of all, thank you very much for all the material you provided.
I have been trying to make it work on a STM32H747 board, which is double core.
I download the program on the CM4 core which is suitable for my application. The problem is that when I try to read the values, temperature stands on 0 °C and Pressure on 236.
It is very strange becouse when I make the reading of uncompensated values I can see the oscilating on time.
The I2C comunication is working by the way.
I don't know if you have any more specific example so you can provided it.
I would really apreciate that.
Thank you very much in advance.
Hello, I'm grateful for the library that was created,
but after I compailer an error occurred.error lies when I initialize
bmp_init (& bmp);
'bmp' undeclared (first use in this function); did you mean 'bmp_t'?
you must add definition of "bmp" at main.c
bmp_t bmp;
main () {
bmp_init (&bmp);
while (1) {
bmp.uncomp.temp = get_ut ();
bmp.data.temp = get_temp (&bmp);
bmp.uncomp.press = get_up (bmp.oss);
bmp.data.press = get_pressure (bmp);
bmp.data.altitude = get_altitude (&bmp);
}
Hello
Sorry for missing "bmp_t bmp;" declaration in main.c file
Thanks @inflamerzt for helping with missing line. I've updated description comment !
Best Regards
C library for BMP180 digital pressure sensor, link
Tis library is destinated for Cortex M7 MCU Hardware, to use it on another ARM Cortex board change the inclusion
#include "stm32f7xx_hal.h"in bmp180.c to needed stm32fX header.The following code is the API calling in your main function :
bmp_t bmp;main () {bmp_init (&bmp);while (1) {bmp.uncomp.temp = get_ut ();bmp.data.temp = get_temp (&bmp);bmp.uncomp.press = get_up (bmp.oss);bmp.data.press = get_pressure (bmp);bmp.data.altitude = get_altitude (&bmp);}