adafruit / Adafruit_CircuitPython_BME680

CircuitPython driver for BME680
MIT License
57 stars 40 forks source link

adafruit_bme680.py, class Adafruit_BME680, _perform_reading(): infinite loop #66

Open mtetcs opened 1 year ago

mtetcs commented 1 year ago

We have an environmental test setup here with several BME680s attached via a TCA9548A. On rare occasions when attempting to read a BME680, we can see _perform_reading() getting stuck in the loop shown below, which effectively halts the data acquisition. Normally each device takes exactly 8 iterations of this loop to collect a value. If we force the loop to terminate after N=20 iterations, successive device reads are successful.

The code below assumes that it will eventually receive new_data, though it seems this isn't always the case. Perhaps this could be modified to address the assumption, and to handle the case that a no-new-data event occurs on the first device read and the values for temp/rh/press/... will be unset?

while not new_data:
    data = self._read(_BME680_REG_MEAS_STATUS, 17)
    new_data = data[0] & 0x80 != 0
    time.sleep(0.005)
caternuson commented 1 year ago

Can you provide a short, simple, complete example sketch that can be used to demonstrate the issue.

mtetcs commented 1 year ago

In principle, the Usage Example in the docs is sufficient to demonstrate the issue, given the presence of the hardware in question. We only sample every 10s for the application here.

Perhaps the gist of the issue is that hardware isn't always 100% reliable. Arguably the best place to handle temporarily unresponsive hardware is in its API, rather than handling it downstream where it would necessitate an additional layer of complexity to forcibly terminate hung read operations. _perform_reading() could plausibly raise a BlockingIOError if it doesn't receive an acceptable response after a given number of iterations, in preference to an infinite loop.

caternuson commented 1 year ago

Is the inclusion of the TCA9548A necessary? Or do you get the same issue even without the TCA being used?

mtetcs commented 1 year ago

No and no. There was no issue with the BME680 hardware in either configuration.

caternuson commented 1 year ago

OK, if there's no issue, then not sure what the issue is?

Is there any issue when using just a single BME680 (no TCA9548A) and running the example code from this library? https://github.com/adafruit/Adafruit_CircuitPython_BME680/blob/main/examples/bme680_simpletest.py

mtetcs commented 1 year ago

The issue reported is that _perform_reading() fails to consider the possibility that the hardware may be non-responsive. Instead of failing gracefully and allowing the caller to deal with the problem, it enters an infinite loop, halting progression.