Skip to content

Instantly share code, notes, and snippets.

@paramoshkinandrew
Created June 24, 2024 22:44
Show Gist options
  • Save paramoshkinandrew/aeacc6c0b9e6e8a330101cbdaf9342df to your computer and use it in GitHub Desktop.
Save paramoshkinandrew/aeacc6c0b9e6e8a330101cbdaf9342df to your computer and use it in GitHub Desktop.
BME280 I2C read data, including compensation formulas
#include <Arduino.h>
#include <Wire.h>
#define BME280_ADDRESS 0x76
unsigned short dig_T1, dig_P1;
short dig_T2, dig_T3, dig_P2, dig_P3, dig_P4, dig_P5, dig_P6, dig_P7, dig_P8, dig_P9, dig_H2, dig_H4, dig_H5;
unsigned char dig_H1, dig_H3;
char dig_H6;
// Shared fine temperature value
signed long int t_fine;
void writeRegister(uint8_t reg, uint8_t value);
// Compensation
float getTemperatureC(signed long int rawTemp);
float getPressurePA(signed long int rawPressure);
uint8_t getHumidity(signed long int rawHumidity);
void setup() {
// Setup serial for some logs
Serial.begin(9600);
// Initialize Wire library
Wire.begin();
/* ---- Verify sensor presence ---- */
// Start transmission to the BME280
Wire.beginTransmission(BME280_ADDRESS);
// Set a register to read from with the next request
Wire.write(0xD0);
// End transmission
Wire.endTransmission();
// Request 1 byte from the BME280, starting with 0xD0 we set before
Wire.requestFrom(BME280_ADDRESS, 1);
// If there's something to read
if (Wire.available()) {
// Read a byte from the I2C bus
uint8_t chipID = Wire.read();
// And compare it with the expected value
if (chipID != 0x60) {
// BME280 IS NOT FOUND
Serial.println("BME280 is not found!");
while (1);
} else {
Serial.println("BME280 is ready!");
}
} else {
Serial.println("BME280 is not found!");
while (1);
}
/* ---- Configure sensor ---- */
// Configuration (1000ms standby, no IRR filter)
writeRegister(0xF5, 0xA0);
// Humidity oversampling (x1) - IMPORTANT, must go before temperature & pressure configs
writeRegister(0xF2, 0x1);
// Temperature & pressure oversampling and sensor mode (x1/x1, normal mode)
writeRegister(0xF4, 0x27);
/* ---- Read calibration values ----*/
// Pull calibration data
Wire.beginTransmission(BME280_ADDRESS);
Wire.write(0x88);
Wire.endTransmission();
// Read 24 bytes (12 pairs) of calibration data
Wire.requestFrom(BME280_ADDRESS, 24);
if (Wire.available()) {
// Temperature calibration
dig_T1 = Wire.read() | ((unsigned short)Wire.read() << 8);
dig_T2 = Wire.read() | ((short)Wire.read() << 8);
dig_T3 = Wire.read() | ((short)Wire.read() << 8);
// Pressure calibration
dig_P1 = Wire.read() | ((unsigned short)Wire.read() << 8);
dig_P2 = Wire.read() | ((short)Wire.read() << 8);
dig_P3 = Wire.read() | ((short)Wire.read() << 8);
dig_P4 = Wire.read() | ((short)Wire.read() << 8);
dig_P5 = Wire.read() | ((short)Wire.read() << 8);
dig_P6 = Wire.read() | ((short)Wire.read() << 8);
dig_P7 = Wire.read() | ((short)Wire.read() << 8);
dig_P8 = Wire.read() | ((short)Wire.read() << 8);
dig_P9 = Wire.read() | ((short)Wire.read() << 8);
} else {
Serial.println("Can not read 24 bytes of calibration");
while (1);
}
// Humidity calibration
Wire.beginTransmission(BME280_ADDRESS);
Wire.write(0xA1);
Wire.endTransmission();
Wire.requestFrom(BME280_ADDRESS, 1);
if (Wire.available()) {
dig_H1 = (unsigned char)Wire.read();
} else {
Serial.println("Can not read dig_H1");
while (1);
}
Wire.beginTransmission(BME280_ADDRESS);
Wire.write(0xE1);
Wire.endTransmission();
Wire.requestFrom(BME280_ADDRESS, 6);
if (Wire.available()) {
dig_H2 = Wire.read() | ((short)Wire.read() << 8);
dig_H3 = Wire.read();
dig_H4 = (short)Wire.read() << 4;
// Tricky part, we read e5 separately
uint8_t e5 = Wire.read();
// And add last 4 bits only
// e5 & 0x0F sets first 4 bits to 0,
// 0x0F = 0b00001111
// e.g. (1111 1111) & (0000 1111) = 1111 0000
dig_H4 |= e5 & 0x0F;
// And for H5, we only need first 4 bits of e5, thus we're shifting right by 4
dig_H5 = ((short)Wire.read() << 4) | (e5 >> 4);
dig_H6 = Wire.read();
} else {
Serial.println("Can not read remaining humidity calibration values");
while (1);
}
}
void loop() {
// Set a register we want to start reading from
Wire.beginTransmission(BME280_ADDRESS);
Wire.write(0xF7);
Wire.endTransmission();
// Request 8 bits of data (from 0xF7 to 0xFE)
Wire.requestFrom(BME280_ADDRESS, 8);
// If there's anything to read
if (Wire.available()) {
// Get raw data form the registers, we use signed long int to compensate in the future
signed long int rawPressure = ((uint32_t)Wire.read() << 12) | ((uint16_t)Wire.read() << 4) | ((uint8_t)Wire.read() >> 4);
signed long int rawTemperature = ((uint32_t)Wire.read() << 12) | ((uint16_t)Wire.read() << 4) | ((uint8_t)Wire.read() >> 4);
signed long int rawHumidity = ((uint16_t)Wire.read() << 8) | Wire.read();
Serial.print("> Pressure mmHg: ");
Serial.println((int)(getPressurePA(rawPressure) * 0.00750062));
Serial.print("> Temperature C: ");
Serial.println(getTemperatureC(rawTemperature));
Serial.print("> Humidity %: ");
Serial.println(getHumidity(rawHumidity));
Serial.println("----------------");
}
delay(1000);
}
void writeRegister(uint8_t reg, uint8_t value) {
Wire.beginTransmission(BME280_ADDRESS);
Wire.write(reg);
Wire.write(value);
Wire.endTransmission();
}
float getTemperatureC(signed long int rawTemp) {
signed long int var1, var2;
var1 = ((((rawTemp >> 3) - (((signed long int)dig_T1) << 1))) * ((signed long int)dig_T2)) >> 11;
var2 = (((rawTemp >> 4) - ((signed long int)dig_T1) * ((rawTemp >> 4) - ((signed long int)dig_T1))) >> 12) * (((signed long int)dig_T3) >> 14);
t_fine = var1 + var2;
return (float)((t_fine * 5 + 128) >> 8) / 100;
}
float getPressurePA(signed long int rawPressure) {
signed long long int var1, var2, p;
var1 = ((signed long long int)t_fine) - 128000;
var2 = var1 * var1 * (signed long long int)dig_P6;
var2 = var2 + ((var1 * (signed long long int)dig_P5) << 17);
var2 = var2 + (((signed long long int)dig_P4) << 35);
var1 = (((((signed long long int)1) << 47) + var1)) * ((signed long long int)dig_P1) >> 33;
if (var1 == 0) {
return 0;
}
p = 1048576 - rawPressure;
p = (((p << 31) - var2) * 3125) / var1;
var1 = (((signed long long int)dig_P9) * (p >> 13) * (p >> 13)) >> 25;
var2 = (((signed long long int)dig_P8) * p) >> 19;
p = ((p + var1 + var2) >> 8) + (((signed long long int)dig_P7) << 4);
return (float)p / 256;
}
uint8_t getHumidity(signed long int rawHumidity) {
signed long int v_x1_u32r = (t_fine - ((signed long int)76800));
v_x1_u32r = (((((rawHumidity << 14) - (((signed long int)dig_H4) << 20) - (((signed long int)dig_H5) * v_x1_u32r)) +
((signed long int)16384)) >>
15) *
(((((((v_x1_u32r * ((signed long int)dig_H6)) >> 10) * (((v_x1_u32r *
((signed long int)dig_H3)) >>
11) +
((signed long int)32768))) >>
10) +
((signed long int)2097152)) *
((signed long int)dig_H2) +
8192) >>
14));
v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * ((signed long int)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 (uint8_t)((v_x1_u32r >> 12) / 1024);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment