Bosch Sensortec Community

    cancel
    Showing results for 
    Search instead for 
    Did you mean: 

    Problem reading BMP388 with BMP3-Sensor-API library on Raspberry Pi

    Problem reading BMP388 with BMP3-Sensor-API library on Raspberry Pi

    ans
    New Poster

    I'm trying to use the BMP3-Sensor-API library from Github to read a BMP388 sensor via I2C, but I always get the same answer of raw values 00 00 80 00 00 80. The hardware is okay, measurements do work with the Adafruit Python library. I have implemented the i2c read and write functions similarly as for the BMP280_driver library, which does work. What am I missing? Here is my code that works with BMP280 but not with BMP388:

    #ifdef BMP280
    #include "bmp280.h"
    #else
    #include "bmp3.h"
    #endif
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <linux/i2c-dev.h>
    #include <sys/ioctl.h>
    #include <fcntl.h>
    #include <time.h>
    #include <errno.h>
    #include <stdbool.h>
    
    #define DEVICE "/dev/i2c-1" // bus 1 on gpio 23 = sda, gpio 24 = scl
    
    int fd_i2c; // file descriptor for i2c
    
    bool i2c_interface_init(const char* device, const uint8_t address);
    bool i2c_read(const uint8_t reg_addr, uint8_t *reg_data, const uint16_t length);
    bool i2c_write(const uint8_t reg_addr, const uint8_t *reg_data, const uint16_t length);
    
    /* Functions needed by the BMP library */
    #ifdef BMP280
    void delay_ms(uint32_t period_ms);
    int8_t i2c_reg_write(uint8_t i2c_addr, uint8_t reg_addr, uint8_t *reg_data, uint16_t length);
    int8_t i2c_reg_read(uint8_t i2c_addr, uint8_t reg_addr, uint8_t *reg_data, uint16_t length);
    void print_rslt(const char api_name[], int8_t rslt);
    #else
    void bmp3_delay_us(uint32_t period, void *intf_ptr);
    BMP3_INTF_RET_TYPE bmp3_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, void *intf_ptr);
    BMP3_INTF_RET_TYPE bmp3_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *intf_ptr);
    void bmp3_check_rslt(const char api_name[], int8_t rslt);
    #endif
    
    
    int main(int argc, char** argv)
    {
        /* Initialize bmp object. */
        int8_t rslt;
        #ifdef BMP280
        struct bmp280_dev bmp;
        bmp.dev_id = BMP280_I2C_ADDR_SEC; /* Assign device I2C address based on the status of SDO pin (GND for PRIMARY(0x76) & VDD for SECONDARY(0x77)) */
        bmp.intf = BMP280_I2C_INTF; /* Select the interface mode as I2C */
        /* Map the I2C read & write function pointer with the functions responsible for I2C bus transfer */
        bmp.read = i2c_reg_read;
        bmp.write = i2c_reg_write;
        bmp.delay_ms = delay_ms; /* Map the delay function pointer with the function responsible for implementing the delay */
        if (i2c_interface_init(DEVICE, bmp.dev_id) == false)
            return EXIT_FAILURE;
        rslt = bmp280_init(&bmp);
        print_rslt(" bmp_init status", rslt);
        #else
        struct bmp3_dev dev;
        dev.intf = BMP3_I2C_INTF;
        uint8_t dev_addr = BMP3_ADDR_I2C_SEC;
        dev.intf_ptr = &dev_addr;
        dev.read = bmp3_i2c_read;
        dev.write = bmp3_i2c_write;
        dev.delay_us = bmp3_delay_us;
        if (i2c_interface_init(DEVICE, dev_addr) == false)
            return EXIT_FAILURE;
        rslt = bmp3_init(&dev);
        bmp3_check_rslt("bmp3_init", rslt);
        #endif
    
        /* Configure sensor settings. */
        #ifdef BMP280
        struct bmp280_config conf;
        rslt = bmp280_get_config(&conf, &bmp); /* Always read the current settings before writing, especially when not all the configuration is modified */
        print_rslt(" bmp280_get_config status", rslt);
        conf.filter = BMP280_FILTER_COEFF_4; /* IIR filter coeff */
        conf.os_pres = BMP280_OS_4X; /* Pressure oversampling set at 4x */
        conf.os_temp = BMP280_OS_1X; /* Temperature oversampling set at 1x */
        conf.odr = BMP280_ODR_125_MS; /* Setting the output data rate as 1Hz (1000ms) */
        rslt = bmp280_set_config(&conf, &bmp);
        print_rslt(" bmp280_set_config status", rslt);
        rslt = bmp280_set_power_mode(BMP280_NORMAL_MODE, &bmp); /* Always set the power mode after setting the configuration. */
        print_rslt(" bmp280_set_power_mode status", rslt);
        #else
        struct bmp3_settings settings = { 0 };
        settings.int_settings.drdy_en = BMP3_ENABLE;
        settings.press_en = BMP3_ENABLE;
        settings.temp_en = BMP3_ENABLE;
        settings.odr_filter.press_os = BMP3_OVERSAMPLING_2X;
        settings.odr_filter.temp_os = BMP3_OVERSAMPLING_2X;
        settings.odr_filter.odr = BMP3_ODR_12_5_HZ;
        uint8_t settings_sel = BMP3_SEL_PRESS_EN | BMP3_SEL_TEMP_EN | BMP3_SEL_PRESS_OS | BMP3_SEL_TEMP_OS | BMP3_SEL_ODR |
                       BMP3_SEL_DRDY_EN;
        rslt = bmp3_set_sensor_settings(settings_sel, &dev);
        bmp3_check_rslt("bmp3_set_sensor_settings", rslt);
        settings.op_mode = BMP3_MODE_NORMAL;
        rslt = bmp3_set_op_mode(&dev);
        bmp3_check_rslt("bmp3_set_op_mode", rslt);
        #endif
    
        /* Main loop. */
        while (1)
        {
            /* Make a pressure reading. */
            double temp = 0.;
            double pres = 0.;
            #ifdef BMP280
            struct bmp280_uncomp_data ucomp_data;
            rslt = bmp280_get_uncomp_data(&ucomp_data, &bmp); /* Read the raw data from sensor. */
            print_rslt(" bmp280_get_uncomp_data status", rslt);
            rslt = bmp280_get_comp_temp_double(&temp, ucomp_data.uncomp_temp, &bmp); /* Get the compensated temperature as floating point value */
            print_rslt(" bmp280_get_comp_temp_double status", rslt);
            rslt = bmp280_get_comp_pres_double(&pres, ucomp_data.uncomp_press, &bmp); /* Get the compensated pressure as floating point value */
            print_rslt(" bmp280_get_comp_pres_double status", rslt);
            #else
            struct bmp3_data data = { 0 };
            rslt = bmp3_get_sensor_data(BMP3_ALL, &data, &dev);
            bmp3_check_rslt("bmp3_get_sensor_data", rslt);
            rslt = bmp3_get_status(&dev); /* Read status register again to clear data ready interrupt status */
            bmp3_check_rslt("bmp3_get_status", rslt);
            #ifdef BMP3_DOUBLE_PRECISION_COMPENSATION
            temp = data.temperature;
            pres = data.pressure;
            #else
            temp = (double)data.temperature / 100.;
            pres = (double)data.pressure / 100.;
            #endif /* !BMP3_DOUBLE_PRECISION_COMPENSATION */
            #endif
            printf("%.1fPa %.1f°C\n", pres, temp);
    
            #ifdef BMP280
            bmp.delay_ms(125); /* Sleep time between measurements = BMP280_ODR_125_MS */
            #else
            usleep(125000); /* Sleep time between measurements */
            #endif
        }
    
        return EXIT_SUCCESS;
    }
    
    
    bool i2c_interface_init(const char* device, const uint8_t address)
    {
        /* Open I2C device */
        if ((fd_i2c = open(device, O_RDWR)) < 0)
        {
            fprintf(stderr, "Failed to open the i2c bus %s\n", device);
            return false;
        }
        if (ioctl(fd_i2c, I2C_SLAVE, address) < 0)
        {
            fprintf(stderr, "Failed to acquire bus access and/or talk to slave.\n");
            return false;
        }
        return true;
    }
    
    bool i2c_read(const uint8_t reg_addr, uint8_t *reg_data, const uint16_t length)
    {
        write(fd_i2c, &reg_addr, 1);
        read(fd_i2c, reg_data, length);
        for (int i=0; i<length; i++)
            printf("%02x ", reg_data[i]); // DEBUG
        return true;
    }
    
    bool i2c_write(const uint8_t reg_addr, const uint8_t *reg_data, const uint16_t length)
    {
        int8_t *buf;
    
        buf = malloc(length + 1);
        buf[0] = reg_addr;
        memcpy(buf + 1, reg_data, length);
        if (write(fd_i2c, buf, length + 1) < length)
            return false;
        free(buf);
        return true;
    }
    
    
    #ifdef BMP280
    void delay_ms(uint32_t period_ms)
    {
        usleep(period_ms * 1000);
    }
    
    int8_t i2c_reg_write(uint8_t i2c_addr, uint8_t reg_addr, uint8_t *reg_data, uint16_t length)
    {
        if (i2c_write(reg_addr, reg_data, length))
            return BMP280_OK;
        else
            return BMP280_E_COMM_FAIL;
    }
    
    int8_t i2c_reg_read(uint8_t i2c_addr, uint8_t reg_addr, uint8_t *reg_data, uint16_t length)
    {
        i2c_read(reg_addr, reg_data, length);
        return BMP280_OK;
    }
    
    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
    BMP3_INTF_RET_TYPE bmp3_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *intf_ptr)
    {
        i2c_read(reg_addr, reg_data, len);
        return BMP3_INTF_RET_SUCCESS;
    }
    
    BMP3_INTF_RET_TYPE bmp3_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, void *intf_ptr)
    {
        if (i2c_write(reg_addr, reg_data, len))
            return BMP3_INTF_RET_SUCCESS;
        else
            return BMP3_E_COMM_FAIL;
    }
    
    void bmp3_delay_us(uint32_t period, void *intf_ptr)
    {
        usleep(period);
    }
    
    void bmp3_check_rslt(const char api_name[], int8_t rslt)
    {
        switch (rslt)
        {
            case BMP3_OK:
    
                /* Do nothing */
                break;
            case BMP3_E_NULL_PTR:
                printf("API [%s] Error [%d] : Null pointer\r\n", api_name, rslt);
                break;
            case BMP3_E_COMM_FAIL:
                printf("API [%s] Error [%d] : Communication failure\r\n", api_name, rslt);
                break;
            case BMP3_E_INVALID_LEN:
                printf("API [%s] Error [%d] : Incorrect length parameter\r\n", api_name, rslt);
                break;
            case BMP3_E_DEV_NOT_FOUND:
                printf("API [%s] Error [%d] : Device not found\r\n", api_name, rslt);
                break;
            case BMP3_E_CONFIGURATION_ERR:
                printf("API [%s] Error [%d] : Configuration Error\r\n", api_name, rslt);
                break;
            case BMP3_W_SENSOR_NOT_ENABLED:
                printf("API [%s] Error [%d] : Warning when Sensor not enabled\r\n", api_name, rslt);
                break;
            case BMP3_W_INVALID_FIFO_REQ_FRAME_CNT:
                printf("API [%s] Error [%d] : Warning when Fifo watermark level is not in limit\r\n", api_name, rslt);
                break;
            default:
                printf("API [%s] Error [%d] : Unknown error code\r\n", api_name, rslt);
                break;
        }
    }
    #endif

     

    8 REPLIES 8

    ans
    New Poster

    I have now tried to use the BMP3 library version from COINES instead of the one from Github, and with that library version my program works without problems (after adapting my program to changed signatures of library functions).

    BSTRobin
    Community Moderator
    Community Moderator

    Hello ans,

    Good news.

    Do you mean you used bmp3_set_op_mode() in COINES, then it works well on your HW board?

    I mean that when I copy over bmp3.c, bmp3.h and bmp3_defs.h from COINES (under examples/bmp3) and adapt my code to the changed library functions, then it works. Why is the library in COINES different from the one on Github?

    BSTRobin
    Community Moderator
    Community Moderator

    Hello ans,

    They are different versions, and the functions are the same.

    Icon--AD-black-48x48Icon--address-consumer-data-black-48x48Icon--appointment-black-48x48Icon--back-left-black-48x48Icon--calendar-black-48x48Icon--center-alignedIcon--Checkbox-checkIcon--clock-black-48x48Icon--close-black-48x48Icon--compare-black-48x48Icon--confirmation-black-48x48Icon--dealer-details-black-48x48Icon--delete-black-48x48Icon--delivery-black-48x48Icon--down-black-48x48Icon--download-black-48x48Ic-OverlayAlertIcon--externallink-black-48x48Icon-Filledforward-right_adjustedIcon--grid-view-black-48x48IC_gd_Check-Circle170821_Icons_Community170823_Bosch_Icons170823_Bosch_Icons170821_Icons_CommunityIC-logout170821_Icons_Community170825_Bosch_Icons170821_Icons_CommunityIC-shopping-cart2170821_Icons_CommunityIC-upIC_UserIcon--imageIcon--info-i-black-48x48Icon--left-alignedIcon--Less-minimize-black-48x48Icon-FilledIcon--List-Check-grennIcon--List-Check-blackIcon--List-Cross-blackIcon--list-view-mobile-black-48x48Icon--list-view-black-48x48Icon--More-Maximize-black-48x48Icon--my-product-black-48x48Icon--newsletter-black-48x48Icon--payment-black-48x48Icon--print-black-48x48Icon--promotion-black-48x48Icon--registration-black-48x48Icon--Reset-black-48x48Icon--right-alignedshare-circle1Icon--share-black-48x48Icon--shopping-bag-black-48x48Icon-shopping-cartIcon--start-play-black-48x48Icon--store-locator-black-48x48Ic-OverlayAlertIcon--summary-black-48x48tumblrIcon-FilledvineIc-OverlayAlertwhishlist