BMP280 I2C temperature & pressure reading issue ***Solved***
Posted: Tue Apr 30, 2019 3:38 am
The BMP280 temperature and pressure reading seemed to be static using the below ESP32 esp-idf I2C code together with official Bosch bmp280 c library
at https://github.com/BoschSensortec/BMP280_driver. I have also tested the result using Arduino Adafruit BMP280 , the output from the Arduino seemed to be much reliable with variation noticed in both temperature and pressure values readout.
I think this issue may be due to either the I2C config or the bmp config missing some vital parameter or wrong setup given the fact the self test always return unkown error code -9 , any advice or solution?
at https://github.com/BoschSensortec/BMP280_driver. I have also tested the result using Arduino Adafruit BMP280 , the output from the Arduino seemed to be much reliable with variation noticed in both temperature and pressure values readout.
I think this issue may be due to either the I2C config or the bmp config missing some vital parameter or wrong setup given the fact the self test always return unkown error code -9 , any advice or solution?
- #include <stdio.h>
- #include <math.h>
- #include "freertos/FreeRTOS.h"
- #include "freertos/task.h"
- #include "esp_system.h"
- #include "esp_spi_flash.h"
- #include "driver/gpio.h"
- #include "driver/i2c.h"
- #include "esp_err.h"
- #include "nvs_flash.h"
- #include "bmp280.h"
- #include "bmp280_defs.h"
- #include "bmp280.c"
- #define SDA_GPIO 21
- #define SCL_GPIO 22
- #define I2C_MASTER_FREQ_HZ CONFIG_I2C_MASTER_FREQUENCY
- struct bmp280_uncomp_data ucomp_data;
- int32_t temp32;
- double temp;
- uint32_t pres32, pres64;
- double pres;
- void i2c_master_init() {
- i2c_config_t i2c_config = {
- .mode = I2C_MODE_MASTER,
- .sda_io_num = SDA_GPIO,
- .scl_io_num = SCL_GPIO,
- .sda_pullup_en = GPIO_PULLUP_ENABLE,
- .scl_pullup_en = GPIO_PULLUP_ENABLE,
- .master.clk_speed = 100000
- };
- i2c_param_config(I2C_NUM_0, &i2c_config);
- i2c_driver_install(I2C_NUM_0, I2C_MODE_MASTER, 0, 0, 0);
- //*************// Verify that the I2C slave is working properly
- esp_err_t esp_retval;
- i2c_cmd_handle_t cmd = i2c_cmd_link_create();
- i2c_master_start(cmd);
- i2c_master_write_byte(cmd, (BMP280_I2C_ADDR_PRIM << 1) | I2C_MASTER_WRITE, true);
- i2c_master_stop(cmd);
- f_retval = i2c_master_cmd_begin(I2C_NUM_0, cmd, RTOS_DELAY_1SEC);
- if (f_retval != ESP_OK) {
- printf("I2C slave NOT working or wrong I2C slave address - error (%i)", f_retval);
- // LABEL
- }
- i2c_cmd_link_delete(cmd);
- }
- int8_t i2c_reg_read(uint8_t i2c_addr, uint8_t reg_addr, uint8_t *reg_data, uint16_t length) {
- int8_t iError;
- esp_err_t esp_err;
- i2c_cmd_handle_t cmd_handle = i2c_cmd_link_create();
- i2c_master_start(cmd_handle);
- i2c_master_write_byte(cmd_handle, (i2c_addr << 1) | I2C_MASTER_WRITE, true);
- i2c_master_write_byte(cmd_handle, reg_addr, true);
- i2c_master_start(cmd_handle);
- i2c_master_write_byte(cmd_handle, (i2c_addr << 1) | I2C_MASTER_READ, true);
- if (length > 1) {
- i2c_master_read(cmd_handle, reg_data, length - 1, I2C_MASTER_ACK);
- }
- i2c_master_read_byte(cmd_handle, reg_data + length - 1, I2C_MASTER_NACK);
- i2c_master_stop(cmd_handle);
- esp_err = i2c_master_cmd_begin(I2C_NUM_0, cmd_handle, 1000 / portTICK_PERIOD_MS);
- if (esp_err == ESP_OK) {
- iError = 0;
- } else {
- iError = -1;
- }
- i2c_cmd_link_delete(cmd_handle);
- return iError;
- }
- int8_t i2c_reg_write(uint8_t i2c_addr, uint8_t reg_addr, uint8_t *reg_data, uint16_t length) {
- /* Implement the I2C write routine according to the target machine. */
- int8_t iError;
- esp_err_t esp_err;
- i2c_cmd_handle_t cmd_handle = i2c_cmd_link_create();
- i2c_master_start(cmd_handle);
- i2c_master_write_byte(cmd_handle, (i2c_addr << 1) | I2C_MASTER_WRITE, true);
- i2c_master_write_byte(cmd_handle, reg_addr, true);
- i2c_master_write(cmd_handle, reg_data, length,true);
- i2c_master_stop(cmd_handle);
- esp_err = i2c_master_cmd_begin(I2C_NUM_0, cmd_handle, 1000 / portTICK_PERIOD_MS);
- if (esp_err == ESP_OK) {
- iError = 0;
- } else {
- iError = -1;
- }
- i2c_cmd_link_delete(cmd_handle);
- return iError;
- }
- void delay_ms(uint32_t period_ms) {
- /* Implement the delay routine according to the target machine */
- //vTaskDelay(period_ms / portTICK_PERIOD_MS);
- //********************//
- ets_delay_us(period_ms * 1000);
- }
- void print_rslt(const char api_name[], int8_t rslt) {
- if (rslt != BMP280_OK) {
- printf("%s\t", api_name);
- if (rslt == BMP280_E_NULL_PTR) {
- printf("Error [%d] : Null pointer error\r\n", rslt);
- } else if (rslt == BMP280_E_COMM_FAIL) {
- printf("Error [%d] : Bus communication failed\r\n", rslt);
- } else if (rslt == BMP280_E_IMPLAUS_TEMP) {
- printf("Error [%d] : Invalid Temperature\r\n", rslt);
- } else if (rslt == BMP280_E_DEV_NOT_FOUND) {
- printf("Error [%d] : Device not found\r\n", rslt);
- } else {
- /* For more error codes refer "*_defs.h" */
- printf("Error [%d] : Unknown error code\r\n", rslt);
- }
- }else{
- printf("%s\t", api_name);
- printf(" BMP280 status [%d]\n ",rslt);
- }
- }
- void bmp280_test(void *pvParamters) {
- struct bmp280_dev bmp;
- struct bmp280_config config;
- int8_t bmpstatus;
- bmp.delay_ms = delay_ms;
- /* Assign device I2C address based on the status of SDO pin (GND for PRIMARY(0x76) & VDD for SECONDARY(0x77)) */
- bmp.dev_id = BMP280_I2C_ADDR_PRIM;
- bmp.intf = BMP280_I2C_INTF;
- bmp.read = i2c_reg_read;
- bmp.write = i2c_reg_write;
- bmpstatus = bmp280_init(&bmp);
- //printf("bmp280 init status %d",bmpstatus);
- print_rslt("bmp280_init status", bmpstatus);
- bmpstatus = bmp280_get_config(&config, &bmp);
- print_rslt("bmp280_get_config status", bmpstatus);
- /* configuring the temperature oversampling, filter coefficient and output data rate */
- /* Overwrite the desired settings */
- config.filter = BMP280_FILTER_COEFF_2;
- //*******// configure the sampling according to data spec sheet recommendation
- /* Temperature oversampling set at 1x */
- config.os_temp = BMP280_OS_1X;
- /* Pressure over sampling ( pressure measurement) */
- config.os_pres = BMP280_OS_8X;
- /* Setting the output data rate as 1HZ(1000ms) */
- config.odr = BMP280_ODR_1000_MS;
- bmpstatus = bmp280_set_config(&config, &bmp);
- print_rslt(" bmp280_set_config status", bmpstatus);
- bmpstatus = bmp280_set_power_mode(BMP280_NORMAL_MODE, &bmp);
- print_rslt(" bmp280_set_power_mode status", bmpstatus);
- while (1) {
- //*************// Add a delay of minimum 50millisec or more to get sensor reading!
- vTaskDelay(50 / portTICK_PERIOD_MS);
- /* Reading the raw data from sensor */
- bmpstatus = bmp280_get_uncomp_data(&ucomp_data, &bmp);
- //print_rslt(" bmp280_raw status", bmpstatus);
- /* Getting the 32 bit compensated temperature */
- bmpstatus = bmp280_get_comp_temp_32bit(&temp32, ucomp_data.uncomp_temp, &bmp);
- //print_rslt(" bmp280_comp_temp32", bmpstatus);
- /* Getting the compensated temperature as floating point value */
- bmpstatus = bmp280_get_comp_temp_double(&temp, ucomp_data.uncomp_temp, &bmp);
- //print_rslt(" bmp280_comp_temp", bmpstatus);
- printf("UT: %d, T32: %d, T: %f \r\n", ucomp_data.uncomp_temp, temp32, temp);
- /* Getting the compensated pressure using 32 bit precision */
- bmpstatus = bmp280_get_comp_pres_32bit(&pres32, ucomp_data.uncomp_press, &bmp);
- // print_rslt(" bmp280_comp_pressure32", bmpstatus);
- /* Getting the compensated pressure using 64 bit precision */
- bmpstatus = bmp280_get_comp_pres_64bit(&pres64, ucomp_data.uncomp_press, &bmp);
- // print_rslt(" bmp280_comp_pressure64", bmpstatus);
- /* Getting the compensated pressure as floating point value */
- bmpstatus = bmp280_get_comp_pres_double(&pres, ucomp_data.uncomp_press, &bmp);
- // print_rslt(" bmp280_comp_pressure", bmpstatus);
- printf("UP: %d, P32: %d, P64: %d, P64N: %d, P: %f\r\n",
- ucomp_data.uncomp_press,
- pres32,
- pres64,
- pres64 / 256,
- pres);
- printf("\n");
- float altitude;
- float pressure = pres64 / 256; // in Si units for Pascal
- pressure /= 100;
- altitude = 44330 * (1.0 - pow(pressure / 1013.25, 0.1903));
- printf("Altitude %f\n", altitude);
- printf("\n");
- /* Sleep time between measurements = BMP280_ODR_1000_MS */
- bmp.delay_ms(1);
- //******************// add a delay of reasonable ms within the while loop
- vTaskDelay(3000 / portTICK_PERIOD_MS);
- }
- vTaskDelete(NULL);
- }
- void app_main() {
- ESP_ERROR_CHECK(nvs_flash_init());
- i2c_master_init();
- xTaskCreate(&bmp280_test, "bmp280_test", 2048, NULL, 6, NULL);
- }