Wednesday, September 12, 2012

EOC bit in Bosch BMP085 I2C registers

Searching for an End-of-conversion (EOC) bit
in the undocumented BMP085 I2C registers

(Answer is: EOC bit exists, you can skip to the bottom for the conclusion)


Here I am, tinkering with the Bosch BMP085 pressure and temperature sensor on a nice little 10DOF board I found on eBay at around $21 (half that of a FreeIMU, although with a little less precise sensors):





On to the problem, the datasheet of the BMP085 happens to be a shame. This is about the only I2C chip I've found where no description of its I2C register map is provided, just a diagram on the "usual" operation and what value to write to which register at what time. No explanations, no bits, no nothing.

As I would rather not have the extra EOC (end of conversion) pin connected, I'd be quite happy to have its value read through the I2C; and something tells me this bit should be available at one of the sensor's undocumented registers.


So, by using the Arduino IDE, I implemented a simple initialization function where it would:

1) read BMP085 calibration parameters (EEPROM)
2) read the uncompensated temperature value
3) read all I2C regs from address 128 to 255 (below them the values are 0)
4) request the uncompensated pressure value with oversampling 3 (writing 0xF4 to register 0xF4), which takes up to 25.5 ms to be measured.
5) During those 25.5 ms proceed to read again all regs 128 to 255
6) Wait 25.5 ms (just in case I2C reading interfered with measuring)
7) Read again all regs 128 to 255

Hence we end up with 3 sets of values for the I2C regs 128 to 255
1st value: before measurement is requested (i.e. sensor is idle)
2nd value: during measurement (i.e. sensor "working")
3rd value: after measurement (i.e. sensor back to idle)

If there is an EOC (end of conversion) bit in a BMP085 I2C register, it should be different during measurement time (2nd value).

Here are the results showing which registers do change at any of the above three moments:




Analysis

Let me share the results in a less-to-more important order:


Registers 0xF6 to 0xF8:

0xF6 and 0xF7 are the measurement's MSB and LSB respectively. Also register 0xF8 changes sometimes (as it is the measurement's XLSB byte).

So, obviously, these registers can not contain the EOC bit we are looking for.


Register 0xF3:

This undocumented register changes its value upon measurement start and so it stays even after finishing it, hence it is of no value as EOC indication.


Register 0xCF:

Actually this register almost always keeps its value (except in the above screenshot :), hence I am skipping it due to its inconsistency as EOC indication.





Register 0xC2:

This is one interesting candidate since it consistently has value 0xBC between measurements and value 0x98 during measurement.


Register 0xF4:

Another good candidate is 0xF4, the register that is written to command the sensor to start a pressure or temperature measurement.
Since oversampling 3 is being used, the value written to it between reading 1st and 2nd values is 0xF4.

As can be seen, bit 3 is auto-cleared at measurement's start, meaning who knows what.

However bit 5 also happens to be auto-cleared AFTER measurement is finished. Does this mean something?





Then, let's keep an eye only on 0xC2 and 0xF4 by sampling them as many times as possible before, during, and after a measurement is started.



Analyzing Register 0xC2 during measurement

So, by connecting to the Arduino board the P_EOC pin of the BMP085 and implementing the following code:

1) Read register 0xC2 and print its value
2) Request pressure with oversampling N
3) Read register 0xC2 and store its value in an array
4) If P_EOC is high, go to 5, if it is low, go back to 3
5) Read register 0xC2 and store its value at the last position in the array
6) Print the array

The results are, for oversampling 0 are:



Hence we can see that 0xC2 register's idle value is 0xBC, whereas during conversion it is 0x84 or 0x98.

Same register values are seen for the rest of oversamplings.



Analyzing Register 0xF4 during measurement

Code is same as with register 0xC2, but this time reading register 0xF4. The results are quite interesting, here is a screenshot:



The register values DURING measurement (step 2 above) are constant and only change (bit 5 cleared) when EOC pin rises, meaning end of conversion.

Please note that measurement took some 9 ms with an oversampling factor of 2, whereas the datasheet indicates only the maximum conversion time of 13.5 ms.

I don't know about you, but I find that difference useful, to say the least.


Same happens with other oversampling values:

- Oversampling 0: register 0xF4 changes its value from 0x30 to 0x10 upon EOC pin rising, after 4 ms real conversion time, as opposed to datasheet's maximum of 4.5 ms

- Oversampling 1: register 0xF4 changes its value from 0x70 to 0x50 upon EOC pin rising, after 6 ms real conversion time, as opposed to datasheet's maximum of 7.5 ms

- Oversampling 2: register 0xF4 changes its value from 0xB0 to 0x90 upon EOC pin rising, after 9 ms real conversion time, as opposed to datasheet's maximum of 13.5 ms

- Oversampling 3: register 0xF4 changes its value from 0xF0 to 0xD0 upon EOC pin rising, after 17 ms real conversion time, as opposed to datasheet's maximum of 25.5 ms




PRESSURE/TEMPERATURE EOC

Up until now all tests are conducted when requesting pressure measurements, however, both registers 0xC2 and 0xF4 show the same behavior when reading temperature.

From my tests, its real conversion time was around 3 ms.



CONCLUSION


On how accurate are these time measures, please note:

1) no Serial printing is done within the main loop (as should be)
2) the EOC pin is checked, in the loop, only after every I2C read, which takes a discrete amount of time, hence the above real times may be slightly above the actual value.
3) (**DISCLAIMER**) the real conversion times above have been measured in one particular day, with certain relatively stable pressure and temperature values, hence the real conversion time may vary for different conditions, probably up to the datasheet's maximum... but then that's why we wanted the EOC indication in the first place!

So, both registers 0xC2 and 0xF4 seem to provide EOC indication. I personally prefer checking 0xF4 for simplicity, hence:



Bit 5 of I2C register 0xF4 in Bosch BMP085 sensor is a busy indication (the inverse of the EOC pin value)



Feedback/constructive criticism is welcome.

2 comments:

  1. Wow, great article! Nice reverse engineering done here.

    ReplyDelete
  2. Yes, it's confirmed by Bosch in their datasheet for BMP180 (an updated version of BMP085). They've added global memory map and bit 5 of register 0xF4 is indeed EOC indication.

    ReplyDelete