ms1963
Posts: 10
Joined: Sat Mar 27, 2021 5:46 pm

C/C++-Library for Bosch BME280 sensor (SPI)

Fri May 07, 2021 10:41 pm

For those interested: I transformed the Raspberry Pi Pico example for accessing the BME280 via SPI (see https://github.com/raspberrypi/pico-exa ... me280_spi/ ) into a C++ library.
The code can be found at https://github.com/ms1963/bme280_spi.
It includes an example program to illustrate the usage of the C++ class BME280.

fivdi
Posts: 440
Joined: Sun Sep 23, 2012 8:09 pm
Contact: Website

Re: C/C++-Library for Bosch BME280 sensor (SPI)

Sun May 09, 2021 6:12 pm

I think there are a few bugs in the bme280_spi example in this function. For example, the first call to read_registers reads 24 bytes into buffer but later in the function buffer[25] is used. A few other things also appear to be incorrect.

ms1963
Posts: 10
Joined: Sat Mar 27, 2021 5:46 pm

Re: C/C++-Library for Bosch BME280 sensor (SPI)

Mon May 10, 2021 2:25 pm

Could you tell me what do you think, might be wrong. I am using the original C code from raspberrypi.org in a C++ wrapper class. Did you check it and encountered any problems?
By the way: You are perfectly right with your comment on the wrong usage of buffer. This problem appears in the original C code. I’ll check this in the Bosch datasheet and correct it.
Any other hints highly appreciated.

fivdi
Posts: 440
Joined: Sun Sep 23, 2012 8:09 pm
Contact: Website

Re: C/C++-Library for Bosch BME280 sensor (SPI)

Mon May 10, 2021 6:24 pm

ms1963 wrote:
Mon May 10, 2021 2:25 pm
Could you tell me what do you think, might be wrong. I am using the original C code from raspberrypi.org in a C++ wrapper class. Did you check it and encountered any problems?

I looked at the code but I didn't test it to see if it works. The reason I saw the problems is because I was working with the BME280 recently using I2C and spotted a few differences. Here is the current implementation of read_compensation_parameters with a number written as a comment after each problem that I can see:

Code: Select all

void read_compensation_parameters() {
    uint8_t buffer[26];

    read_registers(0x88, buffer, 24);               // 1

    dig_T1 = buffer[0] | (buffer[1] << 8);
    dig_T2 = buffer[2] | (buffer[3] << 8);
    dig_T3 = buffer[4] | (buffer[5] << 8);

    dig_P1 = buffer[6] | (buffer[7] << 8);
    dig_P2 = buffer[8] | (buffer[9] << 8);
    dig_P3 = buffer[10] | (buffer[11] << 8);
    dig_P4 = buffer[12] | (buffer[13] << 8);
    dig_P5 = buffer[14] | (buffer[15] << 8);
    dig_P6 = buffer[16] | (buffer[17] << 8);
    dig_P7 = buffer[18] | (buffer[19] << 8);
    dig_P8 = buffer[20] | (buffer[21] << 8);
    dig_P9 = buffer[22] | (buffer[23] << 8);

    dig_H1 = buffer[25];

    read_registers(0xE1, buffer, 8);                // 2

    dig_H2 = buffer[0] | (buffer[1] << 8);
    dig_H3 = (int8_t) buffer[2];
    dig_H4 = buffer[3] << 4 | (buffer[4] & 0xf);    // 3
    dig_H5 = (buffer[5] >> 4) | (buffer[6] << 4);   // 4, 5
    dig_H6 = (int8_t) buffer[7];                    // 6
}
Here is a description of each of the problems:

1 - Reads 24 bytes, should read 26 bytes
2 - Reads 8 bytes, should read 7 bytes
3 - Converts 12 bits to an int16_t in the range 0 to 4095, should convert 12 bits to an int16_t in the range -2048 to 2047
4 - Uses incorrect registers and uses them incorrectly
5 - Converts 12 bits to an int16_t in the range 0 to 4095, should convert 12 bits to an int16_t in the range -2048 to 2047
6 - Uses incorrect register

Here is what I think the code should look like:

Code: Select all

void read_compensation_parameters() {
    uint8_t buffer[26];

    read_registers(0x88, buffer, 26);               // 1

    dig_T1 = buffer[0] | (buffer[1] << 8);
    dig_T2 = buffer[2] | (buffer[3] << 8);
    dig_T3 = buffer[4] | (buffer[5] << 8);

    dig_P1 = buffer[6] | (buffer[7] << 8);
    dig_P2 = buffer[8] | (buffer[9] << 8);
    dig_P3 = buffer[10] | (buffer[11] << 8);
    dig_P4 = buffer[12] | (buffer[13] << 8);
    dig_P5 = buffer[14] | (buffer[15] << 8);
    dig_P6 = buffer[16] | (buffer[17] << 8);
    dig_P7 = buffer[18] | (buffer[19] << 8);
    dig_P8 = buffer[20] | (buffer[21] << 8);
    dig_P9 = buffer[22] | (buffer[23] << 8);

    dig_H1 = buffer[25];

    read_registers(0xE1, buffer, 7);                // 2

    dig_H2 = buffer[0] | (buffer[1] << 8);
    dig_H3 = (int8_t) buffer[2];
    dig_H4 = ((int8_t) buffer[3] << 4) | (buffer[4] & 0xf); // 3
    dig_H5 = ((int8_t) buffer[5] << 4) | (buffer[4] >> 4);  // 4, 5
    dig_H6 = (int8_t) buffer[6];                            // 6
}

Note that I haven't tested this. I'd also recommend taking a close look at the BME280 datasheet.

Return to “General”