TFMini Distance Shield on I2C bus

I am wanting to get the TFMini Distance Shield to work. The good thing is that I am able to get the code for it in python but the problem is that the library doesn’t exist in micropython. On looking up a similar distance shield, I see that the v15311x is available but unfortunately this shield is only able to go up to 4m whereas the TFMini is capable of doing 12m. Is there a way to hack existing libraries for the purpose of getting this device to work? I have sample code for Python which I hope I can modify for use on OpenMV. Code as follows:

For TFmini Plus

from smbus2 import SMBus, i2c_msg

To get the addresses of detected devices type:

sudo i2cdetect -y 1 or 0

I2CBUS = 1

\

LiDAR Address

ADDRESS = 0x10

\

Initialize I2C (SMBus)

bus = SMBus(I2CBUS)

class i2c_device:
def init(self, addr=ADDRESS, port=I2CBUS):
self.addr = addr
self.bus = SMBus(port) # Initialize I2C

Write a single command

def write_cmd(self, cmd):
self.bus.write_byte(self.addr, cmd)
sleep(0.0001)

Write a command and argument

def write_cmd_arg(self, cmd, data):
self.bus.write_byte_data(self.addr, cmd, data)
sleep(0.0001)

Write a block of data

def write_block_data(self, cmd, data):
self.bus.write_i2c_block_data(self.addr, cmd, data)
sleep(0.0001)

Read a single byte

def read(self):
return self.bus.read_byte(self.addr)

Read

def read_data(self, cmd):
return self.bus.read_byte_data(self.addr, cmd)

Read a block of data

def read_block_data(self, cmd):

return self.bus.read_block_data(self.addr, cmd)

return self.bus.read_i2c_block_data(self.addr, cmd, 0)

if name == ‘main’:
lidar = i2c_device()
block = list()
print(“Data reading started…”)
while True:

5A 05 00 01 60

lidar.write_block_data(0x00, [0x5A, 0X05, 0X00, 0X01, 0X60])
sleep(0.01)

we will read nine bytes and then the three parameters

for x in range(0, 9):
byte = lidar.read()
block.insert(x, byte)

Check the headers

if block[0] == 0x59 and block[1] == 0x59:
print(“Printing python3 compatible part”)
distance = block[2] + block[3]*256
strength = block[4] + block[5]*256
temperature = block[6] + block[7]*256
temperature = (temperature/8) - 256
print(“Distance:”+ str(distance))
print(“Strength:” + str(strength))
print(“Temperature:” + str(temperature))

if block[0] == “Y” and block[1] == “Y”:
distL = int(block[2].encode(“hex”), 16)
distH = int(block[3].encode(“hex”), 16)
stL = int(block[4].encode(“hex”), 16)
stH = int(block[5].encode(“hex”), 16)
distance = distL + distH256
strength = stL + stH
256
tempL = int(block[6].encode(“hex”), 16)
tempH = int(block[7].encode(“hex”), 16)
temperature = tempL + tempH*256
temperature = (temperature/8) - 256
print(“Printing python2 portion”)
print(“Distance:”+ str(distance) + “\n”)
print(“Strength:” + str(strength) + “\n”)
print(“Temperature:” + str(temperature) + “\n”)

if key == ord(“q”):

break

bus.close()

Hi, I don’t have the hardware. You have to debug what’s wrong and figure it out.

I understand you need help. But, just posting a giant blob of code and expecting me to fix it is very unrealistic.

Please ask a specific question about something that is not working the way you think it should.

Ok thankyou for trying to assist me. I am a beginner so I apologise for my ignorance in advance. I will rephrase the question. My main issue is what happens if the hardware drivers don’t exist in micropython? I showed code referring to a library that doesn’t exist (SMBus). This question can be applied to a heap of other hardware shields available for Arduino but not for micropython. Arduino typically has example code that will work. Can a solution be to add Arduino hardware and use the communication between OpenMV and Arduino in order to access the data via Arduino I2C bus?

Typically, if you need something that doesn’t exist you write a driver for it. We have all the basics to do this. So, you’d just look at the C driver and call the corresponding functions in python to make a new driver that works the same way.

Ok great. Happy to give it a go. If you can direct me to a link as a step by step on how to create a driver as I have never ever done it before, I will attempt to create the driver. I presume I need to extract the C functions from in this case the SMBus library?

Um, there’s not a step by step…

You just kinda read our API and translate the functions by hand.

E.g. this driver shows off how to do I2C accesses:

So, you just perform the correction I2C accesses and the thing should work. You can also just write the driver using the device datasheet. But, it’s usually easier to just copy the functionality of working C code.

Thanks for that. I have looked at the code and I just want to confirm with you the step needed to make it functional. Steps as follows:

  • Change the sample code file from vl53l1x.py to the hardware name I am writing for. In this case it would be “tfmini.py”
  • Edit the file and search for the class name and change it to the name of my hardware. In this case it would be from “VL53L1X” to “TFMini”
  • Search for the i2C specific address and change it to the respective hardware identified address. In this case the line would be from “def init(self,i2c, address=0x29)” to “def init(self,i2c, address=0x10)”
  • Change all references from “VL53L1X” to “TFMini”
  • Save file
  • Edit my main.py file and insert the following lines:
    from machine import I2C
    from tfmini import TFMini
    import time

i2c = I2C(2)
distance = TFMini(i2c)

while True:
print("range: mm ", distance.read())
time.sleep(50)

  • Save File and run

I presume that if there are any hardware specific lines in VL53L1X that doesn’t exist, I will need to remove and replace them with ones for TFMini by referring to its datasheet. Please let me know anything else I may have missed.

That’s basically the idea. The code is open source so you can extend it and modify it without needing me.

That’s basically the idea. The code is open source so you can extend it and modify it without needing me.