BMP280 how to read temperature?

EkoEko

New member
Hello,
I have a Teensy 3.6 and BMP280 barometric pressure sensor (datasheet: https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmp280-ds001.pdf)

I only want to read temperature for now. But my code has a bug I couldn't find.
I use <i2c_t3.h> (https://github.com/nox771/i2c_t3) instead of <Wire.h>.

Here is the code:

Code:
#include <i2c_t3.h>

#define SCL_pin 37
#define SDA_pin 38
#define bmp_address 0x76         
#define bmp_control_address 0xF4 // ctr_meas in BMP280 datasheet. See chapter 4.2 and 5.2
#define bmp_config_address 0xF5  // config in datasheet. See chapter 4.2 and 4.3.5

union byteArrayToInt32{
  byte arr[4];
  int32_t integer;
};

union byteArrayToInt16{
  byte arr[2];
  int16_t integer;
}; 

union byteArrayToUInt16{
  byte arr[2];
  uint16_t integer;
}; 

byte temperature_register_address[3]={0xFA,0xFB,0xFC};

byte dig_T1_register_address[2]={0x88,0x89};//LSB,MSB See chapter 3.12;
byte dig_T2_register_address[2]={0x8A,0x8B};
byte dig_T3_register_address[2]={0x8C,0x8D};

union byteArrayToUInt16 dig_T1; 
union byteArrayToInt16 dig_T2, dig_T3;
union byteArrayToInt32 raw_temperature;

int32_t t_fine;

void setup() {                   
  Wire1.begin(I2C_MASTER, 0x00, SCL_pin, SDA_pin); // SCL:37 SDA:38 on Teensy 3.6
  Wire1.setDefaultTimeout(10000);

  Wire1.beginTransmission(bmp_address);
  Wire1.write(bmp_control_address);     

/*###################################################################
  Set oversampling rates and operating mode
  bmp_control_address (ctrl_meas) is 8 bits
  
  Lets say it is abcdefgh 
  abc is temperature oversampling rate (chapter 3.3.2)
  def is pressure oversampling rate    (chapter 3.3.1)
  gh is power mode                     ( chapter 3.6 )

  Also see chapter 4.3.4 for ctrl_meas

  osrs_t[2:0]   Temp / Pressure oversampling |   mode[1:0]       Mode
      000                   skipped          |      00        sleep mode
      001                     x1             |     01,10      forced mode
      010                     x2             |      11        normal mode 
      011                     x4             |         
      100                     x8             |      
  101,110,111                 x16            |    
###################################################################*/
  
  Wire1.write(163); // 101 000 11 = 163. Temperature oversampling x16, pressure skipped, normal mode
  Wire1.endTransmission();

  
  Wire1.beginTransmission(bmp_address);
  Wire1.write(bmp_config_address); 
  
/*###################################################################
  Set standby time, IIR filter coefficent and spi mode
  bmp_config_address (config) is 8 bits
  
  Lets say it is abcdefgh 
  abc is standby time in normal mode (    chapter 3.6.3    )
  def is time constant of IIR filter (chapter 3.3.3 and 3.5)
  g is a read only bit
  h is spi mode                     (     chapter 5.3     )

  Also see chapter 4.3.5 for config

   t_sb[2:0]    Standby time (ms) |  (I am not completely sure since)   |  spi3w_en[0]  SPI Mode
      000             0.5         |  (values were not in the datasheet) |      0         4 Wire
      001             62.5        |                                     |      1         3 Wire
      010             125         |  filter[2:0]   Filter coefficent    |
      011             250         |      000              off           |
      100             500         |      010               2            |
      101             1000        |      011               4            |
      110             2000        |      100               8            |
      111             4000        |  101,110,111           16           | 
###################################################################*/

  Wire1.write(44); // 001 100 00 = 0: Standby time 62.5 ms, filter coefficent 8, 4 wire SPI
  Wire1.endTransmission();

  Serial.begin(15200);
  Serial.println("                         DECIMAL ---> BINARY");
}


void loop() {
  
  Wire1.beginTransmission(bmp_address);
  Wire1.write(temperature_register_address,3);
  Wire1.endTransmission();
  Wire1.requestFrom(bmp_address,3);
  raw_temperature.arr[3]=0;
  raw_temperature.arr[2]=Wire1.read();//msb_t;
  raw_temperature.arr[1]=Wire1.read();//lsb_t;
  raw_temperature.arr[0]=Wire1.read();//xlsb_t;

  showRawTemperature();
  
  Wire1.beginTransmission(bmp_address);
  Wire1.write(dig_T1_register_address,2);
  Wire1.endTransmission();
  Wire1.requestFrom(bmp_address,2);
  dig_T1.arr[0]=Wire1.read();
  dig_T1.arr[1]=Wire1.read();

  Wire1.beginTransmission(bmp_address);
  Wire1.write(dig_T2_register_address,2);
  Wire1.endTransmission();
  Wire1.requestFrom(bmp_address,2);
  dig_T2.arr[0]=Wire1.read();
  dig_T2.arr[1]=Wire1.read();

  Wire1.beginTransmission(bmp_address);
  Wire1.write(dig_T3_register_address,2);
  Wire1.endTransmission();
  Wire1.requestFrom(bmp_address,2);
  dig_T3.arr[0]=Wire1.read();
  dig_T3.arr[1]=Wire1.read();

  showDigTs();
  //###################################################

  Serial.print(compensateTemperature(raw_temperature.integer)/100);
  Serial.println(" *C");
  Serial.println("########################");
  smartDelay(200);
}

void smartDelay(unsigned int wait_for){
  unsigned int beginning=millis();
  while(millis()-beginning<wait_for){}
  return;
}

void showRawTemperature(){
  Serial.print("raw_temperature.arr[0] :  ");
  Serial.print(raw_temperature.arr[0]);
  Serial.print(" ---> ");
  Serial.println(raw_temperature.arr[0],BIN);

  Serial.print("raw_temperature.arr[1] :  ");
  Serial.print(raw_temperature.arr[1]);
  Serial.print(" ---> ");
  Serial.println(raw_temperature.arr[1],BIN);

  Serial.print("raw_temperature.arr[2] :  ");
  Serial.print(raw_temperature.arr[2]);
  Serial.print(" ---> ");
  Serial.println(raw_temperature.arr[2],BIN);

  Serial.print("raw_temperature.arr[3] :  ");
  Serial.print(raw_temperature.arr[3]);
  Serial.print(" ---> ");
  Serial.println(raw_temperature.arr[3],BIN);

  Serial.print("raw_temperature.integer:  ");
  Serial.print(raw_temperature.integer);
  Serial.print(" ---> ");
  Serial.println(raw_temperature.integer,BIN);
  Serial.println();
}

void showDigTs(){
  Serial.print("Dig_T1:     ");
  Serial.print(dig_T1.integer);
  Serial.print(" ---> ");
  Serial.println(dig_T1.integer,BIN);

  Serial.print("Dig_T2:     ");
  Serial.print(dig_T2.integer);
  Serial.print(" ---> ");
  Serial.println(dig_T2.integer,BIN);

  Serial.print("Dig_T3:     ");
  Serial.print(dig_T3.integer);
  Serial.print(" ---> ");
  Serial.println(dig_T3.integer,BIN);
  Serial.println();
}

//See chapter 3.11.3 for compensation code
int32_t compensateTemperature(int32_t adc_T){
  int32_t var1, var2, T;
  var1 = ((((adc_T>>3)  - ((int32_t)dig_T1.integer<<1))) * ((int32_t)dig_T2.integer))>>11;
  var2 = (((((adc_T>>4) - ((int32_t)dig_T1.integer))     * ((adc_T>>4) - ((int32_t)dig_T1.integer))) >>12) * ((int32_t)dig_T3.integer))>>14;
  t_fine=var1+var2;
  T = (t_fine*5+128)>>8;
  return T;
}

And the output:
Code:
                         DECIMAL ---> BINARY
raw_temperature.arr[0] :  112 ---> 1110000
raw_temperature.arr[1] :  131 ---> 10000011
raw_temperature.arr[2] :  192 ---> 11000000
raw_temperature.arr[3] :  0 ---> 0
raw_temperature.integer:  12616560 ---> 110000001000001101110000

Dig_T1:     28059 ---> 110110110011011
Dig_T2:     26349 ---> 110011011101101
Dig_T3:     -1000 ---> 11111111111111111111110000011000

139 *C
########################
raw_temperature.arr[0] :  112 ---> 1110000
raw_temperature.arr[1] :  131 ---> 10000011
raw_temperature.arr[2] :  224 ---> 11100000
raw_temperature.arr[3] :  0 ---> 0
raw_temperature.integer:  14713712 ---> 111000001000001101110000

Dig_T1:     28059 ---> 110110110011011
Dig_T2:     26349 ---> 110011011101101
Dig_T3:     -1000 ---> 11111111111111111111110000011000

-25 *C
########################
raw_temperature.arr[0] :  112 ---> 1110000
raw_temperature.arr[1] :  131 ---> 10000011
raw_temperature.arr[2] :  16 ---> 10000
raw_temperature.arr[3] :  0 ---> 0
raw_temperature.integer:  1082224 ---> 100001000001101110000

Dig_T1:     28059 ---> 110110110011011
Dig_T2:     26349 ---> 110011011101101
Dig_T3:     -1000 ---> 11111111111111111111110000011000

194 *C
########################
raw_temperature.arr[0] :  112 ---> 1110000
raw_temperature.arr[1] :  131 ---> 10000011
raw_temperature.arr[2] :  48 ---> 110000
raw_temperature.arr[3] :  0 ---> 0
raw_temperature.integer:  3179376 ---> 1100001000001101110000

Dig_T1:     28059 ---> 110110110011011
Dig_T2:     26349 ---> 110011011101101
Dig_T3:     -1000 ---> 11111111111111111111110000011000

41 *C
########################
raw_temperature.arr[0] :  112 ---> 1110000
raw_temperature.arr[1] :  131 ---> 10000011
raw_temperature.arr[2] :  64 ---> 1000000
raw_temperature.arr[3] :  0 ---> 0
raw_temperature.integer:  4227952 ---> 10000001000001101110000

Dig_T1:     28059 ---> 110110110011011
Dig_T2:     26349 ---> 110011011101101
Dig_T3:     -1000 ---> 11111111111111111111110000011000

-41 *C
########################
.
.
.

And schematic
Teensy_3.6_&_BMP280.png

I have several questions:
1) Is there a problem with reading and writing because I couldn't understand that part in datasheet. Especially RW bit, it's address is not provided how am I going to write it? Is it an automatic process?
I2C_Write_BMP280.PNG
I2C_Read_BMP280.PNG

2) As you can see from the output the most unstable byte is raw_temperature.arr[2] among raw_temperature.arr[X] values.
Code:
  Wire1.beginTransmission(bmp_address);
  Wire1.write(temperature_register_address,3);
  Wire1.endTransmission();
  Wire1.requestFrom(bmp_address,3);
  raw_temperature.arr[3]=0;
  raw_temperature.arr[2]=Wire1.read();//msb_t;
  raw_temperature.arr[1]=Wire1.read();//lsb_t;
  raw_temperature.arr[0]=Wire1.read();//xlsb_t;

But I assigned raw_temperature.arr[2] as the most significant byte.
Memory_Map.PNG
Does it mean I made a mistake about assignment indexes or reading?

3) Dig_TX values (trimming values) does not change, is this normal?
4) Dig_T3 has a value much larger than 16 bits what could be the reason?

Note: I know there is a BMP280 library but I want to learn how to use it without it's library.

Thank you in advance.
 
Have you tried using the Adafruit_BMP280 library? although it uses the Wire library.

You might either try using it and/or glance at it to see how they are reading the temperature.
 
Back
Top