diff --git a/micropython/examples/breakout_vl53l5cx/vl53l5cx_demo.py b/micropython/examples/breakout_vl53l5cx/vl53l5cx_demo.py index 616fed42..cd09a773 100644 --- a/micropython/examples/breakout_vl53l5cx/vl53l5cx_demo.py +++ b/micropython/examples/breakout_vl53l5cx/vl53l5cx_demo.py @@ -2,6 +2,10 @@ import pimoroni_i2c import breakout_vl53l5cx import time +# The VL53L5CX requires a firmware blob to start up. +# Make sure you upload "vl53l5cx_firmware.bin" via Thonny to the root of your filesystem +# You can find it here: https://github.com/ST-mirror/VL53L5CX_ULD_driver/blob/no-fw/lite/en/vl53l5cx_firmware.bin + PINS_BREAKOUT_GARDEN = {"sda": 4, "scl": 5} PINS_PICO_EXPLORER = {"sda": 20, "scl": 21} @@ -11,7 +15,7 @@ i2c = pimoroni_i2c.PimoroniI2C(**PINS_BREAKOUT_GARDEN, baudrate=2_000_000) print("Starting up sensor...") t_sta = time.ticks_ms() -sensor = breakout_vl53l5cx.VL53L5CX(i2c, firmware=open("vl53l5cx_firmware.bin").read()) +sensor = breakout_vl53l5cx.VL53L5CX(i2c) t_end = time.ticks_ms() print("Done in {}ms...".format(t_end - t_sta)) diff --git a/micropython/examples/breakout_vl53l5cx/vl53l5cx_motion.py b/micropython/examples/breakout_vl53l5cx/vl53l5cx_motion.py index 42da1fab..51325d00 100644 --- a/micropython/examples/breakout_vl53l5cx/vl53l5cx_motion.py +++ b/micropython/examples/breakout_vl53l5cx/vl53l5cx_motion.py @@ -3,6 +3,10 @@ import breakout_vl53l5cx import time from ulab import numpy +# The VL53L5CX requires a firmware blob to start up. +# Make sure you upload "vl53l5cx_firmware.bin" via Thonny to the root of your filesystem +# You can find it here: https://github.com/ST-mirror/VL53L5CX_ULD_driver/blob/no-fw/lite/en/vl53l5cx_firmware.bin + PINS_BREAKOUT_GARDEN = {"sda": 4, "scl": 5} PINS_PICO_EXPLORER = {"sda": 20, "scl": 21} @@ -12,7 +16,7 @@ i2c = pimoroni_i2c.PimoroniI2C(**PINS_BREAKOUT_GARDEN, baudrate=2_000_000) print("Starting up sensor...") t_sta = time.ticks_ms() -sensor = breakout_vl53l5cx.VL53L5CX(i2c, firmware=open("vl53l5cx_firmware.bin").read()) +sensor = breakout_vl53l5cx.VL53L5CX(i2c) t_end = time.ticks_ms() print("Done in {}ms...".format(t_end - t_sta)) diff --git a/micropython/examples/breakout_vl53l5cx/vl53l5cx_object_tracking.py b/micropython/examples/breakout_vl53l5cx/vl53l5cx_object_tracking.py index 3d4361a2..ce3aa4b9 100644 --- a/micropython/examples/breakout_vl53l5cx/vl53l5cx_object_tracking.py +++ b/micropython/examples/breakout_vl53l5cx/vl53l5cx_object_tracking.py @@ -3,6 +3,10 @@ import breakout_vl53l5cx import time from ulab import numpy +# The VL53L5CX requires a firmware blob to start up. +# Make sure you upload "vl53l5cx_firmware.bin" via Thonny to the root of your filesystem +# You can find it here: https://github.com/ST-mirror/VL53L5CX_ULD_driver/blob/no-fw/lite/en/vl53l5cx_firmware.bin + # This example attempts to track a "bright" object (such as a white business card) # It uses reflectance to identify the target and compute the X/Y coordinates # of its "center of mass" in the sensors view. @@ -24,7 +28,7 @@ i2c = pimoroni_i2c.PimoroniI2C(**PINS_BREAKOUT_GARDEN, baudrate=2_000_000) print("Starting up sensor...") t_sta = time.ticks_ms() -sensor = breakout_vl53l5cx.VL53L5CX(i2c, firmware=open("vl53l5cx_firmware.bin").read()) +sensor = breakout_vl53l5cx.VL53L5CX(i2c) t_end = time.ticks_ms() print("Done in {}ms...".format(t_end - t_sta)) diff --git a/micropython/modules/breakout_vl53l5cx/vl53l5cx.cpp b/micropython/modules/breakout_vl53l5cx/vl53l5cx.cpp index c37d231f..335d2aba 100644 --- a/micropython/modules/breakout_vl53l5cx/vl53l5cx.cpp +++ b/micropython/modules/breakout_vl53l5cx/vl53l5cx.cpp @@ -8,6 +8,9 @@ extern "C" { #include "vl53l5cx.h" #include "pimoroni_i2c.h" +#include "py/stream.h" +#include "py/reader.h" +#include "extmod/vfs.h" typedef struct _mp_obj_float_t { mp_obj_base_t base; @@ -67,7 +70,7 @@ mp_obj_t VL53L5CX_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw static const mp_arg_t allowed_args[] = { { MP_QSTR_i2c, MP_ARG_OBJ, {.u_obj = nullptr} }, { MP_QSTR_addr, MP_ARG_INT, {.u_int = pimoroni::VL53L5CX::DEFAULT_ADDRESS} }, - { MP_QSTR_firmware, MP_ARG_OBJ | MP_ARG_REQUIRED } + { MP_QSTR_firmware, MP_ARG_OBJ, {.u_obj = nullptr} } }; // Parse args. @@ -79,22 +82,44 @@ mp_obj_t VL53L5CX_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw return mp_const_none; } - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(args[ARG_firmware].u_obj, &bufinfo, MP_BUFFER_READ); - if(bufinfo.len != (size_t)(84 * 1024)) { // firmware blob is always 84K - mp_raise_ValueError("Supplied firmware should be 84k bytes!"); - } - _PimoroniI2C_obj_t *i2c = (_PimoroniI2C_obj_t *)MP_OBJ_TO_PTR(args[ARG_i2c].u_obj); int addr = args[ARG_addr].u_int; self = m_new_obj_with_finaliser(_VL53L5CX_obj_t); self->base.type = &VL53L5CX_type; self->i2c = i2c; + + mp_buffer_info_t bufinfo; + const size_t firmware_size = 84 * 1024; + + if(args[ARG_firmware].u_obj == nullptr) { + mp_obj_t args[2] = { + mp_obj_new_str("vl53l5cx_firmware.bin", strlen("vl53l5cx_firmware.bin")), + MP_OBJ_NEW_QSTR(MP_QSTR_r), + }; + bufinfo.buf = (void *)m_new(uint8_t, firmware_size); + mp_obj_t file = mp_vfs_open(MP_ARRAY_SIZE(args), &args[0], (mp_map_t *)&mp_const_empty_map); + int errcode; + bufinfo.len = mp_stream_rw(file, bufinfo.buf, firmware_size, &errcode, MP_STREAM_RW_READ | MP_STREAM_RW_ONCE); + if (errcode != 0) { + mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("OSError reading vl53l5cx_firmware.bin")); + } + } else { + mp_get_buffer_raise(args[ARG_firmware].u_obj, &bufinfo, MP_BUFFER_READ); + } + + if(bufinfo.len != (size_t)(firmware_size)) { // firmware blob is always 84K + mp_raise_ValueError("Firmware must be 84k bytes!"); + } + self->breakout = new pimoroni::VL53L5CX(i2c->i2c, (uint8_t *)bufinfo.buf, addr); if(!self->breakout->init()) { - mp_raise_msg(&mp_type_RuntimeError, "VL53L5CX: error initialising"); + mp_raise_msg(&mp_type_RuntimeError, "VL53L5CX: init error"); + } + + if(args[ARG_firmware].u_obj == nullptr) { + m_free(bufinfo.buf); } return MP_OBJ_FROM_PTR(self);