Running tof_camera_1.py results in error: ImportError: no module named 'tof'

While trying to run tof_camera_1.py from the examples directory, I get the following error message:

Traceback (most recent call last):
File “”, line 6, in
ImportError: no module named ‘tof’
MicroPython: v1.18-omv-r6 OpenMV: v4.3.1 HAL: v1.9.0 BOARD: NICLAV-STM32H747
Type “help()” for more information.

Any ideas to fix this issue?
Thank you,
Thane

That example is not valid anymore. We need to remove it.

Hi Kwabena,

thank you for the response.
Thane

This example is for the tof module which is not enabled for all cameras by default, and it currently only supports the VL53L5CX ToF sensor.

Hi ,

thank you for your response.

Thane

Sorry to revive this, but if I happen to have that sensor, is there a way to incorporate it? Or is it intended for a shield with that sensor?

We don’t have any shields with that sensor. What are you trying to do? We haven’t released a product with it yet as it’s… very expensive to add to the camera system.

I once was in the situation to deal with that sensor in combination with openMV cams. I did not manage to get in running and ended up with a workaround.
However release notes state that for the drivers “vl53l5cx: Add shutdown function and fix deinit.” That pretty much sounds like there is still development done in that direction, docs mention vl53l5cx (though no electrical information can be found) and the examples (I’ve just checked) still don’t work. Mysterious I think. :slight_smile:

All will be revealed soon. :wink:

So the tof_camera_1.py will be working soon? How soon? What does this example do exactly?

It’s for a new product. Please wait until the product launch.

Could you please let me know if there are any updates, or if not, when one is expected? I intend to use the sensor for my master’s thesis.

Yeah, it works on the AE3: OpenMV AE3 - OpenMV MicroPython 1.28 documentation

I would also like to ask whether the ToF module can be imported on the N6, or whether the firmware would need to be modified as well.

There’s no ToF module on the N6.

Thanks. To be absolutely sure: if I connect a VL53L8CX via I²C, could I use the ToF driver tof — time-of-flight sensor driver - OpenMV MicroPython 1.28 documentation on the N6, or would the firmware need to be modified/rewritten? You said there’s no ToF module on the N6 — does that only refer to an integrated module, or is external ToF hardware over I²C generally unsupported? If firmware changes are required, are there existing driver examples or guidance on the expected effort?

You can just create a new driver using I2C for any ToF sensor: 6.23. I2C basics - OpenMV MicroPython 1.28 documentation

If you point Claude Code at the C driver and ask it to rewrite it in Python for the OpenMV Cam using the machine module, it can generate the code very quickly.

vl53l8cx_tof.py (145.3 KB)

It looks like there’s quite a binary package for this driver… so you might want to restructure this code. But here’s the result. From the AI:

What it is

A single, self-contained MicroPython driver that reproduces OpenMV’s built-in tof C module (modules/py_tof.c) for the VL53L8CX using only machine.I2C — no firmware rebuild needed. It’s a faithful port of ST’s ULD (drivers/vl53l8cx): vl53l8cx_init, the firmware download, DCI read/write/replace, offset/xtalk buffer fix-ups, start_ranging, check_data_ready, and get_ranging_data.

Per your choices: VL53L8CX only, single self-contained file (the ~86 KB sensor firmware + config/xtalk/NVM blobs are embedded as base64 and decoded at import — file is ~145 KB), core ranging only (no image-drawing helpers).

API (mirrors the tof module)

from vl53l8cx_tof import VL53L8CX

tof = VL53L8CX(bus=3)                 # AE3 = I2C3; uploads FW, starts 8x8/15Hz continuous
grid, lo, hi = tof.read_depth()       # grid = 64 floats (mm), row-major 8x8
tof.width(); tof.height(); tof.refresh()   # 8, 8, 15
tof.reset()                           # stop ranging

read_depth(hmirror=False, vflip=False, transpose=False, timeout=100) returns (list, min, max) and applies the same orientation logic (including the default mirror-on) as py_tof_read_depth. Running the file directly prints the live 8×8 grid.

Verification

The blobs extract byte-exact from the C headers (firmware = 0x15000, config = 972, xtalk = 776, NVM = 40). I unit-tested the trickiest ported paths against the C semantics with a mock I2C:

  • start_ranging computes data_read_size = 184 and patches the distance block size to 64 ✓
  • _get_ranging_data word-swap + int16 extraction + header/footer corruption check ✓
  • negative distance truncates toward zero (matching C int16 /= 4) ✓
  • orientation + min/max ✓

Caveats worth noting

  • Not run on real hardware here — the bring-up is a line-by-line port, but I couldn’t exercise the actual I2C bus from this environment.
  • Default wiring is bus=3 (AE3 I2C3); the sensor’s 8-bit address 0x52 is the 7-bit 0x29 machine.I2C expects (both forms accepted).
  • Firmware is chunked to VL53L8CX.CHUNK = 1024 bytes per I2C burst; lower it if a board’s I2C driver rejects large transfers. Python firmware upload is slower than the C path (one-time, at startup).
  • It assumes no XSHUT/reset line; _recover() re-runs the full firmware bring-up on a ranging timeout.

Note that it took Claude about 10 minutes to make the above driver. If you use the AI tools they can do pretty much all the Python you want.