Skip to content

feat: add read burst #50

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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