Qwiic Single Relay holding i2c data line low

Hi,

I am trying to use a Qwiic Single Relay with a FT4222 controller by attempting to communicate with the relay via its i2c address (0x18 or 0x19). The control script is in Python but I am not using the Qwiic_Relay_Py module and instead reading/writing directly to the relay’s i2c address through the FT4222 controller. However, when trying to read from the address, the relay appears to hold the SDA line low (confirmed with logic analyzer), locking up the i2c bus. I’ve been using the same FT4222 and code to successfully communicate with other i2c devices besides the relay. Unplugging the relay while the script is still running resumes normal communication with other i2c devices. I’m wondering if anyone had advice on how to fix this as I’m unsure if it’s a software or hardware issue.

The relay is powered by an external 3.3V supply. I’ve tried the following as well with no luck:

  • Trying addresses 0x18 and 0x19 via the jumper

  • Cutting the traces to disable the pullup resistors

  • Tried a different Qwiic Single Relay

  • Tried a new FT4222 controller with nothing else but the relay hooked up

Any advice would be appreciated, thanks! Here is the code snippet I am using as a ‘driver’ for the relay:

SINGLE_ON = 0x01
SINGLE_OFF = 0x00
SINGLE_STATUS = 0x05


class SparkfunRelay(FT4222Sensor):
    """Sparkfun Qwiic Single Relay"""

    default_name = 'SparkfunRelay'
    address = 0x18  # default i2c address 0x18; jumper switches to 0x19

    def open(self):
        super().open()

        try:
            self.write(SINGLE_OFF)
        except Exception as exc:
            logger.error("Relay Connection Failure ,", exc_info=exc)


    def set_relay_on(self) -> None:
        """ Turns on a single relay """
        self.write(SINGLE_ON)

    def set_relay_off(self) -> None:
        """ Turns off a single relay """
        self.write(SINGLE_OFF)

    def get_relay_state(self):
        """ Queries the relay state (0 - off; 1 - on)"""

        reading = {
            'relay state': self.read(SINGLE_STATUS)
        }
        logger.debug("Relay State: %s", reading)
        return reading

It sounds like your board has a firmware issue - if you purchased the relay from SparkFun, head to www.sparkfun.com/returns/ and fill out the short form and we’ll send out a replacement.

If purchased from a distributor, please contact them about a replacement :smiley:

Thanks for the reply - I purchased two relays from Sparkfun and I’m getting the issue with both which led me to believe the issue was unlikely to be a defective unit. Would it still be worth to try a replacement?

I did some more tests - the relays are working with an Arduino and the Wire library, so I don’t think it is a firmware issue. I’ve attached an image from the logic analyzer. You can see that during scanning, addresses like 0x17 (shown) return SDA high as expected, but the relay at 0x18 ACKs but then holds SDA low, locking up the i2c bus.

I dived into the Arduino Wire library source files to compare the Arduino code with the Qwiic Relay Python library (which I have been basing my code off of) and it seems like not everything is analogous. The Arduino code seems to have several under-the-hood operations within Wire.endTransmission() (particularly to trigger the stop condition) but the Python library just has a Write function, for example. So I think the underlying issue is that I’m not translating the working Arduino code into the Python-controlled i2c commands I need. Any advice about this would be appreciated!

I figured out the issue - kind of like what the Arduino driver was doing, I had to add start and stop conditions to initialize and release communication with the relay properly on the I2C bus. In my case using the Python FT4222 library, I had to perform reads and writes with the built-in flags (like ft4222.I2CMaster.Flag.START_AND_STOP).