Driver for Bosch Sensortec BME280 combined humidity and pressure sensor

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
Clemo
Date:
Tue Sep 06 15:17:20 2016 +0000
Commit message:
First version, works for me

Changed in this revision

bme280.cpp Show annotated file Show diff for this revision Revisions of this file
bme280.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r b16a9b34fa4c bme280.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bme280.cpp	Tue Sep 06 15:17:20 2016 +0000
@@ -0,0 +1,389 @@
+/*
+  bme280.cpp - driver for Bosch Sensortec BME280 combined humidity and pressure sensor.
+
+  Copyright (c) 2015 Elektor
+
+  26/11/2015 - CPV, Initial release.
+  
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library 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
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General
+  Public License along with this library; if not, write to the
+  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+  Boston, MA  02111-1307  USA
+
+*/
+
+#include "bme280.h"
+
+
+BME280::BME280(void)
+{
+  _i2c_address = 0;
+  _t_fine = 0;
+  _temperature = 0;
+  _pressure = 0;
+  _humidity = 0;
+  clearCalibrationData();
+}
+
+
+void BME280::clearCalibrationData(void)
+{
+  _dig_T1 = 0;
+  _dig_T2 = 0;
+  _dig_T3 = 0;
+  _dig_P1 = 0;
+  _dig_P2 = 0;
+  _dig_P3 = 0;
+  _dig_P4 = 0;
+  _dig_P5 = 0;
+  _dig_P6 = 0;
+  _dig_P7 = 0;
+  _dig_P8 = 0;
+  _dig_P9 = 0;
+  _dig_H1 = 0;
+  _dig_H2 = 0;
+  _dig_H3 = 0;
+  _dig_H4 = 0;
+  _dig_H5 = 0;
+  _dig_H6 = 0;
+}
+
+
+uint8_t BME280::begin(uint8_t i2cAddress)
+{
+  _i2c_address = i2cAddress;
+  if (readId()==BME280_ID)
+  {
+    clearCalibrationData();
+    readCalibrationData();
+    return 0;
+  }
+  return (uint8_t)-1;
+}
+
+
+void BME280::busWrite(uint8_t *p_data, uint8_t data_size, uint8_t repeated_start)
+{
+  if (_i2c_address==BME280_I2C_ADDRESS1 || _i2c_address==BME280_I2C_ADDRESS2)
+  {
+    // Assume I2C bus.
+    i2cWrite(_i2c_address,p_data,data_size,repeated_start);
+  }
+  else
+  {
+    // Assume SPI bus.
+    // First byte is supposed to be the address of the register to write to, set R/~W bit to 0.
+    p_data[0] &= 0x7f;
+    spiWrite(p_data,data_size);
+  }
+}
+
+
+void BME280::busRead(uint8_t *p_data, uint8_t data_size)
+{
+  if (_i2c_address==BME280_I2C_ADDRESS1 || _i2c_address==BME280_I2C_ADDRESS2)
+  {
+    // Assume I2C bus.
+    i2cRead(_i2c_address,p_data,data_size);
+  }
+  else
+  {
+    // Assume SPI bus.
+    // First byte is supposed to be the address of the register to write to, set R/~W bit to 1.
+    p_data[0] |= 0x80;
+    spiRead(p_data,data_size);
+  }
+}
+
+
+uint8_t BME280::readUint8(uint8_t reg)
+{
+  uint8_t data;
+  busWrite(&reg,1,1); // Use repeated start.
+  busRead(&data,1); // Read one byte.
+  return data;
+}
+
+
+uint16_t BME280::readUint16(uint8_t reg)
+{
+  uint8_t data[2];
+  uint16_t value;
+  busWrite(&reg,1,1); // Use repeated start.
+  busRead(data,2); // Read two bytes.
+  // Process as little endian, which is the case for calibration data.
+  value = data[1];
+  value = (value<<8) | data[0];
+  return value;
+}
+
+
+void BME280::readCalibrationData(void)
+{
+  _dig_T1 = readUint16(BME280_CAL_T1);
+  _dig_T2 = (int16_t) readUint16(BME280_CAL_T2);
+  _dig_T3 = (int16_t) readUint16(BME280_CAL_T3);
+  _dig_P1 = readUint16(BME280_CAL_P1);
+  _dig_P2 = (int16_t) readUint16(BME280_CAL_P2);
+  _dig_P3 = (int16_t) readUint16(BME280_CAL_P3);
+  _dig_P4 = (int16_t) readUint16(BME280_CAL_P4);
+  _dig_P5 = (int16_t) readUint16(BME280_CAL_P5);
+  _dig_P6 = (int16_t) readUint16(BME280_CAL_P6);
+  _dig_P7 = (int16_t) readUint16(BME280_CAL_P7);
+  _dig_P8 = (int16_t) readUint16(BME280_CAL_P8);
+  _dig_P9 = (int16_t) readUint16(BME280_CAL_P9);
+  _dig_H1 = readUint8(BME280_CAL_H1);
+  _dig_H2 = (int16_t) readUint16(BME280_CAL_H2);
+  _dig_H3 = readUint8(BME280_CAL_H3);
+  // H4 & H5 share a byte.
+  uint8_t temp1 = readUint8(BME280_CAL_H4);
+  uint8_t temp2 = readUint8(BME280_CAL_H45);
+  uint8_t temp3 = readUint8(BME280_CAL_H5);
+  _dig_H4 = (temp1<<4) | (temp2&0x0f);
+  _dig_H5 = (temp3<<4) | (temp2>>4);
+  _dig_H6 = (int8_t) readUint8(BME280_CAL_H6);
+}
+
+
+uint8_t BME280::readFrom(uint8_t reg, uint8_t data_size, uint8_t *p_data)
+{
+  // Set start address to read from.
+  busWrite(&reg,1,1); // Use repeated start.
+  // Now read the requested number of bytes.
+  busRead(p_data,data_size);
+  return data_size;
+}
+
+
+void BME280::read(void)
+{
+  // Get all the measurements in one burst (recommended).
+  uint8_t data[BME280_MEASUREMENT_SIZE];
+  readFrom(BME280_MEASUREMENT_REGISTER,BME280_MEASUREMENT_SIZE,data);
+  // We assume Normal mode, so it is not necessary to reissue a Forced mode command here.
+
+  // Process data.
+  int32_t p = assembleRawValue(&data[0],1);
+  int32_t t = assembleRawValue(&data[3],1);
+  int32_t h = assembleRawValue(&data[6],0);
+
+  _temperature = compensateTemperature(t); // First call this before calling the other compensate functions.
+  _pressure = compensatePressure(p); // Uses value calculated by compensateTemperature.
+  _humidity = compensateHumidity(h); // Uses value calculated by compensateTemperature.
+}
+
+
+int32_t BME280::assembleRawValue(uint8_t *p_data, uint8_t has_xlsb)
+{
+  // Needed to decode sensor data.
+  uint32_t value = p_data[0];
+  value <<= 8;
+  value |= p_data[1];
+  if (has_xlsb!=0)
+  {
+    value <<= 4;
+    value |= (p_data[2]>>4);
+  }
+  return (int32_t) value;
+}
+
+
+void BME280::writeControlRegisters(uint8_t osrs_t, uint8_t osrs_p, uint8_t osrs_h, uint8_t mode)
+{
+  uint8_t data[2];
+  data[0] = BME280_CTRL_HUM_REGISTER;
+  data[1] = (osrs_h&0x07);
+  busWrite(data,2,0);
+  // Writing CTRL_MEAS validates previous write to CTRL_HUM.
+  data[0] = BME280_CTRL_MEAS_REGISTER;
+  data[1] = ((osrs_t&0x07)<<5) | ((osrs_p&0x07)<<2) | (mode&0x03);
+  busWrite(data,2,0);
+}
+
+
+void BME280::writeConfigRegister(uint8_t t_sb, uint8_t filter, uint8_t spi)
+{
+  uint8_t data[2];
+  data[0] = BME280_CONFIG_REGISTER;
+  data[1] = ((t_sb&0x07)<<5) | ((filter&0x07)<<2) | (spi&0x01);
+  busWrite(data,2,0);
+}
+
+
+void BME280::reset(void)
+{
+  uint8_t data[2] = { BME280_RESET_REGISTER, BME280_RESET };
+  busWrite(data,2,0);
+}
+
+
+uint8_t BME280::readId(void)
+{
+  return readUint8(BME280_ID_REGISTER);
+}
+
+
+#if BME280_ALLOW_FLOAT!=0
+
+// From the driver by Bosch Sensortec
+
+//!
+// @brief Reads actual temperature from uncompensated temperature
+// @note returns the value in Degree centigrade
+// @note Output value of "51.23" equals 51.23 DegC.
+//
+//  @param adc_T : value of uncompensated temperature
+//
+//  @return  Return the actual temperature in floating point
+//
+temperature_t BME280::compensateTemperature(int32_t adc_T)
+{
+  double v_x1_u32;
+  double v_x2_u32;
+  double temperature;
+  
+  v_x1_u32  = (((double)adc_T) / 16384.0 - ((double)_dig_T1) / 1024.0) * ((double)_dig_T2);
+  v_x2_u32  = ((((double)adc_T) / 131072.0 - ((double)_dig_T1) / 8192.0) * (((double)adc_T) / 131072.0 - ((double)_dig_T1) / 8192.0)) * ((double)_dig_T3);
+  _t_fine = (int32_t)(v_x1_u32 + v_x2_u32);
+  temperature  = (v_x1_u32 + v_x2_u32) / 5120.0;
+  return temperature;
+}
+
+
+//!
+// @brief Reads actual pressure from uncompensated pressure
+// @note Returns pressure in Pa as double.
+// @note Output value of "96386.2"
+// equals 96386.2 Pa = 963.862 hPa.
+//
+//  @param adc_P : value of uncompensated pressure
+//
+//  @return  Return the actual pressure in floating point
+//
+pressure_t BME280::compensatePressure(int32_t adc_P)
+{
+  double v_x1_u32;
+  double v_x2_u32;
+  double pressure;
+  
+  v_x1_u32 = ((double)_t_fine / 2.0) - 64000.0;
+  v_x2_u32 = v_x1_u32 * v_x1_u32 * ((double)_dig_P6) / 32768.0;
+  v_x2_u32 = v_x2_u32 + v_x1_u32 * ((double)_dig_P5) * 2.0;
+  v_x2_u32 = (v_x2_u32 / 4.0) + (((double)_dig_P4) * 65536.0);
+  v_x1_u32 = (((double)_dig_P3) * v_x1_u32 * v_x1_u32 / 524288.0 + ((double)_dig_P2) * v_x1_u32) / 524288.0;
+  v_x1_u32 = (1.0 + v_x1_u32 / 32768.0) * ((double)_dig_P1);
+  pressure = 1048576.0 - (double)adc_P;
+  // Avoid exception caused by division by zero.
+  if (v_x1_u32 != 0) pressure = (pressure - (v_x2_u32 / 4096.0)) * 6250.0 / v_x1_u32;
+  else return 0;
+  v_x1_u32 = ((double)_dig_P9) * pressure * pressure / 2147483648.0;
+  v_x2_u32 = pressure * ((double)_dig_P8) / 32768.0;
+  pressure = pressure + (v_x1_u32 + v_x2_u32 + ((double)_dig_P7)) / 16.0;
+  
+  return pressure;
+}
+
+
+//!
+// @brief Reads actual humidity from uncompensated humidity
+// @note returns the value in relative humidity (%rH)
+// @note Output value of "42.12" equals 42.12 %rH
+//
+//  @param adc_H : value of uncompensated humidity
+//
+//  @return Return the actual humidity in floating point
+//
+humidity_t BME280::compensateHumidity(int32_t adc_H)
+{
+  double var_h;
+  
+  var_h = (((double)_t_fine) - 76800.0);
+  if (var_h != 0)
+  {
+    var_h = (adc_H - (((double)_dig_H4) * 64.0 + ((double)_dig_H5) / 16384.0 * var_h)) * 
+      (((double)_dig_H2) / 65536.0 * (1.0 + ((double) _dig_H6) / 67108864.0 * 
+      var_h * (1.0 + ((double)_dig_H3) / 67108864.0 * var_h)));
+  }
+  else return 0;
+  var_h = var_h * (1.0 - ((double)_dig_H1)*var_h / 524288.0);
+  if (var_h > 100.0) var_h = 100.0;
+  else if (var_h < 0.0) var_h = 0.0;
+  return var_h;
+}
+
+#else /* BME280_ALLOW_FLOAT */
+
+// From the datasheet.
+// Returns temperature in DegC, resolution is 0.01 DegC. Output value of 5123 equals 51.23 DegC.
+// _t_fine carries fine temperature as "global" value.
+temperature_t BME280::compensateTemperature(int32_t adc_T)
+{
+  int32_t var1, var2, T;
+  var1 = ((((adc_T>>3) - ((int32_t)_dig_T1<<1))) * ((int32_t)_dig_T2)) >> 11;
+  var2 = (((((adc_T>>4) - ((int32_t)_dig_T1)) * ((adc_T>>4) - ((int32_t)_dig_T1))) >> 12) * ((int32_t)_dig_T3)) >> 14;
+  _t_fine = var1 + var2;
+  T = (_t_fine * 5 + 128) >> 8;
+  return T;
+}
+
+
+// From the datasheet.
+// Returns pressure in Pa as unsigned 32 bit integer. Output value of 96386 equals 96386 Pa = 963.86 hPa
+pressure_t BME280::compensatePressure(int32_t adc_P)
+{
+  int32_t var1, var2;
+  uint32_t p;
+  var1 = (((int32_t)_t_fine)>>1) - (int32_t)64000;
+  var2 = (((var1>>2) * (var1>>2)) >> 11 ) * ((int32_t)_dig_P6);
+  var2 = var2 + ((var1*((int32_t)_dig_P5))<<1);
+  var2 = (var2>>2)+(((int32_t)_dig_P4)<<16);
+  var1 = (((_dig_P3 * (((var1>>2) * (var1>>2)) >> 13 )) >> 3) + ((((int32_t)_dig_P2) * var1)>>1))>>18;
+  var1 =((((32768+var1))*((int32_t)_dig_P1))>>15);
+  if (var1 == 0)
+  {
+    return 0; // avoid exception caused by division by zero
+  }
+  p = (((uint32_t)(((int32_t)1048576)-adc_P)-(var2>>12)))*3125;
+  if (p < 0x80000000)
+  {
+    p = (p << 1) / ((uint32_t)var1);
+  }
+  else
+  {
+    p = (p / (uint32_t)var1) * 2;
+  }
+  var1 = (((int32_t)_dig_P9) * ((int32_t)(((p>>3) * (p>>3))>>13)))>>12;
+  var2 = (((int32_t)(p>>2)) * ((int32_t)_dig_P8))>>13;
+  p = (uint32_t)((int32_t)p + ((var1 + var2 + _dig_P7) >> 4));
+  return p;
+}
+
+
+// From the datasheet.
+// Returns humidity in %RH as unsigned 32 bit integer in Q22.10 format (22 integer and 10 fractional bits).
+// Output value of 47445 represents 47445/1024 = 46.333 %RH
+humidity_t BME280::compensateHumidity(int32_t adc_H)
+{
+  int32_t v_x1_u32r;
+  v_x1_u32r = (_t_fine - ((int32_t)76800));
+  v_x1_u32r = (((((adc_H << 14) - (((int32_t)_dig_H4) << 20) - (((int32_t)_dig_H5) * v_x1_u32r)) +
+      ((int32_t)16384)) >> 15) * (((((((v_x1_u32r * ((int32_t)_dig_H6)) >> 10) * (((v_x1_u32r *
+      ((int32_t)_dig_H3)) >> 11) + ((int32_t)32768))) >> 10) + ((int32_t)2097152)) *
+      ((int32_t)_dig_H2) + 8192) >> 14));
+  v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * ((int32_t)_dig_H1)) >> 4));
+  v_x1_u32r = (v_x1_u32r < 0 ? 0 : v_x1_u32r);
+  v_x1_u32r = (v_x1_u32r > 419430400 ? 419430400 : v_x1_u32r);
+  return (uint32_t)(v_x1_u32r>>12);
+}
+
+#endif /* BME280_ALLOW_FLOAT */
diff -r 000000000000 -r b16a9b34fa4c bme280.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bme280.h	Tue Sep 06 15:17:20 2016 +0000
@@ -0,0 +1,216 @@
+/*
+  bme280.h - driver for Bosch Sensortec BME280 combined humidity and pressure sensor.
+
+  Copyright (c) 2015 Elektor
+
+  26/11/2015 - CPV, Initial release.
+  
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library 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
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General
+  Public License along with this library; if not, write to the
+  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+  Boston, MA  02111-1307  USA
+
+*/
+
+#ifndef __BME280_H__
+#define __BME280_H__
+
+#include <stdint.h>
+
+
+#define BME280_ALLOW_FLOAT  (1)
+
+#if BME280_ALLOW_FLOAT!=0
+  typedef double temperature_t;
+  typedef double pressure_t;
+  typedef double humidity_t;
+#else
+  typedef int32_t temperature_t;
+  typedef uint32_t pressure_t;
+  typedef uint32_t humidity_t;
+#endif /* BME280_ALLOW_FLOAT */
+
+
+// Two possible addresses, depending on level on SDO pin.
+#define BME280_I2C_ADDRESS1  (0x76)
+#define BME280_I2C_ADDRESS2  (0x77)
+
+// Calibration registers.
+#define BME280_CAL_T1  (0x88)
+#define BME280_CAL_T2  (0x8a)
+#define BME280_CAL_T3  (0x8c)
+#define BME280_CAL_P1  (0x8e)
+#define BME280_CAL_P2  (0x90)
+#define BME280_CAL_P3  (0x92)
+#define BME280_CAL_P4  (0x94)
+#define BME280_CAL_P5  (0x96)
+#define BME280_CAL_P6  (0x98)
+#define BME280_CAL_P7  (0x9a)
+#define BME280_CAL_P8  (0x9c)
+#define BME280_CAL_P9  (0x9e)
+#define BME280_CAL_H1  (0xa1) /* 8 bits */
+#define BME280_CAL_H2  (0xe1)
+#define BME280_CAL_H3  (0xe3) /* 8 bits */
+#define BME280_CAL_H4  (0xe4) /* 12 bits, combined with H45 */
+#define BME280_CAL_H45  (0xe5) /* 12 bits, combined with H5 */
+#define BME280_CAL_H5  (0xe6) /* 8 bits */
+#define BME280_CAL_H6  (0xe7) /* 8 bits */
+
+// Control registers.
+#define BME280_ID_REGISTER  (0xd0) /* 8 bits */
+#define BME280_RESET_REGISTER  (0xe0) /* 8 bits */
+#define BME280_CTRL_HUM_REGISTER  (0xf2) /* 8 bits */
+#define BME280_STATUS_REGISTER  (0xf3) /* 8 bits */
+#define BME280_CTRL_MEAS_REGISTER  (0xf4) /* 8 bits */
+#define BME280_CONFIG_REGISTER  (0xf5) /* 8 bits */
+
+// Measurement registers.
+#define BME280_PRESSURE  (0xf7) /* 20 bits */
+#define BME280_PRESSURE_MSB  (0xf7) /* 8 bits */
+#define BME280_PRESSURE_LSB  (0xf8) /* 8 bits */
+#define BME280_PRESSURE_XLSB  (0xf9) /* 8 bits */
+#define BME280_TEMPERATURE  (0xfa) /* 20 bits */
+#define BME280_TEMPERATURE_MSB  (0xfa) /* 8 bits */
+#define BME280_TEMPERATURE_LSB  (0xfb) /* 8 bits */
+#define BME280_TEMPERATURE_XLSB  (0xfc) /* 8 bits */
+#define BME280_HUMIDITY  (0xfd) /* 16 bits */
+#define BME280_HUMIDITY_MSB  (0xfd) /* 8 bits */
+#define BME280_HUMIDITY_LSB  (0xfe) /* 8 bits */
+
+// It is recommended to read all the measurements in one go.
+#define BME280_MEASUREMENT_REGISTER  (BME280_PRESSURE)
+#define BME280_MEASUREMENT_SIZE  (8)
+
+// Values for osrs_p & osrs_t fields of CTRL_MEAS register.
+#define BME280_SKIP  (0)
+#define BME280_OVERSAMPLING_1X  (1)
+#define BME280_OVERSAMPLING_2X  (2)
+#define BME280_OVERSAMPLING_4X  (3)
+#define BME280_OVERSAMPLING_8X  (4)
+#define BME280_OVERSAMPLING_16X  (5)
+
+// Values for mode field of CTRL_MEAS register.
+#define BME280_MODE_SLEEP  (0)
+#define BME280_MODE_FORCED  (1)
+#define BME280_MODE_NORMAL  (3)
+
+// Value for RESET register.
+#define BME280_RESET  (0xb6)
+
+// Value of ID register.
+#define BME280_ID  (0x60)
+
+// Values for t_sb field of CONFIG register
+#define BME280_STANDBY_500_US  (0)
+#define BME280_STANDBY_10_MS  (6)
+#define BME280_STANDBY_20_MS  (7)
+#define BME280_STANDBY_63_MS  (1)
+#define BME280_STANDBY_125_MS  (2)
+#define BME280_STANDBY_250_MS  (3)
+#define BME280_STANDBY_500_MS  (4)
+#define BME280_STANDBY_1000_MS  (5)
+
+// Values for filter field of CONFIG register
+#define BME280_FILTER_OFF  (0)
+#define BME280_FILTER_COEFF_2  (1)
+#define BME280_FILTER_COEFF_4  (2)
+#define BME280_FILTER_COEFF_8  (3)
+#define BME280_FILTER_COEFF_16  (4)
+
+
+// I2C write function must support repeated start to avoid interruption of transactions.
+// User-provided function to write data_size bytes from buffer p_data to I2C device at bus address i2c_address.
+// Provide empty function if not used.
+extern void i2cWrite(uint8_t i2c_address, uint8_t *p_data, uint8_t data_size, uint8_t repeated_start);
+// User-provided function to read data_size bytes from I2C device at bus address i2c_address to buffer p_data.
+// Provide empty function if not used.
+extern void i2cRead(uint8_t i2c_address, uint8_t *p_data, uint8_t data_size);
+
+// SPI functions must activate (make low) BME280 CSB pin before doing a transfer
+// and deactivate it (make high) when done.
+// User-provided function to write data_size bytes from buffer p_data to SPI device.
+// Provide empty function if not used.
+extern void spiWrite(uint8_t *p_data, uint8_t data_size);
+// User-provided function to read data_size bytes from SPI device to buffer p_data.
+// Provide empty function if not used.
+extern void spiRead(uint8_t *p_data, uint8_t data_size);
+
+
+class BME280
+{
+public:
+  BME280(void);
+  uint8_t begin(uint8_t i2cAddress=0); // I2C address not set means SPI.
+
+  void readCalibrationData(void);
+  uint8_t readId(void);
+  uint8_t readFrom(uint8_t reg, uint8_t data_size, uint8_t *p_data);
+
+  void read(void);
+
+  // If using floating points, values are scaled, if not then
+  // temperature is 100*T, pressure is Pa en humidity is 1024*%RH
+  temperature_t temperature(void) { return _temperature; } // [degrees Celsius] or 100*[degrees Celsius]
+  pressure_t pressure(void) { return _pressure; } // [Pa]
+  humidity_t humidity(void) { return _humidity; } // [%RH] or 1024*[%RH]
+
+  void writeControlRegisters(uint8_t osrs_t, uint8_t osrs_p, uint8_t osrs_h, uint8_t mode);
+  void writeConfigRegister(uint8_t t_sb, uint8_t filter, uint8_t spi);
+
+  void reset(void);
+
+private:
+  uint8_t _i2c_address;
+
+  void busWrite(uint8_t *p_data, uint8_t data_size, uint8_t repeated_start);
+  void busRead(uint8_t *p_data, uint8_t data_size);
+
+  // Calibration data.
+  uint16_t _dig_T1;
+  int16_t _dig_T2;
+  int16_t _dig_T3;
+  uint16_t _dig_P1;
+  int16_t _dig_P2;
+  int16_t _dig_P3;
+  int16_t _dig_P4;
+  int16_t _dig_P5;
+  int16_t _dig_P6;
+  int16_t _dig_P7;
+  int16_t _dig_P8;
+  int16_t _dig_P9;
+  uint8_t _dig_H1;
+  int16_t _dig_H2;
+  uint8_t _dig_H3;
+  int16_t _dig_H4;
+  int16_t _dig_H5;
+  int8_t _dig_H6;
+  void clearCalibrationData(void);
+
+  uint8_t readUint8(uint8_t reg);
+  uint16_t readUint16(uint8_t reg);
+
+  int32_t assembleRawValue(uint8_t *p_data, uint8_t has_xlsb);
+
+  int32_t _t_fine;
+
+  temperature_t compensateTemperature(int32_t adc_T);
+  pressure_t compensatePressure(int32_t adc_P);
+  humidity_t compensateHumidity(int32_t adc_H);
+
+  temperature_t _temperature;
+  pressure_t _pressure;
+  humidity_t _humidity;
+};
+
+
+#endif /* __BME280_H__*/
\ No newline at end of file
diff -r 000000000000 -r b16a9b34fa4c main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Sep 06 15:17:20 2016 +0000
@@ -0,0 +1,102 @@
+
+#include "mbed.h"
+
+#include <stdint.h>
+#include "bme280.h"
+
+#if defined TARGET_LPC81X
+    // SDA, SCL for Elektor CoCo-ri-Co!
+    #define PIN_SDA  (P0_10)
+    #define PIN_SCL  (P0_11)
+#elif defined TARGET_NRF51_MICROBIT
+    // SDA, SCL for BBC micro:bit
+    #define PIN_SDA  I2C_SDA0 /* (P20) */
+    #define PIN_SCL  I2C_SCL0 /* (P19) */
+#endif
+
+I2C i2c(PIN_SDA,PIN_SCL);
+BME280 bme280;
+
+DigitalOut led1(LED1); // Blue on LPC800-MAX, Pad0 on micro:bit
+DigitalOut led2(LED2); // Green on LPC800-MAX, Pad1 on micro:bit
+DigitalOut led3(LED3); // Red on LPC800-MAX, Pad2 on micro:bit
+
+#if defined TARGET_LPC81X
+    #define LED_ON  (0)
+    #define LED_OFF  (1)
+#elif defined TARGET_NRF51_MICROBIT
+    #define LED_ON  (1)
+    #define LED_OFF  (0)
+#endif
+
+// Note for LPC800-MAX users: check SJ1 and SJ4. 
+// For the USB serial port to work pins 1&2 must be shorted, not pins 2&3.
+
+
+void i2cWrite(uint8_t i2c_address, uint8_t *p_data, uint8_t data_size, uint8_t repeated_start)
+{
+    // mbed uses 8-bit addresses, always confusing.
+    i2c.write(i2c_address<<1,(const char *)p_data,data_size,repeated_start);
+}
+
+
+void i2cRead(uint8_t i2c_address, uint8_t *p_data, uint8_t data_size)
+{
+    // mbed uses 8-bit addresses, always confusing.
+    i2c.read(i2c_address<<1,(char *)p_data,data_size);
+}
+
+
+// Not using BME280 SPI interface, provide stubs.
+void spiWrite(uint8_t *p_data, uint8_t data_size) {}
+void spiRead(uint8_t *p_data, uint8_t data_size) {}
+
+
+int main(void)
+{
+    led1 = LED_OFF;
+    led2 = LED_OFF;
+    led3 = LED_OFF;
+    
+    printf("Elektor project 150652\n");
+    printf("BME280 weather sensor\n");
+#if defined TARGET_LPC81X
+    printf("for LPC800-MAX\n");
+#elif defined TARGET_NRF51_MICROBIT
+    printf("for BBC micro:bit\n");
+#endif
+
+#if BME280_ALLOW_FLOAT!=0
+    printf("Using floating point maths\n");
+#else
+    printf("Using integer maths\n");
+#endif
+
+    if (bme280.begin(BME280_I2C_ADDRESS2)!=0)
+    {
+        printf("\n*** BME280 not found.\n");
+    }
+    printf("\n");
+    
+    // Configure for test purposes.
+    bme280.writeConfigRegister(BME280_STANDBY_500_US,BME280_FILTER_OFF,0);
+    bme280.writeControlRegisters(BME280_OVERSAMPLING_1X,BME280_OVERSAMPLING_1X,BME280_OVERSAMPLING_1X,BME280_MODE_NORMAL);
+
+    while (1)
+    {
+        led1 = LED_ON;
+ 
+        bme280.read();
+#if BME280_ALLOW_FLOAT!=0
+        printf("T=%0.1f degrees C, P=%0.1f mbar, RH=%0.1f%%\n",bme280.temperature(),bme280.pressure()/100,bme280.humidity());
+#else
+        printf("T=%d degrees C, P=%d mbar, RH=%d%%\n",bme280.temperature()/100,bme280.pressure()/100,bme280.humidity()>>10);
+#endif
+
+        // Worst case speed is about 1 Hz.
+        // Keep flash short, it is terribly bright.
+        wait_ms(5);
+        led1 = LED_OFF;
+        wait_ms(995);
+    }
+}
diff -r 000000000000 -r b16a9b34fa4c mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Tue Sep 06 15:17:20 2016 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/165afa46840b
\ No newline at end of file