Hi, I am trying to get temperature and pressure data from a BMP390 sensor by talking to it directly over I2C. I am testing with a mega328p.
I am able to get raw temperature and pressure data from the sensor, but I am having trouble converting them to pascals and celcius using the calibration coefficients.
The temp is wildly off, sometimes in the high 90s or in the negatives. The pressure just overflows, but I am focusing on fixing temp first, so I am not worrying about that for now.
Here are some samples of the kind of serial output I am getting:
Triggering manual measurement...
Raw Temp: 12591491
Computed Temp:
97.64
Raw Pressure: 45928
Computed Pressure:
2109572736.00
Triggering manual measurement...
Raw Temp: 9347
Computed Temp:
-127.49
Raw Pressure: 45928
Computed Pressure:
2109487872.00
I am using the calibration coefficients provided by the sensor and converting them to floats using the formulas in the datasheet.
I also believe the raw temperature values are being read correctly as per the results in the seril output. My maths for converting the temps is based on the example at the end of the datasheet.
Any help would be greatly appreciated.
Here is my sketch:
#include <Arduino.h>
#include <Wire.h>
#define BMP390_ADDRESS 0x77
// BMP390 regs
#define REG_RESET 0x7E
#define REG_CONFIG 0x00
#define REG_PWR_CTRL 0x1B
#define REG_OSR 0x1C
#define REG_ODR 0x1D
#define REG_STATUS 0x03
#define REG_PRESSURE 0x04
#define REG_TEMPERATURE 0x07
#define NVM_PAR_T1_0 0x31
#define NVM_PAR_T1_1 0x32
#define NVM_PAR_T2_0 0x33
#define NVM_PAR_T2_1 0x34
#define NVM_PAR_T3 0x35
#define NVM_PAR_P1_0 0x36
#define NVM_PAR_P1_1 0x37
#define NVM_PAR_P2_0 0x38
#define NVM_PAR_P2_1 0x39
#define NVM_PAR_P3 0x3A
#define NVM_PAR_P4 0x3B
#define NVM_PAR_P5_0 0x3C
#define NVM_PAR_P5_1 0x3D
#define NVM_PAR_P6_0 0x3E
#define NVM_PAR_P6_1 0x3F
#define NVM_PAR_P7 0x40
#define NVM_PAR_P8 0x41
#define NVM_PAR_P9_0 0x42
#define NVM_PAR_P9_1 0x43
#define NVM_PAR_P10 0x44
#define NVM_PAR_P11 0x45
void writeRegister(uint8_t reg, uint8_t value) {
Wire.beginTransmission(BMP390_ADDRESS);
Wire.write(reg);
Wire.write(value);
Wire.endTransmission();
}
uint8_t readRegister(uint8_t reg) {
Wire.beginTransmission(BMP390_ADDRESS);
Wire.write(reg);
Wire.endTransmission();
Wire.requestFrom(BMP390_ADDRESS, 1);
return Wire.read();
}
uint32_t read24bit(uint8_t reg) {
Wire.beginTransmission(BMP390_ADDRESS);
Wire.write(reg);
Wire.endTransmission(false);
Wire.requestFrom(BMP390_ADDRESS, 3);
while (Wire.available() < 3);
uint32_t msb = Wire.read();
uint32_t lsb = Wire.read();
uint32_t xlsb = Wire.read();
uint32_t raw_value = (msb << 16) | (lsb << 8) | xlsb;
return raw_value;
}
struct BMP390_Calibration {
float par_p11;
float par_p10;
float par_p9;
float par_p8;
float par_p7;
float par_p6;
float par_p5;
float par_p4;
float par_p3;
float par_p2;
float par_p1;
float par_t3;
float par_t2;
float par_t1;
float t_lin;
};
void getTempCoefficients(BMP390_Calibration *cal) {
uint16_t par_t1 = (uint16_t)readRegister(NVM_PAR_T1_0) | ((uint16_t)readRegister(NVM_PAR_T1_1) << 8);
int16_t par_t2 = (int16_t)readRegister(NVM_PAR_T2_0) | ((int16_t)readRegister(NVM_PAR_T2_1) << 8);
int8_t par_t3 = (int8_t)readRegister(NVM_PAR_T3);
int8_t par_p11 = (int8_t)readRegister(NVM_PAR_P11);
int8_t par_p10 = (int8_t)readRegister(NVM_PAR_P10);
int16_t par_p9 = (int16_t)readRegister(NVM_PAR_P9_0) | ((int16_t)readRegister(NVM_PAR_P9_1) << 8);
int8_t par_p8 = (int8_t)readRegister(NVM_PAR_P8);
int8_t par_p7 = (int8_t)readRegister(NVM_PAR_P7);
uint16_t par_p6 = (uint16_t)readRegister(NVM_PAR_P6_0) | ((uint16_t)readRegister(NVM_PAR_P6_1) << 8);
uint16_t par_p5 = (uint16_t)readRegister(NVM_PAR_P5_0) | ((uint16_t)readRegister(NVM_PAR_P5_1) << 8);
int8_t par_p4 = (int8_t)readRegister(NVM_PAR_P4);
int8_t par_p3 = (int8_t)readRegister(NVM_PAR_P3);
int16_t par_p2 = (int16_t)readRegister(NVM_PAR_P2_0) | ((int16_t)readRegister(NVM_PAR_P2_1) << 8);
int16_t par_p1 = (int16_t)readRegister(NVM_PAR_P1_0) | ((int16_t)readRegister(NVM_PAR_P1_1) << 8);
cal->par_t1 = par_t1 / 0.00390625f; // precomputed 2^(-8) = 0.00390625
cal->par_t2 = par_t2 / 1073741824.0f; // precomputed 2^30 = 1073741824
cal->par_t3 = par_t3 / 281474976710656.0f; // precomputed 2^48 = 281474976710656
Serial.println("Calibration Coefficients:");
Serial.print("par_t1: "); Serial.println(cal->par_t1, 6);
Serial.print("par_t2: "); Serial.println(cal->par_t2, 6);
Serial.print("par_t3: "); Serial.println(cal->par_t3, 6);
cal->par_p11 = par_p11 / 36893488147419103232.0f; // precomputed 2^65 = 36893488147419103232.0
cal->par_p10 = par_p10 / 281474976710656.0f; // precomputed 2^48 = 281474976710656.0
cal->par_p9 = par_p9 / 281474976710656.0f; // precomputed 2^48 = 281474976710656.0
cal->par_p8 = par_p8 / 32768.0f; // precomputed 2^15 = 32768
cal->par_p7 = par_p7 / 256.0f; // precomputed 2^8 = 256
cal->par_p6 = par_p6 / 64.0f; // precomputed 2^6 = 64
cal->par_p5 = par_p5 / 0.125f; // precomputed 2^(-3) = 0.125
cal->par_p4 = par_p4 / 137438953472.0f; // precomputed 2^37 = 137438953472
cal->par_p3 = par_p3 / 4294967296.0f; // precomputed 2^32 = 4294967296
cal->par_p2 = (par_p2 - 16384) / 536870912.0f; // precomputed 2^14 = 16384, 2^29 = 536870912
cal->par_p1 = (par_p1 - 16384) / 1048576.0f; // precomputed 2^14 = 16384, 2^20 = 1048576
}
float compensateTemp(uint32_t uncompTemp, struct BMP390_Calibration *cal) {
float partialData1;
float partialData2;
partialData1 = (float)(uncompTemp - cal->par_t1);
partialData2 = (float)(partialData1 * cal->par_t2);
cal->t_lin = partialData2 + (partialData1 * partialData1) * cal->par_t3;
return cal->t_lin;
}
float compensatePressure(uint32_t uncompPressure, struct BMP390_Calibration *cal) {
float compensatedPressure;
float partialData1;
float partialData2;
float partialData3;
float partialData4;
float partialOut1;
float partialOut2;
partialData1 = cal->par_p6 * cal->t_lin;
partialData2 = cal->par_p7 * (cal->t_lin * cal->t_lin);
partialData3 = cal->par_p8 * (cal->t_lin * cal->t_lin * cal->t_lin);
partialOut1 = cal->par_p5 + partialData1 + partialData2 + partialData3;
partialData1 = cal->par_p2 * cal->t_lin;
partialData2 = cal->par_p3 * (cal->t_lin * cal->t_lin);
partialData3 = cal->par_p4 * (cal->t_lin * cal->t_lin * cal->t_lin);
partialOut2 = (float)uncompPressure *
(cal->par_p1 + partialData1 + partialData2 + partialData3);
partialData1 = (float)uncompPressure * (float)uncompPressure;
partialData2 = cal->par_p9 + cal->par_p10 * cal->t_lin;
partialData3 = partialData1 + partialData2;
partialData4 = partialData3 + ((float)uncompPressure * (float)uncompPressure * (float)uncompPressure) * cal->par_p11;
compensatedPressure = partialOut1 + partialOut2 + partialData4;
return compensatedPressure;
}
BMP390_Calibration coefficients;
void setup() {
Wire.begin();
Serial.begin(9600);
Serial.println("Initializing BMP390...");
// Perform soft reset
writeRegister(REG_RESET, 0xB6);
delay(10);
getTempCoefficients(&coefficients);
// Disable IIR filter
writeRegister(REG_CONFIG, 0b00000000);
// Set oversampling
writeRegister(REG_OSR, 0b00010011);
// Set output data rate
writeRegister(REG_ODR, 0x02); // 50Hz
Serial.println("BMP390 Initialized.");
}
void loop() {
Serial.println("Triggering manual measurement...");
writeRegister(REG_PWR_CTRL, 0b00100011);
delay(100);
uint32_t rawTemp, rawPressure;
rawTemp = read24bit(REG_TEMPERATURE);
rawPressure = read24bit(REG_PRESSURE);
Serial.print("Raw Temp: ");
Serial.println(rawTemp);
Serial.println("Computed Temp: ");
Serial.println(compensateTemp(rawTemp, &coefficients));
Serial.print("Raw Pressure: ");
Serial.println(rawPressure);
Serial.println("Computed Pressure: ");
Serial.println(compensatePressure(rawPressure, &coefficients));
delay(1000);
}