BMP280 Temperature Register F7 returning low value

I've been trying to add a BMP280 T/P sensor to a monitoring application on a WEMO D1 mini. The system already has a AHT10 T/H sensor and a SSD1306 LCD screen running on it. I've haven't been able to get the Adafruit examples to find the sensor on the I2C bus, so I rolled my own test app to work things out. Everything seems to be okay except for the msb value returned on the sensor read.
The compensation values are returned and it appears to accept the config and meas_ctrl values. I have tried different settings for the oversampling, filtering and time and that doesn't appear to affect the returned measurement values. The value being returned from register F7(the Temperature msb) is about 32% lower than expected. I hard coded the value from the Bosch datasheet (8318208) to verify the conversion math is working with the returned compensation and it spits out about 25C which is reasonable. The code is returning numbers around 613000 and the resulting temperature is around -17C and if I apply heat tot the sensor the value move in the negative direction. If I scale up the F7 value by 1.367 before shifting and combining with the other bytes, the code returns 8362240 and calculates a temperature of 24.9C which is within 2 degrees of its neighboring ATH110. In this state the temperature value increase when heat is applied. I am not sure if I missed something in the setup or timing or . . . . I have tried the code with 4 different BMP280's and 3 different WEMOS modules and they all give the about the same results. At room temperature the code returns a value between 90 and 95, where I estimate for the example value should be between 120 and 130. The BMP280 has CSB pin tied HI and the SDO pin is tied low. VDD is 3.4 VDC from the WEMO's regulator.

The FA to FC registries for a pressure read appear to return reasonable raw values.

Here's the test code. Comments and variable values are to the right of the patinate lines

#include <Wire.h>

#define addr 0X76

uint16_t dig_T1;
int16_t dig_T2;
int16_t dig_T3;
uint16_t dig_P1;
int16_t dig_P2;
int16_t dig_P3;
int16_t dig_P4;
int16_t dig_P5;
int16_t dig_P6;
int16_t dig_P7;
int16_t dig_P8;
int16_t dig_P9;

int32_t t_fine;


int i=0;

//Unsigned short read
uint16_t readCompsU(int Addr, int reg){
  Wire.beginTransmission(Addr);
  Wire.write(reg);
  if(Wire.endTransmission(true) !=0){
    Serial.println("Connection Failed");
  }
    Wire.requestFrom(addr,1,true);
    uint16_t temp1 = Wire.read();
    return temp1;
}
//Signed short read
int16_t readComps(int Addr, int reg){
  Wire.beginTransmission(Addr);
  Wire.write(reg);
  if(Wire.endTransmission(true) !=0){
    Serial.println("Connection Failed");
  }
    Wire.requestFrom(addr,1,true);
    int16_t temp1 = Wire.read();
    return temp1;
}

uint8_t getStatus(){
  Wire.beginTransmission(addr);
  Wire.write(0xF3);
  if(Wire.endTransmission(true) !=0){
  Serial.println("Connection Failed");
  }
    Wire.requestFrom(addr,1,true);
    int16_t temp1 = Wire.read();
    return temp1;
}

//Unsigned long read of 3 adjacent registers
uint32_t sensor_read(int reg){
//  while(getStatus() !=0){
//    delay(1);
//  }
  Wire.beginTransmission(addr);
  Wire.write(reg);
  if(Wire.endTransmission(true) !=0){
    return 0xFFFF;
  }
  Wire.requestFrom(addr,3,true);
  if(Wire.available() !=3){
    return 0xFFFE;
  }
  uint8_t buffer[3];
  for(int i = 0;i<3;i++){
    buffer[i] = Wire.read();
//    Serial.print("buffer i: ");
//    Serial.println(buffer[i]);
  }
  //return  (uint32_t((double)buffer[0]*1.367) << 16 | uint32_t(buffer[1]) << 8) |uint32_t(buffer[2]); //Scale the F7 value
  return  (uint32_t(buffer[0]) << 16 | uint32_t(buffer[1]) << 8) |uint32_t(buffer[2]);
}

