0x01[BME680]: Temperature channel

This post discusses about obtaining calibrated readings from the temperature channel.

So, according to the datasheet the temperature channel is a 20 BIT resolution register divided into:

  1. temp_msb (0x22) <7:0> : Contains the MSB part of raw output data.
  2. temp_lsb (0x23) <7:0> : Contains the LSB part of raw output data.
  3. temp_xlsb (0x24) <7:4> : Contains the XLSB part of raw output data depending on the oversampling ratio setting.

The various oversampling ratio available are {1, 2, 4, 8, 16} and can be set by setting osrs_t<2:0> field of ctrl_meas register.

IIR Filter :

The sensor also has an optional IIR filter to remove short term fluctuations from the temperature and pressure readings. This filtered output reading is responsible for the XLSB(4 Bits) part of measurement.

  • When the IIR filter is enabled, the temperature resolution is 20 bit.
  • When the IIR filter is disabled, the temperature resolution is 16 + (osrs_t – 1) bit, e.g. 18 bit when osrs_t is set to ‘3’.

The sensor has two modes:

  1. Sleep mode.
  2. Forced mode.

These modes can be selected using the mode<1:0> control register and for reading the data it should be in Forced mode only. Also, the sensor automatically returns to sleep mode after a single T P H G cycle is performed.

For reading the temp data, I wrote a function bme680_read_temp() which basically does a regmap_bulk_read() from the 3 registers specified above. Since, we can clearly see from above register addressing the MSB resides at low address and LSB Byte at High address which means it follows Big Endian and I used __be32 type so that if any address space violation takes place Sparse will warn about it.

This raw data need to be compensated using the BME6xy API provided by Bosch Sensortec. This compensation function manipulates the raw data to give out the compensated readings. Without the use of the function we simply cannot get calibrated readings therefore I contacted Bosch Sensortec GmbH about the usage of the mentioned function in my code and several other register addressing and calibration parameters.

We could easily use their function by adding:

  • Copyright (C) 2017 – 2018 Bosch Sensortec GmbH

to the top of our source code but Linux kernel uses GPL License and Bosch has uploaded
a different License file. I’m not sure kernel community would entertain such License file or adding those 39 lines of text above my source code. So, we are still waiting for their approval and legally use their code.

Anyway, for these compensation function we need calibration parameters which are programmed into the devices’ non-volatile memory (NVM) during
production and cannot be altered by the customer. These calibration parameters along with the raw_data supplied from the bme680_read_temp() combined produce the compensated output.

But sadly these details are missing from the datasheet! So, how did I know come to know about these missing details ?

Well, firstly we already have such sensors (not exactly like bme680) in the mainline kernel such as bmp280, bme280, bmi180 consisting of pressure sensors, IMUs and few others. So, I referred especially to the bmp280 in iio/pressure/ directory which is also supplied by Bosch Sensortec. And it has all the data mentioned in the datasheet such as:

  1. calibration parameters: “3.11.2 Trimming parameter readout” Pg21 BMP280 Digital Pressure Sensor datasheet
  2. resolution of the readings output: “3.11.3 Compensation formula
    1. “// Returns temperature in DegC, resolution is 0.01 DegC. Output value of “5123” equals 51.23 DegC.”
    2. /”/ Returns pressure in Pa as unsigned 32 bit integer in Q24.8 format (24 integer bits and 8 fractional bits).
      // Output value of “24674867” represents 24674867/256 = 96386.2 Pa = 963.862 hPa”

So, we can see all these details supplied in the BMP280 datasheet but not in my case!

Therefore, I asked Bosch about these specific missing details and waiting for their reply. For now I have used these functions and calibration details from BME6xy API just to see what readings I get. And I get the correct readings if BME680 has the same/similar resolution as in the case of BMP280. But we can’t be sure until we get a confirmation from Bosch.

The various device attributes:

Screenshot from 2018-06-14 13-34-38

And the readings that I get is below:

Screenshot from 2018-06-14 13-35-16

Don’t mind those reports before the readings in the above image. That was only for debugging purposes 😉

Alright! We get a reading of 3254 which is perfect if it has a similar 0.01 °C resolution as we saw in BMP280 sensor.

Therefore,

3254*0.01 = 32.54 °C

which is my current room temperature 🙂

So, that’s it for this post and I will be discuss about Pressure and subsequent channels in the next post and also, about ACPI matching which I got to learn from my mentor.

Gist Source Code: temperature channel

Published by

Himanshu Jha

Linux kernel hobbyist & C programming Language fanboy

Leave a comment