Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
BME280.cpp@2:853301624d95, 2019-09-03 (annotated)
- Committer:
- mcm
- Date:
- Tue Sep 03 15:15:15 2019 +0000
- Revision:
- 2:853301624d95
- Parent:
- 0:ac5ce2103c04
- Child:
- 3:ab857b70346e
The driver is ready to be tested
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| mcm | 2:853301624d95 | 1 | /** |
| mcm | 2:853301624d95 | 2 | * @brief BME280.cpp |
| mcm | 2:853301624d95 | 3 | * @details Combined humidity and pressure sensor. |
| mcm | 2:853301624d95 | 4 | * Function file. |
| mcm | 2:853301624d95 | 5 | * |
| mcm | 2:853301624d95 | 6 | * |
| mcm | 2:853301624d95 | 7 | * @return N/A |
| mcm | 2:853301624d95 | 8 | * |
| mcm | 2:853301624d95 | 9 | * @author Manuel Caballero |
| mcm | 2:853301624d95 | 10 | * @date 03/September/2019 |
| mcm | 2:853301624d95 | 11 | * @version 03/September/2019 The ORIGIN |
| mcm | 2:853301624d95 | 12 | * @pre This is just a port from Bosh driver to mBed ( c++ ) |
| mcm | 2:853301624d95 | 13 | * @warning N/A |
| mcm | 2:853301624d95 | 14 | * @pre This code belongs to AqueronteBlog ( http://unbarquero.blogspot.com ). |
| mcm | 2:853301624d95 | 15 | */ |
| mcm | 2:853301624d95 | 16 | /**\mainpage |
| mcm | 2:853301624d95 | 17 | * Copyright (C) 2018 - 2019 Bosch Sensortec GmbH |
| mcm | 2:853301624d95 | 18 | * |
| mcm | 2:853301624d95 | 19 | * Redistribution and use in source and binary forms, with or without |
| mcm | 2:853301624d95 | 20 | * modification, are permitted provided that the following conditions are met: |
| mcm | 2:853301624d95 | 21 | * |
| mcm | 2:853301624d95 | 22 | * Redistributions of source code must retain the above copyright |
| mcm | 2:853301624d95 | 23 | * notice, this list of conditions and the following disclaimer. |
| mcm | 2:853301624d95 | 24 | * |
| mcm | 2:853301624d95 | 25 | * Redistributions in binary form must reproduce the above copyright |
| mcm | 2:853301624d95 | 26 | * notice, this list of conditions and the following disclaimer in the |
| mcm | 2:853301624d95 | 27 | * documentation and/or other materials provided with the distribution. |
| mcm | 2:853301624d95 | 28 | * |
| mcm | 2:853301624d95 | 29 | * Neither the name of the copyright holder nor the names of the |
| mcm | 2:853301624d95 | 30 | * contributors may be used to endorse or promote products derived from |
| mcm | 2:853301624d95 | 31 | * this software without specific prior written permission. |
| mcm | 2:853301624d95 | 32 | * |
| mcm | 2:853301624d95 | 33 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND |
| mcm | 2:853301624d95 | 34 | * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR |
| mcm | 2:853301624d95 | 35 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| mcm | 2:853301624d95 | 36 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| mcm | 2:853301624d95 | 37 | * DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER |
| mcm | 2:853301624d95 | 38 | * OR CONTRIBUTORS BE LIABLE FOR ANY |
| mcm | 2:853301624d95 | 39 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, |
| mcm | 2:853301624d95 | 40 | * OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, |
| mcm | 2:853301624d95 | 41 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| mcm | 2:853301624d95 | 42 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| mcm | 2:853301624d95 | 43 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| mcm | 2:853301624d95 | 44 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| mcm | 2:853301624d95 | 45 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
| mcm | 2:853301624d95 | 46 | * ANY WAY OUT OF THE USE OF THIS |
| mcm | 2:853301624d95 | 47 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE |
| mcm | 2:853301624d95 | 48 | * |
| mcm | 2:853301624d95 | 49 | * The information provided is believed to be accurate and reliable. |
| mcm | 2:853301624d95 | 50 | * The copyright holder assumes no responsibility |
| mcm | 2:853301624d95 | 51 | * for the consequences of use |
| mcm | 2:853301624d95 | 52 | * of such information nor for any infringement of patents or |
| mcm | 2:853301624d95 | 53 | * other rights of third parties which may result from its use. |
| mcm | 2:853301624d95 | 54 | * No license is granted by implication or otherwise under any patent or |
| mcm | 2:853301624d95 | 55 | * patent rights of the copyright holder. |
| mcm | 2:853301624d95 | 56 | * |
| mcm | 2:853301624d95 | 57 | * File bme280.c |
| mcm | 2:853301624d95 | 58 | * Date 08 Mar 2019 |
| mcm | 2:853301624d95 | 59 | * Version 3.3.6 |
| mcm | 2:853301624d95 | 60 | * |
| mcm | 2:853301624d95 | 61 | */ |
| mcm | 2:853301624d95 | 62 | |
| mcm | 2:853301624d95 | 63 | /*! @file bme280.c |
| mcm | 2:853301624d95 | 64 | * @brief Sensor driver for BME280 sensor |
| mcm | 2:853301624d95 | 65 | */ |
| mcm | 2:853301624d95 | 66 | #include "BME280.h" |
| mcm | 2:853301624d95 | 67 | |
| mcm | 2:853301624d95 | 68 | BME280::BME280 ( PinName sda, PinName scl, uint32_t freq ) |
| mcm | 2:853301624d95 | 69 | : _i2c ( sda, scl ) |
| mcm | 2:853301624d95 | 70 | { |
| mcm | 2:853301624d95 | 71 | _i2c.frequency ( freq ); |
| mcm | 2:853301624d95 | 72 | } |
| mcm | 2:853301624d95 | 73 | |
| mcm | 2:853301624d95 | 74 | |
| mcm | 2:853301624d95 | 75 | BME280::~BME280() |
| mcm | 2:853301624d95 | 76 | { |
| mcm | 2:853301624d95 | 77 | } |
| mcm | 2:853301624d95 | 78 | |
| mcm | 2:853301624d95 | 79 | |
| mcm | 2:853301624d95 | 80 | /**\name Internal macros */ |
| mcm | 2:853301624d95 | 81 | /* To identify osr settings selected by user */ |
| mcm | 2:853301624d95 | 82 | #define OVERSAMPLING_SETTINGS UINT8_C(0x07) |
| mcm | 2:853301624d95 | 83 | |
| mcm | 2:853301624d95 | 84 | /* To identify filter and standby settings selected by user */ |
| mcm | 2:853301624d95 | 85 | #define FILTER_STANDBY_SETTINGS UINT8_C(0x18) |
| mcm | 2:853301624d95 | 86 | |
| mcm | 2:853301624d95 | 87 | /*! |
| mcm | 2:853301624d95 | 88 | * @brief This internal API puts the device to sleep mode. |
| mcm | 2:853301624d95 | 89 | * |
| mcm | 2:853301624d95 | 90 | * @param[in] dev : Structure instance of bme280_dev. |
| mcm | 2:853301624d95 | 91 | * |
| mcm | 2:853301624d95 | 92 | * @return Result of API execution status. |
| mcm | 2:853301624d95 | 93 | * @retval zero -> Success / +ve value -> Warning / -ve value -> Error |
| mcm | 2:853301624d95 | 94 | */ |
| mcm | 2:853301624d95 | 95 | static int8_t put_device_to_sleep(const struct bme280_dev *dev); |
| mcm | 2:853301624d95 | 96 | |
| mcm | 2:853301624d95 | 97 | /*! |
| mcm | 2:853301624d95 | 98 | * @brief This internal API writes the power mode in the sensor. |
| mcm | 2:853301624d95 | 99 | * |
| mcm | 2:853301624d95 | 100 | * @param[in] dev : Structure instance of bme280_dev. |
| mcm | 2:853301624d95 | 101 | * @param[in] sensor_mode : Variable which contains the power mode to be set. |
| mcm | 2:853301624d95 | 102 | * |
| mcm | 2:853301624d95 | 103 | * @return Result of API execution status. |
| mcm | 2:853301624d95 | 104 | * @retval zero -> Success / +ve value -> Warning / -ve value -> Error |
| mcm | 2:853301624d95 | 105 | */ |
| mcm | 2:853301624d95 | 106 | static int8_t write_power_mode(uint8_t sensor_mode, const struct bme280_dev *dev); |
| mcm | 2:853301624d95 | 107 | |
| mcm | 2:853301624d95 | 108 | /*! |
| mcm | 2:853301624d95 | 109 | * @brief This internal API is used to validate the device pointer for |
| mcm | 2:853301624d95 | 110 | * null conditions. |
| mcm | 2:853301624d95 | 111 | * |
| mcm | 2:853301624d95 | 112 | * @param[in] dev : Structure instance of bme280_dev. |
| mcm | 2:853301624d95 | 113 | * |
| mcm | 2:853301624d95 | 114 | * @return Result of API execution status |
| mcm | 2:853301624d95 | 115 | * @retval zero -> Success / +ve value -> Warning / -ve value -> Error |
| mcm | 2:853301624d95 | 116 | */ |
| mcm | 2:853301624d95 | 117 | static int8_t null_ptr_check(const struct bme280_dev *dev); |
| mcm | 2:853301624d95 | 118 | |
| mcm | 2:853301624d95 | 119 | /*! |
| mcm | 2:853301624d95 | 120 | * @brief This internal API interleaves the register address between the |
| mcm | 2:853301624d95 | 121 | * register data buffer for burst write operation. |
| mcm | 2:853301624d95 | 122 | * |
| mcm | 2:853301624d95 | 123 | * @param[in] reg_addr : Contains the register address array. |
| mcm | 2:853301624d95 | 124 | * @param[out] temp_buff : Contains the temporary buffer to store the |
| mcm | 2:853301624d95 | 125 | * register data and register address. |
| mcm | 2:853301624d95 | 126 | * @param[in] reg_data : Contains the register data to be written in the |
| mcm | 2:853301624d95 | 127 | * temporary buffer. |
| mcm | 2:853301624d95 | 128 | * @param[in] len : No of bytes of data to be written for burst write. |
| mcm | 2:853301624d95 | 129 | */ |
| mcm | 2:853301624d95 | 130 | static void interleave_reg_addr(const uint8_t *reg_addr, uint8_t *temp_buff, const uint8_t *reg_data, uint8_t len); |
| mcm | 2:853301624d95 | 131 | |
| mcm | 2:853301624d95 | 132 | /*! |
| mcm | 2:853301624d95 | 133 | * @brief This internal API reads the calibration data from the sensor, parse |
| mcm | 2:853301624d95 | 134 | * it and store in the device structure. |
| mcm | 2:853301624d95 | 135 | * |
| mcm | 2:853301624d95 | 136 | * @param[in] dev : Structure instance of bme280_dev. |
| mcm | 2:853301624d95 | 137 | * |
| mcm | 2:853301624d95 | 138 | * @return Result of API execution status |
| mcm | 2:853301624d95 | 139 | * @retval zero -> Success / +ve value -> Warning / -ve value -> Error |
| mcm | 2:853301624d95 | 140 | */ |
| mcm | 2:853301624d95 | 141 | static int8_t get_calib_data(struct bme280_dev *dev); |
| mcm | 2:853301624d95 | 142 | |
| mcm | 2:853301624d95 | 143 | /*! |
| mcm | 2:853301624d95 | 144 | * @brief This internal API is used to parse the temperature and |
| mcm | 2:853301624d95 | 145 | * pressure calibration data and store it in the device structure. |
| mcm | 2:853301624d95 | 146 | * |
| mcm | 2:853301624d95 | 147 | * @param[out] dev : Structure instance of bme280_dev to store the calib data. |
| mcm | 2:853301624d95 | 148 | * @param[in] reg_data : Contains the calibration data to be parsed. |
| mcm | 2:853301624d95 | 149 | */ |
| mcm | 2:853301624d95 | 150 | static void parse_temp_press_calib_data(const uint8_t *reg_data, struct bme280_dev *dev); |
| mcm | 2:853301624d95 | 151 | |
| mcm | 2:853301624d95 | 152 | /*! |
| mcm | 2:853301624d95 | 153 | * @brief This internal API is used to parse the humidity calibration data |
| mcm | 2:853301624d95 | 154 | * and store it in device structure. |
| mcm | 2:853301624d95 | 155 | * |
| mcm | 2:853301624d95 | 156 | * @param[out] dev : Structure instance of bme280_dev to store the calib data. |
| mcm | 2:853301624d95 | 157 | * @param[in] reg_data : Contains calibration data to be parsed. |
| mcm | 2:853301624d95 | 158 | */ |
| mcm | 2:853301624d95 | 159 | static void parse_humidity_calib_data(const uint8_t *reg_data, struct bme280_dev *dev); |
| mcm | 2:853301624d95 | 160 | |
| mcm | 2:853301624d95 | 161 | #ifdef BME280_FLOAT_ENABLE |
| mcm | 2:853301624d95 | 162 | |
| mcm | 2:853301624d95 | 163 | /*! |
| mcm | 2:853301624d95 | 164 | * @brief This internal API is used to compensate the raw pressure data and |
| mcm | 2:853301624d95 | 165 | * return the compensated pressure data in double data type. |
| mcm | 2:853301624d95 | 166 | * |
| mcm | 2:853301624d95 | 167 | * @param[in] uncomp_data : Contains the uncompensated pressure data. |
| mcm | 2:853301624d95 | 168 | * @param[in] calib_data : Pointer to the calibration data structure. |
| mcm | 2:853301624d95 | 169 | * |
| mcm | 2:853301624d95 | 170 | * @return Compensated pressure data. |
| mcm | 2:853301624d95 | 171 | * @retval Compensated pressure data in double. |
| mcm | 2:853301624d95 | 172 | */ |
| mcm | 2:853301624d95 | 173 | static double compensate_pressure(const struct bme280_uncomp_data *uncomp_data, |
| mcm | 2:853301624d95 | 174 | const struct bme280_calib_data *calib_data); |
| mcm | 2:853301624d95 | 175 | |
| mcm | 2:853301624d95 | 176 | /*! |
| mcm | 2:853301624d95 | 177 | * @brief This internal API is used to compensate the raw humidity data and |
| mcm | 2:853301624d95 | 178 | * return the compensated humidity data in double data type. |
| mcm | 2:853301624d95 | 179 | * |
| mcm | 2:853301624d95 | 180 | * @param[in] uncomp_data : Contains the uncompensated humidity data. |
| mcm | 2:853301624d95 | 181 | * @param[in] calib_data : Pointer to the calibration data structure. |
| mcm | 2:853301624d95 | 182 | * |
| mcm | 2:853301624d95 | 183 | * @return Compensated humidity data. |
| mcm | 2:853301624d95 | 184 | * @retval Compensated humidity data in double. |
| mcm | 2:853301624d95 | 185 | */ |
| mcm | 2:853301624d95 | 186 | static double compensate_humidity(const struct bme280_uncomp_data *uncomp_data, |
| mcm | 2:853301624d95 | 187 | const struct bme280_calib_data *calib_data); |
| mcm | 2:853301624d95 | 188 | |
| mcm | 2:853301624d95 | 189 | /*! |
| mcm | 2:853301624d95 | 190 | * @brief This internal API is used to compensate the raw temperature data and |
| mcm | 2:853301624d95 | 191 | * return the compensated temperature data in double data type. |
| mcm | 2:853301624d95 | 192 | * |
| mcm | 2:853301624d95 | 193 | * @param[in] uncomp_data : Contains the uncompensated temperature data. |
| mcm | 2:853301624d95 | 194 | * @param[in] calib_data : Pointer to calibration data structure. |
| mcm | 2:853301624d95 | 195 | * |
| mcm | 2:853301624d95 | 196 | * @return Compensated temperature data. |
| mcm | 2:853301624d95 | 197 | * @retval Compensated temperature data in double. |
| mcm | 2:853301624d95 | 198 | */ |
| mcm | 2:853301624d95 | 199 | static double compensate_temperature(const struct bme280_uncomp_data *uncomp_data, |
| mcm | 2:853301624d95 | 200 | struct bme280_calib_data *calib_data); |
| mcm | 2:853301624d95 | 201 | |
| mcm | 2:853301624d95 | 202 | #else |
| mcm | 2:853301624d95 | 203 | |
| mcm | 2:853301624d95 | 204 | /*! |
| mcm | 2:853301624d95 | 205 | * @brief This internal API is used to compensate the raw temperature data and |
| mcm | 2:853301624d95 | 206 | * return the compensated temperature data in integer data type. |
| mcm | 2:853301624d95 | 207 | * |
| mcm | 2:853301624d95 | 208 | * @param[in] uncomp_data : Contains the uncompensated temperature data. |
| mcm | 2:853301624d95 | 209 | * @param[in] calib_data : Pointer to calibration data structure. |
| mcm | 2:853301624d95 | 210 | * |
| mcm | 2:853301624d95 | 211 | * @return Compensated temperature data. |
| mcm | 2:853301624d95 | 212 | * @retval Compensated temperature data in integer. |
| mcm | 2:853301624d95 | 213 | */ |
| mcm | 2:853301624d95 | 214 | static int32_t compensate_temperature(const struct bme280_uncomp_data *uncomp_data, |
| mcm | 2:853301624d95 | 215 | struct bme280_calib_data *calib_data); |
| mcm | 2:853301624d95 | 216 | |
| mcm | 2:853301624d95 | 217 | /*! |
| mcm | 2:853301624d95 | 218 | * @brief This internal API is used to compensate the raw pressure data and |
| mcm | 2:853301624d95 | 219 | * return the compensated pressure data in integer data type. |
| mcm | 2:853301624d95 | 220 | * |
| mcm | 2:853301624d95 | 221 | * @param[in] uncomp_data : Contains the uncompensated pressure data. |
| mcm | 2:853301624d95 | 222 | * @param[in] calib_data : Pointer to the calibration data structure. |
| mcm | 2:853301624d95 | 223 | * |
| mcm | 2:853301624d95 | 224 | * @return Compensated pressure data. |
| mcm | 2:853301624d95 | 225 | * @retval Compensated pressure data in integer. |
| mcm | 2:853301624d95 | 226 | */ |
| mcm | 2:853301624d95 | 227 | static uint32_t compensate_pressure(const struct bme280_uncomp_data *uncomp_data, |
| mcm | 2:853301624d95 | 228 | const struct bme280_calib_data *calib_data); |
| mcm | 2:853301624d95 | 229 | |
| mcm | 2:853301624d95 | 230 | /*! |
| mcm | 2:853301624d95 | 231 | * @brief This internal API is used to compensate the raw humidity data and |
| mcm | 2:853301624d95 | 232 | * return the compensated humidity data in integer data type. |
| mcm | 2:853301624d95 | 233 | * |
| mcm | 2:853301624d95 | 234 | * @param[in] uncomp_data : Contains the uncompensated humidity data. |
| mcm | 2:853301624d95 | 235 | * @param[in] calib_data : Pointer to the calibration data structure. |
| mcm | 2:853301624d95 | 236 | * |
| mcm | 2:853301624d95 | 237 | * @return Compensated humidity data. |
| mcm | 2:853301624d95 | 238 | * @retval Compensated humidity data in integer. |
| mcm | 2:853301624d95 | 239 | */ |
| mcm | 2:853301624d95 | 240 | static uint32_t compensate_humidity(const struct bme280_uncomp_data *uncomp_data, |
| mcm | 2:853301624d95 | 241 | const struct bme280_calib_data *calib_data); |
| mcm | 2:853301624d95 | 242 | |
| mcm | 2:853301624d95 | 243 | #endif |
| mcm | 2:853301624d95 | 244 | |
| mcm | 2:853301624d95 | 245 | /*! |
| mcm | 2:853301624d95 | 246 | * @brief This internal API is used to identify the settings which the user |
| mcm | 2:853301624d95 | 247 | * wants to modify in the sensor. |
| mcm | 2:853301624d95 | 248 | * |
| mcm | 2:853301624d95 | 249 | * @param[in] sub_settings : Contains the settings subset to identify particular |
| mcm | 2:853301624d95 | 250 | * group of settings which the user is interested to change. |
| mcm | 2:853301624d95 | 251 | * @param[in] desired_settings : Contains the user specified settings. |
| mcm | 2:853301624d95 | 252 | * |
| mcm | 2:853301624d95 | 253 | * @return Indicates whether user is interested to modify the settings which |
| mcm | 2:853301624d95 | 254 | * are related to sub_settings. |
| mcm | 2:853301624d95 | 255 | * @retval True -> User wants to modify this group of settings |
| mcm | 2:853301624d95 | 256 | * @retval False -> User does not want to modify this group of settings |
| mcm | 2:853301624d95 | 257 | */ |
| mcm | 2:853301624d95 | 258 | static uint8_t are_settings_changed(uint8_t sub_settings, uint8_t desired_settings); |
| mcm | 2:853301624d95 | 259 | |
| mcm | 2:853301624d95 | 260 | /*! |
| mcm | 2:853301624d95 | 261 | * @brief This API sets the humidity oversampling settings of the sensor. |
| mcm | 2:853301624d95 | 262 | * |
| mcm | 2:853301624d95 | 263 | * @param[in] dev : Structure instance of bme280_dev. |
| mcm | 2:853301624d95 | 264 | * |
| mcm | 2:853301624d95 | 265 | * @return Result of API execution status |
| mcm | 2:853301624d95 | 266 | * @retval zero -> Success / +ve value -> Warning / -ve value -> Error |
| mcm | 2:853301624d95 | 267 | */ |
| mcm | 2:853301624d95 | 268 | static int8_t set_osr_humidity_settings(const struct bme280_settings *settings, const struct bme280_dev *dev); |
| mcm | 2:853301624d95 | 269 | |
| mcm | 2:853301624d95 | 270 | /*! |
| mcm | 2:853301624d95 | 271 | * @brief This internal API sets the oversampling settings for pressure, |
| mcm | 2:853301624d95 | 272 | * temperature and humidity in the sensor. |
| mcm | 2:853301624d95 | 273 | * |
| mcm | 2:853301624d95 | 274 | * @param[in] desired_settings : Variable used to select the settings which |
| mcm | 2:853301624d95 | 275 | * are to be set. |
| mcm | 2:853301624d95 | 276 | * @param[in] dev : Structure instance of bme280_dev. |
| mcm | 2:853301624d95 | 277 | * |
| mcm | 2:853301624d95 | 278 | * @return Result of API execution status |
| mcm | 2:853301624d95 | 279 | * @retval zero -> Success / +ve value -> Warning / -ve value -> Error |
| mcm | 2:853301624d95 | 280 | */ |
| mcm | 2:853301624d95 | 281 | static int8_t set_osr_settings(uint8_t desired_settings, |
| mcm | 2:853301624d95 | 282 | const struct bme280_settings *settings, |
| mcm | 2:853301624d95 | 283 | const struct bme280_dev *dev); |
| mcm | 2:853301624d95 | 284 | |
| mcm | 2:853301624d95 | 285 | /*! |
| mcm | 2:853301624d95 | 286 | * @brief This API sets the pressure and/or temperature oversampling settings |
| mcm | 2:853301624d95 | 287 | * in the sensor according to the settings selected by the user. |
| mcm | 2:853301624d95 | 288 | * |
| mcm | 2:853301624d95 | 289 | * @param[in] dev : Structure instance of bme280_dev. |
| mcm | 2:853301624d95 | 290 | * @param[in] desired_settings: variable to select the pressure and/or |
| mcm | 2:853301624d95 | 291 | * temperature oversampling settings. |
| mcm | 2:853301624d95 | 292 | * |
| mcm | 2:853301624d95 | 293 | * @return Result of API execution status |
| mcm | 2:853301624d95 | 294 | * @retval zero -> Success / +ve value -> Warning / -ve value -> Error |
| mcm | 2:853301624d95 | 295 | */ |
| mcm | 2:853301624d95 | 296 | static int8_t set_osr_press_temp_settings(uint8_t desired_settings, |
| mcm | 2:853301624d95 | 297 | const struct bme280_settings *settings, |
| mcm | 2:853301624d95 | 298 | const struct bme280_dev *dev); |
| mcm | 2:853301624d95 | 299 | |
| mcm | 2:853301624d95 | 300 | /*! |
| mcm | 2:853301624d95 | 301 | * @brief This internal API fills the pressure oversampling settings provided by |
| mcm | 2:853301624d95 | 302 | * the user in the data buffer so as to write in the sensor. |
| mcm | 2:853301624d95 | 303 | * |
| mcm | 2:853301624d95 | 304 | * @param[in] dev : Structure instance of bme280_dev. |
| mcm | 2:853301624d95 | 305 | * @param[out] reg_data : Variable which is filled according to the pressure |
| mcm | 2:853301624d95 | 306 | * oversampling data provided by the user. |
| mcm | 2:853301624d95 | 307 | */ |
| mcm | 2:853301624d95 | 308 | static void fill_osr_press_settings(uint8_t *reg_data, const struct bme280_settings *settings); |
| mcm | 2:853301624d95 | 309 | |
| mcm | 2:853301624d95 | 310 | /*! |
| mcm | 2:853301624d95 | 311 | * @brief This internal API fills the temperature oversampling settings provided |
| mcm | 2:853301624d95 | 312 | * by the user in the data buffer so as to write in the sensor. |
| mcm | 2:853301624d95 | 313 | * |
| mcm | 2:853301624d95 | 314 | * @param[in] dev : Structure instance of bme280_dev. |
| mcm | 2:853301624d95 | 315 | * @param[out] reg_data : Variable which is filled according to the temperature |
| mcm | 2:853301624d95 | 316 | * oversampling data provided by the user. |
| mcm | 2:853301624d95 | 317 | */ |
| mcm | 2:853301624d95 | 318 | static void fill_osr_temp_settings(uint8_t *reg_data, const struct bme280_settings *settings); |
| mcm | 2:853301624d95 | 319 | |
| mcm | 2:853301624d95 | 320 | /*! |
| mcm | 2:853301624d95 | 321 | * @brief This internal API sets the filter and/or standby duration settings |
| mcm | 2:853301624d95 | 322 | * in the sensor according to the settings selected by the user. |
| mcm | 2:853301624d95 | 323 | * |
| mcm | 2:853301624d95 | 324 | * @param[in] dev : Structure instance of bme280_dev. |
| mcm | 2:853301624d95 | 325 | * @param[in] desired_settings : variable to select the filter and/or |
| mcm | 2:853301624d95 | 326 | * standby duration settings. |
| mcm | 2:853301624d95 | 327 | * |
| mcm | 2:853301624d95 | 328 | * @return Result of API execution status |
| mcm | 2:853301624d95 | 329 | * @retval zero -> Success / +ve value -> Warning / -ve value -> Error |
| mcm | 2:853301624d95 | 330 | */ |
| mcm | 2:853301624d95 | 331 | static int8_t set_filter_standby_settings(uint8_t desired_settings, |
| mcm | 2:853301624d95 | 332 | const struct bme280_settings *settings, |
| mcm | 2:853301624d95 | 333 | const struct bme280_dev *dev); |
| mcm | 2:853301624d95 | 334 | |
| mcm | 2:853301624d95 | 335 | /*! |
| mcm | 2:853301624d95 | 336 | * @brief This internal API fills the filter settings provided by the user |
| mcm | 2:853301624d95 | 337 | * in the data buffer so as to write in the sensor. |
| mcm | 2:853301624d95 | 338 | * |
| mcm | 2:853301624d95 | 339 | * @param[in] dev : Structure instance of bme280_dev. |
| mcm | 2:853301624d95 | 340 | * @param[out] reg_data : Variable which is filled according to the filter |
| mcm | 2:853301624d95 | 341 | * settings data provided by the user. |
| mcm | 2:853301624d95 | 342 | */ |
| mcm | 2:853301624d95 | 343 | static void fill_filter_settings(uint8_t *reg_data, const struct bme280_settings *settings); |
| mcm | 2:853301624d95 | 344 | |
| mcm | 2:853301624d95 | 345 | /*! |
| mcm | 2:853301624d95 | 346 | * @brief This internal API fills the standby duration settings provided by the |
| mcm | 2:853301624d95 | 347 | * user in the data buffer so as to write in the sensor. |
| mcm | 2:853301624d95 | 348 | * |
| mcm | 2:853301624d95 | 349 | * @param[in] dev : Structure instance of bme280_dev. |
| mcm | 2:853301624d95 | 350 | * @param[out] reg_data : Variable which is filled according to the standby |
| mcm | 2:853301624d95 | 351 | * settings data provided by the user. |
| mcm | 2:853301624d95 | 352 | */ |
| mcm | 2:853301624d95 | 353 | static void fill_standby_settings(uint8_t *reg_data, const struct bme280_settings *settings); |
| mcm | 2:853301624d95 | 354 | |
| mcm | 2:853301624d95 | 355 | /*! |
| mcm | 2:853301624d95 | 356 | * @brief This internal API parse the oversampling(pressure, temperature |
| mcm | 2:853301624d95 | 357 | * and humidity), filter and standby duration settings and store in the |
| mcm | 2:853301624d95 | 358 | * device structure. |
| mcm | 2:853301624d95 | 359 | * |
| mcm | 2:853301624d95 | 360 | * @param[out] dev : Structure instance of bme280_dev. |
| mcm | 2:853301624d95 | 361 | * @param[in] reg_data : Register data to be parsed. |
| mcm | 2:853301624d95 | 362 | */ |
| mcm | 2:853301624d95 | 363 | static void parse_device_settings(const uint8_t *reg_data, struct bme280_settings *settings); |
| mcm | 2:853301624d95 | 364 | |
| mcm | 2:853301624d95 | 365 | /*! |
| mcm | 2:853301624d95 | 366 | * @brief This internal API reloads the already existing device settings in the |
| mcm | 2:853301624d95 | 367 | * sensor after soft reset. |
| mcm | 2:853301624d95 | 368 | * |
| mcm | 2:853301624d95 | 369 | * @param[in] dev : Structure instance of bme280_dev. |
| mcm | 2:853301624d95 | 370 | * @param[in] settings : Pointer variable which contains the settings to |
| mcm | 2:853301624d95 | 371 | * be set in the sensor. |
| mcm | 2:853301624d95 | 372 | * |
| mcm | 2:853301624d95 | 373 | * @return Result of API execution status |
| mcm | 2:853301624d95 | 374 | * @retval zero -> Success / +ve value -> Warning / -ve value -> Error |
| mcm | 2:853301624d95 | 375 | */ |
| mcm | 2:853301624d95 | 376 | static int8_t reload_device_settings(const struct bme280_settings *settings, const struct bme280_dev *dev); |
| mcm | 2:853301624d95 | 377 | |
| mcm | 2:853301624d95 | 378 | /****************** Global Function Definitions *******************************/ |
| mcm | 2:853301624d95 | 379 | |
| mcm | 2:853301624d95 | 380 | /*! |
| mcm | 2:853301624d95 | 381 | * @brief This API is the entry point. |
| mcm | 2:853301624d95 | 382 | * It reads the chip-id and calibration data from the sensor. |
| mcm | 2:853301624d95 | 383 | */ |
| mcm | 2:853301624d95 | 384 | int8_t BME280::bme280_init(struct bme280_dev *dev) |
| mcm | 2:853301624d95 | 385 | { |
| mcm | 2:853301624d95 | 386 | int8_t rslt; |
| mcm | 2:853301624d95 | 387 | |
| mcm | 2:853301624d95 | 388 | /* chip id read try count */ |
| mcm | 2:853301624d95 | 389 | uint8_t try_count = 5; |
| mcm | 2:853301624d95 | 390 | uint8_t chip_id = 0; |
| mcm | 2:853301624d95 | 391 | |
| mcm | 2:853301624d95 | 392 | /* Check for null pointer in the device structure*/ |
| mcm | 2:853301624d95 | 393 | rslt = null_ptr_check(dev); |
| mcm | 2:853301624d95 | 394 | |
| mcm | 2:853301624d95 | 395 | /* Proceed if null check is fine */ |
| mcm | 2:853301624d95 | 396 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 397 | while (try_count) { |
| mcm | 2:853301624d95 | 398 | /* Read the chip-id of bme280 sensor */ |
| mcm | 2:853301624d95 | 399 | rslt = bme280_get_regs(BME280_CHIP_ID_ADDR, &chip_id, 1, dev); |
| mcm | 2:853301624d95 | 400 | |
| mcm | 2:853301624d95 | 401 | /* Check for chip id validity */ |
| mcm | 2:853301624d95 | 402 | if ((rslt == BME280_OK) && (chip_id == BME280_CHIP_ID)) { |
| mcm | 2:853301624d95 | 403 | dev->chip_id = chip_id; |
| mcm | 2:853301624d95 | 404 | |
| mcm | 2:853301624d95 | 405 | /* Reset the sensor */ |
| mcm | 2:853301624d95 | 406 | rslt = bme280_soft_reset(dev); |
| mcm | 2:853301624d95 | 407 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 408 | /* Read the calibration data */ |
| mcm | 2:853301624d95 | 409 | rslt = get_calib_data(dev); |
| mcm | 2:853301624d95 | 410 | } |
| mcm | 2:853301624d95 | 411 | break; |
| mcm | 2:853301624d95 | 412 | } |
| mcm | 2:853301624d95 | 413 | |
| mcm | 2:853301624d95 | 414 | /* Wait for 1 ms */ |
| mcm | 2:853301624d95 | 415 | dev->delay_ms(1); |
| mcm | 2:853301624d95 | 416 | --try_count; |
| mcm | 2:853301624d95 | 417 | } |
| mcm | 2:853301624d95 | 418 | |
| mcm | 2:853301624d95 | 419 | /* Chip id check failed */ |
| mcm | 2:853301624d95 | 420 | if (!try_count) { |
| mcm | 2:853301624d95 | 421 | rslt = BME280_E_DEV_NOT_FOUND; |
| mcm | 2:853301624d95 | 422 | } |
| mcm | 2:853301624d95 | 423 | } |
| mcm | 2:853301624d95 | 424 | |
| mcm | 2:853301624d95 | 425 | return rslt; |
| mcm | 2:853301624d95 | 426 | } |
| mcm | 2:853301624d95 | 427 | |
| mcm | 2:853301624d95 | 428 | /*! |
| mcm | 2:853301624d95 | 429 | * @brief This API reads the data from the given register address of the sensor. |
| mcm | 2:853301624d95 | 430 | */ |
| mcm | 2:853301624d95 | 431 | int8_t BME280::bme280_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint16_t len, const struct bme280_dev *dev) |
| mcm | 2:853301624d95 | 432 | { |
| mcm | 2:853301624d95 | 433 | int8_t rslt; |
| mcm | 2:853301624d95 | 434 | |
| mcm | 2:853301624d95 | 435 | /* Check for null pointer in the device structure*/ |
| mcm | 2:853301624d95 | 436 | rslt = null_ptr_check(dev); |
| mcm | 2:853301624d95 | 437 | |
| mcm | 2:853301624d95 | 438 | /* Proceed if null check is fine */ |
| mcm | 2:853301624d95 | 439 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 440 | /* If interface selected is SPI */ |
| mcm | 2:853301624d95 | 441 | if (dev->intf != BME280_I2C_INTF) { |
| mcm | 2:853301624d95 | 442 | reg_addr = reg_addr | 0x80; |
| mcm | 2:853301624d95 | 443 | } |
| mcm | 2:853301624d95 | 444 | |
| mcm | 2:853301624d95 | 445 | /* Read the data */ |
| mcm | 2:853301624d95 | 446 | rslt = dev->read(dev->dev_id, reg_addr, reg_data, len); |
| mcm | 2:853301624d95 | 447 | |
| mcm | 2:853301624d95 | 448 | /* Check for communication error */ |
| mcm | 2:853301624d95 | 449 | if (rslt != BME280_OK) { |
| mcm | 2:853301624d95 | 450 | rslt = BME280_E_COMM_FAIL; |
| mcm | 2:853301624d95 | 451 | } |
| mcm | 2:853301624d95 | 452 | } |
| mcm | 2:853301624d95 | 453 | |
| mcm | 2:853301624d95 | 454 | return rslt; |
| mcm | 2:853301624d95 | 455 | } |
| mcm | 2:853301624d95 | 456 | |
| mcm | 2:853301624d95 | 457 | /*! |
| mcm | 2:853301624d95 | 458 | * @brief This API writes the given data to the register address |
| mcm | 2:853301624d95 | 459 | * of the sensor. |
| mcm | 2:853301624d95 | 460 | */ |
| mcm | 2:853301624d95 | 461 | int8_t BME280::bme280_set_regs(uint8_t *reg_addr, const uint8_t *reg_data, uint8_t len, const struct bme280_dev *dev) |
| mcm | 2:853301624d95 | 462 | { |
| mcm | 2:853301624d95 | 463 | int8_t rslt; |
| mcm | 2:853301624d95 | 464 | uint8_t temp_buff[20]; /* Typically not to write more than 10 registers */ |
| mcm | 2:853301624d95 | 465 | |
| mcm | 2:853301624d95 | 466 | if (len > 10) { |
| mcm | 2:853301624d95 | 467 | len = 10; |
| mcm | 2:853301624d95 | 468 | } |
| mcm | 2:853301624d95 | 469 | uint16_t temp_len; |
| mcm | 2:853301624d95 | 470 | uint8_t reg_addr_cnt; |
| mcm | 2:853301624d95 | 471 | |
| mcm | 2:853301624d95 | 472 | /* Check for null pointer in the device structure*/ |
| mcm | 2:853301624d95 | 473 | rslt = null_ptr_check(dev); |
| mcm | 2:853301624d95 | 474 | |
| mcm | 2:853301624d95 | 475 | /* Check for arguments validity */ |
| mcm | 2:853301624d95 | 476 | if ((rslt == BME280_OK) && (reg_addr != NULL) && (reg_data != NULL)) { |
| mcm | 2:853301624d95 | 477 | if (len != 0) { |
| mcm | 2:853301624d95 | 478 | temp_buff[0] = reg_data[0]; |
| mcm | 2:853301624d95 | 479 | |
| mcm | 2:853301624d95 | 480 | /* If interface selected is SPI */ |
| mcm | 2:853301624d95 | 481 | if (dev->intf != BME280_I2C_INTF) { |
| mcm | 2:853301624d95 | 482 | for (reg_addr_cnt = 0; reg_addr_cnt < len; reg_addr_cnt++) { |
| mcm | 2:853301624d95 | 483 | reg_addr[reg_addr_cnt] = reg_addr[reg_addr_cnt] & 0x7F; |
| mcm | 2:853301624d95 | 484 | } |
| mcm | 2:853301624d95 | 485 | } |
| mcm | 2:853301624d95 | 486 | |
| mcm | 2:853301624d95 | 487 | /* Burst write mode */ |
| mcm | 2:853301624d95 | 488 | if (len > 1) { |
| mcm | 2:853301624d95 | 489 | /* Interleave register address w.r.t data for |
| mcm | 2:853301624d95 | 490 | * burst write |
| mcm | 2:853301624d95 | 491 | */ |
| mcm | 2:853301624d95 | 492 | interleave_reg_addr(reg_addr, temp_buff, reg_data, len); |
| mcm | 2:853301624d95 | 493 | temp_len = ((len * 2) - 1); |
| mcm | 2:853301624d95 | 494 | } else { |
| mcm | 2:853301624d95 | 495 | temp_len = len; |
| mcm | 2:853301624d95 | 496 | } |
| mcm | 2:853301624d95 | 497 | rslt = dev->write(dev->dev_id, reg_addr[0], temp_buff, temp_len); |
| mcm | 2:853301624d95 | 498 | |
| mcm | 2:853301624d95 | 499 | /* Check for communication error */ |
| mcm | 2:853301624d95 | 500 | if (rslt != BME280_OK) { |
| mcm | 2:853301624d95 | 501 | rslt = BME280_E_COMM_FAIL; |
| mcm | 2:853301624d95 | 502 | } |
| mcm | 2:853301624d95 | 503 | } else { |
| mcm | 2:853301624d95 | 504 | rslt = BME280_E_INVALID_LEN; |
| mcm | 2:853301624d95 | 505 | } |
| mcm | 2:853301624d95 | 506 | } else { |
| mcm | 2:853301624d95 | 507 | rslt = BME280_E_NULL_PTR; |
| mcm | 2:853301624d95 | 508 | } |
| mcm | 2:853301624d95 | 509 | |
| mcm | 2:853301624d95 | 510 | return rslt; |
| mcm | 2:853301624d95 | 511 | } |
| mcm | 2:853301624d95 | 512 | |
| mcm | 2:853301624d95 | 513 | /*! |
| mcm | 2:853301624d95 | 514 | * @brief This API sets the oversampling, filter and standby duration |
| mcm | 2:853301624d95 | 515 | * (normal mode) settings in the sensor. |
| mcm | 2:853301624d95 | 516 | */ |
| mcm | 2:853301624d95 | 517 | int8_t BME280::bme280_set_sensor_settings(uint8_t desired_settings, const struct bme280_dev *dev) |
| mcm | 2:853301624d95 | 518 | { |
| mcm | 2:853301624d95 | 519 | int8_t rslt; |
| mcm | 2:853301624d95 | 520 | uint8_t sensor_mode; |
| mcm | 2:853301624d95 | 521 | |
| mcm | 2:853301624d95 | 522 | /* Check for null pointer in the device structure*/ |
| mcm | 2:853301624d95 | 523 | rslt = null_ptr_check(dev); |
| mcm | 2:853301624d95 | 524 | |
| mcm | 2:853301624d95 | 525 | /* Proceed if null check is fine */ |
| mcm | 2:853301624d95 | 526 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 527 | rslt = bme280_get_sensor_mode(&sensor_mode, dev); |
| mcm | 2:853301624d95 | 528 | if ((rslt == BME280_OK) && (sensor_mode != BME280_SLEEP_MODE)) { |
| mcm | 2:853301624d95 | 529 | rslt = put_device_to_sleep(dev); |
| mcm | 2:853301624d95 | 530 | } |
| mcm | 2:853301624d95 | 531 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 532 | /* Check if user wants to change oversampling |
| mcm | 2:853301624d95 | 533 | * settings |
| mcm | 2:853301624d95 | 534 | */ |
| mcm | 2:853301624d95 | 535 | if (are_settings_changed(OVERSAMPLING_SETTINGS, desired_settings)) { |
| mcm | 2:853301624d95 | 536 | rslt = set_osr_settings(desired_settings, &dev->settings, dev); |
| mcm | 2:853301624d95 | 537 | } |
| mcm | 2:853301624d95 | 538 | |
| mcm | 2:853301624d95 | 539 | /* Check if user wants to change filter and/or |
| mcm | 2:853301624d95 | 540 | * standby settings |
| mcm | 2:853301624d95 | 541 | */ |
| mcm | 2:853301624d95 | 542 | if ((rslt == BME280_OK) && are_settings_changed(FILTER_STANDBY_SETTINGS, desired_settings)) { |
| mcm | 2:853301624d95 | 543 | rslt = set_filter_standby_settings(desired_settings, &dev->settings, dev); |
| mcm | 2:853301624d95 | 544 | } |
| mcm | 2:853301624d95 | 545 | } |
| mcm | 2:853301624d95 | 546 | } |
| mcm | 2:853301624d95 | 547 | |
| mcm | 2:853301624d95 | 548 | return rslt; |
| mcm | 2:853301624d95 | 549 | } |
| mcm | 2:853301624d95 | 550 | |
| mcm | 2:853301624d95 | 551 | /*! |
| mcm | 2:853301624d95 | 552 | * @brief This API gets the oversampling, filter and standby duration |
| mcm | 2:853301624d95 | 553 | * (normal mode) settings from the sensor. |
| mcm | 2:853301624d95 | 554 | */ |
| mcm | 2:853301624d95 | 555 | int8_t BME280::bme280_get_sensor_settings(struct bme280_dev *dev) |
| mcm | 2:853301624d95 | 556 | { |
| mcm | 2:853301624d95 | 557 | int8_t rslt; |
| mcm | 2:853301624d95 | 558 | uint8_t reg_data[4]; |
| mcm | 2:853301624d95 | 559 | |
| mcm | 2:853301624d95 | 560 | /* Check for null pointer in the device structure*/ |
| mcm | 2:853301624d95 | 561 | rslt = null_ptr_check(dev); |
| mcm | 2:853301624d95 | 562 | |
| mcm | 2:853301624d95 | 563 | /* Proceed if null check is fine */ |
| mcm | 2:853301624d95 | 564 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 565 | rslt = bme280_get_regs(BME280_CTRL_HUM_ADDR, reg_data, 4, dev); |
| mcm | 2:853301624d95 | 566 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 567 | parse_device_settings(reg_data, &dev->settings); |
| mcm | 2:853301624d95 | 568 | } |
| mcm | 2:853301624d95 | 569 | } |
| mcm | 2:853301624d95 | 570 | |
| mcm | 2:853301624d95 | 571 | return rslt; |
| mcm | 2:853301624d95 | 572 | } |
| mcm | 2:853301624d95 | 573 | |
| mcm | 2:853301624d95 | 574 | /*! |
| mcm | 2:853301624d95 | 575 | * @brief This API sets the power mode of the sensor. |
| mcm | 2:853301624d95 | 576 | */ |
| mcm | 2:853301624d95 | 577 | int8_t BME280::bme280_set_sensor_mode(uint8_t sensor_mode, const struct bme280_dev *dev) |
| mcm | 2:853301624d95 | 578 | { |
| mcm | 2:853301624d95 | 579 | int8_t rslt; |
| mcm | 2:853301624d95 | 580 | uint8_t last_set_mode; |
| mcm | 2:853301624d95 | 581 | |
| mcm | 2:853301624d95 | 582 | /* Check for null pointer in the device structure*/ |
| mcm | 2:853301624d95 | 583 | rslt = null_ptr_check(dev); |
| mcm | 2:853301624d95 | 584 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 585 | rslt = bme280_get_sensor_mode(&last_set_mode, dev); |
| mcm | 2:853301624d95 | 586 | |
| mcm | 2:853301624d95 | 587 | /* If the sensor is not in sleep mode put the device to sleep |
| mcm | 2:853301624d95 | 588 | * mode |
| mcm | 2:853301624d95 | 589 | */ |
| mcm | 2:853301624d95 | 590 | if ((rslt == BME280_OK) && (last_set_mode != BME280_SLEEP_MODE)) { |
| mcm | 2:853301624d95 | 591 | rslt = put_device_to_sleep(dev); |
| mcm | 2:853301624d95 | 592 | } |
| mcm | 2:853301624d95 | 593 | |
| mcm | 2:853301624d95 | 594 | /* Set the power mode */ |
| mcm | 2:853301624d95 | 595 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 596 | rslt = write_power_mode(sensor_mode, dev); |
| mcm | 2:853301624d95 | 597 | } |
| mcm | 2:853301624d95 | 598 | } |
| mcm | 2:853301624d95 | 599 | |
| mcm | 2:853301624d95 | 600 | return rslt; |
| mcm | 2:853301624d95 | 601 | } |
| mcm | 2:853301624d95 | 602 | |
| mcm | 2:853301624d95 | 603 | /*! |
| mcm | 2:853301624d95 | 604 | * @brief This API gets the power mode of the sensor. |
| mcm | 2:853301624d95 | 605 | */ |
| mcm | 2:853301624d95 | 606 | int8_t BME280::bme280_get_sensor_mode(uint8_t *sensor_mode, const struct bme280_dev *dev) |
| mcm | 2:853301624d95 | 607 | { |
| mcm | 2:853301624d95 | 608 | int8_t rslt; |
| mcm | 2:853301624d95 | 609 | |
| mcm | 2:853301624d95 | 610 | /* Check for null pointer in the device structure*/ |
| mcm | 2:853301624d95 | 611 | rslt = null_ptr_check(dev); |
| mcm | 2:853301624d95 | 612 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 613 | /* Read the power mode register */ |
| mcm | 2:853301624d95 | 614 | rslt = bme280_get_regs(BME280_PWR_CTRL_ADDR, sensor_mode, 1, dev); |
| mcm | 2:853301624d95 | 615 | |
| mcm | 2:853301624d95 | 616 | /* Assign the power mode in the device structure */ |
| mcm | 2:853301624d95 | 617 | *sensor_mode = BME280_GET_BITS_POS_0(*sensor_mode, BME280_SENSOR_MODE); |
| mcm | 2:853301624d95 | 618 | } |
| mcm | 2:853301624d95 | 619 | |
| mcm | 2:853301624d95 | 620 | return rslt; |
| mcm | 2:853301624d95 | 621 | } |
| mcm | 2:853301624d95 | 622 | |
| mcm | 2:853301624d95 | 623 | /*! |
| mcm | 2:853301624d95 | 624 | * @brief This API performs the soft reset of the sensor. |
| mcm | 2:853301624d95 | 625 | */ |
| mcm | 2:853301624d95 | 626 | int8_t BME280::bme280_soft_reset(const struct bme280_dev *dev) |
| mcm | 2:853301624d95 | 627 | { |
| mcm | 2:853301624d95 | 628 | int8_t rslt; |
| mcm | 2:853301624d95 | 629 | uint8_t reg_addr = BME280_RESET_ADDR; |
| mcm | 2:853301624d95 | 630 | |
| mcm | 2:853301624d95 | 631 | /* 0xB6 is the soft reset command */ |
| mcm | 2:853301624d95 | 632 | uint8_t soft_rst_cmd = 0xB6; |
| mcm | 2:853301624d95 | 633 | |
| mcm | 2:853301624d95 | 634 | /* Check for null pointer in the device structure*/ |
| mcm | 2:853301624d95 | 635 | rslt = null_ptr_check(dev); |
| mcm | 2:853301624d95 | 636 | |
| mcm | 2:853301624d95 | 637 | /* Proceed if null check is fine */ |
| mcm | 2:853301624d95 | 638 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 639 | /* Write the soft reset command in the sensor */ |
| mcm | 2:853301624d95 | 640 | rslt = bme280_set_regs(®_addr, &soft_rst_cmd, 1, dev); |
| mcm | 2:853301624d95 | 641 | |
| mcm | 2:853301624d95 | 642 | /* As per data sheet, startup time is 2 ms. */ |
| mcm | 2:853301624d95 | 643 | dev->delay_ms(2); |
| mcm | 2:853301624d95 | 644 | } |
| mcm | 2:853301624d95 | 645 | |
| mcm | 2:853301624d95 | 646 | return rslt; |
| mcm | 2:853301624d95 | 647 | } |
| mcm | 2:853301624d95 | 648 | |
| mcm | 2:853301624d95 | 649 | /*! |
| mcm | 2:853301624d95 | 650 | * @brief This API reads the pressure, temperature and humidity data from the |
| mcm | 2:853301624d95 | 651 | * sensor, compensates the data and store it in the bme280_data structure |
| mcm | 2:853301624d95 | 652 | * instance passed by the user. |
| mcm | 2:853301624d95 | 653 | */ |
| mcm | 2:853301624d95 | 654 | int8_t BME280::bme280_get_sensor_data(uint8_t sensor_comp, struct bme280_data *comp_data, struct bme280_dev *dev) |
| mcm | 2:853301624d95 | 655 | { |
| mcm | 2:853301624d95 | 656 | int8_t rslt; |
| mcm | 2:853301624d95 | 657 | |
| mcm | 2:853301624d95 | 658 | /* Array to store the pressure, temperature and humidity data read from |
| mcm | 2:853301624d95 | 659 | * the sensor |
| mcm | 2:853301624d95 | 660 | */ |
| mcm | 2:853301624d95 | 661 | uint8_t reg_data[BME280_P_T_H_DATA_LEN] = { 0 }; |
| mcm | 2:853301624d95 | 662 | struct bme280_uncomp_data uncomp_data = { 0 }; |
| mcm | 2:853301624d95 | 663 | |
| mcm | 2:853301624d95 | 664 | /* Check for null pointer in the device structure*/ |
| mcm | 2:853301624d95 | 665 | rslt = null_ptr_check(dev); |
| mcm | 2:853301624d95 | 666 | if ((rslt == BME280_OK) && (comp_data != NULL)) { |
| mcm | 2:853301624d95 | 667 | /* Read the pressure and temperature data from the sensor */ |
| mcm | 2:853301624d95 | 668 | rslt = bme280_get_regs(BME280_DATA_ADDR, reg_data, BME280_P_T_H_DATA_LEN, dev); |
| mcm | 2:853301624d95 | 669 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 670 | /* Parse the read data from the sensor */ |
| mcm | 2:853301624d95 | 671 | bme280_parse_sensor_data(reg_data, &uncomp_data); |
| mcm | 2:853301624d95 | 672 | |
| mcm | 2:853301624d95 | 673 | /* Compensate the pressure and/or temperature and/or |
| mcm | 2:853301624d95 | 674 | * humidity data from the sensor |
| mcm | 2:853301624d95 | 675 | */ |
| mcm | 2:853301624d95 | 676 | rslt = bme280_compensate_data(sensor_comp, &uncomp_data, comp_data, &dev->calib_data); |
| mcm | 2:853301624d95 | 677 | } |
| mcm | 2:853301624d95 | 678 | } else { |
| mcm | 2:853301624d95 | 679 | rslt = BME280_E_NULL_PTR; |
| mcm | 2:853301624d95 | 680 | } |
| mcm | 2:853301624d95 | 681 | |
| mcm | 2:853301624d95 | 682 | return rslt; |
| mcm | 2:853301624d95 | 683 | } |
| mcm | 2:853301624d95 | 684 | |
| mcm | 2:853301624d95 | 685 | /*! |
| mcm | 2:853301624d95 | 686 | * @brief This API is used to parse the pressure, temperature and |
| mcm | 2:853301624d95 | 687 | * humidity data and store it in the bme280_uncomp_data structure instance. |
| mcm | 2:853301624d95 | 688 | */ |
| mcm | 2:853301624d95 | 689 | void BME280::bme280_parse_sensor_data(const uint8_t *reg_data, struct bme280_uncomp_data *uncomp_data) |
| mcm | 2:853301624d95 | 690 | { |
| mcm | 2:853301624d95 | 691 | /* Variables to store the sensor data */ |
| mcm | 2:853301624d95 | 692 | uint32_t data_xlsb; |
| mcm | 2:853301624d95 | 693 | uint32_t data_lsb; |
| mcm | 2:853301624d95 | 694 | uint32_t data_msb; |
| mcm | 2:853301624d95 | 695 | |
| mcm | 2:853301624d95 | 696 | /* Store the parsed register values for pressure data */ |
| mcm | 2:853301624d95 | 697 | data_msb = (uint32_t)reg_data[0] << 12; |
| mcm | 2:853301624d95 | 698 | data_lsb = (uint32_t)reg_data[1] << 4; |
| mcm | 2:853301624d95 | 699 | data_xlsb = (uint32_t)reg_data[2] >> 4; |
| mcm | 2:853301624d95 | 700 | uncomp_data->pressure = data_msb | data_lsb | data_xlsb; |
| mcm | 2:853301624d95 | 701 | |
| mcm | 2:853301624d95 | 702 | /* Store the parsed register values for temperature data */ |
| mcm | 2:853301624d95 | 703 | data_msb = (uint32_t)reg_data[3] << 12; |
| mcm | 2:853301624d95 | 704 | data_lsb = (uint32_t)reg_data[4] << 4; |
| mcm | 2:853301624d95 | 705 | data_xlsb = (uint32_t)reg_data[5] >> 4; |
| mcm | 2:853301624d95 | 706 | uncomp_data->temperature = data_msb | data_lsb | data_xlsb; |
| mcm | 2:853301624d95 | 707 | |
| mcm | 2:853301624d95 | 708 | /* Store the parsed register values for temperature data */ |
| mcm | 2:853301624d95 | 709 | data_lsb = (uint32_t)reg_data[6] << 8; |
| mcm | 2:853301624d95 | 710 | data_msb = (uint32_t)reg_data[7]; |
| mcm | 2:853301624d95 | 711 | uncomp_data->humidity = data_msb | data_lsb; |
| mcm | 2:853301624d95 | 712 | } |
| mcm | 2:853301624d95 | 713 | |
| mcm | 2:853301624d95 | 714 | /*! |
| mcm | 2:853301624d95 | 715 | * @brief This API is used to compensate the pressure and/or |
| mcm | 2:853301624d95 | 716 | * temperature and/or humidity data according to the component selected |
| mcm | 2:853301624d95 | 717 | * by the user. |
| mcm | 2:853301624d95 | 718 | */ |
| mcm | 2:853301624d95 | 719 | int8_t BME280::bme280_compensate_data(uint8_t sensor_comp, |
| mcm | 2:853301624d95 | 720 | const struct bme280_uncomp_data *uncomp_data, |
| mcm | 2:853301624d95 | 721 | struct bme280_data *comp_data, |
| mcm | 2:853301624d95 | 722 | struct bme280_calib_data *calib_data) |
| mcm | 2:853301624d95 | 723 | { |
| mcm | 2:853301624d95 | 724 | int8_t rslt = BME280_OK; |
| mcm | 2:853301624d95 | 725 | |
| mcm | 2:853301624d95 | 726 | if ((uncomp_data != NULL) && (comp_data != NULL) && (calib_data != NULL)) { |
| mcm | 2:853301624d95 | 727 | /* Initialize to zero */ |
| mcm | 2:853301624d95 | 728 | comp_data->temperature = 0; |
| mcm | 2:853301624d95 | 729 | comp_data->pressure = 0; |
| mcm | 2:853301624d95 | 730 | comp_data->humidity = 0; |
| mcm | 2:853301624d95 | 731 | |
| mcm | 2:853301624d95 | 732 | /* If pressure or temperature component is selected */ |
| mcm | 2:853301624d95 | 733 | if (sensor_comp & (BME280_PRESS | BME280_TEMP | BME280_HUM)) { |
| mcm | 2:853301624d95 | 734 | /* Compensate the temperature data */ |
| mcm | 2:853301624d95 | 735 | comp_data->temperature = compensate_temperature(uncomp_data, calib_data); |
| mcm | 2:853301624d95 | 736 | } |
| mcm | 2:853301624d95 | 737 | if (sensor_comp & BME280_PRESS) { |
| mcm | 2:853301624d95 | 738 | /* Compensate the pressure data */ |
| mcm | 2:853301624d95 | 739 | comp_data->pressure = compensate_pressure(uncomp_data, calib_data); |
| mcm | 2:853301624d95 | 740 | } |
| mcm | 2:853301624d95 | 741 | if (sensor_comp & BME280_HUM) { |
| mcm | 2:853301624d95 | 742 | /* Compensate the humidity data */ |
| mcm | 2:853301624d95 | 743 | comp_data->humidity = compensate_humidity(uncomp_data, calib_data); |
| mcm | 2:853301624d95 | 744 | } |
| mcm | 2:853301624d95 | 745 | } else { |
| mcm | 2:853301624d95 | 746 | rslt = BME280_E_NULL_PTR; |
| mcm | 2:853301624d95 | 747 | } |
| mcm | 2:853301624d95 | 748 | |
| mcm | 2:853301624d95 | 749 | return rslt; |
| mcm | 2:853301624d95 | 750 | } |
| mcm | 2:853301624d95 | 751 | |
| mcm | 2:853301624d95 | 752 | /*! |
| mcm | 2:853301624d95 | 753 | * @brief This internal API sets the oversampling settings for pressure, |
| mcm | 2:853301624d95 | 754 | * temperature and humidity in the sensor. |
| mcm | 2:853301624d95 | 755 | */ |
| mcm | 2:853301624d95 | 756 | static int8_t BME280::set_osr_settings(uint8_t desired_settings, |
| mcm | 2:853301624d95 | 757 | const struct bme280_settings *settings, |
| mcm | 2:853301624d95 | 758 | const struct bme280_dev *dev) |
| mcm | 2:853301624d95 | 759 | { |
| mcm | 2:853301624d95 | 760 | int8_t rslt = BME280_W_INVALID_OSR_MACRO; |
| mcm | 2:853301624d95 | 761 | |
| mcm | 2:853301624d95 | 762 | if (desired_settings & BME280_OSR_HUM_SEL) { |
| mcm | 2:853301624d95 | 763 | rslt = set_osr_humidity_settings(settings, dev); |
| mcm | 2:853301624d95 | 764 | } |
| mcm | 2:853301624d95 | 765 | if (desired_settings & (BME280_OSR_PRESS_SEL | BME280_OSR_TEMP_SEL)) { |
| mcm | 2:853301624d95 | 766 | rslt = set_osr_press_temp_settings(desired_settings, settings, dev); |
| mcm | 2:853301624d95 | 767 | } |
| mcm | 2:853301624d95 | 768 | |
| mcm | 2:853301624d95 | 769 | return rslt; |
| mcm | 2:853301624d95 | 770 | } |
| mcm | 2:853301624d95 | 771 | |
| mcm | 2:853301624d95 | 772 | /*! |
| mcm | 2:853301624d95 | 773 | * @brief This API sets the humidity oversampling settings of the sensor. |
| mcm | 2:853301624d95 | 774 | */ |
| mcm | 2:853301624d95 | 775 | static int8_t BME280::set_osr_humidity_settings(const struct bme280_settings *settings, const struct bme280_dev *dev) |
| mcm | 2:853301624d95 | 776 | { |
| mcm | 2:853301624d95 | 777 | int8_t rslt; |
| mcm | 2:853301624d95 | 778 | uint8_t ctrl_hum; |
| mcm | 2:853301624d95 | 779 | uint8_t ctrl_meas; |
| mcm | 2:853301624d95 | 780 | uint8_t reg_addr = BME280_CTRL_HUM_ADDR; |
| mcm | 2:853301624d95 | 781 | |
| mcm | 2:853301624d95 | 782 | ctrl_hum = settings->osr_h & BME280_CTRL_HUM_MSK; |
| mcm | 2:853301624d95 | 783 | |
| mcm | 2:853301624d95 | 784 | /* Write the humidity control value in the register */ |
| mcm | 2:853301624d95 | 785 | rslt = bme280_set_regs(®_addr, &ctrl_hum, 1, dev); |
| mcm | 2:853301624d95 | 786 | |
| mcm | 2:853301624d95 | 787 | /* Humidity related changes will be only effective after a |
| mcm | 2:853301624d95 | 788 | * write operation to ctrl_meas register |
| mcm | 2:853301624d95 | 789 | */ |
| mcm | 2:853301624d95 | 790 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 791 | reg_addr = BME280_CTRL_MEAS_ADDR; |
| mcm | 2:853301624d95 | 792 | rslt = bme280_get_regs(reg_addr, &ctrl_meas, 1, dev); |
| mcm | 2:853301624d95 | 793 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 794 | rslt = bme280_set_regs(®_addr, &ctrl_meas, 1, dev); |
| mcm | 2:853301624d95 | 795 | } |
| mcm | 2:853301624d95 | 796 | } |
| mcm | 2:853301624d95 | 797 | |
| mcm | 2:853301624d95 | 798 | return rslt; |
| mcm | 2:853301624d95 | 799 | } |
| mcm | 2:853301624d95 | 800 | |
| mcm | 2:853301624d95 | 801 | /*! |
| mcm | 2:853301624d95 | 802 | * @brief This API sets the pressure and/or temperature oversampling settings |
| mcm | 2:853301624d95 | 803 | * in the sensor according to the settings selected by the user. |
| mcm | 2:853301624d95 | 804 | */ |
| mcm | 2:853301624d95 | 805 | static int8_t BME280::set_osr_press_temp_settings(uint8_t desired_settings, |
| mcm | 2:853301624d95 | 806 | const struct bme280_settings *settings, |
| mcm | 2:853301624d95 | 807 | const struct bme280_dev *dev) |
| mcm | 2:853301624d95 | 808 | { |
| mcm | 2:853301624d95 | 809 | int8_t rslt; |
| mcm | 2:853301624d95 | 810 | uint8_t reg_addr = BME280_CTRL_MEAS_ADDR; |
| mcm | 2:853301624d95 | 811 | uint8_t reg_data; |
| mcm | 2:853301624d95 | 812 | |
| mcm | 2:853301624d95 | 813 | rslt = bme280_get_regs(reg_addr, ®_data, 1, dev); |
| mcm | 2:853301624d95 | 814 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 815 | if (desired_settings & BME280_OSR_PRESS_SEL) { |
| mcm | 2:853301624d95 | 816 | fill_osr_press_settings(®_data, settings); |
| mcm | 2:853301624d95 | 817 | } |
| mcm | 2:853301624d95 | 818 | if (desired_settings & BME280_OSR_TEMP_SEL) { |
| mcm | 2:853301624d95 | 819 | fill_osr_temp_settings(®_data, settings); |
| mcm | 2:853301624d95 | 820 | } |
| mcm | 2:853301624d95 | 821 | |
| mcm | 2:853301624d95 | 822 | /* Write the oversampling settings in the register */ |
| mcm | 2:853301624d95 | 823 | rslt = bme280_set_regs(®_addr, ®_data, 1, dev); |
| mcm | 2:853301624d95 | 824 | } |
| mcm | 2:853301624d95 | 825 | |
| mcm | 2:853301624d95 | 826 | return rslt; |
| mcm | 2:853301624d95 | 827 | } |
| mcm | 2:853301624d95 | 828 | |
| mcm | 2:853301624d95 | 829 | /*! |
| mcm | 2:853301624d95 | 830 | * @brief This internal API sets the filter and/or standby duration settings |
| mcm | 2:853301624d95 | 831 | * in the sensor according to the settings selected by the user. |
| mcm | 2:853301624d95 | 832 | */ |
| mcm | 2:853301624d95 | 833 | static int8_t BME280::set_filter_standby_settings(uint8_t desired_settings, |
| mcm | 2:853301624d95 | 834 | const struct bme280_settings *settings, |
| mcm | 2:853301624d95 | 835 | const struct bme280_dev *dev) |
| mcm | 2:853301624d95 | 836 | { |
| mcm | 2:853301624d95 | 837 | int8_t rslt; |
| mcm | 2:853301624d95 | 838 | uint8_t reg_addr = BME280_CONFIG_ADDR; |
| mcm | 2:853301624d95 | 839 | uint8_t reg_data; |
| mcm | 2:853301624d95 | 840 | |
| mcm | 2:853301624d95 | 841 | rslt = bme280_get_regs(reg_addr, ®_data, 1, dev); |
| mcm | 2:853301624d95 | 842 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 843 | if (desired_settings & BME280_FILTER_SEL) { |
| mcm | 2:853301624d95 | 844 | fill_filter_settings(®_data, settings); |
| mcm | 2:853301624d95 | 845 | } |
| mcm | 2:853301624d95 | 846 | if (desired_settings & BME280_STANDBY_SEL) { |
| mcm | 2:853301624d95 | 847 | fill_standby_settings(®_data, settings); |
| mcm | 2:853301624d95 | 848 | } |
| mcm | 2:853301624d95 | 849 | |
| mcm | 2:853301624d95 | 850 | /* Write the oversampling settings in the register */ |
| mcm | 2:853301624d95 | 851 | rslt = bme280_set_regs(®_addr, ®_data, 1, dev); |
| mcm | 2:853301624d95 | 852 | } |
| mcm | 2:853301624d95 | 853 | |
| mcm | 2:853301624d95 | 854 | return rslt; |
| mcm | 2:853301624d95 | 855 | } |
| mcm | 2:853301624d95 | 856 | |
| mcm | 2:853301624d95 | 857 | /*! |
| mcm | 2:853301624d95 | 858 | * @brief This internal API fills the filter settings provided by the user |
| mcm | 2:853301624d95 | 859 | * in the data buffer so as to write in the sensor. |
| mcm | 2:853301624d95 | 860 | */ |
| mcm | 2:853301624d95 | 861 | static void BME280::fill_filter_settings(uint8_t *reg_data, const struct bme280_settings *settings) |
| mcm | 2:853301624d95 | 862 | { |
| mcm | 2:853301624d95 | 863 | *reg_data = BME280_SET_BITS(*reg_data, BME280_FILTER, settings->filter); |
| mcm | 2:853301624d95 | 864 | } |
| mcm | 2:853301624d95 | 865 | |
| mcm | 2:853301624d95 | 866 | /*! |
| mcm | 2:853301624d95 | 867 | * @brief This internal API fills the standby duration settings provided by |
| mcm | 2:853301624d95 | 868 | * the user in the data buffer so as to write in the sensor. |
| mcm | 2:853301624d95 | 869 | */ |
| mcm | 2:853301624d95 | 870 | static void BME280::fill_standby_settings(uint8_t *reg_data, const struct bme280_settings *settings) |
| mcm | 2:853301624d95 | 871 | { |
| mcm | 2:853301624d95 | 872 | *reg_data = BME280_SET_BITS(*reg_data, BME280_STANDBY, settings->standby_time); |
| mcm | 2:853301624d95 | 873 | } |
| mcm | 2:853301624d95 | 874 | |
| mcm | 2:853301624d95 | 875 | /*! |
| mcm | 2:853301624d95 | 876 | * @brief This internal API fills the pressure oversampling settings provided by |
| mcm | 2:853301624d95 | 877 | * the user in the data buffer so as to write in the sensor. |
| mcm | 2:853301624d95 | 878 | */ |
| mcm | 2:853301624d95 | 879 | static void BME280::fill_osr_press_settings(uint8_t *reg_data, const struct bme280_settings *settings) |
| mcm | 2:853301624d95 | 880 | { |
| mcm | 2:853301624d95 | 881 | *reg_data = BME280_SET_BITS(*reg_data, BME280_CTRL_PRESS, settings->osr_p); |
| mcm | 2:853301624d95 | 882 | } |
| mcm | 2:853301624d95 | 883 | |
| mcm | 2:853301624d95 | 884 | /*! |
| mcm | 2:853301624d95 | 885 | * @brief This internal API fills the temperature oversampling settings |
| mcm | 2:853301624d95 | 886 | * provided by the user in the data buffer so as to write in the sensor. |
| mcm | 2:853301624d95 | 887 | */ |
| mcm | 2:853301624d95 | 888 | static void BME280::fill_osr_temp_settings(uint8_t *reg_data, const struct bme280_settings *settings) |
| mcm | 2:853301624d95 | 889 | { |
| mcm | 2:853301624d95 | 890 | *reg_data = BME280_SET_BITS(*reg_data, BME280_CTRL_TEMP, settings->osr_t); |
| mcm | 2:853301624d95 | 891 | } |
| mcm | 2:853301624d95 | 892 | |
| mcm | 2:853301624d95 | 893 | /*! |
| mcm | 2:853301624d95 | 894 | * @brief This internal API parse the oversampling(pressure, temperature |
| mcm | 2:853301624d95 | 895 | * and humidity), filter and standby duration settings and store in the |
| mcm | 2:853301624d95 | 896 | * device structure. |
| mcm | 2:853301624d95 | 897 | */ |
| mcm | 2:853301624d95 | 898 | static void BME280::parse_device_settings(const uint8_t *reg_data, struct bme280_settings *settings) |
| mcm | 2:853301624d95 | 899 | { |
| mcm | 2:853301624d95 | 900 | settings->osr_h = BME280_GET_BITS_POS_0(reg_data[0], BME280_CTRL_HUM); |
| mcm | 2:853301624d95 | 901 | settings->osr_p = BME280_GET_BITS(reg_data[2], BME280_CTRL_PRESS); |
| mcm | 2:853301624d95 | 902 | settings->osr_t = BME280_GET_BITS(reg_data[2], BME280_CTRL_TEMP); |
| mcm | 2:853301624d95 | 903 | settings->filter = BME280_GET_BITS(reg_data[3], BME280_FILTER); |
| mcm | 2:853301624d95 | 904 | settings->standby_time = BME280_GET_BITS(reg_data[3], BME280_STANDBY); |
| mcm | 2:853301624d95 | 905 | } |
| mcm | 2:853301624d95 | 906 | |
| mcm | 2:853301624d95 | 907 | /*! |
| mcm | 2:853301624d95 | 908 | * @brief This internal API writes the power mode in the sensor. |
| mcm | 2:853301624d95 | 909 | */ |
| mcm | 2:853301624d95 | 910 | static int8_t BME280::write_power_mode(uint8_t sensor_mode, const struct bme280_dev *dev) |
| mcm | 2:853301624d95 | 911 | { |
| mcm | 2:853301624d95 | 912 | int8_t rslt; |
| mcm | 2:853301624d95 | 913 | uint8_t reg_addr = BME280_PWR_CTRL_ADDR; |
| mcm | 2:853301624d95 | 914 | |
| mcm | 2:853301624d95 | 915 | /* Variable to store the value read from power mode register */ |
| mcm | 2:853301624d95 | 916 | uint8_t sensor_mode_reg_val; |
| mcm | 2:853301624d95 | 917 | |
| mcm | 2:853301624d95 | 918 | /* Read the power mode register */ |
| mcm | 2:853301624d95 | 919 | rslt = bme280_get_regs(reg_addr, &sensor_mode_reg_val, 1, dev); |
| mcm | 2:853301624d95 | 920 | |
| mcm | 2:853301624d95 | 921 | /* Set the power mode */ |
| mcm | 2:853301624d95 | 922 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 923 | sensor_mode_reg_val = BME280_SET_BITS_POS_0(sensor_mode_reg_val, BME280_SENSOR_MODE, sensor_mode); |
| mcm | 2:853301624d95 | 924 | |
| mcm | 2:853301624d95 | 925 | /* Write the power mode in the register */ |
| mcm | 2:853301624d95 | 926 | rslt = bme280_set_regs(®_addr, &sensor_mode_reg_val, 1, dev); |
| mcm | 2:853301624d95 | 927 | } |
| mcm | 2:853301624d95 | 928 | |
| mcm | 2:853301624d95 | 929 | return rslt; |
| mcm | 2:853301624d95 | 930 | } |
| mcm | 2:853301624d95 | 931 | |
| mcm | 2:853301624d95 | 932 | /*! |
| mcm | 2:853301624d95 | 933 | * @brief This internal API puts the device to sleep mode. |
| mcm | 2:853301624d95 | 934 | */ |
| mcm | 2:853301624d95 | 935 | static int8_t BME280::put_device_to_sleep(const struct bme280_dev *dev) |
| mcm | 2:853301624d95 | 936 | { |
| mcm | 2:853301624d95 | 937 | int8_t rslt; |
| mcm | 2:853301624d95 | 938 | uint8_t reg_data[4]; |
| mcm | 2:853301624d95 | 939 | struct bme280_settings settings; |
| mcm | 2:853301624d95 | 940 | |
| mcm | 2:853301624d95 | 941 | rslt = bme280_get_regs(BME280_CTRL_HUM_ADDR, reg_data, 4, dev); |
| mcm | 2:853301624d95 | 942 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 943 | parse_device_settings(reg_data, &settings); |
| mcm | 2:853301624d95 | 944 | rslt = bme280_soft_reset(dev); |
| mcm | 2:853301624d95 | 945 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 946 | rslt = reload_device_settings(&settings, dev); |
| mcm | 2:853301624d95 | 947 | } |
| mcm | 2:853301624d95 | 948 | } |
| mcm | 2:853301624d95 | 949 | |
| mcm | 2:853301624d95 | 950 | return rslt; |
| mcm | 2:853301624d95 | 951 | } |
| mcm | 2:853301624d95 | 952 | |
| mcm | 2:853301624d95 | 953 | /*! |
| mcm | 2:853301624d95 | 954 | * @brief This internal API reloads the already existing device settings in |
| mcm | 2:853301624d95 | 955 | * the sensor after soft reset. |
| mcm | 2:853301624d95 | 956 | */ |
| mcm | 2:853301624d95 | 957 | static int8_t BME280::reload_device_settings(const struct bme280_settings *settings, const struct bme280_dev *dev) |
| mcm | 2:853301624d95 | 958 | { |
| mcm | 2:853301624d95 | 959 | int8_t rslt; |
| mcm | 2:853301624d95 | 960 | |
| mcm | 2:853301624d95 | 961 | rslt = set_osr_settings(BME280_ALL_SETTINGS_SEL, settings, dev); |
| mcm | 2:853301624d95 | 962 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 963 | rslt = set_filter_standby_settings(BME280_ALL_SETTINGS_SEL, settings, dev); |
| mcm | 2:853301624d95 | 964 | } |
| mcm | 2:853301624d95 | 965 | |
| mcm | 2:853301624d95 | 966 | return rslt; |
| mcm | 2:853301624d95 | 967 | } |
| mcm | 2:853301624d95 | 968 | |
| mcm | 2:853301624d95 | 969 | #ifdef BME280_FLOAT_ENABLE |
| mcm | 2:853301624d95 | 970 | |
| mcm | 2:853301624d95 | 971 | /*! |
| mcm | 2:853301624d95 | 972 | * @brief This internal API is used to compensate the raw temperature data and |
| mcm | 2:853301624d95 | 973 | * return the compensated temperature data in double data type. |
| mcm | 2:853301624d95 | 974 | */ |
| mcm | 2:853301624d95 | 975 | static double BME280::compensate_temperature(const struct bme280_uncomp_data *uncomp_data, struct bme280_calib_data *calib_data) |
| mcm | 2:853301624d95 | 976 | { |
| mcm | 2:853301624d95 | 977 | double var1; |
| mcm | 2:853301624d95 | 978 | double var2; |
| mcm | 2:853301624d95 | 979 | double temperature; |
| mcm | 2:853301624d95 | 980 | double temperature_min = -40; |
| mcm | 2:853301624d95 | 981 | double temperature_max = 85; |
| mcm | 2:853301624d95 | 982 | |
| mcm | 2:853301624d95 | 983 | var1 = ((double)uncomp_data->temperature) / 16384.0 - ((double)calib_data->dig_T1) / 1024.0; |
| mcm | 2:853301624d95 | 984 | var1 = var1 * ((double)calib_data->dig_T2); |
| mcm | 2:853301624d95 | 985 | var2 = (((double)uncomp_data->temperature) / 131072.0 - ((double)calib_data->dig_T1) / 8192.0); |
| mcm | 2:853301624d95 | 986 | var2 = (var2 * var2) * ((double)calib_data->dig_T3); |
| mcm | 2:853301624d95 | 987 | calib_data->t_fine = (int32_t)(var1 + var2); |
| mcm | 2:853301624d95 | 988 | temperature = (var1 + var2) / 5120.0; |
| mcm | 2:853301624d95 | 989 | if (temperature < temperature_min) { |
| mcm | 2:853301624d95 | 990 | temperature = temperature_min; |
| mcm | 2:853301624d95 | 991 | } else if (temperature > temperature_max) { |
| mcm | 2:853301624d95 | 992 | temperature = temperature_max; |
| mcm | 2:853301624d95 | 993 | } |
| mcm | 2:853301624d95 | 994 | |
| mcm | 2:853301624d95 | 995 | return temperature; |
| mcm | 2:853301624d95 | 996 | } |
| mcm | 2:853301624d95 | 997 | |
| mcm | 2:853301624d95 | 998 | /*! |
| mcm | 2:853301624d95 | 999 | * @brief This internal API is used to compensate the raw pressure data and |
| mcm | 2:853301624d95 | 1000 | * return the compensated pressure data in double data type. |
| mcm | 2:853301624d95 | 1001 | */ |
| mcm | 2:853301624d95 | 1002 | static double BME280::compensate_pressure(const struct bme280_uncomp_data *uncomp_data, |
| mcm | 2:853301624d95 | 1003 | const struct bme280_calib_data *calib_data) |
| mcm | 2:853301624d95 | 1004 | { |
| mcm | 2:853301624d95 | 1005 | double var1; |
| mcm | 2:853301624d95 | 1006 | double var2; |
| mcm | 2:853301624d95 | 1007 | double var3; |
| mcm | 2:853301624d95 | 1008 | double pressure; |
| mcm | 2:853301624d95 | 1009 | double pressure_min = 30000.0; |
| mcm | 2:853301624d95 | 1010 | double pressure_max = 110000.0; |
| mcm | 2:853301624d95 | 1011 | |
| mcm | 2:853301624d95 | 1012 | var1 = ((double)calib_data->t_fine / 2.0) - 64000.0; |
| mcm | 2:853301624d95 | 1013 | var2 = var1 * var1 * ((double)calib_data->dig_P6) / 32768.0; |
| mcm | 2:853301624d95 | 1014 | var2 = var2 + var1 * ((double)calib_data->dig_P5) * 2.0; |
| mcm | 2:853301624d95 | 1015 | var2 = (var2 / 4.0) + (((double)calib_data->dig_P4) * 65536.0); |
| mcm | 2:853301624d95 | 1016 | var3 = ((double)calib_data->dig_P3) * var1 * var1 / 524288.0; |
| mcm | 2:853301624d95 | 1017 | var1 = (var3 + ((double)calib_data->dig_P2) * var1) / 524288.0; |
| mcm | 2:853301624d95 | 1018 | var1 = (1.0 + var1 / 32768.0) * ((double)calib_data->dig_P1); |
| mcm | 2:853301624d95 | 1019 | |
| mcm | 2:853301624d95 | 1020 | /* avoid exception caused by division by zero */ |
| mcm | 2:853301624d95 | 1021 | if (var1) { |
| mcm | 2:853301624d95 | 1022 | pressure = 1048576.0 - (double) uncomp_data->pressure; |
| mcm | 2:853301624d95 | 1023 | pressure = (pressure - (var2 / 4096.0)) * 6250.0 / var1; |
| mcm | 2:853301624d95 | 1024 | var1 = ((double)calib_data->dig_P9) * pressure * pressure / 2147483648.0; |
| mcm | 2:853301624d95 | 1025 | var2 = pressure * ((double)calib_data->dig_P8) / 32768.0; |
| mcm | 2:853301624d95 | 1026 | pressure = pressure + (var1 + var2 + ((double)calib_data->dig_P7)) / 16.0; |
| mcm | 2:853301624d95 | 1027 | if (pressure < pressure_min) { |
| mcm | 2:853301624d95 | 1028 | pressure = pressure_min; |
| mcm | 2:853301624d95 | 1029 | } else if (pressure > pressure_max) { |
| mcm | 2:853301624d95 | 1030 | pressure = pressure_max; |
| mcm | 2:853301624d95 | 1031 | } |
| mcm | 2:853301624d95 | 1032 | } else { /* Invalid case */ |
| mcm | 2:853301624d95 | 1033 | pressure = pressure_min; |
| mcm | 2:853301624d95 | 1034 | } |
| mcm | 2:853301624d95 | 1035 | |
| mcm | 2:853301624d95 | 1036 | return pressure; |
| mcm | 2:853301624d95 | 1037 | } |
| mcm | 2:853301624d95 | 1038 | |
| mcm | 2:853301624d95 | 1039 | /*! |
| mcm | 2:853301624d95 | 1040 | * @brief This internal API is used to compensate the raw humidity data and |
| mcm | 2:853301624d95 | 1041 | * return the compensated humidity data in double data type. |
| mcm | 2:853301624d95 | 1042 | */ |
| mcm | 2:853301624d95 | 1043 | static double BME280::compensate_humidity(const struct bme280_uncomp_data *uncomp_data, |
| mcm | 2:853301624d95 | 1044 | const struct bme280_calib_data *calib_data) |
| mcm | 2:853301624d95 | 1045 | { |
| mcm | 2:853301624d95 | 1046 | double humidity; |
| mcm | 2:853301624d95 | 1047 | double humidity_min = 0.0; |
| mcm | 2:853301624d95 | 1048 | double humidity_max = 100.0; |
| mcm | 2:853301624d95 | 1049 | double var1; |
| mcm | 2:853301624d95 | 1050 | double var2; |
| mcm | 2:853301624d95 | 1051 | double var3; |
| mcm | 2:853301624d95 | 1052 | double var4; |
| mcm | 2:853301624d95 | 1053 | double var5; |
| mcm | 2:853301624d95 | 1054 | double var6; |
| mcm | 2:853301624d95 | 1055 | |
| mcm | 2:853301624d95 | 1056 | var1 = ((double)calib_data->t_fine) - 76800.0; |
| mcm | 2:853301624d95 | 1057 | var2 = (((double)calib_data->dig_H4) * 64.0 + (((double)calib_data->dig_H5) / 16384.0) * var1); |
| mcm | 2:853301624d95 | 1058 | var3 = uncomp_data->humidity - var2; |
| mcm | 2:853301624d95 | 1059 | var4 = ((double)calib_data->dig_H2) / 65536.0; |
| mcm | 2:853301624d95 | 1060 | var5 = (1.0 + (((double)calib_data->dig_H3) / 67108864.0) * var1); |
| mcm | 2:853301624d95 | 1061 | var6 = 1.0 + (((double)calib_data->dig_H6) / 67108864.0) * var1 * var5; |
| mcm | 2:853301624d95 | 1062 | var6 = var3 * var4 * (var5 * var6); |
| mcm | 2:853301624d95 | 1063 | humidity = var6 * (1.0 - ((double)calib_data->dig_H1) * var6 / 524288.0); |
| mcm | 2:853301624d95 | 1064 | if (humidity > humidity_max) { |
| mcm | 2:853301624d95 | 1065 | humidity = humidity_max; |
| mcm | 2:853301624d95 | 1066 | } else if (humidity < humidity_min) { |
| mcm | 2:853301624d95 | 1067 | humidity = humidity_min; |
| mcm | 2:853301624d95 | 1068 | } |
| mcm | 2:853301624d95 | 1069 | |
| mcm | 2:853301624d95 | 1070 | return humidity; |
| mcm | 2:853301624d95 | 1071 | } |
| mcm | 2:853301624d95 | 1072 | |
| mcm | 2:853301624d95 | 1073 | #else |
| mcm | 2:853301624d95 | 1074 | |
| mcm | 2:853301624d95 | 1075 | /*! |
| mcm | 2:853301624d95 | 1076 | * @brief This internal API is used to compensate the raw temperature data and |
| mcm | 2:853301624d95 | 1077 | * return the compensated temperature data in integer data type. |
| mcm | 2:853301624d95 | 1078 | */ |
| mcm | 2:853301624d95 | 1079 | static int32_t BME280::compensate_temperature(const struct bme280_uncomp_data *uncomp_data, |
| mcm | 2:853301624d95 | 1080 | struct bme280_calib_data *calib_data) |
| mcm | 2:853301624d95 | 1081 | { |
| mcm | 2:853301624d95 | 1082 | int32_t var1; |
| mcm | 2:853301624d95 | 1083 | int32_t var2; |
| mcm | 2:853301624d95 | 1084 | int32_t temperature; |
| mcm | 2:853301624d95 | 1085 | int32_t temperature_min = -4000; |
| mcm | 2:853301624d95 | 1086 | int32_t temperature_max = 8500; |
| mcm | 2:853301624d95 | 1087 | |
| mcm | 2:853301624d95 | 1088 | var1 = (int32_t)((uncomp_data->temperature / 8) - ((int32_t)calib_data->dig_T1 * 2)); |
| mcm | 2:853301624d95 | 1089 | var1 = (var1 * ((int32_t)calib_data->dig_T2)) / 2048; |
| mcm | 2:853301624d95 | 1090 | var2 = (int32_t)((uncomp_data->temperature / 16) - ((int32_t)calib_data->dig_T1)); |
| mcm | 2:853301624d95 | 1091 | var2 = (((var2 * var2) / 4096) * ((int32_t)calib_data->dig_T3)) / 16384; |
| mcm | 2:853301624d95 | 1092 | calib_data->t_fine = var1 + var2; |
| mcm | 2:853301624d95 | 1093 | temperature = (calib_data->t_fine * 5 + 128) / 256; |
| mcm | 2:853301624d95 | 1094 | if (temperature < temperature_min) { |
| mcm | 2:853301624d95 | 1095 | temperature = temperature_min; |
| mcm | 2:853301624d95 | 1096 | } else if (temperature > temperature_max) { |
| mcm | 2:853301624d95 | 1097 | temperature = temperature_max; |
| mcm | 2:853301624d95 | 1098 | } |
| mcm | 2:853301624d95 | 1099 | |
| mcm | 2:853301624d95 | 1100 | return temperature; |
| mcm | 2:853301624d95 | 1101 | } |
| mcm | 2:853301624d95 | 1102 | #ifdef BME280_64BIT_ENABLE |
| mcm | 2:853301624d95 | 1103 | |
| mcm | 2:853301624d95 | 1104 | /*! |
| mcm | 2:853301624d95 | 1105 | * @brief This internal API is used to compensate the raw pressure data and |
| mcm | 2:853301624d95 | 1106 | * return the compensated pressure data in integer data type with higher |
| mcm | 2:853301624d95 | 1107 | * accuracy. |
| mcm | 2:853301624d95 | 1108 | */ |
| mcm | 2:853301624d95 | 1109 | static uint32_t BME280::compensate_pressure(const struct bme280_uncomp_data *uncomp_data, |
| mcm | 2:853301624d95 | 1110 | const struct bme280_calib_data *calib_data) |
| mcm | 2:853301624d95 | 1111 | { |
| mcm | 2:853301624d95 | 1112 | int64_t var1; |
| mcm | 2:853301624d95 | 1113 | int64_t var2; |
| mcm | 2:853301624d95 | 1114 | int64_t var3; |
| mcm | 2:853301624d95 | 1115 | int64_t var4; |
| mcm | 2:853301624d95 | 1116 | uint32_t pressure; |
| mcm | 2:853301624d95 | 1117 | uint32_t pressure_min = 3000000; |
| mcm | 2:853301624d95 | 1118 | uint32_t pressure_max = 11000000; |
| mcm | 2:853301624d95 | 1119 | |
| mcm | 2:853301624d95 | 1120 | var1 = ((int64_t)calib_data->t_fine) - 128000; |
| mcm | 2:853301624d95 | 1121 | var2 = var1 * var1 * (int64_t)calib_data->dig_P6; |
| mcm | 2:853301624d95 | 1122 | var2 = var2 + ((var1 * (int64_t)calib_data->dig_P5) * 131072); |
| mcm | 2:853301624d95 | 1123 | var2 = var2 + (((int64_t)calib_data->dig_P4) * 34359738368); |
| mcm | 2:853301624d95 | 1124 | var1 = ((var1 * var1 * (int64_t)calib_data->dig_P3) / 256) + ((var1 * ((int64_t)calib_data->dig_P2) * 4096)); |
| mcm | 2:853301624d95 | 1125 | var3 = ((int64_t)1) * 140737488355328; |
| mcm | 2:853301624d95 | 1126 | var1 = (var3 + var1) * ((int64_t)calib_data->dig_P1) / 8589934592; |
| mcm | 2:853301624d95 | 1127 | |
| mcm | 2:853301624d95 | 1128 | /* To avoid divide by zero exception */ |
| mcm | 2:853301624d95 | 1129 | if (var1 != 0) { |
| mcm | 2:853301624d95 | 1130 | var4 = 1048576 - uncomp_data->pressure; |
| mcm | 2:853301624d95 | 1131 | var4 = (((var4 * INT64_C(2147483648)) - var2) * 3125) / var1; |
| mcm | 2:853301624d95 | 1132 | var1 = (((int64_t)calib_data->dig_P9) * (var4 / 8192) * (var4 / 8192)) / 33554432; |
| mcm | 2:853301624d95 | 1133 | var2 = (((int64_t)calib_data->dig_P8) * var4) / 524288; |
| mcm | 2:853301624d95 | 1134 | var4 = ((var4 + var1 + var2) / 256) + (((int64_t)calib_data->dig_P7) * 16); |
| mcm | 2:853301624d95 | 1135 | pressure = (uint32_t)(((var4 / 2) * 100) / 128); |
| mcm | 2:853301624d95 | 1136 | if (pressure < pressure_min) { |
| mcm | 2:853301624d95 | 1137 | pressure = pressure_min; |
| mcm | 2:853301624d95 | 1138 | } else if (pressure > pressure_max) { |
| mcm | 2:853301624d95 | 1139 | pressure = pressure_max; |
| mcm | 2:853301624d95 | 1140 | } |
| mcm | 2:853301624d95 | 1141 | } else { |
| mcm | 2:853301624d95 | 1142 | pressure = pressure_min; |
| mcm | 2:853301624d95 | 1143 | } |
| mcm | 2:853301624d95 | 1144 | |
| mcm | 2:853301624d95 | 1145 | return pressure; |
| mcm | 2:853301624d95 | 1146 | } |
| mcm | 2:853301624d95 | 1147 | #else |
| mcm | 2:853301624d95 | 1148 | |
| mcm | 2:853301624d95 | 1149 | /*! |
| mcm | 2:853301624d95 | 1150 | * @brief This internal API is used to compensate the raw pressure data and |
| mcm | 2:853301624d95 | 1151 | * return the compensated pressure data in integer data type. |
| mcm | 2:853301624d95 | 1152 | */ |
| mcm | 2:853301624d95 | 1153 | static uint32_t BME280::compensate_pressure(const struct bme280_uncomp_data *uncomp_data, |
| mcm | 2:853301624d95 | 1154 | const struct bme280_calib_data *calib_data) |
| mcm | 2:853301624d95 | 1155 | { |
| mcm | 2:853301624d95 | 1156 | int32_t var1; |
| mcm | 2:853301624d95 | 1157 | int32_t var2; |
| mcm | 2:853301624d95 | 1158 | int32_t var3; |
| mcm | 2:853301624d95 | 1159 | int32_t var4; |
| mcm | 2:853301624d95 | 1160 | uint32_t var5; |
| mcm | 2:853301624d95 | 1161 | uint32_t pressure; |
| mcm | 2:853301624d95 | 1162 | uint32_t pressure_min = 30000; |
| mcm | 2:853301624d95 | 1163 | uint32_t pressure_max = 110000; |
| mcm | 2:853301624d95 | 1164 | |
| mcm | 2:853301624d95 | 1165 | var1 = (((int32_t)calib_data->t_fine) / 2) - (int32_t)64000; |
| mcm | 2:853301624d95 | 1166 | var2 = (((var1 / 4) * (var1 / 4)) / 2048) * ((int32_t)calib_data->dig_P6); |
| mcm | 2:853301624d95 | 1167 | var2 = var2 + ((var1 * ((int32_t)calib_data->dig_P5)) * 2); |
| mcm | 2:853301624d95 | 1168 | var2 = (var2 / 4) + (((int32_t)calib_data->dig_P4) * 65536); |
| mcm | 2:853301624d95 | 1169 | var3 = (calib_data->dig_P3 * (((var1 / 4) * (var1 / 4)) / 8192)) / 8; |
| mcm | 2:853301624d95 | 1170 | var4 = (((int32_t)calib_data->dig_P2) * var1) / 2; |
| mcm | 2:853301624d95 | 1171 | var1 = (var3 + var4) / 262144; |
| mcm | 2:853301624d95 | 1172 | var1 = (((32768 + var1)) * ((int32_t)calib_data->dig_P1)) / 32768; |
| mcm | 2:853301624d95 | 1173 | |
| mcm | 2:853301624d95 | 1174 | /* avoid exception caused by division by zero */ |
| mcm | 2:853301624d95 | 1175 | if (var1) { |
| mcm | 2:853301624d95 | 1176 | var5 = (uint32_t)((uint32_t)1048576) - uncomp_data->pressure; |
| mcm | 2:853301624d95 | 1177 | pressure = ((uint32_t)(var5 - (uint32_t)(var2 / 4096))) * 3125; |
| mcm | 2:853301624d95 | 1178 | if (pressure < 0x80000000) { |
| mcm | 2:853301624d95 | 1179 | pressure = (pressure << 1) / ((uint32_t)var1); |
| mcm | 2:853301624d95 | 1180 | } else { |
| mcm | 2:853301624d95 | 1181 | pressure = (pressure / (uint32_t)var1) * 2; |
| mcm | 2:853301624d95 | 1182 | } |
| mcm | 2:853301624d95 | 1183 | var1 = (((int32_t)calib_data->dig_P9) * ((int32_t)(((pressure / 8) * (pressure / 8)) / 8192))) / 4096; |
| mcm | 2:853301624d95 | 1184 | var2 = (((int32_t)(pressure / 4)) * ((int32_t)calib_data->dig_P8)) / 8192; |
| mcm | 2:853301624d95 | 1185 | pressure = (uint32_t)((int32_t)pressure + ((var1 + var2 + calib_data->dig_P7) / 16)); |
| mcm | 2:853301624d95 | 1186 | if (pressure < pressure_min) { |
| mcm | 2:853301624d95 | 1187 | pressure = pressure_min; |
| mcm | 2:853301624d95 | 1188 | } else if (pressure > pressure_max) { |
| mcm | 2:853301624d95 | 1189 | pressure = pressure_max; |
| mcm | 2:853301624d95 | 1190 | } |
| mcm | 2:853301624d95 | 1191 | } else { |
| mcm | 2:853301624d95 | 1192 | pressure = pressure_min; |
| mcm | 2:853301624d95 | 1193 | } |
| mcm | 2:853301624d95 | 1194 | |
| mcm | 2:853301624d95 | 1195 | return pressure; |
| mcm | 2:853301624d95 | 1196 | } |
| mcm | 2:853301624d95 | 1197 | #endif |
| mcm | 2:853301624d95 | 1198 | |
| mcm | 2:853301624d95 | 1199 | /*! |
| mcm | 2:853301624d95 | 1200 | * @brief This internal API is used to compensate the raw humidity data and |
| mcm | 2:853301624d95 | 1201 | * return the compensated humidity data in integer data type. |
| mcm | 2:853301624d95 | 1202 | */ |
| mcm | 2:853301624d95 | 1203 | static uint32_t BME280::compensate_humidity(const struct bme280_uncomp_data *uncomp_data, |
| mcm | 2:853301624d95 | 1204 | const struct bme280_calib_data *calib_data) |
| mcm | 2:853301624d95 | 1205 | { |
| mcm | 2:853301624d95 | 1206 | int32_t var1; |
| mcm | 2:853301624d95 | 1207 | int32_t var2; |
| mcm | 2:853301624d95 | 1208 | int32_t var3; |
| mcm | 2:853301624d95 | 1209 | int32_t var4; |
| mcm | 2:853301624d95 | 1210 | int32_t var5; |
| mcm | 2:853301624d95 | 1211 | uint32_t humidity; |
| mcm | 2:853301624d95 | 1212 | uint32_t humidity_max = 102400; |
| mcm | 2:853301624d95 | 1213 | |
| mcm | 2:853301624d95 | 1214 | var1 = calib_data->t_fine - ((int32_t)76800); |
| mcm | 2:853301624d95 | 1215 | var2 = (int32_t)(uncomp_data->humidity * 16384); |
| mcm | 2:853301624d95 | 1216 | var3 = (int32_t)(((int32_t)calib_data->dig_H4) * 1048576); |
| mcm | 2:853301624d95 | 1217 | var4 = ((int32_t)calib_data->dig_H5) * var1; |
| mcm | 2:853301624d95 | 1218 | var5 = (((var2 - var3) - var4) + (int32_t)16384) / 32768; |
| mcm | 2:853301624d95 | 1219 | var2 = (var1 * ((int32_t)calib_data->dig_H6)) / 1024; |
| mcm | 2:853301624d95 | 1220 | var3 = (var1 * ((int32_t)calib_data->dig_H3)) / 2048; |
| mcm | 2:853301624d95 | 1221 | var4 = ((var2 * (var3 + (int32_t)32768)) / 1024) + (int32_t)2097152; |
| mcm | 2:853301624d95 | 1222 | var2 = ((var4 * ((int32_t)calib_data->dig_H2)) + 8192) / 16384; |
| mcm | 2:853301624d95 | 1223 | var3 = var5 * var2; |
| mcm | 2:853301624d95 | 1224 | var4 = ((var3 / 32768) * (var3 / 32768)) / 128; |
| mcm | 2:853301624d95 | 1225 | var5 = var3 - ((var4 * ((int32_t)calib_data->dig_H1)) / 16); |
| mcm | 2:853301624d95 | 1226 | var5 = (var5 < 0 ? 0 : var5); |
| mcm | 2:853301624d95 | 1227 | var5 = (var5 > 419430400 ? 419430400 : var5); |
| mcm | 2:853301624d95 | 1228 | humidity = (uint32_t)(var5 / 4096); |
| mcm | 2:853301624d95 | 1229 | if (humidity > humidity_max) { |
| mcm | 2:853301624d95 | 1230 | humidity = humidity_max; |
| mcm | 2:853301624d95 | 1231 | } |
| mcm | 2:853301624d95 | 1232 | |
| mcm | 2:853301624d95 | 1233 | return humidity; |
| mcm | 2:853301624d95 | 1234 | } |
| mcm | 2:853301624d95 | 1235 | #endif |
| mcm | 2:853301624d95 | 1236 | |
| mcm | 2:853301624d95 | 1237 | /*! |
| mcm | 2:853301624d95 | 1238 | * @brief This internal API reads the calibration data from the sensor, parse |
| mcm | 2:853301624d95 | 1239 | * it and store in the device structure. |
| mcm | 2:853301624d95 | 1240 | */ |
| mcm | 2:853301624d95 | 1241 | static int8_t BME280::get_calib_data(struct bme280_dev *dev) |
| mcm | 2:853301624d95 | 1242 | { |
| mcm | 2:853301624d95 | 1243 | int8_t rslt; |
| mcm | 2:853301624d95 | 1244 | uint8_t reg_addr = BME280_TEMP_PRESS_CALIB_DATA_ADDR; |
| mcm | 2:853301624d95 | 1245 | |
| mcm | 2:853301624d95 | 1246 | /* Array to store calibration data */ |
| mcm | 2:853301624d95 | 1247 | uint8_t calib_data[BME280_TEMP_PRESS_CALIB_DATA_LEN] = { 0 }; |
| mcm | 2:853301624d95 | 1248 | |
| mcm | 2:853301624d95 | 1249 | /* Read the calibration data from the sensor */ |
| mcm | 2:853301624d95 | 1250 | rslt = bme280_get_regs(reg_addr, calib_data, BME280_TEMP_PRESS_CALIB_DATA_LEN, dev); |
| mcm | 2:853301624d95 | 1251 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 1252 | /* Parse temperature and pressure calibration data and store |
| mcm | 2:853301624d95 | 1253 | * it in device structure |
| mcm | 2:853301624d95 | 1254 | */ |
| mcm | 2:853301624d95 | 1255 | parse_temp_press_calib_data(calib_data, dev); |
| mcm | 2:853301624d95 | 1256 | reg_addr = BME280_HUMIDITY_CALIB_DATA_ADDR; |
| mcm | 2:853301624d95 | 1257 | |
| mcm | 2:853301624d95 | 1258 | /* Read the humidity calibration data from the sensor */ |
| mcm | 2:853301624d95 | 1259 | rslt = bme280_get_regs(reg_addr, calib_data, BME280_HUMIDITY_CALIB_DATA_LEN, dev); |
| mcm | 2:853301624d95 | 1260 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 1261 | /* Parse humidity calibration data and store it in |
| mcm | 2:853301624d95 | 1262 | * device structure |
| mcm | 2:853301624d95 | 1263 | */ |
| mcm | 2:853301624d95 | 1264 | parse_humidity_calib_data(calib_data, dev); |
| mcm | 2:853301624d95 | 1265 | } |
| mcm | 2:853301624d95 | 1266 | } |
| mcm | 2:853301624d95 | 1267 | |
| mcm | 2:853301624d95 | 1268 | return rslt; |
| mcm | 2:853301624d95 | 1269 | } |
| mcm | 2:853301624d95 | 1270 | |
| mcm | 2:853301624d95 | 1271 | /*! |
| mcm | 2:853301624d95 | 1272 | * @brief This internal API interleaves the register address between the |
| mcm | 2:853301624d95 | 1273 | * register data buffer for burst write operation. |
| mcm | 2:853301624d95 | 1274 | */ |
| mcm | 2:853301624d95 | 1275 | static void BME280::interleave_reg_addr(const uint8_t *reg_addr, uint8_t *temp_buff, const uint8_t *reg_data, uint8_t len) |
| mcm | 2:853301624d95 | 1276 | { |
| mcm | 2:853301624d95 | 1277 | uint8_t index; |
| mcm | 2:853301624d95 | 1278 | |
| mcm | 2:853301624d95 | 1279 | for (index = 1; index < len; index++) { |
| mcm | 2:853301624d95 | 1280 | temp_buff[(index * 2) - 1] = reg_addr[index]; |
| mcm | 2:853301624d95 | 1281 | temp_buff[index * 2] = reg_data[index]; |
| mcm | 2:853301624d95 | 1282 | } |
| mcm | 2:853301624d95 | 1283 | } |
| mcm | 2:853301624d95 | 1284 | |
| mcm | 2:853301624d95 | 1285 | /*! |
| mcm | 2:853301624d95 | 1286 | * @brief This internal API is used to parse the temperature and |
| mcm | 2:853301624d95 | 1287 | * pressure calibration data and store it in device structure. |
| mcm | 2:853301624d95 | 1288 | */ |
| mcm | 2:853301624d95 | 1289 | static void BME280::parse_temp_press_calib_data(const uint8_t *reg_data, struct bme280_dev *dev) |
| mcm | 2:853301624d95 | 1290 | { |
| mcm | 2:853301624d95 | 1291 | struct bme280_calib_data *calib_data = &dev->calib_data; |
| mcm | 2:853301624d95 | 1292 | |
| mcm | 2:853301624d95 | 1293 | calib_data->dig_T1 = BME280_CONCAT_BYTES(reg_data[1], reg_data[0]); |
| mcm | 2:853301624d95 | 1294 | calib_data->dig_T2 = (int16_t)BME280_CONCAT_BYTES(reg_data[3], reg_data[2]); |
| mcm | 2:853301624d95 | 1295 | calib_data->dig_T3 = (int16_t)BME280_CONCAT_BYTES(reg_data[5], reg_data[4]); |
| mcm | 2:853301624d95 | 1296 | calib_data->dig_P1 = BME280_CONCAT_BYTES(reg_data[7], reg_data[6]); |
| mcm | 2:853301624d95 | 1297 | calib_data->dig_P2 = (int16_t)BME280_CONCAT_BYTES(reg_data[9], reg_data[8]); |
| mcm | 2:853301624d95 | 1298 | calib_data->dig_P3 = (int16_t)BME280_CONCAT_BYTES(reg_data[11], reg_data[10]); |
| mcm | 2:853301624d95 | 1299 | calib_data->dig_P4 = (int16_t)BME280_CONCAT_BYTES(reg_data[13], reg_data[12]); |
| mcm | 2:853301624d95 | 1300 | calib_data->dig_P5 = (int16_t)BME280_CONCAT_BYTES(reg_data[15], reg_data[14]); |
| mcm | 2:853301624d95 | 1301 | calib_data->dig_P6 = (int16_t)BME280_CONCAT_BYTES(reg_data[17], reg_data[16]); |
| mcm | 2:853301624d95 | 1302 | calib_data->dig_P7 = (int16_t)BME280_CONCAT_BYTES(reg_data[19], reg_data[18]); |
| mcm | 2:853301624d95 | 1303 | calib_data->dig_P8 = (int16_t)BME280_CONCAT_BYTES(reg_data[21], reg_data[20]); |
| mcm | 2:853301624d95 | 1304 | calib_data->dig_P9 = (int16_t)BME280_CONCAT_BYTES(reg_data[23], reg_data[22]); |
| mcm | 2:853301624d95 | 1305 | calib_data->dig_H1 = reg_data[25]; |
| mcm | 2:853301624d95 | 1306 | } |
| mcm | 2:853301624d95 | 1307 | |
| mcm | 2:853301624d95 | 1308 | /*! |
| mcm | 2:853301624d95 | 1309 | * @brief This internal API is used to parse the humidity calibration data |
| mcm | 2:853301624d95 | 1310 | * and store it in device structure. |
| mcm | 2:853301624d95 | 1311 | */ |
| mcm | 2:853301624d95 | 1312 | static void BME280::parse_humidity_calib_data(const uint8_t *reg_data, struct bme280_dev *dev) |
| mcm | 2:853301624d95 | 1313 | { |
| mcm | 2:853301624d95 | 1314 | struct bme280_calib_data *calib_data = &dev->calib_data; |
| mcm | 2:853301624d95 | 1315 | int16_t dig_H4_lsb; |
| mcm | 2:853301624d95 | 1316 | int16_t dig_H4_msb; |
| mcm | 2:853301624d95 | 1317 | int16_t dig_H5_lsb; |
| mcm | 2:853301624d95 | 1318 | int16_t dig_H5_msb; |
| mcm | 2:853301624d95 | 1319 | |
| mcm | 2:853301624d95 | 1320 | calib_data->dig_H2 = (int16_t)BME280_CONCAT_BYTES(reg_data[1], reg_data[0]); |
| mcm | 2:853301624d95 | 1321 | calib_data->dig_H3 = reg_data[2]; |
| mcm | 2:853301624d95 | 1322 | dig_H4_msb = (int16_t)(int8_t)reg_data[3] * 16; |
| mcm | 2:853301624d95 | 1323 | dig_H4_lsb = (int16_t)(reg_data[4] & 0x0F); |
| mcm | 2:853301624d95 | 1324 | calib_data->dig_H4 = dig_H4_msb | dig_H4_lsb; |
| mcm | 2:853301624d95 | 1325 | dig_H5_msb = (int16_t)(int8_t)reg_data[5] * 16; |
| mcm | 2:853301624d95 | 1326 | dig_H5_lsb = (int16_t)(reg_data[4] >> 4); |
| mcm | 2:853301624d95 | 1327 | calib_data->dig_H5 = dig_H5_msb | dig_H5_lsb; |
| mcm | 2:853301624d95 | 1328 | calib_data->dig_H6 = (int8_t)reg_data[6]; |
| mcm | 2:853301624d95 | 1329 | } |
| mcm | 2:853301624d95 | 1330 | |
| mcm | 2:853301624d95 | 1331 | /*! |
| mcm | 2:853301624d95 | 1332 | * @brief This internal API is used to identify the settings which the user |
| mcm | 2:853301624d95 | 1333 | * wants to modify in the sensor. |
| mcm | 2:853301624d95 | 1334 | */ |
| mcm | 2:853301624d95 | 1335 | static uint8_t BME280::are_settings_changed(uint8_t sub_settings, uint8_t desired_settings) |
| mcm | 2:853301624d95 | 1336 | { |
| mcm | 2:853301624d95 | 1337 | uint8_t settings_changed = FALSE; |
| mcm | 2:853301624d95 | 1338 | |
| mcm | 2:853301624d95 | 1339 | if (sub_settings & desired_settings) { |
| mcm | 2:853301624d95 | 1340 | /* User wants to modify this particular settings */ |
| mcm | 2:853301624d95 | 1341 | settings_changed = TRUE; |
| mcm | 2:853301624d95 | 1342 | } else { |
| mcm | 2:853301624d95 | 1343 | /* User don't want to modify this particular settings */ |
| mcm | 2:853301624d95 | 1344 | settings_changed = FALSE; |
| mcm | 2:853301624d95 | 1345 | } |
| mcm | 2:853301624d95 | 1346 | |
| mcm | 2:853301624d95 | 1347 | return settings_changed; |
| mcm | 2:853301624d95 | 1348 | } |
| mcm | 2:853301624d95 | 1349 | |
| mcm | 2:853301624d95 | 1350 | /*! |
| mcm | 2:853301624d95 | 1351 | * @brief This internal API is used to validate the device structure pointer for |
| mcm | 2:853301624d95 | 1352 | * null conditions. |
| mcm | 2:853301624d95 | 1353 | */ |
| mcm | 2:853301624d95 | 1354 | static int8_t BME280::null_ptr_check(const struct bme280_dev *dev) |
| mcm | 2:853301624d95 | 1355 | { |
| mcm | 2:853301624d95 | 1356 | int8_t rslt; |
| mcm | 2:853301624d95 | 1357 | |
| mcm | 2:853301624d95 | 1358 | if ((dev == NULL) || (dev->read == NULL) || (dev->write == NULL) || (dev->delay_ms == NULL)) { |
| mcm | 2:853301624d95 | 1359 | /* Device structure pointer is not valid */ |
| mcm | 2:853301624d95 | 1360 | rslt = BME280_E_NULL_PTR; |
| mcm | 2:853301624d95 | 1361 | } else { |
| mcm | 2:853301624d95 | 1362 | /* Device structure is fine */ |
| mcm | 2:853301624d95 | 1363 | rslt = BME280_OK; |
| mcm | 2:853301624d95 | 1364 | } |
| mcm | 2:853301624d95 | 1365 | |
| mcm | 2:853301624d95 | 1366 | return rslt; |
| mcm | 2:853301624d95 | 1367 | } |