Add support for BME280 I2C Barometric, humidity and temperature sensor
authorNathael Pajani <nathael.pajani@ed3l.fr>
Thu, 15 Sep 2016 03:13:50 +0000 (05:13 +0200)
committerNathael Pajani <nathael.pajani@ed3l.fr>
Fri, 10 Feb 2023 18:02:59 +0000 (19:02 +0100)
extdrv/bme280_humidity_sensor.c [new file with mode: 0644]
include/extdrv/bme280_humidity_sensor.h [new file with mode: 0644]

diff --git a/extdrv/bme280_humidity_sensor.c b/extdrv/bme280_humidity_sensor.c
new file mode 100644 (file)
index 0000000..fe8fd24
--- /dev/null
@@ -0,0 +1,322 @@
+/****************************************************************************
+ *   extdrv/bme280_humidity_sensor.c
+ *
+ * BME280 I2C Barometric, humidity and temperature sensor driver
+ *
+ * Copyright 2016 Nathael Pajani <nathael.pajani@ed3l.fr>
+ *
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *************************************************************************** */
+
+
+#include "lib/stdint.h"
+#include "core/system.h"
+#include "lib/errno.h"
+#include "drivers/i2c.h"
+
+#include "extdrv/bme280_humidity_sensor.h"
+
+
+
+/* Check the sensor presence, return 1 if found */
+#define PROBE_BUF_SIZE  3
+int bme280_probe_sensor(struct bme280_sensor_config* conf)
+{
+    char cmd_buf[PROBE_BUF_SIZE] = { conf->addr, BME280_REGS(chip_id), (conf->addr | I2C_READ_BIT), };
+       char ctrl_buf[PROBE_BUF_SIZE] = { I2C_CONT, I2C_DO_REPEATED_START, I2C_CONT, };
+       uint8_t id = 0;
+
+    /* Did we already probe the sensor ? */
+    if (conf->probe_ok != 1) {
+        conf->probe_ok = i2c_read(conf->bus_num, &cmd_buf, PROBE_BUF_SIZE, ctrl_buf, &id, 1);
+               if ((conf->probe_ok == 1) && (id != BME280_ID)) {
+                       conf->probe_ok = 0;
+               }
+    }
+    return conf->probe_ok;
+}
+
+
+/* Get calibration data from internal sensor memory
+ * These values are required to compute the pressure, temperature and humidity values
+ *   from the uncompensated "raw" values read from the sensor ADC result registers.
+ * Calibration data for pressure and temperature is aligned, packed, and in little
+ *    endian byte order, so it is stored directly to the conf->cal structure.
+ * Calibration data for humidity is split among different registers and not aligned,
+ *    so we use a temporary data buffer.
+ * Note : On the LPC822 the I2C bus requires some time to go idle, so we need to
+ *    sleep some time between two conscutive I2C access.
+ *    this should be done in the I2C driver, but is not yet implemented, so it is
+ *    done here. These msleep() calls may be removed for other micro-controllers, and
+ *    when the I2C driver for the LPC822 is imporved.
+ * Return value:
+ *   Upon successfull completion, returns 0. On error, returns a negative integer
+ *   equivalent to errors from glibc.
+ */
+#define CAL_CMD_SIZE  3
+int bme280_get_calibration_data(struct bme280_sensor_config* conf)
+{
+       int ret = 0;
+       char cmd_buf[CAL_CMD_SIZE] = { conf->addr, BME280_CAL_REGS(T), (conf->addr | I2C_READ_BIT), };
+       char ctrl_buf[CAL_CMD_SIZE] = { I2C_CONT, I2C_DO_REPEATED_START, I2C_CONT, };
+       uint8_t data[BME280_CAL_REGS_H_LEN];
+
+       if (bme280_probe_sensor(conf) != 1) {
+               return -ENODEV;
+       }
+
+       /* Give some time for I2C bus to go idle */
+       msleep(1);
+       /* Easy part : Temperature and Presure calibration data is packed, aligned, and
+        *   in little endian byte order */
+       /* Start by reading temperature calibration data */
+       ret = i2c_read(conf->bus_num, cmd_buf, CAL_CMD_SIZE, ctrl_buf, &(conf->cal.T1), BME280_CAL_REGS_T_LEN);
+       if (ret != BME280_CAL_REGS_T_LEN) {
+               conf->probe_ok = 0;
+               return ret;
+       }
+       msleep(1); /* Again some time for I2C bus to go idle */
+       /* Read pressure calibration data */
+       cmd_buf[1] = BME280_CAL_REGS(P);
+       ret = i2c_read(conf->bus_num, cmd_buf, CAL_CMD_SIZE, ctrl_buf, &(conf->cal.P1), BME280_CAL_REGS_P_LEN);
+       if (ret != BME280_CAL_REGS_P_LEN) {
+               conf->probe_ok = 0;
+               return ret;
+       }
+       msleep(1); /* ... */
+
+       /* Read humidity calibration data. This one is split among bytes and not aligned. use
+        *   temporary data buffer and then copy to conf structure. */
+       /* First part */
+       cmd_buf[1] = BME280_CAL_REGS(Ha);
+       ret = i2c_read(conf->bus_num, cmd_buf, CAL_CMD_SIZE, ctrl_buf, data, BME280_CAL_REGS_Ha_LEN);
+       if (ret != BME280_CAL_REGS_Ha_LEN) {
+               conf->probe_ok = 0;
+               return ret;
+       }
+       msleep(1); /* ... */
+       /* Second part */
+       cmd_buf[1] = BME280_CAL_REGS(Hb);
+       ret = i2c_read(conf->bus_num, cmd_buf, CAL_CMD_SIZE, ctrl_buf, (data + BME280_CAL_REGS_Ha_LEN), BME280_CAL_REGS_Hb_LEN);
+       if (ret != BME280_CAL_REGS_Hb_LEN) {
+               conf->probe_ok = 0;
+               return ret;
+       }
+       /* And store in calibration structure */
+       conf->cal.H1 = data[0];
+       conf->cal.H2 = ((data[1] & 0xFF) | ((data[2] & 0xFF) << 8));
+       conf->cal.H3 = data[3];
+       conf->cal.H4 = (((data[4] & 0xFF) << 4) | (data[5] & 0x0F));
+       conf->cal.H5 = (((data[6] & 0xFF) << 4) | ((data[5] & 0xF0) >> 4));
+       conf->cal.H6 = data[7];
+
+       return 0;
+}
+
+/* Sensor config
+ * Performs configuration of the sensor and recovers calibration data from sensor's internal
+ *   memory.
+ * Return value:
+ *   Upon successfull completion, returns 0. On error, returns a negative integer
+ *   equivalent to errors from glibc.
+ *   -EBADFD : I2C not initialized
+ *   -EBUSY : Device or ressource Busy or Arbitration lost
+ *   -EINVAL : Invalid argument (buf)
+ *   -ENODEV : No such device
+ *   -EREMOTEIO : Device did not acknowledge : Any device present ?
+ *   -EIO : Bad one: Illegal start or stop, or illegal state in i2c state machine
+ */
+#define CONF_BUF_SIZE 7
+int bme280_configure(struct bme280_sensor_config* conf)
+{
+    int ret = 0;
+    char cmd_buf[CONF_BUF_SIZE] = {
+                       conf->addr,
+                       BME280_REGS(ctrl_humidity), BME280_CTRL_HUM(conf->humidity_oversampling),
+                       BME280_REGS(ctrl_measure),
+                               BME280_CTRL_MEA(conf->pressure_oversampling, conf->temp_oversampling, conf->mode),
+                       BME280_REGS(config), BME280_CONFIG(conf->standby_len, conf->filter_coeff),
+                };
+
+    if (bme280_probe_sensor(conf) != 1) {
+        return -ENODEV;
+    }
+       /* The call to bme280_configure() was certainly the first access to the sensor, so
+        *   the probe part made I2C access, thus leave some delay for I2C to become available again. */
+       msleep(1);
+       /* Send the configuration */
+    ret = i2c_write(conf->bus_num, cmd_buf, CONF_BUF_SIZE, NULL);
+    if (ret != CONF_BUF_SIZE) {
+               conf->probe_ok = 0;
+        return -EIO;
+    }
+
+       ret = bme280_get_calibration_data(conf);
+
+    return ret;
+}
+
+
+/* Humidity, Temperature and Pressure Read
+ * Performs a read of the data from the sensor.
+ * 'hum', 'temp' and 'pressure': integer addresses for conversion result.
+ * Return value(s):
+ *   Upon successfull completion, returns 0 and the raw sensor values read are placed in the
+ *   provided integer(s). On error, returns a negative integer equivalent to errors from
+ *   glibc.
+ *   -EBADFD : I2C not initialized
+ *   -EBUSY : Device or ressource Busy or Arbitration lost
+ *   -EINVAL : Invalid argument (buf)
+ *   -ENODEV : No such device
+ *   -EREMOTEIO : Device did not acknowledge : Any device present ?
+ *   -EIO : Bad one: Illegal start or stop, or illegal state in i2c state machine
+ */
+#define READ_CMD_SIZE   3
+int bme280_sensor_read(struct bme280_sensor_config* conf, uint32_t* pressure, uint32_t* temp, uint16_t* hum)
+{
+    int ret = 0;
+    char cmd_buf[READ_CMD_SIZE] = { conf->addr, BME280_REGS(raw_data), (conf->addr | I2C_READ_BIT), };
+       char ctrl_buf[READ_CMD_SIZE] = { I2C_CONT, I2C_DO_REPEATED_START, I2C_CONT, };
+    uint8_t data[BME280_DATA_SIZE];
+
+    if (conf->probe_ok != 1) {
+           if (bme280_probe_sensor(conf) != 1) {
+                       return -ENODEV;
+           }
+               msleep(1);
+       }
+
+       /* Start by reading all data */
+    ret = i2c_read(conf->bus_num, cmd_buf, READ_CMD_SIZE, ctrl_buf, data, BME280_DATA_SIZE);
+    if (ret != BME280_DATA_SIZE) {
+               conf->probe_ok = 0;
+        return ret;
+    }
+       if (pressure != NULL) {
+               *pressure = BME280_DATA_20(data[0], data[1], data[2]);
+       }
+       if (temp != NULL) {
+               *temp = BME280_DATA_20(data[3], data[4], data[5]);
+       }
+       if (hum != NULL) {
+               *hum = BME280_DATA_16(data[6], data[7]);
+       }
+
+    return 0;
+}
+
+
+
+/* Compute actual temperature from uncompensated temperature
+ * Param :
+ *  - conf : bme280_sensor_configuration structure, with calibration data read from sensor
+ *  - utemp : uncompensated (raw) temperature value read from sensor
+ * Returns the value in 0.01 degree Centigrade
+ * Output value of "5123" equals 51.23 DegC.
+ */
+int bme280_compensate_temperature(struct bme280_sensor_config* conf, int utemp)
+{
+       int tmp1 = 0, tmp2 = 0;
+       int temperature = 0;
+
+       /* Calculate tmp1 */
+       tmp1 = ((((utemp >> 3) - ((int)conf->cal.T1 << 1))) * conf->cal.T2) >> 11;
+       /* Calculate tmp2 */
+       tmp2 = (((utemp >> 4) - (int)conf->cal.T1) * ((utemp >> 4) - (int)conf->cal.T1)) >> 12;
+       tmp2 = (tmp2 * conf->cal.T3) >> 14;
+       /* Calculate t_fine */
+       conf->fine_temp = tmp1 + tmp2;
+       /* Calculate temperature */
+       temperature = (conf->fine_temp * 5 + 128) >> 8;
+       return temperature;
+}
+
+/* Compute actual pressure from uncompensated pressure
+ * Returns the value in Pascal(Pa) or 0 on error (invalid value which would cause division by 0).
+ * Output value of "96386" equals 96386 Pa = 963.86 hPa = 963.86 millibar
+ */
+uint32_t bme280_compensate_pressure(struct bme280_sensor_config* conf, int uncomp_pressure)
+{
+       int tmp1 = 0, tmp2 = 0, tmp3 = 0;
+       uint32_t pressure = 0;
+
+       /* Calculate tmp1 */
+       tmp1 = (conf->fine_temp >> 1) - 64000;
+       /* Calculate tmp2 */
+       tmp2 = (((tmp1 >> 2) * (tmp1 >> 2)) >> 11) * conf->cal.P6;
+       tmp2 = tmp2 + ((tmp1 * conf->cal.P5) << 1);
+       tmp2 = (tmp2 >> 2) + (conf->cal.P4 << 16);
+       /* Update tmp1 */
+       tmp3 = (conf->cal.P3 * (((tmp1 >> 2) * (tmp1 >> 2)) >> 13)) >> 3;
+       tmp1 = (tmp3 + ((conf->cal.P2 * tmp1) >> 1)) >> 18;
+       tmp1 = (((32768 + tmp1)) * (int)conf->cal.P1) >> 15;
+       /* Calculate pressure */
+       pressure = ((uint32_t)(1048576 - uncomp_pressure) - (tmp2 >> 12)) * 3125;
+
+       /* Avoid exception caused by division by zero */
+       if (tmp1 == 0) {
+               return 0;
+       }
+       if (pressure < 0x80000000) {
+               pressure = (pressure << 1) / ((uint32_t)tmp1);
+       } else {
+               pressure = (pressure / (uint32_t)tmp1) * 2;
+       }
+
+       tmp1 = (conf->cal.P9 * ((int)(((pressure >> 3) * (pressure >> 3)) >> 13))) >> 12;
+       tmp2 = (((int)(pressure >> 2)) * conf->cal.P8) >> 13;
+       pressure = (uint32_t)((int)pressure + ((tmp1 + tmp2 + conf->cal.P7) >> 4));
+
+       return pressure;
+}
+
+
+/* Compute actual humidity from uncompensated humidity
+ * Returns the value in 0.01 %rH
+ * Output value of "4132" equals 41.32 %rH.
+ */
+uint32_t bme280_compensate_humidity(struct bme280_sensor_config* conf, int uncomp_humidity)
+{
+       int tmp1 = 0, tmp2 = 0, tmp3 = 0;
+       uint32_t humidity = 0;
+
+       /* Calculate tmp1 */
+       tmp1 = conf->fine_temp - 76800;
+       /* Calculate tmp2 */
+       tmp2 = ((uncomp_humidity << 14) - (conf->cal.H4 << 20) - (conf->cal.H5 * tmp1) + 16384) >> 15;
+       /* Calculate tmp3 */
+       tmp3 = ((((tmp1 * conf->cal.H6) >> 10) * (((tmp1 * (int)conf->cal.H3) >> 11) + 32768)) >> 10) + 2097152;
+       /* Update tmp1 */
+       tmp1 = tmp2 * ((tmp3 * conf->cal.H2 + 8192) >> 14);
+       tmp1 = tmp1 - (((((tmp1 >> 15) * (tmp1 >> 15)) >> 7) * (int)conf->cal.H1) >> 4);
+       if (tmp1 < 0) {
+               tmp1 = 0;
+       }
+       if (tmp1 > 419430400) {
+               tmp1 = 419430400;
+       }
+       humidity = (uint32_t)(tmp1 >> 12);
+       /* Convert from 32bit integer in Q22.10 format (22 integer 10 fractional bits) to a value
+        *   in 0.01 %rH :
+        * A value of 42313 represents 42313 / 1024 = 41.321 %rH, convert it to 4132, which is 41.32 %rH.
+        */
+       humidity = ((humidity >> 10) * 100) + ((((humidity & 0x3FF) * 1000) >> 10) / 10);
+       return humidity;
+
+}
+
+
+
diff --git a/include/extdrv/bme280_humidity_sensor.h b/include/extdrv/bme280_humidity_sensor.h
new file mode 100644 (file)
index 0000000..b8a5208
--- /dev/null
@@ -0,0 +1,222 @@
+/****************************************************************************
+ *   extdrv/bme280_humidity_sensor.h
+ *
+ * BME280 I2C Barometric, humidity and temperature sensor driver
+ *
+ * Copyright 2016 Nathael Pajani <nathael.pajani@ed3l.fr>
+ *
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *************************************************************************** */
+
+
+#include "lib/stdint.h"
+#include "core/system.h"
+
+struct bme280_calibration_data {
+       /* Temperature */
+       uint16_t T1;   /* 0x88 */
+       int16_t T2;    /* 0x8A */
+       int16_t T3;    /* 0x8C */
+       /* Pressure */
+       uint16_t P1;   /* 0x8E */
+       int16_t P2;    /* 0x90 */
+       int16_t P3;    /* 0x92 */
+       int16_t P4;    /* 0x94 */
+       int16_t P5;    /* 0x96 */
+       int16_t P6;    /* 0x98 */
+       int16_t P7;    /* 0x9A */
+       int16_t P8;    /* 0x9C */
+       int16_t P9;    /* 0x9E */
+       /* Humidity */
+       uint8_t H1;    /* 0xA1 */
+       int16_t H2;    /* 0xE1 .. 0xE2 */
+       uint8_t H3;    /* 0xE3 */
+       int16_t H4;    /* 0xE4 .. 0xE5[3:0] */
+       int16_t H5;    /* 0xE5[7:4] .. 0xE6 */
+       int8_t H6;     /* 0xE7 */
+};
+
+/* BME280 sensor instance data. */
+struct bme280_sensor_config {
+    uint8_t addr;
+       uint8_t bus_num;
+    uint8_t probe_ok;
+       uint8_t humidity_oversampling;
+       uint8_t temp_oversampling;
+       uint8_t pressure_oversampling;
+       uint8_t mode;
+    uint8_t standby_len;
+    uint8_t filter_coeff;
+       struct bme280_calibration_data cal;
+       int fine_temp;
+};
+
+#define BME280_DATA_SIZE   8
+struct bme280_data {
+       uint8_t pressure[3];      /* 0xF7 .. 0xF9 */
+       uint8_t temperature[3];  /* 0xFA .. 0xFC */
+       uint8_t humidity[2];     /* 0xFD .. 0xFE */
+} __attribute__ ((__packed__));
+
+
+struct bme280_calibration_regs {
+       /* Temperature */
+       uint16_t T[3];   /* 0x88 .. 0x8D */
+       /* Pressure */
+       uint16_t P[9];   /* 0x8E .. 0x9F */
+       /* Humidity */
+       uint8_t res0[1];
+       uint8_t Ha;    /* 0xA1 */
+       uint8_t res1[63];
+       uint8_t Hb[7];    /* 0xE1 .. 0xE7 */
+};
+#define BME280_CAL_REGS(x)   (((uint8_t)offsetof(struct bme280_calibration_regs, x)) + 0x88)
+#define BME280_CAL_REGS_T_LEN   6
+#define BME280_CAL_REGS_P_LEN   18
+#define BME280_CAL_REGS_Ha_LEN  1
+#define BME280_CAL_REGS_Hb_LEN  7
+#define BME280_CAL_REGS_H_LEN   (BME280_CAL_REGS_Ha_LEN + BME280_CAL_REGS_Hb_LEN)
+
+struct bme280_internal_regs {
+       uint8_t chip_id;         /* 0xD0 - Value should be 0x60 */
+       uint8_t reserved0[15];
+       uint8_t reset;           /* 0xE0 */
+       uint8_t reserved1[17];
+       uint8_t ctrl_humidity;   /* 0xF2 */
+       uint8_t status;          /* 0xF3 */
+       uint8_t ctrl_measure;    /* 0xF4 */
+       uint8_t config;          /* 0xF5 */
+       uint8_t reserved2[1];
+       union {
+               uint8_t raw_data[8];   /* 0xF7 .. 0xFE */
+               struct bme280_data data;
+       };
+} __attribute__ ((__packed__));
+#define BME280_REGS(x)   (((uint8_t)offsetof(struct bme280_internal_regs, x)) + 0xD0)
+
+
+#define BME280_ID   0x60
+#define BME280_RESET_MAGIC  0xB6
+
+/* Oversampling values */
+#define BME280_SKIP     0x00
+#define BME280_OS_x1    0x01
+#define BME280_OS_x2    0x02
+#define BME280_OS_x4    0x03
+#define BME280_OS_x8    0x04
+#define BME280_OS_x16   0x05
+
+/* Mode values */
+#define BME280_SLEEP    0x00
+#define BME280_FORCED   0x01
+#define BME280_NORMAL   0x03
+
+/* Control registers helpers */
+#define BME280_CTRL_HUM(hum)    ((hum) & 0x07)
+#define BME280_CTRL_MEA(pres, temp, mode)  \
+                       ( (((temp) & 0x07) << 5) | (((pres) & 0x07) << 2) | ((mode) & 0x03) )
+
+
+/* Standby */
+#define BME280_SB_05ms     0x00
+#define BME280_SB_10ms     0x06
+#define BME280_SB_20ms     0x07
+#define BME280_SB_62ms     0x01
+#define BME280_SB_125ms    0x02
+#define BME280_SB_250ms    0x03
+#define BME280_SB_500ms    0x04
+#define BME280_SB_1000ms   0x05
+
+/* Filter */
+#define BME280_FILT_OFF    0x00
+#define BME280_FILT_2      0x01
+#define BME280_FILT_4      0x02
+#define BME280_FILT_8      0x03
+#define BME280_FILT_16     0x04
+
+/* Config register helper */
+#define BME280_CONFIG(stb, filt)   ( (((stb) & 0x07) << 5) | (((filt) & 0x07) << 2) )
+
+
+/* Data helpers */
+#define BME280_DATA_20(msb, lsb, xlsb)  ((((msb) & 0xFF) << 12) | (((lsb) & 0xFF) << 4) | (((xlsb) & 0xF0) >> 4))
+#define BME280_DATA_16(msb, lsb)        ((((msb) & 0xFF) << 8) | ((lsb) & 0xFF))
+
+
+
+/* Check the sensor presence, return 1 if found */
+int bme280_probe_sensor(struct bme280_sensor_config* conf);
+
+
+/* Sensor config
+ * Performs configuration of the sensor and recovers calibration data from sensor's internal
+ *   memory.
+ * Return value:
+ *   Upon successfull completion, returns 0. On error, returns a negative integer
+ *   equivalent to errors from glibc.
+ *   -EBADFD : I2C not initialized
+ *   -EBUSY : Device or ressource Busy or Arbitration lost
+ *   -EINVAL : Invalid argument (buf)
+ *   -ENODEV : No such device
+ *   -EREMOTEIO : Device did not acknowledge : Any device present ?
+ *   -EIO : Bad one: Illegal start or stop, or illegal state in i2c state machine
+ */
+int bme280_configure(struct bme280_sensor_config* conf);
+
+
+
+/* Humidity, Temperature and Pressure Read
+ * Performs a read of the data from the sensor.
+ * 'hum', 'temp' and 'pressure': integer addresses for conversion result.
+ * Return value(s):
+ *   Upon successfull completion, returns 0 and the raw sensor values read are placed in the
+ *   provided integer(s). On error, returns a negative integer equivalent to errors from
+ *   glibc.
+ *   -EBADFD : I2C not initialized
+ *   -EBUSY : Device or ressource Busy or Arbitration lost
+ *   -EINVAL : Invalid argument (buf)
+ *   -ENODEV : No such device
+ *   -EREMOTEIO : Device did not acknowledge : Any device present ?
+ *   -EIO : Bad one: Illegal start or stop, or illegal state in i2c state machine
+ */
+int bme280_sensor_read(struct bme280_sensor_config* conf, uint32_t* temp, uint32_t* pressure, uint16_t* hum);
+
+
+/* Compute actual temperature from uncompensated temperature
+ * Param :
+ *  - conf : bme280_sensor_configuration structure, with calibration data read from sensor
+ *  - utemp : uncompensated (raw) temperature value read from sensor
+ * Returns the value in 0.01 degree Centigrade
+ * Output value of "5123" equals 51.23 DegC.
+ */
+int bme280_compensate_temperature(struct bme280_sensor_config* conf, int utemp);
+
+
+/* Compute actual pressure from uncompensated pressure
+ * Returns the value in Pascal(Pa) or 0 on error (invalid value which would cause division by 0).
+ * Output value of "96386" equals 96386 Pa = 963.86 hPa = 963.86 millibar
+ */
+uint32_t bme280_compensate_pressure(struct bme280_sensor_config* conf, int uncomp_pressure);
+
+
+/* Compute actual humidity from uncompensated humidity
+ * Returns the value in 0.01 %rH
+ * Output value of "4132" equals 41.32 %rH.
+ */
+uint32_t bme280_compensate_humidity(struct bme280_sensor_config* conf, int uncomp_humidity);
+
+
+