Skip to content

Commit

Permalink
Merge pull request #50 from cdonate/feature/data_burst_readout
Browse files Browse the repository at this point in the history
feat: add read burst
  • Loading branch information
nseidle authored Dec 30, 2020
2 parents 9e01070 + ac0b596 commit 10a8157
Show file tree
Hide file tree
Showing 3 changed files with 187 additions and 0 deletions.
68 changes: 68 additions & 0 deletions examples/Example11_BurstRead/Example11_BurstRead.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
Get environmental readings as a burst from the BME280
By: Claudio Donaté
Date: December 30th, 2020
License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license).
Feel like supporting our work? Buy a board from SparkFun!
https://www.sparkfun.com/products/14348 - Qwiic Combo Board
https://www.sparkfun.com/products/13676 - BME280 Breakout Board
This example shows how to read humidity, pressure, and current temperature from the BME280 over I2C reading all registers at once.
Please check BME280 Datasheet, section 4, Data readout for detail explanations on why.
Hardware connections:
BME280 -> Arduino
GND -> GND
3.3 -> 3.3
SDA -> A4
SCL -> A5
*/

#include <Wire.h>

#include "SparkFunBME280.h"

#define CELSIUS_SCALE 0 //Default
#define FAHRENHEIT_SCALE 1

BME280 mySensor;
BME280_SensorMeasurements measurements;

void setup()
{
Serial.begin(9600);
Serial.println("Reading basic values from BME280 as a Burst");

Wire.begin();

if (mySensor.beginI2C() == false) //Begin communication over I2C
{
Serial.println("The sensor did not respond. Please check wiring.");
while(1); //Freeze
}
}

void loop()
{
while (mySensor.isMeasuring()) // Wait for sensor to finish measuring
{
Serial.print(".");
};

mySensor.readAllMeasurements(&measurements); // Return temperature in Celsius
// mySensor.readAllMeasurements(&measurements, FAHRENHEIT_SCALE);

Serial.print("\nHumidity: ");
Serial.print(measurements.humidity, 0);

Serial.print(" Pressure: ");
Serial.print(measurements.pressure, 0);

Serial.print(" Temp: ");
Serial.print(measurements.temperature, 2);

Serial.println();

delay(50);
}
104 changes: 104 additions & 0 deletions src/SparkFunBME280.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,29 @@ void BME280::reset( void )

}

//****************************************************************************//
//
// Burst Measurement Section
//
//****************************************************************************//

//Read all sensor registers as a burst. See BME280 Datasheet section 4. Data readout
//tempScale = 0 for Celsius scale (default setting)
//tempScale = 1 for Fahrenheit scale
void BME280::readAllMeasurements(BME280_SensorMeasurements *measurements, byte tempScale){

uint8_t dataBurst[8];
readRegisterRegion(dataBurst, BME280_MEASUREMENTS_REG, 8);

if(tempScale == 0){
readTempCFromBurst(dataBurst, measurements);
}else{
readTempFFromBurst(dataBurst, measurements);
}
readFloatPressureFromBurst(dataBurst, measurements);
readFloatHumidityFromBurst(dataBurst, measurements);
}

//****************************************************************************//
//
// Pressure Section
Expand Down Expand Up @@ -390,6 +413,37 @@ float BME280::readFloatPressure( void )

}

void BME280::readFloatPressureFromBurst(uint8_t buffer[], BME280_SensorMeasurements *measurements)
{

// Set pressure in Pa as unsigned 32 bit integer in Q24.8 format (24 integer bits and 8 fractional bits).
// Output value of “24674867” represents 24674867/256 = 96386.2 Pa = 963.862 hPa

int32_t adc_P = ((uint32_t)buffer[0] << 12) | ((uint32_t)buffer[1] << 4) | ((buffer[2] >> 4) & 0x0F);

int64_t var1, var2, p_acc;
var1 = ((int64_t)t_fine) - 128000;
var2 = var1 * var1 * (int64_t)calibration.dig_P6;
var2 = var2 + ((var1 * (int64_t)calibration.dig_P5)<<17);
var2 = var2 + (((int64_t)calibration.dig_P4)<<35);
var1 = ((var1 * var1 * (int64_t)calibration.dig_P3)>>8) + ((var1 * (int64_t)calibration.dig_P2)<<12);
var1 = (((((int64_t)1)<<47)+var1))*((int64_t)calibration.dig_P1)>>33;
if (var1 == 0)
{
measurements->pressure = 0; // avoid exception caused by division by zero
}
else
{
p_acc = 1048576 - adc_P;
p_acc = (((p_acc<<31) - var2)*3125)/var1;
var1 = (((int64_t)calibration.dig_P9) * (p_acc>>13) * (p_acc>>13)) >> 25;
var2 = (((int64_t)calibration.dig_P8) * p_acc) >> 19;
p_acc = ((p_acc + var1 + var2) >> 8) + (((int64_t)calibration.dig_P7)<<4);

measurements->pressure = (float)p_acc / 256.0;
}
}

// Sets the internal variable _referencePressure so the altitude is calculated properly.
// This is also known as "sea level pressure" and is in Pascals. The value is probably
// within 10% of 101325. This varies based on the weather:
Expand Down Expand Up @@ -459,6 +513,25 @@ float BME280::readFloatHumidity( void )
return (float)(var1>>12) / 1024.0;
}

