Ultrasonic distance sensor tct40/qwiic micropython support

Hi, I recently purchased a TCT-40/qwiic ultrasonic sensor with the intention of adding it to the XRP robot platform that I have been successfully operating via python via the XRPCode web-based interface. I also have the OTOS qwiic sensor, which works fine with python. However, I’m having trouble finding if there’s support for the TCT-40/qwiic sensor for micropython, similar to what’s available for the OTOS sensor.

Any help is appreciated.

We don’t have a micropython library ready-made for that sensor, though they are compatible and you can certainly write some micropython code to use the TCT40 over qwiic/i2c on the XRP; here’s a thread with some links to get started TCT40 I2C command documentation?

So if I buy another blue sensor (that comes with the XRP kit), i should be able to run two of those with python, correct?

Sure - you can wire it to either ‘qwiic’ or ‘extra’ port using one of these Flexible Qwiic Cable - Female Jumper (4-pin) and communicate with it that way…just remember to adjust the new ultrasonic’s rear jumper pads if you use i2c (default is GPIO mode)

Edit: If using the OTOS as well I’d wire it to ‘extra’ and put the OTOS on the ‘qwiic’ port :wink:

Great, thanks for the help!

I have written a python interface for the sparkfun/qwiic ultrasonic sensor (red SEN-17777). It’s pretty basic, but here’s the code. No license or attribution needed. Feel free to use / modify / distribute in any way you see fit. I’m open to recommendations for improvement as well. I wrote this to work as a second ultrasonic sensor on the XRP platform.

import qwiic_i2c
import time

class QwiicRangefinder:
    """
    A class for an I2C-based rangefinder (SparkFun Qwiic Ultrasonic)
    connected to Qwiic at address 0x2F.
    """

    _DEFAULT_I2C_ADDRESS = 0x2F  # Default I2C address
    _CMD_MEASURE_DISTANCE = 0x01  # Command to trigger and read distance

    def __init__(self, address=None, i2c_driver=None):
        """
        Initializes the rangefinder on I2C.
        
        :param address: I2C address of the rangefinder (default: 0x2F).
        :param i2c_driver: Optional I2C driver instance.
        """
        self.address = address if address else self._DEFAULT_I2C_ADDRESS

        # Load I2C driver
        if i2c_driver is None:
            self._i2c = qwiic_i2c.getI2CDriver()
            if self._i2c is None:
                print("Error: Unable to load I2C driver.")
                return
        else:
            self._i2c = i2c_driver

    def is_connected(self):
        """
        Check if the rangefinder is connected via I2C.
        
        :return: True if device responds, False otherwise.
        """
        return self._i2c.isDeviceConnected(self.address)

    def begin(self):
        """
        Initializes the rangefinder.
        
        :return: True if the device is ready, False otherwise.
        """
        return self.is_connected()

    def get_distance(self):
        """
        Triggers a measurement and reads the previous distance.

        :return: Distance in millimeters (mm), or -1 if read fails.
        """
        try:
            # Send the command to trigger a new measurement
            self._i2c.writeCommand(self.address, self._CMD_MEASURE_DISTANCE)

            # Wait for measurement to complete
            time.sleep(0.1)

            # Request 2 bytes from the sensor
            data = self._i2c.readBlock(self.address, self._CMD_MEASURE_DISTANCE, 2)

            if data is None or len(data) < 2:
                return -1  # Sensor did not return valid data

            # Convert the received bytes to a 16-bit integer (big-endian)
            distance = (data[0] << 8) | data[1]

            return distance/10  # Distance in cm
        except:
            return -1  # Return -1 if reading fails

# Example Usage:
if __name__ == "__main__":
    sensor = QwiicRangefinder()
    if sensor.begin():
        print("Qwiic Rangefinder Connected!")
        while True:
            print("Distance: {} mm".format(sensor.get_distance()))
            time.sleep(0.5)
    else:
        print("Sensor not detected.")
2 Likes