Digital Read of BME280 register via I2C without using Adafruit Library

All,

For the purpose of deepening my knowledge of I2C communication I am attempting to not use the Adafruit library to read/write registers of Bosch's BME280.

Before getting into the code...

  • I have already used the I2C scanner address to confirm the IP address of my sensor is 0x76.
  • I have used the Adafruit library with success to communicate with the sensor using 0x76 as its address.

Now the code...

#include <Wire.h>

#define BME280_ADDRESS (0x76)

int c = 1;
int written_bytes = 0;
byte transmission_status=255;

void setup() {

Serial.begin(9600);
Serial.println("Conected");
}

void loop() {
//////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////Read BME Registers/////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
if (c == 1)
{

delay(1000);

//Read address of Chip
Wire.beginTransmission((uint8_t)0x76);
written_bytes=Wire.write((uint8_t)0xD0);
transmission_status=Wire.endTransmission();
Wire.requestFrom((uint8_t)0x76,(byte)1);
uint8_t value = Wire.read();
Serial.println(value, HEX);
Serial.println(written_bytes);
Serial.println(transmission_status);

c = 2;
}
}

My problem is...

I am expecting the value of the register to be 0x60 but I am getting FF.

written_bytes prints a value of 1 and trnsmission_status prints a value of 2.

I have attached the datasheet for the BME280 for your reference. Please help me learn!

bme280 datasheet.pdf (1.53 MB)

I figured it out. It was something small....

I was missing Wire.begin(0x76).

Few queries:

1. What is the meaning of Wire.begin(0x76); when you include this line in the Master Code (the Arduino UNO)?

2. When the value 0x76 is already a byte value, why have you uselessly caste it -- (uint8_t)0x76?

3. What is reflected in the variable transmission_status by the execution of the transmission_status = Wire.endTransmission() instruction?

4. Why have you not executed the Wire.available() instruction after the execution of Wire.requestFrom() command to check the status of 'data availability?'

5. Is BME280 an active I2C Slave? If not, why have you configured your Arduino (UNO) to be addressed as a an active Slave having had the execution of the instruction Wire.begin(0x76);? Which Master (active slave) is going to communicate with your Arduino at the Slave Address 0x76?

GolamMostfa,

My answers to your queries...

  1. The short answer is I am not certain.. I just noticed it in all of my reference sketches.

  2. There is no use. Thanks for the pointer.

  3. See below...
    1:data too long to fit in transmit buffer
    2:received NACK on transmit of address
    3:received NACK on transmit of data
    4:other error

  4. Is it required to use Wire.Available every time you request?

  5. I am not sure. However my device is working properly after using this. I looked at Adafruit library for the BME280 and it has the same Wire.Begin().

GolamMostafa:
4. Why have you not executed the Wire.available() instruction after the execution of Wire.requestFrom() command to check the status of 'data availability?'

This one OP did correctly.
Wire.available() is utterly useless after Wire.requestFrom(), as the latter guarantees that the requested number of bytes are available for reading. It's in fact worse than the (equally useless) cast to uint8_t which will simply be ignored by the compiler and not increase the overall program size...

brd904:
My answers to your queries...

  1. The short answer is I am not certain.. I just noticed it in all of my reference sketches.

  2. There is no use. Thanks for the pointer.

  3. See below...
    1:data too long to fit in transmit buffer
    2:received NACK on transmit of address
    3:received NACK on transmit of data
    4:other error

  4. Is it required to use Wire.Available every time you request?

  5. I am not sure. However my device is working properly after using this. I looked at Adafruit library for the BME280 and it has the same Wire.Begin().

  1. Wire.begin(0x76); instruction indicates that the (now) Master could also be addressed as a Slave (by another Master) at I2C address 0x76.

  2. OK.

  3. 0 means successful transmission.

Wire.beginTransmission(0x76);
byte busStatus = Wire.endTransmission();
if (busStatus == 0)
{
   Serial.print("Slave is Present!");
}
else
{
   Serial.print("Slave coul not be detceted!");
   while(1);    //wait for ever
}
  1. See Post#4.

  2. BME280 is a passive slave. It can not initiate data transfer by generating SCL pulses. In an I2C Bus, we can not have two slaves having the same address.

So I should of put Wire.Begin() instead of Wire.Begin(0x76) because I need to enter as the Master not a slave?

Exactly.

brd904:
So I should of put Wire.Begin() instead of Wire.Begin(0x76) because I need to enter as the Master not a slave?

wvmarle:
Exactly.

Exactly, it is:

Wire.begin();