BME688 sensor library for nRF52832

Hi,

I'm developing a project with nRF52832 and BOSH BME688 sensor.

I downloaded the library from github to use the sensor (here it is the link https://github.com/BoschSensortec/BME68x-Sensor-API).

I found a big problem: the libraries refer to another library, called coines, that is not included in the github repository, because it is a low level library specific for each microprocessor (here the explanation https://www.bosch-sensortec.com/software-tools/tools/coines/).

I try to download the installer but it creates a multiple other library that creates problem.

So, I was wondering if someone already has the coines.h and coines.c files to import in my project.

Thanks for helping.

Parents
  • Yes, I find out that I have to modify the following codes

    /*!
     * I2C read function map to COINES platform
     */
    BME68X_INTF_RET_TYPE bme68x_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *intf_ptr)
    {
        uint8_t dev_addr = *(uint8_t*)intf_ptr;
    
        return coines_read_i2c(dev_addr, reg_addr, reg_data, (uint16_t)len);
    }
    
    /*!
     * I2C write function map to COINES platform
     */
    BME68X_INTF_RET_TYPE bme68x_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, void *intf_ptr)
    {
        uint8_t dev_addr = *(uint8_t*)intf_ptr;
    
        return coines_write_i2c(dev_addr, reg_addr, (uint8_t *)reg_data, (uint16_t)len);
    }
    
    
    
    /*!
     * Delay function map to COINES platform
     */
    void bme68x_delay_us(uint32_t period, void *intf_ptr)
    {
        coines_delay_usec(period);
    }
    
    void bme68x_check_rslt(const char api_name[], int8_t rslt)
    {
        switch (rslt)
        {
            case BME68X_OK:
    
                /* Do nothing */
                break;
            case BME68X_E_NULL_PTR:
                printf("API name [%s]  Error [%d] : Null pointer\r\n", api_name, rslt);
                break;
            case BME68X_E_COM_FAIL:
                printf("API name [%s]  Error [%d] : Communication failure\r\n", api_name, rslt);
                break;
            case BME68X_E_INVALID_LENGTH:
                printf("API name [%s]  Error [%d] : Incorrect length parameter\r\n", api_name, rslt);
                break;
            case BME68X_E_DEV_NOT_FOUND:
                printf("API name [%s]  Error [%d] : Device not found\r\n", api_name, rslt);
                break;
            case BME68X_E_SELF_TEST:
                printf("API name [%s]  Error [%d] : Self test error\r\n", api_name, rslt);
                break;
            case BME68X_W_NO_NEW_DATA:
                printf("API name [%s]  Warning [%d] : No new data found\r\n", api_name, rslt);
                break;
            default:
                printf("API name [%s]  Error [%d] : Unknown error code\r\n", api_name, rslt);
                break;
        }
    }
    
    int8_t bme68x_interface_init(struct bme68x_dev *bme, uint8_t intf)
    {
        int8_t rslt = BME68X_OK;
        struct coines_board_info board_info;
    
        if (bme != NULL)
        {
            int16_t result = coines_open_comm_intf(COINES_COMM_INTF_USB);
            if (result < COINES_SUCCESS)
            {
                printf(
                    "\n Unable to connect with Application Board ! \n" " 1. Check if the board is connected and powered on. \n" " 2. Check if Application Board USB driver is installed. \n"
                    " 3. Check if board is in use by another application. (Insufficient permissions to access USB) \n");
                exit(result);
            }
    
            result = coines_get_board_info(&board_info);
    
    #if defined(PC)
            setbuf(stdout, NULL);
    #endif
    
            if (result == COINES_SUCCESS)
            {
                if ((board_info.shuttle_id != BME68X_SHUTTLE_ID))
                {
                    printf("! Warning invalid sensor shuttle \n ," "This application will not support this sensor \n");
                    exit(COINES_E_FAILURE);
                }
            }
    
            coines_set_shuttleboard_vdd_vddio_config(0, 0);
            coines_delay_msec(100);
    
            /* Bus configuration : I2C */
            if (intf == BME68X_I2C_INTF)
            {
                printf("I2C Interface\n");
                dev_addr = BME68X_I2C_ADDR_LOW;
                bme->read = bme68x_i2c_read;
                bme->write = bme68x_i2c_write;
                bme->intf = BME68X_I2C_INTF;
                coines_config_i2c_bus(COINES_I2C_BUS_0, COINES_I2C_STANDARD_MODE);
            }
            /* Bus configuration : SPI */
            else if (intf == BME68X_SPI_INTF)
            {
                printf("SPI Interface\n");
                dev_addr = COINES_SHUTTLE_PIN_7;
                bme->read = bme68x_spi_read;
                bme->write = bme68x_spi_write;
                bme->intf = BME68X_SPI_INTF;
                coines_config_spi_bus(COINES_SPI_BUS_0, COINES_SPI_SPEED_7_5_MHZ, COINES_SPI_MODE0);
            }
    
            coines_delay_msec(100);
    
            coines_set_shuttleboard_vdd_vddio_config(3300, 3300);
    
            coines_delay_msec(100);
    
            bme->delay_us = bme68x_delay_us;
            bme->intf_ptr = &dev_addr;
            bme->amb_temp = 25; /* The ambient temperature in deg C is used for defining the heater temperature */
        }
        else
        {
            rslt = BME68X_E_NULL_PTR;
        }
    
        return rslt;
    }
    
    void bme68x_coines_deinit(void)
    {
        fflush(stdout);
    
        coines_set_shuttleboard_vdd_vddio_config(0, 0);
        coines_delay_msec(1000);
    
        /* Coines interface reset */
        coines_soft_reset();
        coines_delay_msec(1000);
        coines_close_comm_intf(COINES_COMM_INTF_USB);
    }

    In particular, I have to replace all the elements that refer to coines with the specific function of nRF52832 (to adapt the generic library to the  microcontroller that I use)

    For example, I replace 

    coines_delay_usec(1000); with nrf_delay_us(1000);
    but for the other instructions I'm not sure or I do not know how to do; in particular for 
    coines_set_shuttleboard_vdd_vddio_config(3300, 3300);
    coines_config_spi_bus(COINES_SPI_BUS_0, COINES_SPI_SPEED_7_5_MHZ, COINES_SPI_MODE0);
    coines_soft_reset();
    coines_close_comm_intf(COINES_COMM_INTF_USB);
    Thanks for helping
  • Andrea Rossi said:
    coines_set_shuttleboard_vdd_vddio_config(3300, 3300);

    The shuttleboard probably have a SW configurable power supply that you will not need to use. You do need to make sure that the BME688's VDDIO net is at the same voltage potential as the nRF52's VDD net. 

    Andrea Rossi said:
    coines_config_spi_bus(COINES_SPI_BUS_0, COINES_SPI_SPEED_7_5_MHZ, COINES_SPI_MODE0);

    You will have to replace this function with the nrfx_spim_init function. 

    Andrea Rossi said:
    coines_soft_reset();

    You need to read the definition of this function to figure out what it does and why.


    Andrea Rossi said:
    coines_close_comm_intf(COINES_COMM_INTF_USB);

    I don't think you need this at all. I assume it just disables a USB interface on the shuttleboard.


  • I think you're a bit off-track. The COINES thing seems to be some kind of C interface library for desktop PC's. 

    You should only need the bme68x.c, bme68x.h, and bme68x_defs.h I think. 

    From the bme68x_defs.h: 

    /*
     * @brief BME68X device structure
     */
    struct bme68x_dev
    {
        /*! Chip Id */
        uint8_t chip_id;
    
        /*!
         * The interface pointer is used to enable the user
         * to link their interface descriptors for reference during the
         * implementation of the read and write interfaces to the
         * hardware.
         */
        void *intf_ptr;
    
        /*!
         *             Variant id
         * ----------------------------------------
         *     Value   |           Variant
         * ----------------------------------------
         *      0      |   BME68X_VARIANT_GAS_LOW
         *      1      |   BME68X_VARIANT_GAS_HIGH
         * ----------------------------------------
         */
        uint32_t variant_id;
    
        /*! SPI/I2C interface */
        enum bme68x_intf intf;
    
        /*! Memory page used */
        uint8_t mem_page;
    
        /*! Ambient temperature in Degree C*/
        int8_t amb_temp;
    
        /*! Sensor calibration data */
        struct bme68x_calib_data calib;
    
        /*! Read function pointer */
        bme68x_read_fptr_t read;
    
        /*! Write function pointer */
        bme68x_write_fptr_t write;
    
        /*! Delay function pointer */
        bme68x_delay_us_fptr_t delay_us;
    
        /*! To store interface pointer error */
        BME68X_INTF_RET_TYPE intf_rslt;
    
        /*! Store the info messages */
        uint8_t info_msg;
    };


    You need to create a bme68x_dev in the source file that will call the bme68x driver APIs, with the proper function pointers and data. This device is what the the functions in bme68x.c will use to call the appropriate low-level SPI driver calls, etc. 

  • Hi, Thanks for the help.

    After deeper search, I understand that I have to adapt the common.c file to the platform that I'm using, so I have to replace all the generic function (with coines) with the specific one for my microcontroller.

    For example, I replace

    BME68X_INTF_RET_TYPE bme68x_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, void *intf_ptr)
    {
        uint8_t dev_addr = *(uint8_t*)intf_ptr;
        return coines_write_i2c(dev_addr, reg_addr, (uint8_t *)reg_data, (uint16_t)len);
    }
    with 
    BME68X_INTF_RET_TYPE bme68x_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, void *intf_ptr)
    {
    uint8_t dev_addr = *(uint8_t*)intf_ptr;
    return nrf_drv_twi_tx(dev_addr, reg_addr, (uint8_t *)reg_data, (uint16_t)len, false);
    }
    (I hope that I put correctly the various parameters, if not, I would be very glad if you can tell me which are the correct ones).
    But I cannot understand how to replace this command
    coines_config_i2c_bus(COINES_I2C_BUS_0, COINES_I2C_STANDARD_MODE);
    I don't know if this information is important, but in my project I have already initialized the twi comunication for transmit data to other sensors.
  • Again, my advice is to chuck the whole COINES thing out the window as it does not seem to add anything useful for your project. The COINES framework is used to talk to bosch sensors from a PC via an MCU. If you don't need to do that you should not use that framework. 

    If you do need COINES for your project I suggest you ask Bosch for assistance in setting it up.

Reply Children
Related