Skip to content

Reading from the sensor in Continuous mode is blocking, and the continuous mode example mis-reports the call timing. #34

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
whogben opened this issue Mar 6, 2022 · 6 comments

Comments

@whogben
Copy link
Contributor

whogben commented Mar 6, 2022

Hi there,

I came across this issue while trying to read a VL53l0x without blocking program execution for a long time. No matter how I tried it, I tended to get blocked for 40-60ms on reading the sensor.

I tried using this Simple Continuous Example and noticed that it was reporting 0.00 and 1.00 ms for the continuous mode read times - perfect! Except, when I added my own timing check around the loop, I am getting 49ms for each read call:

with vl53.continuous_mode():
    while True:
        # try to adjust the sleep time (simulating program doing something else)
        # and see how fast the sensor returns the range
        time.sleep(0.2)

        curTime = time.time()
        ns = time.monotonic_ns() # new line
        print("Range: {0}mm ({1:.2f}ms)".format(vl53.range, time.time() - curTime))
        real_ms = (time.monotonic_ns() - ns)/1_000_000 # new line
        print('(real ms ' + str(real_ms) + ')') # new line

This includes my attempt at measuring around the existing time measurement, and output looks like this:

Range: 301mm (0.00ms)
  (real ms 49.3774)
  Range: 301mm (0.00ms)
  (real ms 49.4079)
  Range: 301mm (0.00ms)
  (real ms 49.4079)

Can anyone confirm if:

  1. my time measurement is correct and the example is in fact reporting a smaller number of ms than it takes?
  2. continous_mode is supposed to make it so that you can read_range() quickly (ie in a few ms or less?)

Thanks for your time.

@ladyada
Copy link
Member

ladyada commented Mar 6, 2022

it'll always take 33ms (at least) to measure, plus 20ms for processing, since thats the timing budget. if it says less something is wonky with your timing. 49ms sounds right!

@whogben
Copy link
Contributor Author

whogben commented Mar 6, 2022

Thanks for the quick reply!

Do you know if there is another adafruit sensor where it would be possible for the sensor to perform readings on it's own, and the circuitpython program to just get the latest reading back? I'm trying to use a distance sensor for a realtime system, and can't afford to suspend execution while the sensor is working.

@ladyada
Copy link
Member

ladyada commented Mar 6, 2022

you can read thru the driver code to see how continuous works, basically you need to check if the data is ready before you try to read it, otherwise it will block

@whogben
Copy link
Contributor Author

whogben commented Mar 6, 2022

I'm attempting it now, and will try to make it my first pull request, but I've run into a snag: It seems the time is being eaten up by the I2C device read/write calls, and not any looping inside the sensor module.

Looking at the read_range() function, I assumed this is where we wait for the data to be ready:

while (self._read_u8(_RESULT_INTERRUPT_STATUS) & 0x07) == 0:

However, when I profiled the function, the loop is only evaluated and it's contents never executed.

The delays are coming from the _read_u8 and _write_u16 methods, in which it's the base I2C device that's using the time. For example, this _read_u8 method takes 19ms on my Feather S2:

def _read_u8(self, address):

If the base I2C device read/write are where the time is taken, does that mean that it's not possible to check if data is available from the sensor faster than this (without modifying the I2C device implementation)?

What's strange is I am also using I2C device with the PCA9865 driver, only the I2C device writes don't appear produce similar delays in that driver - though I haven't explicitly measured.

@whogben
Copy link
Contributor Author

whogben commented Mar 6, 2022

(Also, this bug report was based on me misunderstanding what continuous_mode is supposed to do - it can be closed or moved to a more appropriate venue.)

@ladyada ladyada closed this as completed Mar 6, 2022
@whogben
Copy link
Contributor Author

whogben commented Mar 8, 2022

The maximum block time can be reduced from 50ms to 2.5ms* using two methods:

  • Up the I2C device clock frequency from 100khz to 400khz
  • Add an optional param to read_range that lets you poll it until data is available (returns -1 when range is not available yet)

Pull request here

*testing with Feather S2, measurement_timing_budget of 200ms, calling read_range every 50ms

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants