VL53L4CD I2C + CircuitPython Misbehaving
Hi everyone,
I'm thoroughly flummoxed and in need of guidance. I have a VL53L4CD rangefinder on the SparkFun breakout board that will not play nice with my Raspberry Pi. Long story short, the rangefinder seems to be ACKing prematurely under certain conditions. Confusingly, an identical setup has worked great in the past.
Background
Last year I used the VL53L4CD as part of a simple Raspberry Pi 4B-controlled payload. Using the SparkFun breakout board we did some lab testing with the rangefinder connected straight to the Pi, powered by the Pi's 3V3 regulator. We had some issues with continually bombarding the rangefinder with DataReady() requests but by waiting a few ms between queries our problems went away. The final product involved a couple custom PCBs with a beefier 3V3 linear regulator for the non-Pi electronics and an LTC4316 I2C address translator in between the Pi and rangefinder, and the whole setup worked great. Software was the CircuitPython library with Adafruit Blinka as a compatibility layer for the Pi 4B. This has worked without issue for months.
Some weeks ago I started building a second model of the same system. Made another batch of the PCBs, wired up the rangefinder, and got `[Errno 5] Input/output error`, which started me down the following rabbit hole.
The Problem
When connected to a Raspberry Pi 4B, the rangefinder seems to get confused and ACK when it shouldn't. I have tried this with three different Pi's and two different rangefinders, everything I had in stock this week. Both rangefinders were recently purchased from Mouser. The setup is as simply breadboarded as I can get, with ~1k8 pullup resistors; I have pix but since I only get three uploads for this post I'll save it for the comments. The behavior is inconsistent, but almost always I2C communication fails during initialization of the rangefinder (though I have twice gotten a single measurement from it). Below is an example of what I'm seeing:
Fig. 1: Failed rangefinder initialization. Yellow: SDA, Cyan: SCL
Fig. 2: Premature ACK and rangefinder holding SDA low. Yellow: SDA, Cyan: SCL
As in the captions, the yellow trace is SDA and cyan is SCL. The current CircuitPython instruction being executed is line 194, `self._write_register(0x002D, init_seq)`. You can see that in the decoded section of Fig. 1, where the Pi has written to register 0x002D bytes 0x12, 0x00, 0x00, 0x11 from the initialization sequence.
As far as I can tell, the slightly lower SDA voltage is the rangefinder pulling down to write to the bus or ACK, which is the basis of my suspicion for premature ACKing. As you can see in the second figure, the previous byte 0x00 was ACK'd successfully and the Pi moves to sending the next byte. On the fifth bit, the rangefinder ACKs again (which will clobber a 1 if the Pi was trying to write, which is what tipped me off to this problem in the first place) and is now out of sync with the byte-stream. The Pi interprets the rangefinder's silence as a NACK and releases SDA, but sometimes (as shown above) the rangefinder then takes SDA and holds it low until I power cycle it.
...But the Rangefinder Works!
To try and simplify the software side of things, I connected it to an Arduino Mega, using the relevant software library. I was too lazy to disable the internal pull-up resistors on the I2C pins, so the bus voltage is a smidge higher but still (barely) within the datasheet allowance. Shown below is successful communication with the same rangefinder as in the traces above. I have seen at least one out-of-turn ACK with the Arduino but I don't have a good picture, and it happens much more infrequently. The one difference I see is the Arduino seems to add a couple μs of clock delay (I don't know if you call that clock stretching if it's on the master side) between bytes. I have not yet tried banging in the same behavior in the Pi. The message shown is part of the polling loop querying register 0x0030 to see if data are ready to be read.
Fig. 3: Successful communication with the Arduino. Yellow: SDA, Cyan: SCL
Conclusion
I really don't know what would be different between the successful rangefinder-Pi system I put together six months ago and the replica I made this week, other than a minor update in Linux version, which I have not yet tried rolling back. Unfortunately I don't have access to the old system at the moment as it was just delivered to the international space station about ten minutes ago. I've found some similar posts [1][2][3][4] where my hero
Thanks in advance!
-Thomas
