Skip to content

Commit 10a8157

Browse files
authored
Merge pull request #50 from cdonate/feature/data_burst_readout
feat: add read burst
2 parents 9e01070 + ac0b596 commit 10a8157

File tree

3 files changed

+187
-0
lines changed

3 files changed

+187
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
Get environmental readings as a burst from the BME280
3+
By: Claudio Donaté
4+
Date: December 30th, 2020
5+
License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license).
6+
7+
Feel like supporting our work? Buy a board from SparkFun!
8+
https://www.sparkfun.com/products/14348 - Qwiic Combo Board
9+
https://www.sparkfun.com/products/13676 - BME280 Breakout Board
10+
11+
This example shows how to read humidity, pressure, and current temperature from the BME280 over I2C reading all registers at once.
12+
Please check BME280 Datasheet, section 4, Data readout for detail explanations on why.
13+
14+
Hardware connections:
15+
BME280 -> Arduino
16+
GND -> GND
17+
3.3 -> 3.3
18+
SDA -> A4
19+
SCL -> A5
20+
*/
21+
22+
#include <Wire.h>
23+
24+
#include "SparkFunBME280.h"
25+
26+
#define CELSIUS_SCALE 0 //Default
27+
#define FAHRENHEIT_SCALE 1
28+
29+
BME280 mySensor;
30+
BME280_SensorMeasurements measurements;
31+
32+
void setup()
33+
{
34+
Serial.begin(9600);
35+
Serial.println("Reading basic values from BME280 as a Burst");
36+
37+
Wire.begin();
38+
39+
if (mySensor.beginI2C() == false) //Begin communication over I2C
40+
{
41+
Serial.println("The sensor did not respond. Please check wiring.");
42+
while(1); //Freeze
43+
}
44+
}
45+
46+
void loop()
47+
{
48+
while (mySensor.isMeasuring()) // Wait for sensor to finish measuring
49+
{
50+
Serial.print(".");
51+
};
52+
53+
mySensor.readAllMeasurements(&measurements); // Return temperature in Celsius
54+
// mySensor.readAllMeasurements(&measurements, FAHRENHEIT_SCALE);
55+
56+
Serial.print("\nHumidity: ");
57+
Serial.print(measurements.humidity, 0);
58+
59+
Serial.print(" Pressure: ");
60+
Serial.print(measurements.pressure, 0);
61+
62+
Serial.print(" Temp: ");
63+
Serial.print(measurements.temperature, 2);
64+
65+
Serial.println();
66+
67+
delay(50);
68+
}

src/SparkFunBME280.cpp

+104
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,29 @@ void BME280::reset( void )
355355

356356
}
357357

358+
//****************************************************************************//
359+
//
360+
// Burst Measurement Section
361+
//
362+
//****************************************************************************//
363+
364+
//Read all sensor registers as a burst. See BME280 Datasheet section 4. Data readout
365+
//tempScale = 0 for Celsius scale (default setting)
366+
//tempScale = 1 for Fahrenheit scale
367+
void BME280::readAllMeasurements(BME280_SensorMeasurements *measurements, byte tempScale){
368+
369+
uint8_t dataBurst[8];
370+
readRegisterRegion(dataBurst, BME280_MEASUREMENTS_REG, 8);
371+
372+
if(tempScale == 0){
373+
readTempCFromBurst(dataBurst, measurements);
374+
}else{
375+
readTempFFromBurst(dataBurst, measurements);
376+
}
377+
readFloatPressureFromBurst(dataBurst, measurements);
378+
readFloatHumidityFromBurst(dataBurst, measurements);
379+
}
380+
358381
//****************************************************************************//
359382
//
360383
// Pressure Section
@@ -390,6 +413,37 @@ float BME280::readFloatPressure( void )
390413

391414
}
392415

416+
void BME280::readFloatPressureFromBurst(uint8_t buffer[], BME280_SensorMeasurements *measurements)
417+
{
418+
419+
// Set pressure in Pa as unsigned 32 bit integer in Q24.8 format (24 integer bits and 8 fractional bits).
420+
// Output value of “24674867” represents 24674867/256 = 96386.2 Pa = 963.862 hPa
421+
422+
int32_t adc_P = ((uint32_t)buffer[0] << 12) | ((uint32_t)buffer[1] << 4) | ((buffer[2] >> 4) & 0x0F);
423+
424+
int64_t var1, var2, p_acc;
425+
var1 = ((int64_t)t_fine) - 128000;
426+
var2 = var1 * var1 * (int64_t)calibration.dig_P6;
427+
var2 = var2 + ((var1 * (int64_t)calibration.dig_P5)<<17);
428+
var2 = var2 + (((int64_t)calibration.dig_P4)<<35);
429+
var1 = ((var1 * var1 * (int64_t)calibration.dig_P3)>>8) + ((var1 * (int64_t)calibration.dig_P2)<<12);
430+
var1 = (((((int64_t)1)<<47)+var1))*((int64_t)calibration.dig_P1)>>33;
431+
if (var1 == 0)
432+
{
433+
measurements->pressure = 0; // avoid exception caused by division by zero
434+
}
435+
else
436+
{
437+
p_acc = 1048576 - adc_P;
438+
p_acc = (((p_acc<<31) - var2)*3125)/var1;
439+
var1 = (((int64_t)calibration.dig_P9) * (p_acc>>13) * (p_acc>>13)) >> 25;
440+
var2 = (((int64_t)calibration.dig_P8) * p_acc) >> 19;
441+
p_acc = ((p_acc + var1 + var2) >> 8) + (((int64_t)calibration.dig_P7)<<4);
442+
443+
measurements->pressure = (float)p_acc / 256.0;
444+
}
445+
}
446+
393447
// Sets the internal variable _referencePressure so the altitude is calculated properly.
394448
// This is also known as "sea level pressure" and is in Pascals. The value is probably
395449
// within 10% of 101325. This varies based on the weather:
@@ -459,6 +513,25 @@ float BME280::readFloatHumidity( void )
459513
return (float)(var1>>12) / 1024.0;
460514
}
461515

