Created
June 24, 2024 22:44
-
-
Save paramoshkinandrew/aeacc6c0b9e6e8a330101cbdaf9342df to your computer and use it in GitHub Desktop.
BME280 I2C read data, including compensation formulas
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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