void BME280::readFloatHumidityFromBurst(uint8_t buffer[], BME280_SensorMeasurements *measurements)
{

// Set 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
int32_t adc_H = ((uint32_t)buffer[6] << 8) | ((uint32_t)buffer[7]);

int32_t var1;
var1 = (t_fine - ((int32_t)76800));
var1 = (((((adc_H << 14) - (((int32_t)calibration.dig_H4) << 20) - (((int32_t)calibration.dig_H5) * var1)) +
((int32_t)16384)) >> 15) * (((((((var1 * ((int32_t)calibration.dig_H6)) >> 10) * (((var1 * ((int32_t)calibration.dig_H3)) >> 11) + ((int32_t)32768))) >> 10) + ((int32_t)2097152)) *
((int32_t)calibration.dig_H2) + 8192) >> 14));
var1 = (var1 - (((((var1 >> 15) * (var1 >> 15)) >> 7) * ((int32_t)calibration.dig_H1)) >> 4));
var1 = (var1 < 0 ? 0 : var1);
var1 = (var1 > 419430400 ? 419430400 : var1);

measurements->humidity = (float)(var1>>12) / 1024.0;
}

//****************************************************************************//
//
// Temperature Section
Expand Down Expand Up @@ -494,6 +567,29 @@ float BME280::readTempC( void )
return output;
}

float BME280::readTempFromBurst(uint8_t buffer[])
{
int32_t adc_T = ((uint32_t)buffer[3] << 12) | ((uint32_t)buffer[4] << 4) | ((buffer[5] >> 4) & 0x0F);

//By datasheet, calibrate
int64_t var1, var2;

var1 = ((((adc_T>>3) - ((int32_t)calibration.dig_T1<<1))) * ((int32_t)calibration.dig_T2)) >> 11;
var2 = (((((adc_T>>4) - ((int32_t)calibration.dig_T1)) * ((adc_T>>4) - ((int32_t)calibration.dig_T1))) >> 12) *
((int32_t)calibration.dig_T3)) >> 14;
t_fine = var1 + var2;
float output = (t_fine * 5 + 128) >> 8;

output = output / 100 + settings.tempCorrection;

return output;
}

void BME280::readTempCFromBurst(uint8_t buffer[], BME280_SensorMeasurements *measurements)
{
measurements->temperature = readTempFromBurst(buffer);
}

float BME280::readTempF( void )
{
float output = readTempC();
Expand All @@ -502,6 +598,14 @@ float BME280::readTempF( void )
return output;
}

void BME280::readTempFFromBurst(uint8_t buffer[], BME280_SensorMeasurements *measurements)
{
float output = readTempFromBurst(buffer);
output = (output * 9) / 5 + 32;

measurements->temperature = output;
}

//****************************************************************************//
//
// Dew point Section
Expand Down
15 changes: 15 additions & 0 deletions src/SparkFunBME280.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ Distributed as-is; no warranty is given.
#define BME280_STAT_REG 0xF3 //Status Reg
#define BME280_CTRL_MEAS_REG 0xF4 //Ctrl Measure Reg
#define BME280_CONFIG_REG 0xF5 //Configuration Reg
#define BME280_MEASUREMENTS_REG 0xF7 //Measurements register start
#define BME280_PRESSURE_MSB_REG 0xF7 //Pressure MSB
#define BME280_PRESSURE_LSB_REG 0xF8 //Pressure LSB
#define BME280_PRESSURE_XLSB_REG 0xF9 //Pressure XLSB
Expand Down Expand Up @@ -172,6 +173,14 @@ struct SensorCalibration

};

struct BME280_SensorMeasurements
{
public:
float temperature;
float pressure;
float humidity;
};

//This is the main operational class of the driver.

class BME280
Expand Down Expand Up @@ -215,18 +224,22 @@ class BME280

//Software reset routine
void reset( void );
void readAllMeasurements(BME280_SensorMeasurements *measurements, byte tempScale = 0);

//Returns the values as floats.
float readFloatPressure( void );
float readFloatAltitudeMeters( void );
float readFloatAltitudeFeet( void );
void readFloatPressureFromBurst(uint8_t buffer[], BME280_SensorMeasurements *measurements);

float readFloatHumidity( void );
void readFloatHumidityFromBurst(uint8_t buffer[], BME280_SensorMeasurements *measurements);

//Temperature related methods
void setTemperatureCorrection(float corr);
float readTempC( void );
float readTempF( void );
float readTempFromBurst(uint8_t buffer[]);

//Dewpoint related methods
//From Pavel-Sayekat: https://github.com/sparkfun/SparkFun_BME280_Breakout_Board/pull/6/files
Expand All @@ -248,6 +261,8 @@ class BME280

private:
uint8_t checkSampleValue(uint8_t userValue); //Checks for valid over sample values
void readTempCFromBurst(uint8_t buffer[], BME280_SensorMeasurements *measurements);
void readTempFFromBurst(uint8_t buffer[], BME280_SensorMeasurements *measurements);

uint8_t _wireType = HARD_WIRE; //Default to Wire.h
TwoWire *_hardPort = NO_WIRE; //The generic connection to user's chosen I2C hardware
Expand Down

0 comments on commit 10a8157

Please sign in to comment.