#include #include #include "common_porting.h" #include "cmsis_os.h" #include "stm32f4xx_hal.h" #include "bme680_task.h" #include "bme680.h" #if defined(USE_BME680) struct bme680_dev bme680dev; #if defined(BME680_SELF_TEST) #define MIN_TEMPERATURE INT16_C(0) /* 0 degree Celsius */ #define MAX_TEMPERATURE INT16_C(6000) /* 60 degree Celsius */ #define MIN_PRESSURE UINT32_C(90000) /* 900 hecto Pascals */ #define MAX_PRESSURE UINT32_C(110000) /* 1100 hecto Pascals */ #define MIN_HUMIDITY UINT32_C(20000) /* 20% relative humidity */ #define MAX_HUMIDITY UINT32_C(80000) /* 80% relative humidity*/ #define HEATR_DUR 2000 #define N_MEAS 6 #define LOW_TEMP 150 #define HIGH_TEMP 350 /* Self test fail error */ #define BME680_W_SELF_TEST_FAILED 3 /*! * @brief Function to analyze the sensor data * * @param[in] data Array of measurement data * @param[in] n_meas Number of measurements * * @return Error code * @retval 0 Success * @retval > 0 Warning */ static int8_t analyze_sensor_data(struct bme680_field_data *data, uint8_t n_meas) { int8_t rslt = BME680_OK; uint8_t self_test_failed = 0, i; uint32_t cent_res = 0; if ((data[0].temperature < MIN_TEMPERATURE) || (data[0].temperature > MAX_TEMPERATURE)) self_test_failed++; if ((data[0].pressure < MIN_PRESSURE) || (data[0].pressure > MAX_PRESSURE)) self_test_failed++; if ((data[0].humidity < MIN_HUMIDITY) || (data[0].humidity > MAX_HUMIDITY)) self_test_failed++; for (i = 0; i < n_meas; i++) /* Every gas measurement should be valid */ if (!(data[i].status & BME680_GASM_VALID_MSK)) self_test_failed++; if (n_meas >= 6) cent_res = (data[3].gas_resistance + data[5].gas_resistance) / (2 * data[4].gas_resistance); if ((cent_res * 5) < 6) self_test_failed++; if (self_test_failed) rslt = BME680_W_SELF_TEST_FAILED; return rslt; } /*! * @brief Self-test API for the BME680 */ static int8_t bme680_self_test(struct bme680_dev *dev) { int8_t rslt = BME680_OK; struct bme680_field_data data[N_MEAS]; struct bme680_dev t_dev; /* Copy required parameters from reference bme680_dev struct */ t_dev.dev_id = dev->dev_id; t_dev.amb_temp = 25; t_dev.read = dev->read; t_dev.write = dev->write; t_dev.intf = dev->intf; t_dev.delay_ms = dev->delay_ms; rslt = bme680_init(&t_dev); if (rslt == BME680_OK) { /* Select the power mode */ /* Must be set before writing the sensor configuration */ t_dev.power_mode = BME680_FORCED_MODE; uint16_t settings_sel; /* Set the temperature, pressure and humidity & filter settings */ t_dev.tph_sett.os_hum = BME680_OS_1X; t_dev.tph_sett.os_pres = BME680_OS_16X; t_dev.tph_sett.os_temp = BME680_OS_2X; /* Set the remaining gas sensor settings and link the heating profile */ t_dev.gas_sett.run_gas = BME680_ENABLE_GAS_MEAS; t_dev.gas_sett.heatr_dur = HEATR_DUR; settings_sel = BME680_OST_SEL | BME680_OSP_SEL | BME680_OSH_SEL | BME680_GAS_SENSOR_SEL; uint16_t profile_dur = 0; bme680_get_profile_dur(&profile_dur, &t_dev); uint8_t i = 0; while ((rslt == BME680_OK) && (i < N_MEAS)) { if (rslt == BME680_OK) { if (i % 2 == 0) t_dev.gas_sett.heatr_temp = HIGH_TEMP; /* Higher temperature */ else t_dev.gas_sett.heatr_temp = LOW_TEMP; /* Lower temperature */ rslt = bme680_set_sensor_settings(settings_sel, &t_dev); if (rslt == BME680_OK) { rslt = bme680_set_sensor_mode(&t_dev); /* Trigger a measurement */ t_dev.delay_ms(profile_dur); /* Wait for the measurement to complete */ rslt = bme680_get_sensor_data(&data[i], &t_dev); } } i++; } if (rslt == BME680_OK) rslt = analyze_sensor_data(data, N_MEAS); } return rslt; } #endif int8_t BME680_Set_ForcedMode(struct bme680_dev *dev) { int8_t rslt; uint8_t set_required_settings; /* Set the temperature, pressure and humidity settings */ dev->tph_sett.os_hum = BME680_OS_2X; dev->tph_sett.os_pres = BME680_OS_4X; dev->tph_sett.os_temp = BME680_OS_8X; dev->tph_sett.filter = BME680_FILTER_SIZE_3; /* Set the remaining gas sensor settings and link the heating profile */ dev->gas_sett.run_gas = BME680_ENABLE_GAS_MEAS; /* Create a ramp heat waveform in 3 steps */ dev->gas_sett.heatr_temp = 320; /* degree Celsius */ dev->gas_sett.heatr_dur = 150; /* milliseconds */ /* Select the power mode */ /* Must be set before writing the sensor configuration */ dev->power_mode = BME680_FORCED_MODE; /* Set the required sensor settings needed */ set_required_settings = BME680_OST_SEL | BME680_OSP_SEL | BME680_OSH_SEL | BME680_FILTER_SEL | BME680_GAS_SENSOR_SEL; /* Set the desired sensor configuration */ rslt = bme680_set_sensor_settings(set_required_settings,dev); /* Set the power mode */ rslt = bme680_set_sensor_mode(dev); return rslt; } int8_t BME680_Get_Sensordata(struct bme680_dev *dev) { int8_t rslt; /* Get the total measurement duration so as to sleep or wait till the * measurement is complete */ uint16_t meas_period; bme680_get_profile_dur(&meas_period, dev); struct bme680_field_data data; dev->delay_ms(meas_period); /* Delay till the measurement is ready */ rslt = bme680_get_sensor_data(&data, dev); PDEBUG("T: %.2f degC, P: %.2f hPa, H %.2f %%rH , meas_period=%d", data.temperature / 100.0f, data.pressure / 100.0f, data.humidity / 1000.0f, meas_period); /* Avoid using measurements from an unstable heating setup */ if(data.status & BME680_GASM_VALID_MSK) { PDEBUG(", G: %d ohms", data.gas_resistance); } PDEBUG("\r\n"); /* Trigger the next measurement if you would like to read data out continuously */ if (dev->power_mode == BME680_FORCED_MODE) { rslt = bme680_set_sensor_mode(dev); } return rslt; } int8_t Init_BME680(struct bme680_dev *dev) { int8_t rslt = BME680_OK; #if defined(USE_I2C_INTERFACE) dev->dev_id = BME680_I2C_ADDR_SECONDARY; dev->intf = BME680_I2C_INTF; dev->read = SensorAPI_I2Cx_Read; dev->write = SensorAPI_I2Cx_Write; dev->delay_ms = HAL_Delay; dev->amb_temp = 25; /* The ambient temperature in deg C is used for defining the heater temperature */ #elif defined(USE_SPI_INTERFACE) dev->dev_id = 0; dev->intf = BME680_SPI_INTF; dev->read = SensorAPI_SPIx_Read; dev->write = SensorAPI_SPIx_Write; dev->delay_ms = HAL_Delay; dev->amb_temp = 25; /* The ambient temperature in deg C is used for defining the heater temperature */ #endif #if defined(BME680_SELF_TEST) PDEBUG("Start BME680 self test\r\n"); rslt = bme680_self_test(dev); if(rslt == BME680_OK) { PDEBUG("bme680_self_test is successful\r\n"); } else { PDEBUG("bme680_self_test is failed\r\n"); } #endif bme680_soft_reset(dev); dev->delay_ms(10); rslt = bme680_init(dev); if(rslt != BME680_OK) { PDEBUG("bme680_init failed, rslt=%d\r\n", rslt); } else { PDEBUG("bme680_init successful, chip id=0x%02X\r\n", dev->chip_id); } rslt = BME680_Set_ForcedMode(dev); if(rslt != BME680_OK) { PDEBUG("BME680_Set_ForcedMode failed, rslt=%d\r\n", rslt); } return rslt; } void StartBME680Task(void const * argument) { int8_t rslt = BME680_OK; struct bme680_dev *dev; dev = &bme680dev; Init_BME680(dev); for(;;) { BME680_Get_Sensordata(dev); } } #endif