516+
void BME280::readFloatHumidityFromBurst(uint8_t buffer[], BME280_SensorMeasurements *measurements)
517+
{
518+
519+
// Set humidity in %RH as unsigned 32 bit integer in Q22. 10 format (22 integer and 10 fractional bits).
520+
// Output value of “47445” represents 47445/1024 = 46. 333 %RH
521+
int32_t adc_H = ((uint32_t)buffer[6] << 8) | ((uint32_t)buffer[7]);
522+
523+
int32_t var1;
524+
var1 = (t_fine - ((int32_t)76800));
525+
var1 = (((((adc_H << 14) - (((int32_t)calibration.dig_H4) << 20) - (((int32_t)calibration.dig_H5) * var1)) +
526+
((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)) *
527+
((int32_t)calibration.dig_H2) + 8192) >> 14));
528+
var1 = (var1 - (((((var1 >> 15) * (var1 >> 15)) >> 7) * ((int32_t)calibration.dig_H1)) >> 4));
529+
var1 = (var1 < 0 ? 0 : var1);
530+
var1 = (var1 > 419430400 ? 419430400 : var1);
531+
532+
measurements->humidity = (float)(var1>>12) / 1024.0;
533+
}
534+
462535
//****************************************************************************//
463536
//
464537
// Temperature Section
@@ -494,6 +567,29 @@ float BME280::readTempC( void )
494567
return output;
495568
}
496569

570+
float BME280::readTempFromBurst(uint8_t buffer[])
571+
{
572+
int32_t adc_T = ((uint32_t)buffer[3] << 12) | ((uint32_t)buffer[4] << 4) | ((buffer[5] >> 4) & 0x0F);
573+
574+
//By datasheet, calibrate
575+
int64_t var1, var2;
576+
577+
var1 = ((((adc_T>>3) - ((int32_t)calibration.dig_T1<<1))) * ((int32_t)calibration.dig_T2)) >> 11;
578+
var2 = (((((adc_T>>4) - ((int32_t)calibration.dig_T1)) * ((adc_T>>4) - ((int32_t)calibration.dig_T1))) >> 12) *
579+
((int32_t)calibration.dig_T3)) >> 14;
580+
t_fine = var1 + var2;
581+
float output = (t_fine * 5 + 128) >> 8;
582+
583+
output = output / 100 + settings.tempCorrection;
584+
585+
return output;
586+
}
587+
588+
void BME280::readTempCFromBurst(uint8_t buffer[], BME280_SensorMeasurements *measurements)
589+
{
590+
measurements->temperature = readTempFromBurst(buffer);
591+
}
592+
497593
float BME280::readTempF( void )
498594
{
499595
float output = readTempC();
@@ -502,6 +598,14 @@ float BME280::readTempF( void )
502598
return output;
503599
}
504600

601+
void BME280::readTempFFromBurst(uint8_t buffer[], BME280_SensorMeasurements *measurements)
602+
{
603+
float output = readTempFromBurst(buffer);
604+
output = (output * 9) / 5 + 32;
605+
606+
measurements->temperature = output;
607+
}
608+
505609
//****************************************************************************//
506610
//
507611
// Dew point Section

src/SparkFunBME280.h

+15
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ Distributed as-is; no warranty is given.
105105
#define BME280_STAT_REG 0xF3 //Status Reg
106106
#define BME280_CTRL_MEAS_REG 0xF4 //Ctrl Measure Reg
107107
#define BME280_CONFIG_REG 0xF5 //Configuration Reg
108+
#define BME280_MEASUREMENTS_REG 0xF7 //Measurements register start
108109
#define BME280_PRESSURE_MSB_REG 0xF7 //Pressure MSB
109110
#define BME280_PRESSURE_LSB_REG 0xF8 //Pressure LSB
110111
#define BME280_PRESSURE_XLSB_REG 0xF9 //Pressure XLSB
@@ -172,6 +173,14 @@ struct SensorCalibration
172173

173174
};
174175

176+
struct BME280_SensorMeasurements
177+
{
178+
public:
179+
float temperature;
180+
float pressure;
181+
float humidity;
182+
};
183+
175184
//This is the main operational class of the driver.
176185

177186
class BME280
@@ -215,18 +224,22 @@ class BME280
215224

216225
//Software reset routine
217226
void reset( void );
227+
void readAllMeasurements(BME280_SensorMeasurements *measurements, byte tempScale = 0);
218228

219229
//Returns the values as floats.
220230
float readFloatPressure( void );
221231
float readFloatAltitudeMeters( void );
222232
float readFloatAltitudeFeet( void );
233+
void readFloatPressureFromBurst(uint8_t buffer[], BME280_SensorMeasurements *measurements);
223234

224235
float readFloatHumidity( void );
236+
void readFloatHumidityFromBurst(uint8_t buffer[], BME280_SensorMeasurements *measurements);
225237

226238
//Temperature related methods
227239
void setTemperatureCorrection(float corr);
228240
float readTempC( void );
229241
float readTempF( void );
242+
float readTempFromBurst(uint8_t buffer[]);
230243

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

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

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

0 commit comments

Comments
 (0)