06-20-2023 11:14 AM
I have readed the BME680 chip identification code in the register 0xD0 with I2C, the return value is 0x61. therefore, i think the i2c communication is well.
but When I use the function 'bme68x_selftest_check' in bme68x.c, the function always keeps returning error-5. Does anyone know what I did wrong?
bme680.variant_id = BME68X_I2C_ADDR_HIGH;
bme680.intf = BME68X_I2C_INTF;
bme680.read = BME680_read_buf;
bme680.write = BME680_write_byte;
bme680.delay_us = BME_delay_us;
rslt = bme68x_init(&bme680); /* Initialize BME680 sensor */
bme68x_check_rslt("bme68x_init", rslt);
rslt =bme68x_selftest_check(&bme680);
NRF_LOG_INFO("bme68x_selftest_check: %d \r\n", rslt); NRF_LOG_FLUSH();
06-20-2023 04:56 PM
Hi huahua,
Did you strictly refer BME68x self test example code https://github.com/boschsensortec/BME68x-Sensor-API/blob/master/examples/self_test/self_test.c
06-21-2023 12:52 PM
I tried to follow the example provided by Bosch, but the self-test still reported errors -5 BME68X_E_SELF_TEST . Since the self-test example provided by Bosch is based on the stm32 F4 platform, I replaced the I2C driver code. i use the NEF52840 microcontroller. The code is as follows.Does anyone know what I did wrong?
void twi_BME680_init(void)
{
ret_code_t err_code;
const nrf_drv_twi_config_t twi_BME680_config = {
.scl = TWI_BME_SCL_M,
.sda = TWI_BME_SDA_M,
.frequency = NRF_DRV_TWI_FREQ_100K,
.interrupt_priority = APP_IRQ_PRIORITY_HIGH,
.clear_bus_init = false
};
err_code = nrf_drv_twi_init(&BME680_twi, &twi_BME680_config, NULL, NULL);
APP_ERROR_CHECK(err_code);
nrf_drv_twi_enable(&BME680_twi);
}
BME68X_INTF_RET_TYPE bme680_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, void *intf_ptr)
{
uint8_t device_addr = *(uint8_t*)intf_ptr;
(void)intf_ptr;
return BME680_write_byte(device_addr, reg_addr, (uint8_t *)reg_data, (uint16_t)len);
}
BME68X_INTF_RET_TYPE bme680_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *intf_ptr)
{
uint8_t device_addr = *(uint8_t*)intf_ptr;
(void)intf_ptr;
return BME680_read_byte(device_addr, reg_addr, reg_data, (uint16_t)len);
}
void BME_delay_us(uint32_t period, void *intf_ptr)
{
(void)intf_ptr;
nrf_delay_us(period);
}
void bme680_intf_init()
{
/* Initialize BME680 structure */
bme680.variant_id = BME68X_VARIANT_GAS_LOW;
static Bme_addr = BME68X_I2C_ADDR_LOW;//0x76
bme680.chip_id = BME68X_CHIP_ID;
bme680.read = bme680_i2c_read;
bme680.write = bme680_i2c_write;
bme680.intf = BME68X_I2C_INTF;
bme680.delay_us = BME_delay_us;
bme680.intf_ptr = &Bme_addr;
bme680.amb_temp = 25;
}
int main(void)
{
twi_BME680_init();//Initializes the I2C
bme680_intf_init();
rslt = bme68x_init(&bme680); /* Initialize BME680 sensor */
bme68x_check_rslt("bme68x_init", rslt);
rslt =bme68x_selftest_check(&bme680);
bme68x_check_rslt("bme68x_selftest_check", rslt);
while(1)
{}
}
06-21-2023 02:56 PM
int8_t bme68x_selftest_check(const struct bme68x_dev *dev)
{
int8_t rslt;
uint8_t n_fields;
uint8_t i = 0;
struct bme68x_data data[BME68X_N_MEAS] = { { 0 } };
struct bme68x_dev t_dev;
struct bme68x_conf conf;
struct bme68x_heatr_conf heatr_conf;
struct bme68x_heatr_conf heatr_conf_check;
uint8_t op_mode_check; op_mode_check=0xff;
rslt = null_ptr_check(dev);
if (rslt == BME68X_OK)
{
/* Copy required parameters from reference bme68x_dev struct */
t_dev.amb_temp = 25;
t_dev.read = dev->read;
t_dev.write = dev->write;
t_dev.intf = dev->intf;
t_dev.delay_us = dev->delay_us;
t_dev.intf_ptr = dev->intf_ptr;
rslt = bme68x_init(&t_dev);
}
if (rslt == BME68X_OK)
{
/* Set the temperature, pressure and humidity & filter settings */
conf.os_hum = BME68X_OS_1X;
conf.os_pres = BME68X_OS_16X;
conf.os_temp = BME68X_OS_2X;
/* Set the remaining gas sensor settings and link the heating profile */
heatr_conf.enable = BME68X_ENABLE;
heatr_conf.heatr_dur = BME68X_HEATR_DUR1;
heatr_conf.heatr_temp = BME68X_HIGH_TEMP;
rslt = bme68x_set_heatr_conf(BME68X_FORCED_MODE, &heatr_conf, &t_dev);
if (rslt == BME68X_OK)
{
bme68x_get_heatr_conf(&heatr_conf_check,&t_dev);
rslt = bme68x_set_conf(&conf, &t_dev);
if (rslt == BME68X_OK)
{
rslt = bme68x_set_op_mode(BME68X_FORCED_MODE, &t_dev); /* Trigger a measurement */
if (rslt == BME68X_OK)
{
bme68x_get_op_mode(&op_mode_check,&t_dev);
/* Wait for the measurement to complete */
t_dev.delay_us(1000000, t_dev.intf_ptr);
rslt = bme68x_get_data(BME68X_FORCED_MODE, &data[0], &n_fields, &t_dev);
if (rslt == BME68X_OK)
{
if ((data[0].idac != 0x00) && (data[0].idac != 0xFF) &&
(data[0].status & BME68X_GASM_VALID_MSK))
{
rslt = BME68X_OK;
}
else
{
rslt = BME68X_E_SELF_TEST;
}
}
}
}
}
heatr_conf.heatr_dur = BME68X_HEATR_DUR2;
while ((rslt == BME68X_OK) && (i < BME68X_N_MEAS))
{
if (i % 2 == 0)
{
heatr_conf.heatr_temp = BME68X_HIGH_TEMP; /* Higher temperature */
}
else
{
heatr_conf.heatr_temp = BME68X_LOW_TEMP; /* Lower temperature */
}
rslt = bme68x_set_heatr_conf(BME68X_FORCED_MODE, &heatr_conf, &t_dev);
if (rslt == BME68X_OK)
{
rslt = bme68x_set_conf(&conf, &t_dev);
if (rslt == BME68X_OK)
{
rslt = bme68x_set_op_mode(BME68X_FORCED_MODE, &t_dev); /* Trigger a measurement */
if (rslt == BME68X_OK)
{
/* Wait for the measurement to complete */
t_dev.delay_us(BME68X_HEATR_DUR2_DELAY, t_dev.intf_ptr);
rslt = bme68x_get_data(BME68X_FORCED_MODE, &data[i], &n_fields, &t_dev);
}
}
}
i++;
}
if (rslt == BME68X_OK)
{
rslt = analyze_sensor_data(data, BME68X_N_MEAS);
}
}
return rslt;
}
07-10-2023 04:57 PM
Hi huahua,
On my side, BME68x selft-test example code run well on STM32F4 platform. I used STM32 board + BM680 shuttle 3.0 board.
I also upload BME68x self-test example code on STM32F4 for your reference. Enable the following macro definition in user_define.h.
#elif defined(USE_BME68X)
#define BME68X_SELF_TEST
...
#endif