adafruit / Adafruit-Raspberry-Pi-Python-Code

Adafruit library code for Raspberry Pi
1.43k stars 688 forks source link

spurious incorrect readings on BMP180 pressure sensor #98

Closed quantenschaum closed 9 years ago

quantenschaum commented 9 years ago

I'm using a BMP180 pressure sensor hooked up to a Raspberry Pi on the I2C bus. I read the data from the sensors using your BMP085 library. This works fine in general, but sometimes I get bogus values for the pressure (I did not monitor temperature). These wrong values are always smaller than the correct (within the device's accuracy) pressure value.

I'm logging the pressure data with rrdtool and this is what I get (y axis ranges from 980 to 1020):

pressure-1

The blue curve shows the values in question, a new value is fed into the RRD every 10s.

I looked into the datasheet of the BMP180 and found that after requesting a conversion (measurement) you need to wait some time before performing the readout of the data from the sensor. Depending on the sensor mode this takes about 5 to 26ms (page 12).

The code in Adafruit_BMP085.py reads:

  def readRawTemp(self):
    "Reads the raw (uncompensated) temperature from the sensor"
    self.i2c.write8(self.__BMP085_CONTROL, self.__BMP085_READTEMPCMD)
    time.sleep(0.005)  # Wait 5ms
    raw = self.readU16(self.__BMP085_TEMPDATA)
    if (self.debug):
      print "DBG: Raw Temp: 0x%04X (%d)" % (raw & 0xFFFF, raw)
    return raw

  def readRawPressure(self):
    "Reads the raw (uncompensated) pressure level from the sensor"
    self.i2c.write8(self.__BMP085_CONTROL, self.__BMP085_READPRESSURECMD + (self.mode << 6))
    if (self.mode == self.__BMP085_ULTRALOWPOWER):
      time.sleep(0.005)
    elif (self.mode == self.__BMP085_HIGHRES):
      time.sleep(0.014)
    elif (self.mode == self.__BMP085_ULTRAHIGHRES):
      time.sleep(0.026)
    else:
      time.sleep(0.008)
    msb = self.i2c.readU8(self.__BMP085_PRESSUREDATA)
    lsb = self.i2c.readU8(self.__BMP085_PRESSUREDATA+1)
    xlsb = self.i2c.readU8(self.__BMP085_PRESSUREDATA+2)
    raw = ((msb << 16) + (lsb << 8) + xlsb) >> (8 - self.mode)
    if (self.debug):
      print "DBG: Raw Pressure: 0x%04X (%d)" % (raw & 0xFFFF, raw)
    return raw

So, python's time.sleep() is used to make the code wait for the conversion. This seems to be a problem, since the timing is not sufficiently accurate (maybe?). If I reduce the sleep time, I always get bogus results. Increasing the sleep times by a factor of 10 seems to make it better, but does to fix it in general.

What is going on here?

microbuilder commented 9 years ago

Please raise this on the support forums. We can't do support via github since the support team doesn't monitor the issues actively here (they aren't subscribed to every repo for alerts, etc.).

alexellis commented 9 years ago

@quantenschaum Did you get anywhere with this query?

quantenschaum commented 9 years ago

I don't remember exactly what I did, but on a similiar setup with different hardware the issue disappeared. Probably it was a fault of the single device I was using.