nRF51822, BME280, SSD1306_i2c, BLE400

Dependencies:   mbed SSD1306_128x64_I2C

Files at this revision

API Documentation at this revision

Comitter:
mamont090671
Date:
Thu Nov 28 11:43:48 2019 +0000
Commit message:
BME280, nRF51822, SSD1306_i2c, BLE400;

Changed in this revision

SSD1306_128x64_I2C.lib Show annotated file Show diff for this revision Revisions of this file
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
mbed_logo.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SSD1306_128x64_I2C.lib	Thu Nov 28 11:43:48 2019 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/users/jk1lot/code/SSD1306_128x64_I2C/#46dcbaa430f4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bme280.cpp	Thu Nov 28 11:43:48 2019 +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 */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bme280.h	Thu Nov 28 11:43:48 2019 +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__*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Thu Nov 28 11:43:48 2019 +0000
@@ -0,0 +1,141 @@
+#include "mbed.h"
+#include "SSD1306.h"
+#include "bme280.h"
+#include "stdlib.h"
+#include "mbed_logo.h"
+
+#define D_SDA                  P0_0
+#define D_SCL                  P0_1
+
+//Functions
+void triggerfall_1();//Button1 falling interrupt function
+void triggerrise_1();//Button1 rising interrupt function
+void triggerfall_2();//Button1 falling interrupt function
+void triggerrise_2();//Button1 rising interrupt function
+
+float t;
+float pr;
+int h;
+
+uint8_t address = 0x78;
+
+I2C i2c(D_SDA, D_SCL);
+
+SSD1306 oled(i2c, address);
+BME280 bme280;
+
+//Initiate IO
+DigitalOut led0(LED1);
+DigitalOut led1(LED2);
+DigitalOut led2(P0_20);
+DigitalOut led3(P0_21);
+DigitalOut led4(P0_22, 0);
+DigitalIn  sw1(BUTTON1);
+DigitalIn  sw2(BUTTON2);
+
+//Initiate input interrupts
+InterruptIn sw1Press(BUTTON1);
+InterruptIn sw2Press(BUTTON2);
+
+//bme280
+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);
+}
+
+//ssd1306
+void Start_page()
+{
+    int i=0;
+    oled.writeString(1, 3, "Fight Robot");
+    while(i<100) {
+        oled.writeProgressBar(20,40,i);
+        i++;
+        wait_ms(10);
+    }
+    i = 0;
+    oled.writeBitmap((uint8_t*) mbed_logo);
+    while(i<100){
+        i++;
+        wait_ms(10);
+    }
+}
+void Display_Meteo(float t, float pr, int h)
+{
+//    sprintf(buf, "%f", t);
+    oled.writeString(1, 2, "T: ");
+    oled.printf("%.2f",t);
+    oled.printf("%s"," C");
+    oled.writeString(3, 2, "P: ");
+    oled.printf("%.1f",pr);
+    oled.printf("%s"," mmHg");
+    oled.writeString(5, 2, "H: ");
+    oled.printf("%d",h);
+    oled.printf("%s"," %");
+}
+
+int main()
+{
+    //Initialise LED output
+    led0=0;
+    led1=0;
+    led2=0;
+    led3=0;
+ 
+    //Set falling and rising edge to apppropriate interrup function
+    sw1Press.fall(&triggerfall_1);
+    sw1Press.rise(&triggerrise_1);
+    sw2Press.fall(&triggerfall_2);
+    sw2Press.rise(&triggerrise_2);
+
+    bme280.begin(BME280_I2C_ADDRESS1);
+    // 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);
+    Start_page();
+    oled.clearDisplay();
+
+    while(1) {
+        led4=!led4;
+        bme280.read();
+        t = bme280.temperature();
+        float p = bme280.pressure()/100;
+        pr = p*0.750062;
+        h = bme280.humidity();
+        Display_Meteo(t, pr, h);
+        wait_ms(1000);
+    }
+}
+//Button1 falling interrupt function
+void triggerfall_1()
+{
+//Toggle LED1
+    led0=!led0;
+}
+ 
+//Button1 rising interrupt function
+void triggerrise_1()
+{
+//Toggle LED2
+    led1=!led1;
+}
+//Button1 falling interrupt function
+void triggerfall_2()
+{
+//Toggle LED1
+    led2=!led2;
+}
+ 
+//Button1 rising interrupt function
+void triggerrise_2()
+{
+//Toggle LED2
+    led3=!led3;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Thu Nov 28 11:43:48 2019 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/users/mbed_official/code/mbed/builds/65be27845400
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed_logo.h	Thu Nov 28 11:43:48 2019 +0000
@@ -0,0 +1,71 @@
+//------------------------------------------------------------------------------
+// File generated by LCD Assistant
+// http://en.radzio.dxp.pl/bitmap_converter/
+//------------------------------------------------------------------------------
+ 
+const uint8_t mbed_logo [] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE,
+0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFC, 0xFC, 0xFC, 0xF8, 0xFC, 0x7C,
+0x3C, 0x3E, 0x3E, 0x3E, 0x3E, 0x7E, 0xFC, 0xFC, 0xFC, 0xF8, 0xF8, 0xFC, 0x7C, 0x3C, 0x3E, 0x3E,
+0x3E, 0x3E, 0x7E, 0xFC, 0xFC, 0xFC, 0xF8, 0xF0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
+0xFF, 0xFF, 0xFF, 0xFF, 0x7C, 0x3C, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x7E, 0x7C, 0xFC, 0xFC, 0xF8,
+0xF0, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFC,
+0x7C, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3C, 0x7C, 0xFC, 0xF8, 0xF8, 0xF0, 0xE0, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFC, 0x7E, 0x7E, 0x3E, 0x3E, 0x3E, 0x3E,
+0x3C, 0x7C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
+0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF,
+0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x39, 0x38,
+0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x39, 0x3F, 0x3F, 0x3F, 0x3F, 0x3E, 0x00,
+0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
+0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF8, 0xFE, 0x7F,
+0x3F, 0x1F, 0x0F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF, 0xFC, 0xF0,
+0xF0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xF0, 0xF0, 0xF8, 0xF8, 0x70, 0x60, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x01, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF, 0xFC, 0xF8, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+0xF0, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+0x03, 0x03, 0x01, 0x00, 0x00, 0x01, 0x01, 0x03, 0x03, 0x03, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01,
+0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};