fossasia / pslab-python

Python Library for PSLab Desktop: https://pslab.io
GNU General Public License v3.0
1.63k stars 225 forks source link

feat: Added VL531X Time-of-Flight Proximity Sensor #228

Closed AsCress closed 4 months ago

AsCress commented 4 months ago

Superseeds #130, adds support for the VL531X Time-of-Flight Proximity Sensor. I've taken #130 and made changes to update the I2C calls, making them compatible with our current I2C API. Other suggested changes in #130 are also implemented. All credits to @orangecms for the functionality and the port from Adafruit's implementation.

Changes

Screenshots / Recordings

I've tested this and it works nicely. Here's how one can get data from the sensor -

Screenshot 2024-07-24 182409

@bessman I see a couple of TODOs and questions in the comments. How should we go about them ? Should we just let them be there and merge this or should we document this more ? Do inform me if I haven't properly followed conventions in here:))

Summary by Sourcery

This pull request introduces support for the VL531X Time-of-Flight Proximity Sensor by adding a new class VL531X that inherits from I2CSlave. The I2C calls have been updated to be compatible with the current I2C API, and the class has been refactored to use slave methods. The sensor is now included in the list of supported sensors.

sourcery-ai[bot] commented 4 months ago

Reviewer's Guide by Sourcery

This pull request adds support for the VL531X Time-of-Flight Proximity Sensor. The implementation includes a new VL531X class that inherits from I2CSlave, facilitating easy initialization and integration with the existing I2C API. The changes also update the import statements in 'supported.py' and add the VL531X sensor to the supported dictionary with its I2C address. The new class includes methods for sensor initialization, configuration, and data reading, ensuring compatibility with the current I2C API.

File-Level Changes

Files Changes
pslab/external/supported.py
pslab/external/VL531X.py
Added support for VL531X Time-of-Flight Proximity Sensor, including sensor initialization, configuration, and data reading methods.

Tips - Trigger a new Sourcery review by commenting `@sourcery-ai review` on the pull request. - Continue your discussion with Sourcery by replying directly to review comments. - You can change your review settings at any time by accessing your [dashboard](https://app.sourcery.ai): - Enable or disable the Sourcery-generated pull request summary or reviewer's guide; - Change the review language; - You can always [contact us](mailto:support@sourcery.ai) if you have any questions or feedback.
bessman commented 4 months ago

If #130 is used a base, please make your changes on top of those commits, not rebased on development. orangecms should be credited for the work he did.

I see a couple of TODOs and questions in the comments. How should we go about them ? Should we just let them be there and merge this or should we document this more ?

Ideally, the TODOs should be dealt with by answering the questions they pose.

Take _TUNING_CONFIG for example, which is 80 or so register/value pairs which are sent to the sensor as part of the initialization. Doing what, exactly? The purpose and function of _TUNING_CONFIG is completely opaque to me.

That's just one example. If the questions remain unanswered, the TODOs should also remain.

To be honest, I don't like this code. I don't understand it, even using the datasheet as a reference. Which is why #130 was not merged in the first place.

There exist drivers for this sensor which do not rely (as heavily) on writing magic numbers to undocumented registers, such as:

https://github.com/embvm-drivers/ST-VL53L1X https://github.com/pololu/vl53l1x-st-api-arduino https://github.com/pololu/vl53l1x-arduino

I would prefer an implementation adapted from such code. But I recognize that would be a lot of work.

Alternatively, we could use Adafruit's circuitpython driver (which also suffers from magic number-itis, but at least then it's not OUR magic numbers) via pslab-python's circuitpython busio compatibility layer. It should be as simple as:

import adafruit_vl53l1x
from pslab.bus.busio import I2C

i2c = I2C()
vl53 = adafruit_vl53l1x.VL53L1X(i2c)

vl53.start_ranging()

while True:
    if vl53.data_ready:
        print("Distance: {} cm".format(vl53.distance))
        vl53.clear_interrupt()
        time.sleep(1.0)

