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@3:ab857b70346e, 2019-09-03 (annotated)
- Committer:
- mcm
- Date:
- Tue Sep 03 15:36:35 2019 +0000
- Revision:
- 3:ab857b70346e
- Parent:
- 2:853301624d95
Some bugs were fixed in order to adapt the driver to mBed, it is ready for testing.
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 | |
| mcm | 2:853301624d95 | 89 | /****************** Global Function Definitions *******************************/ |
| mcm | 2:853301624d95 | 90 | |
| mcm | 2:853301624d95 | 91 | /*! |
| mcm | 2:853301624d95 | 92 | * @brief This API is the entry point. |
| mcm | 2:853301624d95 | 93 | * It reads the chip-id and calibration data from the sensor. |
| mcm | 2:853301624d95 | 94 | */ |
| mcm | 2:853301624d95 | 95 | int8_t BME280::bme280_init(struct bme280_dev *dev) |
| mcm | 2:853301624d95 | 96 | { |
| mcm | 2:853301624d95 | 97 | int8_t rslt; |
| mcm | 2:853301624d95 | 98 | |
| mcm | 2:853301624d95 | 99 | /* chip id read try count */ |
| mcm | 2:853301624d95 | 100 | uint8_t try_count = 5; |
| mcm | 2:853301624d95 | 101 | uint8_t chip_id = 0; |
| mcm | 2:853301624d95 | 102 | |
| mcm | 2:853301624d95 | 103 | /* Check for null pointer in the device structure*/ |
| mcm | 2:853301624d95 | 104 | rslt = null_ptr_check(dev); |
| mcm | 2:853301624d95 | 105 | |
| mcm | 2:853301624d95 | 106 | /* Proceed if null check is fine */ |
| mcm | 2:853301624d95 | 107 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 108 | while (try_count) { |
| mcm | 2:853301624d95 | 109 | /* Read the chip-id of bme280 sensor */ |
| mcm | 2:853301624d95 | 110 | rslt = bme280_get_regs(BME280_CHIP_ID_ADDR, &chip_id, 1, dev); |
| mcm | 2:853301624d95 | 111 | |
| mcm | 2:853301624d95 | 112 | /* Check for chip id validity */ |
| mcm | 2:853301624d95 | 113 | if ((rslt == BME280_OK) && (chip_id == BME280_CHIP_ID)) { |
| mcm | 2:853301624d95 | 114 | dev->chip_id = chip_id; |
| mcm | 2:853301624d95 | 115 | |
| mcm | 2:853301624d95 | 116 | /* Reset the sensor */ |
| mcm | 2:853301624d95 | 117 | rslt = bme280_soft_reset(dev); |
| mcm | 2:853301624d95 | 118 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 119 | /* Read the calibration data */ |
| mcm | 2:853301624d95 | 120 | rslt = get_calib_data(dev); |
| mcm | 2:853301624d95 | 121 | } |
| mcm | 2:853301624d95 | 122 | break; |
| mcm | 2:853301624d95 | 123 | } |
| mcm | 2:853301624d95 | 124 | |
| mcm | 2:853301624d95 | 125 | /* Wait for 1 ms */ |
| mcm | 2:853301624d95 | 126 | dev->delay_ms(1); |
| mcm | 2:853301624d95 | 127 | --try_count; |
| mcm | 2:853301624d95 | 128 | } |
| mcm | 2:853301624d95 | 129 | |
| mcm | 2:853301624d95 | 130 | /* Chip id check failed */ |
| mcm | 2:853301624d95 | 131 | if (!try_count) { |
| mcm | 2:853301624d95 | 132 | rslt = BME280_E_DEV_NOT_FOUND; |
| mcm | 2:853301624d95 | 133 | } |
| mcm | 2:853301624d95 | 134 | } |
| mcm | 2:853301624d95 | 135 | |
| mcm | 2:853301624d95 | 136 | return rslt; |
| mcm | 2:853301624d95 | 137 | } |
| mcm | 2:853301624d95 | 138 | |
| mcm | 2:853301624d95 | 139 | /*! |
| mcm | 2:853301624d95 | 140 | * @brief This API reads the data from the given register address of the sensor. |
| mcm | 2:853301624d95 | 141 | */ |
| mcm | 2:853301624d95 | 142 | 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 | 143 | { |
| mcm | 2:853301624d95 | 144 | int8_t rslt; |
| mcm | 2:853301624d95 | 145 | |
| mcm | 2:853301624d95 | 146 | /* Check for null pointer in the device structure*/ |
| mcm | 2:853301624d95 | 147 | rslt = null_ptr_check(dev); |
| mcm | 2:853301624d95 | 148 | |
| mcm | 2:853301624d95 | 149 | /* Proceed if null check is fine */ |
| mcm | 2:853301624d95 | 150 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 151 | /* If interface selected is SPI */ |
| mcm | 2:853301624d95 | 152 | if (dev->intf != BME280_I2C_INTF) { |
| mcm | 2:853301624d95 | 153 | reg_addr = reg_addr | 0x80; |
| mcm | 2:853301624d95 | 154 | } |
| mcm | 2:853301624d95 | 155 | |
| mcm | 2:853301624d95 | 156 | /* Read the data */ |
| mcm | 2:853301624d95 | 157 | rslt = dev->read(dev->dev_id, reg_addr, reg_data, len); |
| mcm | 2:853301624d95 | 158 | |
| mcm | 2:853301624d95 | 159 | /* Check for communication error */ |
| mcm | 2:853301624d95 | 160 | if (rslt != BME280_OK) { |
| mcm | 2:853301624d95 | 161 | rslt = BME280_E_COMM_FAIL; |
| mcm | 2:853301624d95 | 162 | } |
| mcm | 2:853301624d95 | 163 | } |
| mcm | 2:853301624d95 | 164 | |
| mcm | 2:853301624d95 | 165 | return rslt; |
| mcm | 2:853301624d95 | 166 | } |
| mcm | 2:853301624d95 | 167 | |
| mcm | 2:853301624d95 | 168 | /*! |
| mcm | 2:853301624d95 | 169 | * @brief This API writes the given data to the register address |
| mcm | 2:853301624d95 | 170 | * of the sensor. |
| mcm | 2:853301624d95 | 171 | */ |
| mcm | 2:853301624d95 | 172 | 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 | 173 | { |
| mcm | 2:853301624d95 | 174 | int8_t rslt; |
| mcm | 2:853301624d95 | 175 | uint8_t temp_buff[20]; /* Typically not to write more than 10 registers */ |
| mcm | 2:853301624d95 | 176 | |
| mcm | 2:853301624d95 | 177 | if (len > 10) { |
| mcm | 2:853301624d95 | 178 | len = 10; |
| mcm | 2:853301624d95 | 179 | } |
| mcm | 2:853301624d95 | 180 | uint16_t temp_len; |
| mcm | 2:853301624d95 | 181 | uint8_t reg_addr_cnt; |
| mcm | 2:853301624d95 | 182 | |
| mcm | 2:853301624d95 | 183 | /* Check for null pointer in the device structure*/ |
| mcm | 2:853301624d95 | 184 | rslt = null_ptr_check(dev); |
| mcm | 2:853301624d95 | 185 | |
| mcm | 2:853301624d95 | 186 | /* Check for arguments validity */ |
| mcm | 2:853301624d95 | 187 | if ((rslt == BME280_OK) && (reg_addr != NULL) && (reg_data != NULL)) { |
| mcm | 2:853301624d95 | 188 | if (len != 0) { |
| mcm | 2:853301624d95 | 189 | temp_buff[0] = reg_data[0]; |
| mcm | 2:853301624d95 | 190 | |
| mcm | 2:853301624d95 | 191 | /* If interface selected is SPI */ |
| mcm | 2:853301624d95 | 192 | if (dev->intf != BME280_I2C_INTF) { |
| mcm | 2:853301624d95 | 193 | for (reg_addr_cnt = 0; reg_addr_cnt < len; reg_addr_cnt++) { |
| mcm | 2:853301624d95 | 194 | reg_addr[reg_addr_cnt] = reg_addr[reg_addr_cnt] & 0x7F; |
| mcm | 2:853301624d95 | 195 | } |
| mcm | 2:853301624d95 | 196 | } |
| mcm | 2:853301624d95 | 197 | |
| mcm | 2:853301624d95 | 198 | /* Burst write mode */ |
| mcm | 2:853301624d95 | 199 | if (len > 1) { |
| mcm | 2:853301624d95 | 200 | /* Interleave register address w.r.t data for |
| mcm | 2:853301624d95 | 201 | * burst write |
| mcm | 2:853301624d95 | 202 | */ |
| mcm | 2:853301624d95 | 203 | interleave_reg_addr(reg_addr, temp_buff, reg_data, len); |
| mcm | 2:853301624d95 | 204 | temp_len = ((len * 2) - 1); |
| mcm | 2:853301624d95 | 205 | } else { |
| mcm | 2:853301624d95 | 206 | temp_len = len; |
| mcm | 2:853301624d95 | 207 | } |
| mcm | 2:853301624d95 | 208 | rslt = dev->write(dev->dev_id, reg_addr[0], temp_buff, temp_len); |
| mcm | 2:853301624d95 | 209 | |
| mcm | 2:853301624d95 | 210 | /* Check for communication error */ |
| mcm | 2:853301624d95 | 211 | if (rslt != BME280_OK) { |
| mcm | 2:853301624d95 | 212 | rslt = BME280_E_COMM_FAIL; |
| mcm | 2:853301624d95 | 213 | } |
| mcm | 2:853301624d95 | 214 | } else { |
| mcm | 2:853301624d95 | 215 | rslt = BME280_E_INVALID_LEN; |
| mcm | 2:853301624d95 | 216 | } |
| mcm | 2:853301624d95 | 217 | } else { |
| mcm | 2:853301624d95 | 218 | rslt = BME280_E_NULL_PTR; |
| mcm | 2:853301624d95 | 219 | } |
| mcm | 2:853301624d95 | 220 | |
| mcm | 2:853301624d95 | 221 | return rslt; |
| mcm | 2:853301624d95 | 222 | } |
| mcm | 2:853301624d95 | 223 | |
| mcm | 2:853301624d95 | 224 | /*! |
| mcm | 2:853301624d95 | 225 | * @brief This API sets the oversampling, filter and standby duration |
| mcm | 2:853301624d95 | 226 | * (normal mode) settings in the sensor. |
| mcm | 2:853301624d95 | 227 | */ |
| mcm | 2:853301624d95 | 228 | int8_t BME280::bme280_set_sensor_settings(uint8_t desired_settings, const struct bme280_dev *dev) |
| mcm | 2:853301624d95 | 229 | { |
| mcm | 2:853301624d95 | 230 | int8_t rslt; |
| mcm | 2:853301624d95 | 231 | uint8_t sensor_mode; |
| mcm | 2:853301624d95 | 232 | |
| mcm | 2:853301624d95 | 233 | /* Check for null pointer in the device structure*/ |
| mcm | 2:853301624d95 | 234 | rslt = null_ptr_check(dev); |
| mcm | 2:853301624d95 | 235 | |
| mcm | 2:853301624d95 | 236 | /* Proceed if null check is fine */ |
| mcm | 2:853301624d95 | 237 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 238 | rslt = bme280_get_sensor_mode(&sensor_mode, dev); |
| mcm | 2:853301624d95 | 239 | if ((rslt == BME280_OK) && (sensor_mode != BME280_SLEEP_MODE)) { |
| mcm | 2:853301624d95 | 240 | rslt = put_device_to_sleep(dev); |
| mcm | 2:853301624d95 | 241 | } |
| mcm | 2:853301624d95 | 242 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 243 | /* Check if user wants to change oversampling |
| mcm | 2:853301624d95 | 244 | * settings |
| mcm | 2:853301624d95 | 245 | */ |
| mcm | 2:853301624d95 | 246 | if (are_settings_changed(OVERSAMPLING_SETTINGS, desired_settings)) { |
| mcm | 2:853301624d95 | 247 | rslt = set_osr_settings(desired_settings, &dev->settings, dev); |
| mcm | 2:853301624d95 | 248 | } |
| mcm | 2:853301624d95 | 249 | |
| mcm | 2:853301624d95 | 250 | /* Check if user wants to change filter and/or |
| mcm | 2:853301624d95 | 251 | * standby settings |
| mcm | 2:853301624d95 | 252 | */ |
| mcm | 2:853301624d95 | 253 | if ((rslt == BME280_OK) && are_settings_changed(FILTER_STANDBY_SETTINGS, desired_settings)) { |
| mcm | 2:853301624d95 | 254 | rslt = set_filter_standby_settings(desired_settings, &dev->settings, dev); |
| mcm | 2:853301624d95 | 255 | } |
| mcm | 2:853301624d95 | 256 | } |
| mcm | 2:853301624d95 | 257 | } |
| mcm | 2:853301624d95 | 258 | |
| mcm | 2:853301624d95 | 259 | return rslt; |
| mcm | 2:853301624d95 | 260 | } |
| mcm | 2:853301624d95 | 261 | |
| mcm | 2:853301624d95 | 262 | /*! |
| mcm | 2:853301624d95 | 263 | * @brief This API gets the oversampling, filter and standby duration |
| mcm | 2:853301624d95 | 264 | * (normal mode) settings from the sensor. |
| mcm | 2:853301624d95 | 265 | */ |
| mcm | 2:853301624d95 | 266 | int8_t BME280::bme280_get_sensor_settings(struct bme280_dev *dev) |
| mcm | 2:853301624d95 | 267 | { |
| mcm | 2:853301624d95 | 268 | int8_t rslt; |
| mcm | 2:853301624d95 | 269 | uint8_t reg_data[4]; |
| mcm | 2:853301624d95 | 270 | |
| mcm | 2:853301624d95 | 271 | /* Check for null pointer in the device structure*/ |
| mcm | 2:853301624d95 | 272 | rslt = null_ptr_check(dev); |
| mcm | 2:853301624d95 | 273 | |
| mcm | 2:853301624d95 | 274 | /* Proceed if null check is fine */ |
| mcm | 2:853301624d95 | 275 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 276 | rslt = bme280_get_regs(BME280_CTRL_HUM_ADDR, reg_data, 4, dev); |
| mcm | 2:853301624d95 | 277 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 278 | parse_device_settings(reg_data, &dev->settings); |
| mcm | 2:853301624d95 | 279 | } |
| mcm | 2:853301624d95 | 280 | } |
| mcm | 2:853301624d95 | 281 | |
| mcm | 2:853301624d95 | 282 | return rslt; |
| mcm | 2:853301624d95 | 283 | } |
| mcm | 2:853301624d95 | 284 | |
| mcm | 2:853301624d95 | 285 | /*! |
| mcm | 2:853301624d95 | 286 | * @brief This API sets the power mode of the sensor. |
| mcm | 2:853301624d95 | 287 | */ |
| mcm | 2:853301624d95 | 288 | int8_t BME280::bme280_set_sensor_mode(uint8_t sensor_mode, const struct bme280_dev *dev) |
| mcm | 2:853301624d95 | 289 | { |
| mcm | 2:853301624d95 | 290 | int8_t rslt; |
| mcm | 2:853301624d95 | 291 | uint8_t last_set_mode; |
| mcm | 2:853301624d95 | 292 | |
| mcm | 2:853301624d95 | 293 | /* Check for null pointer in the device structure*/ |
| mcm | 2:853301624d95 | 294 | rslt = null_ptr_check(dev); |
| mcm | 2:853301624d95 | 295 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 296 | rslt = bme280_get_sensor_mode(&last_set_mode, dev); |
| mcm | 2:853301624d95 | 297 | |
| mcm | 2:853301624d95 | 298 | /* If the sensor is not in sleep mode put the device to sleep |
| mcm | 2:853301624d95 | 299 | * mode |
| mcm | 2:853301624d95 | 300 | */ |
| mcm | 2:853301624d95 | 301 | if ((rslt == BME280_OK) && (last_set_mode != BME280_SLEEP_MODE)) { |
| mcm | 2:853301624d95 | 302 | rslt = put_device_to_sleep(dev); |
| mcm | 2:853301624d95 | 303 | } |
| mcm | 2:853301624d95 | 304 | |
| mcm | 2:853301624d95 | 305 | /* Set the power mode */ |
| mcm | 2:853301624d95 | 306 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 307 | rslt = write_power_mode(sensor_mode, dev); |
| mcm | 2:853301624d95 | 308 | } |
| mcm | 2:853301624d95 | 309 | } |
| mcm | 2:853301624d95 | 310 | |
| mcm | 2:853301624d95 | 311 | return rslt; |
| mcm | 2:853301624d95 | 312 | } |
| mcm | 2:853301624d95 | 313 | |
| mcm | 2:853301624d95 | 314 | /*! |
| mcm | 2:853301624d95 | 315 | * @brief This API gets the power mode of the sensor. |
| mcm | 2:853301624d95 | 316 | */ |
| mcm | 2:853301624d95 | 317 | int8_t BME280::bme280_get_sensor_mode(uint8_t *sensor_mode, const struct bme280_dev *dev) |
| mcm | 2:853301624d95 | 318 | { |
| mcm | 2:853301624d95 | 319 | int8_t rslt; |
| mcm | 2:853301624d95 | 320 | |
| mcm | 2:853301624d95 | 321 | /* Check for null pointer in the device structure*/ |
| mcm | 2:853301624d95 | 322 | rslt = null_ptr_check(dev); |
| mcm | 2:853301624d95 | 323 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 324 | /* Read the power mode register */ |
| mcm | 2:853301624d95 | 325 | rslt = bme280_get_regs(BME280_PWR_CTRL_ADDR, sensor_mode, 1, dev); |
| mcm | 2:853301624d95 | 326 | |
| mcm | 2:853301624d95 | 327 | /* Assign the power mode in the device structure */ |
| mcm | 2:853301624d95 | 328 | *sensor_mode = BME280_GET_BITS_POS_0(*sensor_mode, BME280_SENSOR_MODE); |
| mcm | 2:853301624d95 | 329 | } |
| mcm | 2:853301624d95 | 330 | |
| mcm | 2:853301624d95 | 331 | return rslt; |
| mcm | 2:853301624d95 | 332 | } |
| mcm | 2:853301624d95 | 333 | |
| mcm | 2:853301624d95 | 334 | /*! |
| mcm | 2:853301624d95 | 335 | * @brief This API performs the soft reset of the sensor. |
| mcm | 2:853301624d95 | 336 | */ |
| mcm | 2:853301624d95 | 337 | int8_t BME280::bme280_soft_reset(const struct bme280_dev *dev) |
| mcm | 2:853301624d95 | 338 | { |
| mcm | 2:853301624d95 | 339 | int8_t rslt; |
| mcm | 2:853301624d95 | 340 | uint8_t reg_addr = BME280_RESET_ADDR; |
| mcm | 2:853301624d95 | 341 | |
| mcm | 2:853301624d95 | 342 | /* 0xB6 is the soft reset command */ |
| mcm | 2:853301624d95 | 343 | uint8_t soft_rst_cmd = 0xB6; |
| mcm | 2:853301624d95 | 344 | |
| mcm | 2:853301624d95 | 345 | /* Check for null pointer in the device structure*/ |
| mcm | 2:853301624d95 | 346 | rslt = null_ptr_check(dev); |
| mcm | 2:853301624d95 | 347 | |
| mcm | 2:853301624d95 | 348 | /* Proceed if null check is fine */ |
| mcm | 2:853301624d95 | 349 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 350 | /* Write the soft reset command in the sensor */ |
| mcm | 2:853301624d95 | 351 | rslt = bme280_set_regs(®_addr, &soft_rst_cmd, 1, dev); |
| mcm | 2:853301624d95 | 352 | |
| mcm | 2:853301624d95 | 353 | /* As per data sheet, startup time is 2 ms. */ |
| mcm | 2:853301624d95 | 354 | dev->delay_ms(2); |
| mcm | 2:853301624d95 | 355 | } |
| mcm | 2:853301624d95 | 356 | |
| mcm | 2:853301624d95 | 357 | return rslt; |
| mcm | 2:853301624d95 | 358 | } |
| mcm | 2:853301624d95 | 359 | |
| mcm | 2:853301624d95 | 360 | /*! |
| mcm | 2:853301624d95 | 361 | * @brief This API reads the pressure, temperature and humidity data from the |
| mcm | 2:853301624d95 | 362 | * sensor, compensates the data and store it in the bme280_data structure |
| mcm | 2:853301624d95 | 363 | * instance passed by the user. |
| mcm | 2:853301624d95 | 364 | */ |
| mcm | 2:853301624d95 | 365 | int8_t BME280::bme280_get_sensor_data(uint8_t sensor_comp, struct bme280_data *comp_data, struct bme280_dev *dev) |
| mcm | 2:853301624d95 | 366 | { |
| mcm | 2:853301624d95 | 367 | int8_t rslt; |
| mcm | 2:853301624d95 | 368 | |
| mcm | 2:853301624d95 | 369 | /* Array to store the pressure, temperature and humidity data read from |
| mcm | 2:853301624d95 | 370 | * the sensor |
| mcm | 2:853301624d95 | 371 | */ |
| mcm | 2:853301624d95 | 372 | uint8_t reg_data[BME280_P_T_H_DATA_LEN] = { 0 }; |
| mcm | 2:853301624d95 | 373 | struct bme280_uncomp_data uncomp_data = { 0 }; |
| mcm | 2:853301624d95 | 374 | |
| mcm | 2:853301624d95 | 375 | /* Check for null pointer in the device structure*/ |
| mcm | 2:853301624d95 | 376 | rslt = null_ptr_check(dev); |
| mcm | 2:853301624d95 | 377 | if ((rslt == BME280_OK) && (comp_data != NULL)) { |
| mcm | 2:853301624d95 | 378 | /* Read the pressure and temperature data from the sensor */ |
| mcm | 2:853301624d95 | 379 | rslt = bme280_get_regs(BME280_DATA_ADDR, reg_data, BME280_P_T_H_DATA_LEN, dev); |
| mcm | 2:853301624d95 | 380 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 381 | /* Parse the read data from the sensor */ |
| mcm | 2:853301624d95 | 382 | bme280_parse_sensor_data(reg_data, &uncomp_data); |
| mcm | 2:853301624d95 | 383 | |
| mcm | 2:853301624d95 | 384 | /* Compensate the pressure and/or temperature and/or |
| mcm | 2:853301624d95 | 385 | * humidity data from the sensor |
| mcm | 2:853301624d95 | 386 | */ |
| mcm | 2:853301624d95 | 387 | rslt = bme280_compensate_data(sensor_comp, &uncomp_data, comp_data, &dev->calib_data); |
| mcm | 2:853301624d95 | 388 | } |
| mcm | 2:853301624d95 | 389 | } else { |
| mcm | 2:853301624d95 | 390 | rslt = BME280_E_NULL_PTR; |
| mcm | 2:853301624d95 | 391 | } |
| mcm | 2:853301624d95 | 392 | |
| mcm | 2:853301624d95 | 393 | return rslt; |
| mcm | 2:853301624d95 | 394 | } |
| mcm | 2:853301624d95 | 395 | |
| mcm | 2:853301624d95 | 396 | /*! |
| mcm | 2:853301624d95 | 397 | * @brief This API is used to parse the pressure, temperature and |
| mcm | 2:853301624d95 | 398 | * humidity data and store it in the bme280_uncomp_data structure instance. |
| mcm | 2:853301624d95 | 399 | */ |
| mcm | 2:853301624d95 | 400 | void BME280::bme280_parse_sensor_data(const uint8_t *reg_data, struct bme280_uncomp_data *uncomp_data) |
| mcm | 2:853301624d95 | 401 | { |
| mcm | 2:853301624d95 | 402 | /* Variables to store the sensor data */ |
| mcm | 2:853301624d95 | 403 | uint32_t data_xlsb; |
| mcm | 2:853301624d95 | 404 | uint32_t data_lsb; |
| mcm | 2:853301624d95 | 405 | uint32_t data_msb; |
| mcm | 2:853301624d95 | 406 | |
| mcm | 2:853301624d95 | 407 | /* Store the parsed register values for pressure data */ |
| mcm | 2:853301624d95 | 408 | data_msb = (uint32_t)reg_data[0] << 12; |
| mcm | 2:853301624d95 | 409 | data_lsb = (uint32_t)reg_data[1] << 4; |
| mcm | 2:853301624d95 | 410 | data_xlsb = (uint32_t)reg_data[2] >> 4; |
| mcm | 2:853301624d95 | 411 | uncomp_data->pressure = data_msb | data_lsb | data_xlsb; |
| mcm | 2:853301624d95 | 412 | |
| mcm | 2:853301624d95 | 413 | /* Store the parsed register values for temperature data */ |
| mcm | 2:853301624d95 | 414 | data_msb = (uint32_t)reg_data[3] << 12; |
| mcm | 2:853301624d95 | 415 | data_lsb = (uint32_t)reg_data[4] << 4; |
| mcm | 2:853301624d95 | 416 | data_xlsb = (uint32_t)reg_data[5] >> 4; |
| mcm | 2:853301624d95 | 417 | uncomp_data->temperature = data_msb | data_lsb | data_xlsb; |
| mcm | 2:853301624d95 | 418 | |
| mcm | 2:853301624d95 | 419 | /* Store the parsed register values for temperature data */ |
| mcm | 2:853301624d95 | 420 | data_lsb = (uint32_t)reg_data[6] << 8; |
| mcm | 2:853301624d95 | 421 | data_msb = (uint32_t)reg_data[7]; |
| mcm | 2:853301624d95 | 422 | uncomp_data->humidity = data_msb | data_lsb; |
| mcm | 2:853301624d95 | 423 | } |
| mcm | 2:853301624d95 | 424 | |
| mcm | 2:853301624d95 | 425 | /*! |
| mcm | 2:853301624d95 | 426 | * @brief This API is used to compensate the pressure and/or |
| mcm | 2:853301624d95 | 427 | * temperature and/or humidity data according to the component selected |
| mcm | 2:853301624d95 | 428 | * by the user. |
| mcm | 2:853301624d95 | 429 | */ |
| mcm | 2:853301624d95 | 430 | int8_t BME280::bme280_compensate_data(uint8_t sensor_comp, |
| mcm | 2:853301624d95 | 431 | const struct bme280_uncomp_data *uncomp_data, |
| mcm | 2:853301624d95 | 432 | struct bme280_data *comp_data, |
| mcm | 2:853301624d95 | 433 | struct bme280_calib_data *calib_data) |
| mcm | 2:853301624d95 | 434 | { |
| mcm | 2:853301624d95 | 435 | int8_t rslt = BME280_OK; |
| mcm | 2:853301624d95 | 436 | |
| mcm | 2:853301624d95 | 437 | if ((uncomp_data != NULL) && (comp_data != NULL) && (calib_data != NULL)) { |
| mcm | 2:853301624d95 | 438 | /* Initialize to zero */ |
| mcm | 2:853301624d95 | 439 | comp_data->temperature = 0; |
| mcm | 2:853301624d95 | 440 | comp_data->pressure = 0; |
| mcm | 2:853301624d95 | 441 | comp_data->humidity = 0; |
| mcm | 2:853301624d95 | 442 | |
| mcm | 2:853301624d95 | 443 | /* If pressure or temperature component is selected */ |
| mcm | 2:853301624d95 | 444 | if (sensor_comp & (BME280_PRESS | BME280_TEMP | BME280_HUM)) { |
| mcm | 2:853301624d95 | 445 | /* Compensate the temperature data */ |
| mcm | 2:853301624d95 | 446 | comp_data->temperature = compensate_temperature(uncomp_data, calib_data); |
| mcm | 2:853301624d95 | 447 | } |
| mcm | 2:853301624d95 | 448 | if (sensor_comp & BME280_PRESS) { |
| mcm | 2:853301624d95 | 449 | /* Compensate the pressure data */ |
| mcm | 2:853301624d95 | 450 | comp_data->pressure = compensate_pressure(uncomp_data, calib_data); |
| mcm | 2:853301624d95 | 451 | } |
| mcm | 2:853301624d95 | 452 | if (sensor_comp & BME280_HUM) { |
| mcm | 2:853301624d95 | 453 | /* Compensate the humidity data */ |
| mcm | 2:853301624d95 | 454 | comp_data->humidity = compensate_humidity(uncomp_data, calib_data); |
| mcm | 2:853301624d95 | 455 | } |
| mcm | 2:853301624d95 | 456 | } else { |
| mcm | 2:853301624d95 | 457 | rslt = BME280_E_NULL_PTR; |
| mcm | 2:853301624d95 | 458 | } |
| mcm | 2:853301624d95 | 459 | |
| mcm | 2:853301624d95 | 460 | return rslt; |
| mcm | 2:853301624d95 | 461 | } |
| mcm | 2:853301624d95 | 462 | |
| mcm | 2:853301624d95 | 463 | /*! |
| mcm | 2:853301624d95 | 464 | * @brief This internal API sets the oversampling settings for pressure, |
| mcm | 2:853301624d95 | 465 | * temperature and humidity in the sensor. |
| mcm | 2:853301624d95 | 466 | */ |
| mcm | 3:ab857b70346e | 467 | int8_t BME280::set_osr_settings(uint8_t desired_settings, |
| mcm | 2:853301624d95 | 468 | const struct bme280_settings *settings, |
| mcm | 2:853301624d95 | 469 | const struct bme280_dev *dev) |
| mcm | 2:853301624d95 | 470 | { |
| mcm | 2:853301624d95 | 471 | int8_t rslt = BME280_W_INVALID_OSR_MACRO; |
| mcm | 2:853301624d95 | 472 | |
| mcm | 2:853301624d95 | 473 | if (desired_settings & BME280_OSR_HUM_SEL) { |
| mcm | 2:853301624d95 | 474 | rslt = set_osr_humidity_settings(settings, dev); |
| mcm | 2:853301624d95 | 475 | } |
| mcm | 2:853301624d95 | 476 | if (desired_settings & (BME280_OSR_PRESS_SEL | BME280_OSR_TEMP_SEL)) { |
| mcm | 2:853301624d95 | 477 | rslt = set_osr_press_temp_settings(desired_settings, settings, dev); |
| mcm | 2:853301624d95 | 478 | } |
| mcm | 2:853301624d95 | 479 | |
| mcm | 2:853301624d95 | 480 | return rslt; |
| mcm | 2:853301624d95 | 481 | } |
| mcm | 2:853301624d95 | 482 | |
| mcm | 2:853301624d95 | 483 | /*! |
| mcm | 2:853301624d95 | 484 | * @brief This API sets the humidity oversampling settings of the sensor. |
| mcm | 2:853301624d95 | 485 | */ |
| mcm | 3:ab857b70346e | 486 | int8_t BME280::set_osr_humidity_settings(const struct bme280_settings *settings, const struct bme280_dev *dev) |
| mcm | 2:853301624d95 | 487 | { |
| mcm | 2:853301624d95 | 488 | int8_t rslt; |
| mcm | 2:853301624d95 | 489 | uint8_t ctrl_hum; |
| mcm | 2:853301624d95 | 490 | uint8_t ctrl_meas; |
| mcm | 2:853301624d95 | 491 | uint8_t reg_addr = BME280_CTRL_HUM_ADDR; |
| mcm | 2:853301624d95 | 492 | |
| mcm | 2:853301624d95 | 493 | ctrl_hum = settings->osr_h & BME280_CTRL_HUM_MSK; |
| mcm | 2:853301624d95 | 494 | |
| mcm | 2:853301624d95 | 495 | /* Write the humidity control value in the register */ |
| mcm | 2:853301624d95 | 496 | rslt = bme280_set_regs(®_addr, &ctrl_hum, 1, dev); |
| mcm | 2:853301624d95 | 497 | |
| mcm | 2:853301624d95 | 498 | /* Humidity related changes will be only effective after a |
| mcm | 2:853301624d95 | 499 | * write operation to ctrl_meas register |
| mcm | 2:853301624d95 | 500 | */ |
| mcm | 2:853301624d95 | 501 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 502 | reg_addr = BME280_CTRL_MEAS_ADDR; |
| mcm | 2:853301624d95 | 503 | rslt = bme280_get_regs(reg_addr, &ctrl_meas, 1, dev); |
| mcm | 2:853301624d95 | 504 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 505 | rslt = bme280_set_regs(®_addr, &ctrl_meas, 1, dev); |
| mcm | 2:853301624d95 | 506 | } |
| mcm | 2:853301624d95 | 507 | } |
| mcm | 2:853301624d95 | 508 | |
| mcm | 2:853301624d95 | 509 | return rslt; |
| mcm | 2:853301624d95 | 510 | } |
| mcm | 2:853301624d95 | 511 | |
| mcm | 2:853301624d95 | 512 | /*! |
| mcm | 2:853301624d95 | 513 | * @brief This API sets the pressure and/or temperature oversampling settings |
| mcm | 2:853301624d95 | 514 | * in the sensor according to the settings selected by the user. |
| mcm | 2:853301624d95 | 515 | */ |
| mcm | 3:ab857b70346e | 516 | int8_t BME280::set_osr_press_temp_settings(uint8_t desired_settings, |
| mcm | 2:853301624d95 | 517 | const struct bme280_settings *settings, |
| mcm | 2:853301624d95 | 518 | const struct bme280_dev *dev) |
| mcm | 2:853301624d95 | 519 | { |
| mcm | 2:853301624d95 | 520 | int8_t rslt; |
| mcm | 2:853301624d95 | 521 | uint8_t reg_addr = BME280_CTRL_MEAS_ADDR; |
| mcm | 2:853301624d95 | 522 | uint8_t reg_data; |
| mcm | 2:853301624d95 | 523 | |
| mcm | 2:853301624d95 | 524 | rslt = bme280_get_regs(reg_addr, ®_data, 1, dev); |
| mcm | 2:853301624d95 | 525 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 526 | if (desired_settings & BME280_OSR_PRESS_SEL) { |
| mcm | 2:853301624d95 | 527 | fill_osr_press_settings(®_data, settings); |
| mcm | 2:853301624d95 | 528 | } |
| mcm | 2:853301624d95 | 529 | if (desired_settings & BME280_OSR_TEMP_SEL) { |
| mcm | 2:853301624d95 | 530 | fill_osr_temp_settings(®_data, settings); |
| mcm | 2:853301624d95 | 531 | } |
| mcm | 2:853301624d95 | 532 | |
| mcm | 2:853301624d95 | 533 | /* Write the oversampling settings in the register */ |
| mcm | 2:853301624d95 | 534 | rslt = bme280_set_regs(®_addr, ®_data, 1, dev); |
| mcm | 2:853301624d95 | 535 | } |
| mcm | 2:853301624d95 | 536 | |
| mcm | 2:853301624d95 | 537 | return rslt; |
| mcm | 2:853301624d95 | 538 | } |
| mcm | 2:853301624d95 | 539 | |
| mcm | 2:853301624d95 | 540 | /*! |
| mcm | 2:853301624d95 | 541 | * @brief This internal API sets the filter and/or standby duration settings |
| mcm | 2:853301624d95 | 542 | * in the sensor according to the settings selected by the user. |
| mcm | 2:853301624d95 | 543 | */ |
| mcm | 3:ab857b70346e | 544 | int8_t BME280::set_filter_standby_settings(uint8_t desired_settings, |
| mcm | 2:853301624d95 | 545 | const struct bme280_settings *settings, |
| mcm | 2:853301624d95 | 546 | const struct bme280_dev *dev) |
| mcm | 2:853301624d95 | 547 | { |
| mcm | 2:853301624d95 | 548 | int8_t rslt; |
| mcm | 2:853301624d95 | 549 | uint8_t reg_addr = BME280_CONFIG_ADDR; |
| mcm | 2:853301624d95 | 550 | uint8_t reg_data; |
| mcm | 2:853301624d95 | 551 | |
| mcm | 2:853301624d95 | 552 | rslt = bme280_get_regs(reg_addr, ®_data, 1, dev); |
| mcm | 2:853301624d95 | 553 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 554 | if (desired_settings & BME280_FILTER_SEL) { |
| mcm | 2:853301624d95 | 555 | fill_filter_settings(®_data, settings); |
| mcm | 2:853301624d95 | 556 | } |
| mcm | 2:853301624d95 | 557 | if (desired_settings & BME280_STANDBY_SEL) { |
| mcm | 2:853301624d95 | 558 | fill_standby_settings(®_data, settings); |
| mcm | 2:853301624d95 | 559 | } |
| mcm | 2:853301624d95 | 560 | |
| mcm | 2:853301624d95 | 561 | /* Write the oversampling settings in the register */ |
| mcm | 2:853301624d95 | 562 | rslt = bme280_set_regs(®_addr, ®_data, 1, dev); |
| mcm | 2:853301624d95 | 563 | } |
| mcm | 2:853301624d95 | 564 | |
| mcm | 2:853301624d95 | 565 | return rslt; |
| mcm | 2:853301624d95 | 566 | } |
| mcm | 2:853301624d95 | 567 | |
| mcm | 2:853301624d95 | 568 | /*! |
| mcm | 2:853301624d95 | 569 | * @brief This internal API fills the filter settings provided by the user |
| mcm | 2:853301624d95 | 570 | * in the data buffer so as to write in the sensor. |
| mcm | 2:853301624d95 | 571 | */ |
| mcm | 3:ab857b70346e | 572 | void BME280::fill_filter_settings(uint8_t *reg_data, const struct bme280_settings *settings) |
| mcm | 2:853301624d95 | 573 | { |
| mcm | 2:853301624d95 | 574 | *reg_data = BME280_SET_BITS(*reg_data, BME280_FILTER, settings->filter); |
| mcm | 2:853301624d95 | 575 | } |
| mcm | 2:853301624d95 | 576 | |
| mcm | 2:853301624d95 | 577 | /*! |
| mcm | 2:853301624d95 | 578 | * @brief This internal API fills the standby duration settings provided by |
| mcm | 2:853301624d95 | 579 | * the user in the data buffer so as to write in the sensor. |
| mcm | 2:853301624d95 | 580 | */ |
| mcm | 3:ab857b70346e | 581 | void BME280::fill_standby_settings(uint8_t *reg_data, const struct bme280_settings *settings) |
| mcm | 2:853301624d95 | 582 | { |
| mcm | 2:853301624d95 | 583 | *reg_data = BME280_SET_BITS(*reg_data, BME280_STANDBY, settings->standby_time); |
| mcm | 2:853301624d95 | 584 | } |
| mcm | 2:853301624d95 | 585 | |
| mcm | 2:853301624d95 | 586 | /*! |
| mcm | 2:853301624d95 | 587 | * @brief This internal API fills the pressure oversampling settings provided by |
| mcm | 2:853301624d95 | 588 | * the user in the data buffer so as to write in the sensor. |
| mcm | 2:853301624d95 | 589 | */ |
| mcm | 3:ab857b70346e | 590 | void BME280::fill_osr_press_settings(uint8_t *reg_data, const struct bme280_settings *settings) |
| mcm | 2:853301624d95 | 591 | { |
| mcm | 2:853301624d95 | 592 | *reg_data = BME280_SET_BITS(*reg_data, BME280_CTRL_PRESS, settings->osr_p); |
| mcm | 2:853301624d95 | 593 | } |
| mcm | 2:853301624d95 | 594 | |
| mcm | 2:853301624d95 | 595 | /*! |
| mcm | 2:853301624d95 | 596 | * @brief This internal API fills the temperature oversampling settings |
| mcm | 2:853301624d95 | 597 | * provided by the user in the data buffer so as to write in the sensor. |
| mcm | 2:853301624d95 | 598 | */ |
| mcm | 3:ab857b70346e | 599 | void BME280::fill_osr_temp_settings(uint8_t *reg_data, const struct bme280_settings *settings) |
| mcm | 2:853301624d95 | 600 | { |
| mcm | 2:853301624d95 | 601 | *reg_data = BME280_SET_BITS(*reg_data, BME280_CTRL_TEMP, settings->osr_t); |
| mcm | 2:853301624d95 | 602 | } |
| mcm | 2:853301624d95 | 603 | |
| mcm | 2:853301624d95 | 604 | /*! |
| mcm | 2:853301624d95 | 605 | * @brief This internal API parse the oversampling(pressure, temperature |
| mcm | 2:853301624d95 | 606 | * and humidity), filter and standby duration settings and store in the |
| mcm | 2:853301624d95 | 607 | * device structure. |
| mcm | 2:853301624d95 | 608 | */ |
| mcm | 3:ab857b70346e | 609 | void BME280::parse_device_settings(const uint8_t *reg_data, struct bme280_settings *settings) |
| mcm | 2:853301624d95 | 610 | { |
| mcm | 2:853301624d95 | 611 | settings->osr_h = BME280_GET_BITS_POS_0(reg_data[0], BME280_CTRL_HUM); |
| mcm | 2:853301624d95 | 612 | settings->osr_p = BME280_GET_BITS(reg_data[2], BME280_CTRL_PRESS); |
| mcm | 2:853301624d95 | 613 | settings->osr_t = BME280_GET_BITS(reg_data[2], BME280_CTRL_TEMP); |
| mcm | 2:853301624d95 | 614 | settings->filter = BME280_GET_BITS(reg_data[3], BME280_FILTER); |
| mcm | 2:853301624d95 | 615 | settings->standby_time = BME280_GET_BITS(reg_data[3], BME280_STANDBY); |
| mcm | 2:853301624d95 | 616 | } |
| mcm | 2:853301624d95 | 617 | |
| mcm | 2:853301624d95 | 618 | /*! |
| mcm | 2:853301624d95 | 619 | * @brief This internal API writes the power mode in the sensor. |
| mcm | 2:853301624d95 | 620 | */ |
| mcm | 3:ab857b70346e | 621 | int8_t BME280::write_power_mode(uint8_t sensor_mode, const struct bme280_dev *dev) |
| mcm | 2:853301624d95 | 622 | { |
| mcm | 2:853301624d95 | 623 | int8_t rslt; |
| mcm | 2:853301624d95 | 624 | uint8_t reg_addr = BME280_PWR_CTRL_ADDR; |
| mcm | 2:853301624d95 | 625 | |
| mcm | 2:853301624d95 | 626 | /* Variable to store the value read from power mode register */ |
| mcm | 2:853301624d95 | 627 | uint8_t sensor_mode_reg_val; |
| mcm | 2:853301624d95 | 628 | |
| mcm | 2:853301624d95 | 629 | /* Read the power mode register */ |
| mcm | 2:853301624d95 | 630 | rslt = bme280_get_regs(reg_addr, &sensor_mode_reg_val, 1, dev); |
| mcm | 2:853301624d95 | 631 | |
| mcm | 2:853301624d95 | 632 | /* Set the power mode */ |
| mcm | 2:853301624d95 | 633 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 634 | sensor_mode_reg_val = BME280_SET_BITS_POS_0(sensor_mode_reg_val, BME280_SENSOR_MODE, sensor_mode); |
| mcm | 2:853301624d95 | 635 | |
| mcm | 2:853301624d95 | 636 | /* Write the power mode in the register */ |
| mcm | 2:853301624d95 | 637 | rslt = bme280_set_regs(®_addr, &sensor_mode_reg_val, 1, dev); |
| mcm | 2:853301624d95 | 638 | } |
| mcm | 2:853301624d95 | 639 | |
| mcm | 2:853301624d95 | 640 | return rslt; |
| mcm | 2:853301624d95 | 641 | } |
| mcm | 2:853301624d95 | 642 | |
| mcm | 2:853301624d95 | 643 | /*! |
| mcm | 2:853301624d95 | 644 | * @brief This internal API puts the device to sleep mode. |
| mcm | 2:853301624d95 | 645 | */ |
| mcm | 3:ab857b70346e | 646 | int8_t BME280::put_device_to_sleep(const struct bme280_dev *dev) |
| mcm | 2:853301624d95 | 647 | { |
| mcm | 2:853301624d95 | 648 | int8_t rslt; |
| mcm | 2:853301624d95 | 649 | uint8_t reg_data[4]; |
| mcm | 2:853301624d95 | 650 | struct bme280_settings settings; |
| mcm | 2:853301624d95 | 651 | |
| mcm | 2:853301624d95 | 652 | rslt = bme280_get_regs(BME280_CTRL_HUM_ADDR, reg_data, 4, dev); |
| mcm | 2:853301624d95 | 653 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 654 | parse_device_settings(reg_data, &settings); |
| mcm | 2:853301624d95 | 655 | rslt = bme280_soft_reset(dev); |
| mcm | 2:853301624d95 | 656 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 657 | rslt = reload_device_settings(&settings, dev); |
| mcm | 2:853301624d95 | 658 | } |
| mcm | 2:853301624d95 | 659 | } |
| mcm | 2:853301624d95 | 660 | |
| mcm | 2:853301624d95 | 661 | return rslt; |
| mcm | 2:853301624d95 | 662 | } |
| mcm | 2:853301624d95 | 663 | |
| mcm | 2:853301624d95 | 664 | /*! |
| mcm | 2:853301624d95 | 665 | * @brief This internal API reloads the already existing device settings in |
| mcm | 2:853301624d95 | 666 | * the sensor after soft reset. |
| mcm | 2:853301624d95 | 667 | */ |
| mcm | 3:ab857b70346e | 668 | int8_t BME280::reload_device_settings(const struct bme280_settings *settings, const struct bme280_dev *dev) |
| mcm | 2:853301624d95 | 669 | { |
| mcm | 2:853301624d95 | 670 | int8_t rslt; |
| mcm | 2:853301624d95 | 671 | |
| mcm | 2:853301624d95 | 672 | rslt = set_osr_settings(BME280_ALL_SETTINGS_SEL, settings, dev); |
| mcm | 2:853301624d95 | 673 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 674 | rslt = set_filter_standby_settings(BME280_ALL_SETTINGS_SEL, settings, dev); |
| mcm | 2:853301624d95 | 675 | } |
| mcm | 2:853301624d95 | 676 | |
| mcm | 2:853301624d95 | 677 | return rslt; |
| mcm | 2:853301624d95 | 678 | } |
| mcm | 2:853301624d95 | 679 | |
| mcm | 2:853301624d95 | 680 | #ifdef BME280_FLOAT_ENABLE |
| mcm | 2:853301624d95 | 681 | |
| mcm | 2:853301624d95 | 682 | /*! |
| mcm | 2:853301624d95 | 683 | * @brief This internal API is used to compensate the raw temperature data and |
| mcm | 2:853301624d95 | 684 | * return the compensated temperature data in double data type. |
| mcm | 2:853301624d95 | 685 | */ |
| mcm | 3:ab857b70346e | 686 | double BME280::compensate_temperature(const struct bme280_uncomp_data *uncomp_data, struct bme280_calib_data *calib_data) |
| mcm | 2:853301624d95 | 687 | { |
| mcm | 2:853301624d95 | 688 | double var1; |
| mcm | 2:853301624d95 | 689 | double var2; |
| mcm | 2:853301624d95 | 690 | double temperature; |
| mcm | 2:853301624d95 | 691 | double temperature_min = -40; |
| mcm | 2:853301624d95 | 692 | double temperature_max = 85; |
| mcm | 2:853301624d95 | 693 | |
| mcm | 2:853301624d95 | 694 | var1 = ((double)uncomp_data->temperature) / 16384.0 - ((double)calib_data->dig_T1) / 1024.0; |
| mcm | 2:853301624d95 | 695 | var1 = var1 * ((double)calib_data->dig_T2); |
| mcm | 2:853301624d95 | 696 | var2 = (((double)uncomp_data->temperature) / 131072.0 - ((double)calib_data->dig_T1) / 8192.0); |
| mcm | 2:853301624d95 | 697 | var2 = (var2 * var2) * ((double)calib_data->dig_T3); |
| mcm | 2:853301624d95 | 698 | calib_data->t_fine = (int32_t)(var1 + var2); |
| mcm | 2:853301624d95 | 699 | temperature = (var1 + var2) / 5120.0; |
| mcm | 2:853301624d95 | 700 | if (temperature < temperature_min) { |
| mcm | 2:853301624d95 | 701 | temperature = temperature_min; |
| mcm | 2:853301624d95 | 702 | } else if (temperature > temperature_max) { |
| mcm | 2:853301624d95 | 703 | temperature = temperature_max; |
| mcm | 2:853301624d95 | 704 | } |
| mcm | 2:853301624d95 | 705 | |
| mcm | 2:853301624d95 | 706 | return temperature; |
| mcm | 2:853301624d95 | 707 | } |
| mcm | 2:853301624d95 | 708 | |
| mcm | 2:853301624d95 | 709 | /*! |
| mcm | 2:853301624d95 | 710 | * @brief This internal API is used to compensate the raw pressure data and |
| mcm | 2:853301624d95 | 711 | * return the compensated pressure data in double data type. |
| mcm | 2:853301624d95 | 712 | */ |
| mcm | 3:ab857b70346e | 713 | double BME280::compensate_pressure(const struct bme280_uncomp_data *uncomp_data, |
| mcm | 2:853301624d95 | 714 | const struct bme280_calib_data *calib_data) |
| mcm | 2:853301624d95 | 715 | { |
| mcm | 2:853301624d95 | 716 | double var1; |
| mcm | 2:853301624d95 | 717 | double var2; |
| mcm | 2:853301624d95 | 718 | double var3; |
| mcm | 2:853301624d95 | 719 | double pressure; |
| mcm | 2:853301624d95 | 720 | double pressure_min = 30000.0; |
| mcm | 2:853301624d95 | 721 | double pressure_max = 110000.0; |
| mcm | 2:853301624d95 | 722 | |
| mcm | 2:853301624d95 | 723 | var1 = ((double)calib_data->t_fine / 2.0) - 64000.0; |
| mcm | 2:853301624d95 | 724 | var2 = var1 * var1 * ((double)calib_data->dig_P6) / 32768.0; |
| mcm | 2:853301624d95 | 725 | var2 = var2 + var1 * ((double)calib_data->dig_P5) * 2.0; |
| mcm | 2:853301624d95 | 726 | var2 = (var2 / 4.0) + (((double)calib_data->dig_P4) * 65536.0); |
| mcm | 2:853301624d95 | 727 | var3 = ((double)calib_data->dig_P3) * var1 * var1 / 524288.0; |
| mcm | 2:853301624d95 | 728 | var1 = (var3 + ((double)calib_data->dig_P2) * var1) / 524288.0; |
| mcm | 2:853301624d95 | 729 | var1 = (1.0 + var1 / 32768.0) * ((double)calib_data->dig_P1); |
| mcm | 2:853301624d95 | 730 | |
| mcm | 2:853301624d95 | 731 | /* avoid exception caused by division by zero */ |
| mcm | 2:853301624d95 | 732 | if (var1) { |
| mcm | 2:853301624d95 | 733 | pressure = 1048576.0 - (double) uncomp_data->pressure; |
| mcm | 2:853301624d95 | 734 | pressure = (pressure - (var2 / 4096.0)) * 6250.0 / var1; |
| mcm | 2:853301624d95 | 735 | var1 = ((double)calib_data->dig_P9) * pressure * pressure / 2147483648.0; |
| mcm | 2:853301624d95 | 736 | var2 = pressure * ((double)calib_data->dig_P8) / 32768.0; |
| mcm | 2:853301624d95 | 737 | pressure = pressure + (var1 + var2 + ((double)calib_data->dig_P7)) / 16.0; |
| mcm | 2:853301624d95 | 738 | if (pressure < pressure_min) { |
| mcm | 2:853301624d95 | 739 | pressure = pressure_min; |
| mcm | 2:853301624d95 | 740 | } else if (pressure > pressure_max) { |
| mcm | 2:853301624d95 | 741 | pressure = pressure_max; |
| mcm | 2:853301624d95 | 742 | } |
| mcm | 2:853301624d95 | 743 | } else { /* Invalid case */ |
| mcm | 2:853301624d95 | 744 | pressure = pressure_min; |
| mcm | 2:853301624d95 | 745 | } |
| mcm | 2:853301624d95 | 746 | |
| mcm | 2:853301624d95 | 747 | return pressure; |
| mcm | 2:853301624d95 | 748 | } |
| mcm | 2:853301624d95 | 749 | |
| mcm | 2:853301624d95 | 750 | /*! |
| mcm | 2:853301624d95 | 751 | * @brief This internal API is used to compensate the raw humidity data and |
| mcm | 2:853301624d95 | 752 | * return the compensated humidity data in double data type. |
| mcm | 2:853301624d95 | 753 | */ |
| mcm | 3:ab857b70346e | 754 | double BME280::compensate_humidity(const struct bme280_uncomp_data *uncomp_data, |
| mcm | 2:853301624d95 | 755 | const struct bme280_calib_data *calib_data) |
| mcm | 2:853301624d95 | 756 | { |
| mcm | 2:853301624d95 | 757 | double humidity; |
| mcm | 2:853301624d95 | 758 | double humidity_min = 0.0; |
| mcm | 2:853301624d95 | 759 | double humidity_max = 100.0; |
| mcm | 2:853301624d95 | 760 | double var1; |
| mcm | 2:853301624d95 | 761 | double var2; |
| mcm | 2:853301624d95 | 762 | double var3; |
| mcm | 2:853301624d95 | 763 | double var4; |
| mcm | 2:853301624d95 | 764 | double var5; |
| mcm | 2:853301624d95 | 765 | double var6; |
| mcm | 2:853301624d95 | 766 | |
| mcm | 2:853301624d95 | 767 | var1 = ((double)calib_data->t_fine) - 76800.0; |
| mcm | 2:853301624d95 | 768 | var2 = (((double)calib_data->dig_H4) * 64.0 + (((double)calib_data->dig_H5) / 16384.0) * var1); |
| mcm | 2:853301624d95 | 769 | var3 = uncomp_data->humidity - var2; |
| mcm | 2:853301624d95 | 770 | var4 = ((double)calib_data->dig_H2) / 65536.0; |
| mcm | 2:853301624d95 | 771 | var5 = (1.0 + (((double)calib_data->dig_H3) / 67108864.0) * var1); |
| mcm | 2:853301624d95 | 772 | var6 = 1.0 + (((double)calib_data->dig_H6) / 67108864.0) * var1 * var5; |
| mcm | 2:853301624d95 | 773 | var6 = var3 * var4 * (var5 * var6); |
| mcm | 2:853301624d95 | 774 | humidity = var6 * (1.0 - ((double)calib_data->dig_H1) * var6 / 524288.0); |
| mcm | 2:853301624d95 | 775 | if (humidity > humidity_max) { |
| mcm | 2:853301624d95 | 776 | humidity = humidity_max; |
| mcm | 2:853301624d95 | 777 | } else if (humidity < humidity_min) { |
| mcm | 2:853301624d95 | 778 | humidity = humidity_min; |
| mcm | 2:853301624d95 | 779 | } |
| mcm | 2:853301624d95 | 780 | |
| mcm | 2:853301624d95 | 781 | return humidity; |
| mcm | 2:853301624d95 | 782 | } |
| mcm | 2:853301624d95 | 783 | |
| mcm | 2:853301624d95 | 784 | #else |
| mcm | 2:853301624d95 | 785 | |
| mcm | 2:853301624d95 | 786 | /*! |
| mcm | 2:853301624d95 | 787 | * @brief This internal API is used to compensate the raw temperature data and |
| mcm | 2:853301624d95 | 788 | * return the compensated temperature data in integer data type. |
| mcm | 2:853301624d95 | 789 | */ |
| mcm | 3:ab857b70346e | 790 | int32_t BME280::compensate_temperature(const struct bme280_uncomp_data *uncomp_data, |
| mcm | 2:853301624d95 | 791 | struct bme280_calib_data *calib_data) |
| mcm | 2:853301624d95 | 792 | { |
| mcm | 2:853301624d95 | 793 | int32_t var1; |
| mcm | 2:853301624d95 | 794 | int32_t var2; |
| mcm | 2:853301624d95 | 795 | int32_t temperature; |
| mcm | 2:853301624d95 | 796 | int32_t temperature_min = -4000; |
| mcm | 2:853301624d95 | 797 | int32_t temperature_max = 8500; |
| mcm | 2:853301624d95 | 798 | |
| mcm | 2:853301624d95 | 799 | var1 = (int32_t)((uncomp_data->temperature / 8) - ((int32_t)calib_data->dig_T1 * 2)); |
| mcm | 2:853301624d95 | 800 | var1 = (var1 * ((int32_t)calib_data->dig_T2)) / 2048; |
| mcm | 2:853301624d95 | 801 | var2 = (int32_t)((uncomp_data->temperature / 16) - ((int32_t)calib_data->dig_T1)); |
| mcm | 2:853301624d95 | 802 | var2 = (((var2 * var2) / 4096) * ((int32_t)calib_data->dig_T3)) / 16384; |
| mcm | 2:853301624d95 | 803 | calib_data->t_fine = var1 + var2; |
| mcm | 2:853301624d95 | 804 | temperature = (calib_data->t_fine * 5 + 128) / 256; |
| mcm | 2:853301624d95 | 805 | if (temperature < temperature_min) { |
| mcm | 2:853301624d95 | 806 | temperature = temperature_min; |
| mcm | 2:853301624d95 | 807 | } else if (temperature > temperature_max) { |
| mcm | 2:853301624d95 | 808 | temperature = temperature_max; |
| mcm | 2:853301624d95 | 809 | } |
| mcm | 2:853301624d95 | 810 | |
| mcm | 2:853301624d95 | 811 | return temperature; |
| mcm | 2:853301624d95 | 812 | } |
| mcm | 2:853301624d95 | 813 | #ifdef BME280_64BIT_ENABLE |
| mcm | 2:853301624d95 | 814 | |
| mcm | 2:853301624d95 | 815 | /*! |
| mcm | 2:853301624d95 | 816 | * @brief This internal API is used to compensate the raw pressure data and |
| mcm | 2:853301624d95 | 817 | * return the compensated pressure data in integer data type with higher |
| mcm | 2:853301624d95 | 818 | * accuracy. |
| mcm | 2:853301624d95 | 819 | */ |
| mcm | 3:ab857b70346e | 820 | uint32_t BME280::compensate_pressure(const struct bme280_uncomp_data *uncomp_data, |
| mcm | 2:853301624d95 | 821 | const struct bme280_calib_data *calib_data) |
| mcm | 2:853301624d95 | 822 | { |
| mcm | 2:853301624d95 | 823 | int64_t var1; |
| mcm | 2:853301624d95 | 824 | int64_t var2; |
| mcm | 2:853301624d95 | 825 | int64_t var3; |
| mcm | 2:853301624d95 | 826 | int64_t var4; |
| mcm | 2:853301624d95 | 827 | uint32_t pressure; |
| mcm | 2:853301624d95 | 828 | uint32_t pressure_min = 3000000; |
| mcm | 2:853301624d95 | 829 | uint32_t pressure_max = 11000000; |
| mcm | 2:853301624d95 | 830 | |
| mcm | 2:853301624d95 | 831 | var1 = ((int64_t)calib_data->t_fine) - 128000; |
| mcm | 2:853301624d95 | 832 | var2 = var1 * var1 * (int64_t)calib_data->dig_P6; |
| mcm | 2:853301624d95 | 833 | var2 = var2 + ((var1 * (int64_t)calib_data->dig_P5) * 131072); |
| mcm | 2:853301624d95 | 834 | var2 = var2 + (((int64_t)calib_data->dig_P4) * 34359738368); |
| mcm | 2:853301624d95 | 835 | var1 = ((var1 * var1 * (int64_t)calib_data->dig_P3) / 256) + ((var1 * ((int64_t)calib_data->dig_P2) * 4096)); |
| mcm | 2:853301624d95 | 836 | var3 = ((int64_t)1) * 140737488355328; |
| mcm | 2:853301624d95 | 837 | var1 = (var3 + var1) * ((int64_t)calib_data->dig_P1) / 8589934592; |
| mcm | 2:853301624d95 | 838 | |
| mcm | 2:853301624d95 | 839 | /* To avoid divide by zero exception */ |
| mcm | 2:853301624d95 | 840 | if (var1 != 0) { |
| mcm | 2:853301624d95 | 841 | var4 = 1048576 - uncomp_data->pressure; |
| mcm | 2:853301624d95 | 842 | var4 = (((var4 * INT64_C(2147483648)) - var2) * 3125) / var1; |
| mcm | 2:853301624d95 | 843 | var1 = (((int64_t)calib_data->dig_P9) * (var4 / 8192) * (var4 / 8192)) / 33554432; |
| mcm | 2:853301624d95 | 844 | var2 = (((int64_t)calib_data->dig_P8) * var4) / 524288; |
| mcm | 2:853301624d95 | 845 | var4 = ((var4 + var1 + var2) / 256) + (((int64_t)calib_data->dig_P7) * 16); |
| mcm | 2:853301624d95 | 846 | pressure = (uint32_t)(((var4 / 2) * 100) / 128); |
| mcm | 2:853301624d95 | 847 | if (pressure < pressure_min) { |
| mcm | 2:853301624d95 | 848 | pressure = pressure_min; |
| mcm | 2:853301624d95 | 849 | } else if (pressure > pressure_max) { |
| mcm | 2:853301624d95 | 850 | pressure = pressure_max; |
| mcm | 2:853301624d95 | 851 | } |
| mcm | 2:853301624d95 | 852 | } else { |
| mcm | 2:853301624d95 | 853 | pressure = pressure_min; |
| mcm | 2:853301624d95 | 854 | } |
| mcm | 2:853301624d95 | 855 | |
| mcm | 2:853301624d95 | 856 | return pressure; |
| mcm | 2:853301624d95 | 857 | } |
| mcm | 2:853301624d95 | 858 | #else |
| mcm | 2:853301624d95 | 859 | |
| mcm | 2:853301624d95 | 860 | /*! |
| mcm | 2:853301624d95 | 861 | * @brief This internal API is used to compensate the raw pressure data and |
| mcm | 2:853301624d95 | 862 | * return the compensated pressure data in integer data type. |
| mcm | 2:853301624d95 | 863 | */ |
| mcm | 3:ab857b70346e | 864 | uint32_t BME280::compensate_pressure(const struct bme280_uncomp_data *uncomp_data, |
| mcm | 2:853301624d95 | 865 | const struct bme280_calib_data *calib_data) |
| mcm | 2:853301624d95 | 866 | { |
| mcm | 2:853301624d95 | 867 | int32_t var1; |
| mcm | 2:853301624d95 | 868 | int32_t var2; |
| mcm | 2:853301624d95 | 869 | int32_t var3; |
| mcm | 2:853301624d95 | 870 | int32_t var4; |
| mcm | 2:853301624d95 | 871 | uint32_t var5; |
| mcm | 2:853301624d95 | 872 | uint32_t pressure; |
| mcm | 2:853301624d95 | 873 | uint32_t pressure_min = 30000; |
| mcm | 2:853301624d95 | 874 | uint32_t pressure_max = 110000; |
| mcm | 2:853301624d95 | 875 | |
| mcm | 2:853301624d95 | 876 | var1 = (((int32_t)calib_data->t_fine) / 2) - (int32_t)64000; |
| mcm | 2:853301624d95 | 877 | var2 = (((var1 / 4) * (var1 / 4)) / 2048) * ((int32_t)calib_data->dig_P6); |
| mcm | 2:853301624d95 | 878 | var2 = var2 + ((var1 * ((int32_t)calib_data->dig_P5)) * 2); |
| mcm | 2:853301624d95 | 879 | var2 = (var2 / 4) + (((int32_t)calib_data->dig_P4) * 65536); |
| mcm | 2:853301624d95 | 880 | var3 = (calib_data->dig_P3 * (((var1 / 4) * (var1 / 4)) / 8192)) / 8; |
| mcm | 2:853301624d95 | 881 | var4 = (((int32_t)calib_data->dig_P2) * var1) / 2; |
| mcm | 2:853301624d95 | 882 | var1 = (var3 + var4) / 262144; |
| mcm | 2:853301624d95 | 883 | var1 = (((32768 + var1)) * ((int32_t)calib_data->dig_P1)) / 32768; |
| mcm | 2:853301624d95 | 884 | |
| mcm | 2:853301624d95 | 885 | /* avoid exception caused by division by zero */ |
| mcm | 2:853301624d95 | 886 | if (var1) { |
| mcm | 2:853301624d95 | 887 | var5 = (uint32_t)((uint32_t)1048576) - uncomp_data->pressure; |
| mcm | 2:853301624d95 | 888 | pressure = ((uint32_t)(var5 - (uint32_t)(var2 / 4096))) * 3125; |
| mcm | 2:853301624d95 | 889 | if (pressure < 0x80000000) { |
| mcm | 2:853301624d95 | 890 | pressure = (pressure << 1) / ((uint32_t)var1); |
| mcm | 2:853301624d95 | 891 | } else { |
| mcm | 2:853301624d95 | 892 | pressure = (pressure / (uint32_t)var1) * 2; |
| mcm | 2:853301624d95 | 893 | } |
| mcm | 2:853301624d95 | 894 | var1 = (((int32_t)calib_data->dig_P9) * ((int32_t)(((pressure / 8) * (pressure / 8)) / 8192))) / 4096; |
| mcm | 2:853301624d95 | 895 | var2 = (((int32_t)(pressure / 4)) * ((int32_t)calib_data->dig_P8)) / 8192; |
| mcm | 2:853301624d95 | 896 | pressure = (uint32_t)((int32_t)pressure + ((var1 + var2 + calib_data->dig_P7) / 16)); |
| mcm | 2:853301624d95 | 897 | if (pressure < pressure_min) { |
| mcm | 2:853301624d95 | 898 | pressure = pressure_min; |
| mcm | 2:853301624d95 | 899 | } else if (pressure > pressure_max) { |
| mcm | 2:853301624d95 | 900 | pressure = pressure_max; |
| mcm | 2:853301624d95 | 901 | } |
| mcm | 2:853301624d95 | 902 | } else { |
| mcm | 2:853301624d95 | 903 | pressure = pressure_min; |
| mcm | 2:853301624d95 | 904 | } |
| mcm | 2:853301624d95 | 905 | |
| mcm | 2:853301624d95 | 906 | return pressure; |
| mcm | 2:853301624d95 | 907 | } |
| mcm | 2:853301624d95 | 908 | #endif |
| mcm | 2:853301624d95 | 909 | |
| mcm | 2:853301624d95 | 910 | /*! |
| mcm | 2:853301624d95 | 911 | * @brief This internal API is used to compensate the raw humidity data and |
| mcm | 2:853301624d95 | 912 | * return the compensated humidity data in integer data type. |
| mcm | 2:853301624d95 | 913 | */ |
| mcm | 3:ab857b70346e | 914 | uint32_t BME280::compensate_humidity(const struct bme280_uncomp_data *uncomp_data, |
| mcm | 2:853301624d95 | 915 | const struct bme280_calib_data *calib_data) |
| mcm | 2:853301624d95 | 916 | { |
| mcm | 2:853301624d95 | 917 | int32_t var1; |
| mcm | 2:853301624d95 | 918 | int32_t var2; |
| mcm | 2:853301624d95 | 919 | int32_t var3; |
| mcm | 2:853301624d95 | 920 | int32_t var4; |
| mcm | 2:853301624d95 | 921 | int32_t var5; |
| mcm | 2:853301624d95 | 922 | uint32_t humidity; |
| mcm | 2:853301624d95 | 923 | uint32_t humidity_max = 102400; |
| mcm | 2:853301624d95 | 924 | |
| mcm | 2:853301624d95 | 925 | var1 = calib_data->t_fine - ((int32_t)76800); |
| mcm | 2:853301624d95 | 926 | var2 = (int32_t)(uncomp_data->humidity * 16384); |
| mcm | 2:853301624d95 | 927 | var3 = (int32_t)(((int32_t)calib_data->dig_H4) * 1048576); |
| mcm | 2:853301624d95 | 928 | var4 = ((int32_t)calib_data->dig_H5) * var1; |
| mcm | 2:853301624d95 | 929 | var5 = (((var2 - var3) - var4) + (int32_t)16384) / 32768; |
| mcm | 2:853301624d95 | 930 | var2 = (var1 * ((int32_t)calib_data->dig_H6)) / 1024; |
| mcm | 2:853301624d95 | 931 | var3 = (var1 * ((int32_t)calib_data->dig_H3)) / 2048; |
| mcm | 2:853301624d95 | 932 | var4 = ((var2 * (var3 + (int32_t)32768)) / 1024) + (int32_t)2097152; |
| mcm | 2:853301624d95 | 933 | var2 = ((var4 * ((int32_t)calib_data->dig_H2)) + 8192) / 16384; |
| mcm | 2:853301624d95 | 934 | var3 = var5 * var2; |
| mcm | 2:853301624d95 | 935 | var4 = ((var3 / 32768) * (var3 / 32768)) / 128; |
| mcm | 2:853301624d95 | 936 | var5 = var3 - ((var4 * ((int32_t)calib_data->dig_H1)) / 16); |
| mcm | 2:853301624d95 | 937 | var5 = (var5 < 0 ? 0 : var5); |
| mcm | 2:853301624d95 | 938 | var5 = (var5 > 419430400 ? 419430400 : var5); |
| mcm | 2:853301624d95 | 939 | humidity = (uint32_t)(var5 / 4096); |
| mcm | 2:853301624d95 | 940 | if (humidity > humidity_max) { |
| mcm | 2:853301624d95 | 941 | humidity = humidity_max; |
| mcm | 2:853301624d95 | 942 | } |
| mcm | 2:853301624d95 | 943 | |
| mcm | 2:853301624d95 | 944 | return humidity; |
| mcm | 2:853301624d95 | 945 | } |
| mcm | 2:853301624d95 | 946 | #endif |
| mcm | 2:853301624d95 | 947 | |
| mcm | 2:853301624d95 | 948 | /*! |
| mcm | 2:853301624d95 | 949 | * @brief This internal API reads the calibration data from the sensor, parse |
| mcm | 2:853301624d95 | 950 | * it and store in the device structure. |
| mcm | 2:853301624d95 | 951 | */ |
| mcm | 3:ab857b70346e | 952 | int8_t BME280::get_calib_data(struct bme280_dev *dev) |
| mcm | 2:853301624d95 | 953 | { |
| mcm | 2:853301624d95 | 954 | int8_t rslt; |
| mcm | 2:853301624d95 | 955 | uint8_t reg_addr = BME280_TEMP_PRESS_CALIB_DATA_ADDR; |
| mcm | 2:853301624d95 | 956 | |
| mcm | 2:853301624d95 | 957 | /* Array to store calibration data */ |
| mcm | 2:853301624d95 | 958 | uint8_t calib_data[BME280_TEMP_PRESS_CALIB_DATA_LEN] = { 0 }; |
| mcm | 2:853301624d95 | 959 | |
| mcm | 2:853301624d95 | 960 | /* Read the calibration data from the sensor */ |
| mcm | 2:853301624d95 | 961 | rslt = bme280_get_regs(reg_addr, calib_data, BME280_TEMP_PRESS_CALIB_DATA_LEN, dev); |
| mcm | 2:853301624d95 | 962 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 963 | /* Parse temperature and pressure calibration data and store |
| mcm | 2:853301624d95 | 964 | * it in device structure |
| mcm | 2:853301624d95 | 965 | */ |
| mcm | 2:853301624d95 | 966 | parse_temp_press_calib_data(calib_data, dev); |
| mcm | 2:853301624d95 | 967 | reg_addr = BME280_HUMIDITY_CALIB_DATA_ADDR; |
| mcm | 2:853301624d95 | 968 | |
| mcm | 2:853301624d95 | 969 | /* Read the humidity calibration data from the sensor */ |
| mcm | 2:853301624d95 | 970 | rslt = bme280_get_regs(reg_addr, calib_data, BME280_HUMIDITY_CALIB_DATA_LEN, dev); |
| mcm | 2:853301624d95 | 971 | if (rslt == BME280_OK) { |
| mcm | 2:853301624d95 | 972 | /* Parse humidity calibration data and store it in |
| mcm | 2:853301624d95 | 973 | * device structure |
| mcm | 2:853301624d95 | 974 | */ |
| mcm | 2:853301624d95 | 975 | parse_humidity_calib_data(calib_data, dev); |
| mcm | 2:853301624d95 | 976 | } |
| mcm | 2:853301624d95 | 977 | } |
| mcm | 2:853301624d95 | 978 | |
| mcm | 2:853301624d95 | 979 | return rslt; |
| mcm | 2:853301624d95 | 980 | } |
| mcm | 2:853301624d95 | 981 | |
| mcm | 2:853301624d95 | 982 | /*! |
| mcm | 2:853301624d95 | 983 | * @brief This internal API interleaves the register address between the |
| mcm | 2:853301624d95 | 984 | * register data buffer for burst write operation. |
| mcm | 2:853301624d95 | 985 | */ |
| mcm | 3:ab857b70346e | 986 | 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 | 987 | { |
| mcm | 2:853301624d95 | 988 | uint8_t index; |
| mcm | 2:853301624d95 | 989 | |
| mcm | 2:853301624d95 | 990 | for (index = 1; index < len; index++) { |
| mcm | 2:853301624d95 | 991 | temp_buff[(index * 2) - 1] = reg_addr[index]; |
| mcm | 2:853301624d95 | 992 | temp_buff[index * 2] = reg_data[index]; |
| mcm | 2:853301624d95 | 993 | } |
| mcm | 2:853301624d95 | 994 | } |
| mcm | 2:853301624d95 | 995 | |
| mcm | 2:853301624d95 | 996 | /*! |
| mcm | 2:853301624d95 | 997 | * @brief This internal API is used to parse the temperature and |
| mcm | 2:853301624d95 | 998 | * pressure calibration data and store it in device structure. |
| mcm | 2:853301624d95 | 999 | */ |
| mcm | 3:ab857b70346e | 1000 | void BME280::parse_temp_press_calib_data(const uint8_t *reg_data, struct bme280_dev *dev) |
| mcm | 2:853301624d95 | 1001 | { |
| mcm | 2:853301624d95 | 1002 | struct bme280_calib_data *calib_data = &dev->calib_data; |
| mcm | 2:853301624d95 | 1003 | |
| mcm | 2:853301624d95 | 1004 | calib_data->dig_T1 = BME280_CONCAT_BYTES(reg_data[1], reg_data[0]); |
| mcm | 2:853301624d95 | 1005 | calib_data->dig_T2 = (int16_t)BME280_CONCAT_BYTES(reg_data[3], reg_data[2]); |
| mcm | 2:853301624d95 | 1006 | calib_data->dig_T3 = (int16_t)BME280_CONCAT_BYTES(reg_data[5], reg_data[4]); |
| mcm | 2:853301624d95 | 1007 | calib_data->dig_P1 = BME280_CONCAT_BYTES(reg_data[7], reg_data[6]); |
| mcm | 2:853301624d95 | 1008 | calib_data->dig_P2 = (int16_t)BME280_CONCAT_BYTES(reg_data[9], reg_data[8]); |
| mcm | 2:853301624d95 | 1009 | calib_data->dig_P3 = (int16_t)BME280_CONCAT_BYTES(reg_data[11], reg_data[10]); |
| mcm | 2:853301624d95 | 1010 | calib_data->dig_P4 = (int16_t)BME280_CONCAT_BYTES(reg_data[13], reg_data[12]); |
| mcm | 2:853301624d95 | 1011 | calib_data->dig_P5 = (int16_t)BME280_CONCAT_BYTES(reg_data[15], reg_data[14]); |
| mcm | 2:853301624d95 | 1012 | calib_data->dig_P6 = (int16_t)BME280_CONCAT_BYTES(reg_data[17], reg_data[16]); |
| mcm | 2:853301624d95 | 1013 | calib_data->dig_P7 = (int16_t)BME280_CONCAT_BYTES(reg_data[19], reg_data[18]); |
| mcm | 2:853301624d95 | 1014 | calib_data->dig_P8 = (int16_t)BME280_CONCAT_BYTES(reg_data[21], reg_data[20]); |
| mcm | 2:853301624d95 | 1015 | calib_data->dig_P9 = (int16_t)BME280_CONCAT_BYTES(reg_data[23], reg_data[22]); |
| mcm | 2:853301624d95 | 1016 | calib_data->dig_H1 = reg_data[25]; |
| mcm | 2:853301624d95 | 1017 | } |
| mcm | 2:853301624d95 | 1018 | |
| mcm | 2:853301624d95 | 1019 | /*! |
| mcm | 2:853301624d95 | 1020 | * @brief This internal API is used to parse the humidity calibration data |
| mcm | 2:853301624d95 | 1021 | * and store it in device structure. |
| mcm | 2:853301624d95 | 1022 | */ |
| mcm | 3:ab857b70346e | 1023 | void BME280::parse_humidity_calib_data(const uint8_t *reg_data, struct bme280_dev *dev) |
| mcm | 2:853301624d95 | 1024 | { |
| mcm | 2:853301624d95 | 1025 | struct bme280_calib_data *calib_data = &dev->calib_data; |
| mcm | 2:853301624d95 | 1026 | int16_t dig_H4_lsb; |
| mcm | 2:853301624d95 | 1027 | int16_t dig_H4_msb; |
| mcm | 2:853301624d95 | 1028 | int16_t dig_H5_lsb; |
| mcm | 2:853301624d95 | 1029 | int16_t dig_H5_msb; |
| mcm | 2:853301624d95 | 1030 | |
| mcm | 2:853301624d95 | 1031 | calib_data->dig_H2 = (int16_t)BME280_CONCAT_BYTES(reg_data[1], reg_data[0]); |
| mcm | 2:853301624d95 | 1032 | calib_data->dig_H3 = reg_data[2]; |
| mcm | 2:853301624d95 | 1033 | dig_H4_msb = (int16_t)(int8_t)reg_data[3] * 16; |
| mcm | 2:853301624d95 | 1034 | dig_H4_lsb = (int16_t)(reg_data[4] & 0x0F); |
| mcm | 2:853301624d95 | 1035 | calib_data->dig_H4 = dig_H4_msb | dig_H4_lsb; |
| mcm | 2:853301624d95 | 1036 | dig_H5_msb = (int16_t)(int8_t)reg_data[5] * 16; |
| mcm | 2:853301624d95 | 1037 | dig_H5_lsb = (int16_t)(reg_data[4] >> 4); |
| mcm | 2:853301624d95 | 1038 | calib_data->dig_H5 = dig_H5_msb | dig_H5_lsb; |
| mcm | 2:853301624d95 | 1039 | calib_data->dig_H6 = (int8_t)reg_data[6]; |
| mcm | 2:853301624d95 | 1040 | } |
| mcm | 2:853301624d95 | 1041 | |
| mcm | 2:853301624d95 | 1042 | /*! |
| mcm | 2:853301624d95 | 1043 | * @brief This internal API is used to identify the settings which the user |
| mcm | 2:853301624d95 | 1044 | * wants to modify in the sensor. |
| mcm | 2:853301624d95 | 1045 | */ |
| mcm | 3:ab857b70346e | 1046 | uint8_t BME280::are_settings_changed(uint8_t sub_settings, uint8_t desired_settings) |
| mcm | 2:853301624d95 | 1047 | { |
| mcm | 2:853301624d95 | 1048 | uint8_t settings_changed = FALSE; |
| mcm | 2:853301624d95 | 1049 | |
| mcm | 2:853301624d95 | 1050 | if (sub_settings & desired_settings) { |
| mcm | 2:853301624d95 | 1051 | /* User wants to modify this particular settings */ |
| mcm | 2:853301624d95 | 1052 | settings_changed = TRUE; |
| mcm | 2:853301624d95 | 1053 | } else { |
| mcm | 2:853301624d95 | 1054 | /* User don't want to modify this particular settings */ |
| mcm | 2:853301624d95 | 1055 | settings_changed = FALSE; |
| mcm | 2:853301624d95 | 1056 | } |
| mcm | 2:853301624d95 | 1057 | |
| mcm | 2:853301624d95 | 1058 | return settings_changed; |
| mcm | 2:853301624d95 | 1059 | } |
| mcm | 2:853301624d95 | 1060 | |
| mcm | 2:853301624d95 | 1061 | /*! |
| mcm | 2:853301624d95 | 1062 | * @brief This internal API is used to validate the device structure pointer for |
| mcm | 2:853301624d95 | 1063 | * null conditions. |
| mcm | 2:853301624d95 | 1064 | */ |
| mcm | 3:ab857b70346e | 1065 | int8_t BME280::null_ptr_check(const struct bme280_dev *dev) |
| mcm | 2:853301624d95 | 1066 | { |
| mcm | 2:853301624d95 | 1067 | int8_t rslt; |
| mcm | 2:853301624d95 | 1068 | |
| mcm | 2:853301624d95 | 1069 | if ((dev == NULL) || (dev->read == NULL) || (dev->write == NULL) || (dev->delay_ms == NULL)) { |
| mcm | 2:853301624d95 | 1070 | /* Device structure pointer is not valid */ |
| mcm | 2:853301624d95 | 1071 | rslt = BME280_E_NULL_PTR; |
| mcm | 2:853301624d95 | 1072 | } else { |
| mcm | 2:853301624d95 | 1073 | /* Device structure is fine */ |
| mcm | 2:853301624d95 | 1074 | rslt = BME280_OK; |
| mcm | 2:853301624d95 | 1075 | } |
| mcm | 2:853301624d95 | 1076 | |
| mcm | 2:853301624d95 | 1077 | return rslt; |
| mcm | 2:853301624d95 | 1078 | } |