{"id":13802469,"url":"https://github.com/mp-extras/vl53l5cx","last_synced_at":"2025-05-13T13:31:25.825Z","repository":{"id":215170673,"uuid":"414461724","full_name":"mp-extras/vl53l5cx","owner":"mp-extras","description":"MicroPython and CircuitPython support for ST VL53L5CX TOF sensor","archived":false,"fork":false,"pushed_at":"2023-08-14T20:14:53.000Z","size":431,"stargazers_count":11,"open_issues_count":4,"forks_count":5,"subscribers_count":4,"default_branch":"main","last_synced_at":"2024-04-22T12:36:09.892Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mp-extras.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2021-10-07T04:36:22.000Z","updated_at":"2024-03-18T01:16:52.000Z","dependencies_parsed_at":"2024-01-07T21:53:35.508Z","dependency_job_id":null,"html_url":"https://github.com/mp-extras/vl53l5cx","commit_stats":null,"previous_names":["mp-extras/vl53l5cx"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mp-extras%2Fvl53l5cx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mp-extras%2Fvl53l5cx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mp-extras%2Fvl53l5cx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mp-extras%2Fvl53l5cx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mp-extras","download_url":"https://codeload.github.com/mp-extras/vl53l5cx/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225218071,"owners_count":17439713,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-04T00:01:45.123Z","updated_at":"2024-11-18T17:31:28.353Z","avatar_url":"https://github.com/mp-extras.png","language":"Python","funding_links":[],"categories":["Libraries"],"sub_categories":["Sensors"],"readme":"# VL53L5CX MicroPython and CircuitPython Package\n\nThis package provides a class that is (mostly) a straight port of the ST [Ultra Lite Driver (ULD) C module](https://www.st.com/content/st_com/en/products/embedded-software/imaging-software/stsw-img023.html). With this class, you can configure and acquire data from a VL53L5CX sensor in both 4x4 and 8x8 resolutions. You can find details on the sensor operation and API in the [ST user manual UM2884](https://www.st.com/resource/en/user_manual/um2884-a-guide-to-using-the-vl53l5cx-multizone-timeofflight-ranging-sensor-with-wide-field-of-view-ultra-lite-driver-uld-stmicroelectronics.pdf). The figure below shows a graphical display of a color depth map for an 8x8 resolution sample, `demo.py`.\n\n![Range as colors demo](ttgo_vl53l5cx.png)\n\nThe code has been tested with the VL53L5CX breakout board from [Pesky Products on Tindie](https://www.tindie.com/products/onehorse/vl53l5cx-ranging-camera/) using a [Pimoroni Tiny 2040](https://shop.pimoroni.com/products/tiny-2040) with both MicroPython (v1.16) and CircuitPython (v7.0) and a [LILYGO TTGO T-Display](http://www.lilygo.cn/prod_view.aspx?TypeId=50062\u0026Id=1126\u0026FId=t3:50062:3) using MicroPython (v1.17).\n\n## Installation\n\nCopy the `vl53l5cx` directory to your board's `lib` directory using the usual mechanism for your board. The firmware file, `vl_fw_config.bin`, is generated from the ULD source file `vl53lcx_buffers.h` using the `fw_file.c` utility.\n\n### MicroPython\n\n``` bash\nmpremote mkdir :lib/vl53l5cx\nmpremote cp vl53l5cx/__init__.py :lib/vl53l5cx/__init__.py\nmpremote cp vl53l5cx/_config_file.py :lib/vl53l5cx/_config_file.py\nmpremote cp vl53l5cx/mp.py :lib/vl53l5cx/mp.py\nmpremote cp vl53l5cx/vl_fw_config.bin :lib/vl53l5cx/vl_fw_config.bin\n```\n\nYou could also compile the source files first using `mpy-cross` and then copy the corresponding `.mpy` files.\n\n### CircuitPython\n\n``` bash\ncp -r vl53l5cx path-to-cp-disk/lib\n```\n\nThere are no external dependencies for the `vl53l5cx` package. Some examples may have external requirements.\n\n## Usage\n\nThe VL53L5CX class requires at least an I2C device to interact with the sensor. In addition, depending on your HW (board), you may require a Pin for the LPN pin. If your board pulls this pin low, you will need to connect a Pin to pull the LPN pin high. In addition, this Pin can be supplied to the VL53L5CX class to perform a soft reset.\n\nThe interface for the class is the same for both MicroPython and CircuitPython, but the objects used to create an instance are different. The `sensor.py` utility module encapsulates the differences for each platform and keeps from duplication in the examples. You can use this as-is or just copy the code for your platform into your applications.\n\n### MicroPython Create\n\n``` python\nfrom machine import I2C, Pin\n\nfrom vl53l5cx.mp import VL53L5CXMP\n\nscl_pin, sda_pin, lpn_pin, _ = (22, 21, 12, 13)\ni2c = I2C(0, scl=Pin(scl_pin, Pin.OUT), sda=Pin(sda_pin), freq=1_000_000)\n\ntof = VL53L5CXMP(i2c, lpn=Pin(lpn_pin, Pin.OUT, value=1))\n```\n\n### CircuitPython Create\n\n``` python\nimport busio\nfrom microcontroller import pin\nfrom digitalio import DigitalInOut, Direction\n\nfrom vl53l5cx.cp import VL53L5CXCP\n\nscl_pin, sda_pin, lpn_pin, _ = (pin.GPIO1, pin.GPIO0, pin.GPIO28, pin.GPIO5)\ni2c = busio.I2C(scl_pin, sda_pin, frequency=1_000_000)\n\nlpn = DigitalInOut(lpn_pin)\nlpn.direction = Direction.OUTPUT\nlpn.value = True\n\ntof = VL53L5CXCP(i2c, lpn=lpn)\n```\n\nYou will need to adjust the pin numbers/ids based on your board's connections to the VL53L5CX sensor.\n\n### Basic Example\n\nOnce you have an instance, the code to interact with the sensor is the same, so the examples below do not show the creation code. Instead, this code is factored out into a helper module, `sensor.py`, that provides a wrapper function, `make_sensor`.\n\n\n``` python\nfrom sensor import make_sensor\n\nfrom vl53l5cx import DATA_TARGET_STATUS, DATA_DISTANCE_MM\nfrom vl53l5cx import STATUS_VALID, RESOLUTION_4X4\n\n\ndef main():\n    tof = make_sensor()\n    tof.reset()\n\n    if not tof.is_alive():\n        raise ValueError(\"VL53L5CX not detected\")\n\n    tof.init()\n\n    tof.resolution = RESOLUTION_4X4\n    grid = 3\n\n    tof.ranging_freq = 2\n\n    tof.start_ranging({DATA_DISTANCE_MM, DATA_TARGET_STATUS})\n\n    while True:\n        if tof.check_data_ready():\n            results = tof.get_ranging_data()\n            distance = results.distance_mm\n            status = results.target_status\n\n            for i, d in enumerate(distance):\n                if status[i] == STATUS_VALID:\n                    print(\"{:4}\".format(d), end=\" \")\n                else:\n                    print(\"xxxx\", end=\" \")\n\n                if (i \u0026 grid) == grid:\n                    print(\"\")\n\n            print(\"\")\n\n\nmain()\n```\n\nRun the example using the method appropriate for your platform.\n\n``` bash\nlinux$ mpremote run basic.py\nxxxx 1564  671 1754\nxxxx 1537 1834 1770\nxxxx 1572 1665 1736\nxxxx xxxx xxxx 1727\n\nxxxx xxxx  671 1754\nxxxx 1530 1857 1765\nxxxx 1546 1665 1751\nxxxx xxxx xxxx 1703\n\nxxxx xxxx  671 1743\nxxxx 1566 1857 1717\nxxxx 1560 1665 1744\nxxxx 1543 1616 1712\n```\n\n### Selecting Results\n\nYou can select all or a subset of the nine possible results produced by the sensor when starting operation via `start_ranging()`. The `Results` object returned from `get_ranging_data()` will contain a property for each of the specified results. Note that the single argument to `start_ranging()` is a set, list, or other iterable.\n\n``` python\nfrom vl53l5cx import DATA_TARGET_STATUS, DATA_DISTANCE_MM\n\ntof.start_ranging({DATA_TARGET_STATUS, DATA_DISTANCE_MM})\n\nresults = tof.get_ranging_data()\n\nprint(len(results.distance_mm), len(results.target_status))\n```\n\n| start_ranging() option | Results property  |\n|:-:|:-:|\n| DATA_AMBIENT_PER_SPAD | ambient_per_spad |\n| DATA_NB_SPADS_ENABLED | nb_spads_enabled |\n| DATA_NB_TARGET_DETECTED | nb_target_detected |\n| DATA_SIGNAL_PER_SPAD | signal_per_spad |\n| DATA_RANGE_SIGMA_MM | range_sigma_mm |\n| DATA_DISTANCE_MM | distance_mm |\n| DATA_REFLECTANCE | reflectance |\n| DATA_TARGET_STATUS | target_status |\n| DATA_MOTION_INDICATOR | motion_indicator |\n\n### Interrupt Example\n\nInstead of polling for data available via the `check_data_ready` method, you can use the interrupt pin from the VL53L5CX to signal data is ready. The examples below show how this can be used with the `light sleep` functionality in both MicroPython and CircuitPython.\n\n``` python\n# MicroPython\nfrom machine import lightsleep, Pin\nfrom esp32 import wake_on_ext1, WAKEUP_ALL_LOW\n\nfrom sensor import make_sensor\n\nfrom vl53l5cx import DATA_TARGET_STATUS, DATA_DISTANCE_MM\nfrom vl53l5cx import RESOLUTION_4X4\n\n\ndef main():\n    wake_on_ext1([Pin(13, Pin.IN)], WAKEUP_ALL_LOW)\n\n    tof = make_sensor()\n    tof.reset()\n    tof.init()\n\n    tof.resolution = RESOLUTION_4X4\n    tof.ranging_freq = 30\n\n    tof.start_ranging({DATA_DISTANCE_MM, DATA_TARGET_STATUS})\n\n    while True:\n        lightsleep()\n\n        results = tof.get_ranging_data()\n        print(min(results.distance_mm), max(results.distance_mm))\n\n\nmain()\n```\n\n``` python\n# CircuitPython\nimport alarm\nfrom microcontroller import pin\n\nfrom sensor import make_sensor\n\nfrom vl53l5cx import DATA_TARGET_STATUS, DATA_DISTANCE_MM\nfrom vl53l5cx import RESOLUTION_4X4\n\n\ndef main():\n    pin_alarm = alarm.pin.PinAlarm(pin=pin.GPIO5, value=False, pull=True)\n\n    tof = make_sensor()\n    tof.reset()\n    tof.init()\n\n    tof.resolution = RESOLUTION_4X4\n    tof.ranging_freq = 30\n\n    tof.start_ranging({DATA_DISTANCE_MM, DATA_TARGET_STATUS})\n\n    while True:\n        alarm.light_sleep_until_alarms(pin_alarm)\n\n        results = tof.get_ranging_data()\n        print(min(results.distance_mm), max(results.distance_mm))\n\n\nmain()\n```\n\n### Power Example\n\nThe VL53L5CX can be operated in a \"sleep\" (LP idle) mode where it consumes less power when not ranging. The [data sheet](https://www.st.com/resource/en/datasheet/vl53l5cx.pdf) lists the current consumption in Section 4.4.\n\n![Current consumption](vl53l5cx_current_table.png)\n\nThe example below shows how to switch between \"wakeup\" (HP idle) and \"sleep\" (LP idle) using the `power_mode` property. Measured current consumption (including SoC and board usage) is shown in the graph.\n\n``` python\nfrom time import sleep\n\nfrom sensor import make_sensor\n\nfrom vl53l5cx import POWER_MODE_WAKEUP, POWER_MODE_SLEEP\n\n\ndef main():\n    tof = make_sensor()\n    tof.reset()\n    tof.init()\n\n    assert(tof.power_mode == POWER_MODE_WAKEUP)\n    sleep(0.5)\n\n    tof.power_mode = POWER_MODE_SLEEP\n    assert(tof.power_mode == POWER_MODE_SLEEP)\n    sleep(0.5)\n\n    tof.power_mode = POWER_MODE_WAKEUP\n    assert(tof.power_mode == POWER_MODE_WAKEUP)\n    sleep(0.5)\n\n    tof.power_mode = POWER_MODE_SLEEP\n    assert(tof.power_mode == POWER_MODE_SLEEP)\n    sleep(0.5)\n\n    tof.power_mode = POWER_MODE_WAKEUP\n    assert(tof.power_mode == POWER_MODE_WAKEUP)\n    sleep(0.5)\n\n\nmain()\n```\n\n![Measured current consumption](vl53l5cx_sleep_wakeup_current.png)\n\n## TODO\n\n* Add threshold support\n* Add motion indicator support\n* xtalk calibration support to enable custom xtalk config data rather than default\n* More than one target per zone (fixed at 1 currently)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmp-extras%2Fvl53l5cx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmp-extras%2Fvl53l5cx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmp-extras%2Fvl53l5cx/lists"}