void setup() {
  // put your setup code here, to run once:
Serial.begin(115200); //Start Serial
Wire.begin(); //Start Wire
delay(1000);  //Delay 1 sec for allow Serial to come up
Serial.println(); //Print a blank line to seperate from garbage line on reset button push

//Configure BMP280
Wire.beginTransmission(addr); //Make the i2c connection to 0x76
Wire.write(0xF4); //ctrl_meas 
Wire.write(0x27); //osrs_t = 1x; osrs_p = 1x; mode = normal (00100111)
Wire.endTransmission(true); //Hard end connection
Wire.beginTransmission(addr); //Make the i2c connection to 0x76
Wire.write(0xF5); //config
Wire.write(0x40); //t_sb = 1 sec; filter = OFF; spi = OFF (01000000)
Wire.endTransmission(true); //Hard end connection

//Get the compensation factors - can't use a buster read, chip locks up after first read
dig_T1 = (readCompsU(addr,0X89)<<8)|(readCompsU(addr,0X88)); // Returns 27554  (datasheet example has 27504)
dig_T2 = (readCompsU(addr,0X8B)<<8)|(readCompsU(addr,0X8A)); // Returns 25544  (datasheet example has 26435)
dig_T3 = (readCompsU(addr,0X8D)<<8)|(readCompsU(addr,0X8C)); // Returns 50     (datasheet example has -1000)
dig_P1 = (readCompsU(addr,0X8F)<<8)|(readCompsU(addr,0X8E)); // Returns 36896  (datasheet example has 36477)
dig_P2 = (readCompsU(addr,0X91)<<8)|(readCompsU(addr,0X90)); // Returns -10678 (datasheet example has -10685)
dig_P3 = (readCompsU(addr,0X93)<<8)|(readCompsU(addr,0X92)); // Returns 3024   (datasheet example has 3024)
dig_P4 = (readCompsU(addr,0X95)<<8)|(readCompsU(addr,0X94)); // Returns 5200   (datasheet example has 2855)
dig_P5 = (readCompsU(addr,0X97)<<8)|(readCompsU(addr,0X96)); // Returns 65     (datasheet example has 140)
dig_P6 = (readCompsU(addr,0X99)<<8)|(readCompsU(addr,0X98)); // Returns -7     (datasheet example has -7)
dig_P7 = (readCompsU(addr,0X9B)<<8)|(readCompsU(addr,0X9A)); // Returns 15500  (datasheet example has 15500)
dig_P8 = (readCompsU(addr,0X9D)<<8)|(readCompsU(addr,0X9C)); // Returns -14600 (datasheet example has -14600)
dig_P9 = (readCompsU(addr,0X9F)<<8)|(readCompsU(addr,0X9E)); // Returns 6000   (datasheet example has 6000)
}

void loop() {
  int32_t var1;
  int32_t var2;
  int32_t adc_T;
//Temperature read
  adc_T = sensor_read(0xF7); //Read the sensor's temperature registors
//  This is returning in the 6000000 to 6100000; Example adt_T=6130944 range: 0xF7 = 93, 0xF8 = 140, 0xF9 = 0
//  adc_T = 8318208; Test value from reference sheet example, this give value temperature value
//  Reversed engineered 0xF7 = 126, 0xF8 = 237, 0xF9 = 0
  Serial.print("adc_T: ");
  Serial.println(adc_T);
  /***Code from Adafruit cpp file**/
  adc_T >>= 4; 
  var1 = ((((adc_T >> 3) - ((int32_t)dig_T1 << 1))) * ((int32_t)dig_T2)) >>11;
  var2 = (((((adc_T >> 4) - ((int32_t)dig_T1)) * ((adc_T >> 4) - ((int32_t)dig_T1))) >>12) * ((int32_t)dig_T3)) >>14;
  t_fine = var1 + var2;
  float T = (t_fine * 5 + 128) >> 8;
  /***End of Adafruit Code snippit***/
  
  Serial.print("var1: ");
  Serial.println(var1);
  Serial.print("var2: ");
  Serial.println(var2);
  Serial.print("t_fine: ");
  Serial.println(t_fine);
  Serial.print("T: ");
  Serial.println(T);
  Serial.println();
  delay(5000);

Serial.println();
  
}

According to the BMP280 datasheet from Bosch register 0xF7 to 0xF9 contain the pressure and not the temperature.

1 Like

There goes the dyslexia again + short term memory. I don't know how many times I looked at that memory map and just reversed thing in my mind. Guess the 70's were harder on me than I though. Thanks, pylon

Hey! thanks kms3156 for posting your code. I was having "issues" with my code and yours works like a charm.

You wouldn't have similar code for the pressure that you would like to share?

Hi @kms3156

I've written a non-blocking library for the BMP280 available here:

There's also example code that works with the 0x76 alternate I2C address:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.