/**\mainpage * Copyright (C) 2017 - 2018 Bosch Sensortec GmbH * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the copyright holder nor the names of the * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER * OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE * * The information provided is believed to be accurate and reliable. * The copyright holder assumes no responsibility * for the consequences of use * of such information nor for any infringement of patents or * other rights of third parties which may result from its use. * No license is granted by implication or otherwise under any patent or * patent rights of the copyright holder. * * File bme680_selftest.c * @date 5 Jul 2017 * @version 3.5.1 * */ /*! * @addtogroup bme680_selftest * @brief * @{*/ #include "bme680_selftest.h" #define MIN_TEMPERATURE INT16_C(0) /* 0 degree Celsius */ #define MAX_TEMPERATURE INT16_C(4000) /* 40 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 200 #define HIGH_TEMP 350 /*! * @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); /*! * @brief Self-test API for the BME680 */ 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 = LOW_TEMP; /* Lower temperature */ else t_dev.gas_sett.heatr_temp = HIGH_TEMP; /* Higher 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; } /*! * @brief Function to analyze the sensor data */ 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 | BME680_HEAT_STAB_MSK))) self_test_failed++; for (i = 2; i < n_meas; i += 2) { /* Invert formula to get integer values for centroid resistance, i.e. > 1 */ cent_res = (data[i - 2].gas_resistance + data[i].gas_resistance) / (2 * data[i - 1].gas_resistance); } if ((cent_res < 3) || (cent_res > 20)) /* 0.05 > cent_res^-1 < 0.03 */ self_test_failed++; if (self_test_failed) rslt = BME680_W_SELF_TEST_FAILED; return rslt; } /** @}*/