Could you try and see if the above snippet works?

To summarize the above, I see three approaches, which I've ordered here from my most to least favorite:

  1. A driver with fewer magic numbers and more documentation, based on the three drivers mentioned above.
  2. Use Adafruit's driver via pslab.bus.busio (which, if it works, is simple enough that it might not even need to be included in pslab-python at all?)
  3. Use this driver as-is.

If option # 2 does not work well, I can be persuaded to go for # 3.

AsCress commented 4 months ago

@bessman Thank you very much for your comments !! I just want to mention a few things:

  1. The sensor which I proposed to work on and which PR #130 implements is the VL53L0X. I don't know much but apparently it is different from VL53L1X, hence the libraries you mentioned don't work with the VL53L0X. A few libraries available for VL53L0X are as follows: https://github.com/adafruit/Adafruit_CircuitPython_VL53L0X https://github.com/adafruit/Adafruit_VL53L0X https://github.com/pololu/vl53l0x-arduino Each one of these is based on the STSW-IMG005 VL53L0X API, released by STMicroelectronics. This API doesn't provide documentation for those registers and hence each one of these implementations is forced to use the same magic numbers. I also recognize that in this PR and in PR #130, we have incorrectly named our classes and stuff as VL531X. It should be VL53L0X instead.

  2. I read your comment in #130 about making the PSLAB's I2C implementation compatible with busio.I2C, and was certainly convinced that this is the way to go forward (refer to our meet also in which you said that we shouldn't be having the code for sensors in our main repository). However, I did not know that we already have a compatibility layer. This compatibility layer works amazing ! I tried running this piece of code:

    
    import adafruit_vl53l0x
    import time

from pslab.bus.busio import I2C

i2c = I2C() vl53 = adafruit_vl53l0x.VL53L0X(i2c)

while True: print("Range: {0}mm".format(vl53.range)) time.sleep(1.0)

It gives this output and the sensor works absolutely fine:

Range: 31mm Range: 28mm Range: 29mm Range: 28mm Range: 67mm Range: 386mm Range: 390mm Range: 398mm Range: 397mm Range: 400mm Range: 249mm Range: 81mm Range: 80mm Range: 79mm Range: 81mm



My views on this are that since we have a compatibility layer which works nicely, we shouldn't add sensors manually to our repository any more. We already have access to a whole big lot of sensors.
Personally, I would rank option # 2 higher than # 1.
What are your views on this ? Are there any crucial advantages of # 1 which I am missing here, since you ranked it the highest ?
bessman commented 4 months ago

The sensor which I proposed to work on and which PR #130 implements is the VL53L0X.

Noted. I wasn't sure which of 0X or 1X was the target or what the difference between them is.

It gives this output and the sensor works absolutely fine:

Awesome! Which firmware version is this? You mentioned that you were having problems with I2C in the latest firmware.

My views on this are that since we have a compatibility layer which works nicely, we shouldn't add sensors manually to our repository any more. We already have access to a whole big lot of sensors. Personally, I would rank option # 2 higher than # 1. What are your views on this ? Are there any crucial advantages of # 1 which I am missing here, since you ranked it the highest ?

Yes, I agree. There may be advantages to rolling our own driver in special cases, e.g. if it's a sensor that is very popular to use in conjunction with the pslab, or if the circuitpython driver doesn't work well. In this case, I think we should prefer the circuitpython driver.

Are you OK to close this PR in favor of using the circuitpython driver?

AsCress commented 4 months ago

Awesome! Which firmware version is this? You mentioned that you were having problems with I2C in the latest firmware.

The busio compatibility layer works nicely on both the legacy and the latest firmware version, referring to our recent discussion.

There may be advantages to rolling our own driver in special cases

True indeed. We can always observe which sensors are used the most and possibly write our own libraries for them.

Are you OK to close this PR in favor of using the circuitpython driver?

Absolutely ! The circuitpython drivers are the way ahead for all the sensors which Adafruit supports currently:))