Failing to get I2C to work properly using FT232H, Python, Bl
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

Failing to get I2C to work properly using FT232H, Python, Bl

by EE_ANGEL on Fri Sep 10, 2021 4:24 pm

I'm working on a project that requires some communication from a windows PC to program a Digipot.
I'm using the DS1308-100 Digipot and the FT232H Breakout from Adafruit (The USB-C version)
I've got communication setup using board.I2C(), I can get the address of the DS1803 (0x28) and when I send commands, I believe I am getting an ACK from the digipot.
As far as I can tell , none of my commands are actually taking effect though. I'm not sure if I am screwing up something with the electronics or with the program at the moment. I am relatively experienced with electronics, but I've never used an I2C component before. I am not very experienced with programming but I have been working with python fairly heavily over the last 6 months trying to learn.

Ignore the numbers, I couldn't figure out how to quickly change the image on Fritzing, but this is the general setup. Pretend the FT232RQ is actually the FT232H breakout board from Adafruit and pretend the ULN2003A is actually DS1308-100
Note: The board shows SDA between pins D1 & D2 on the FT232H with SCL on D0 and the guide on Adafruit for the FT232H says to tie D1 & D2 together, but for some reason on the board it says to tie D0 & D1 together. I'm assuming that is a typo and it is actually supposed to say tie D1 & D2 together. There is also a switch on the front for "I2C Mode"which I have in the "ON" position.
Note 2: I have tried both the older version instructions (tying D1 & D2 together as in the image) and using just a single pin (Either D1 or D2) and neither version behaves noticeably differently, all actions have the same result as far as I can tell.
DS1308-100 + FT232H Breakout.PNG
DS1308-100 + FT232H Breakout.PNG (137.53 KiB) Viewed 60 times

DS1308 Pinout.PNG
DS1308 Pinout.PNG (9.78 KiB) Viewed 60 times

Pins 5-7 on DS1308-100 are Address pins, so tying them all to ground should make the device address "000"

From the Datasheet, write commands should be of the form:
Start -> Control Byte [ACK] -> Command Byte [ACK] -> Data Byte [ACK] -> Stop
From the Datasheet, read commands should be of the form:
Start -> Control Byte [ACK] -> Data Byte [ACK] -> Stop
With optional extra stuff right before Stop. Info on the structure of the Control Byte, Command Byte, and Data Byte are in the code below
Code: Select all | TOGGLE FULL SIZE
import board

def main():
    i2c = board.I2C()

    print("I2C devices found: ", [hex(i) for i in i2c.scan()])
    # print out: I2C devices found:  ['0x28']
    test_control= bytes([0x50])  # 0x50 == 0b01010000 (0101 + 000 + 0)
    test_command = bytes([0xAB])  # 0xAB == 0b10101011 (101010 + 11)
    test_data = bytes([0x00])  # 0x00 == 0b00000000, 0xFF == 0b11111111
    test_read = bytes([0x51])  # 0x51 == 0b01010001 (0101 + 000 + 1)
    read_result = bytearray(8)  # Should be empty

    # 4 bit control code  -  0101
    # 3 bit device select  -  Assume: 00, 01, 11 (Based on whether A0, A1, and A2 are tied to Vcc or GND)
    # 1 bit read/write  -  0, 1 (Write/Read)
    # Write Potentiometer-0  -  101010 01
    # Write Potentiometer-1  -   101010 10
    # Write Potentiometer-B  -  101010 11

    i2c.writeto(0x28, test_control, stop=False)
    i2c.writeto(0x28, test_command, stop=False)
    i2c.writeto(0x28, test_data, stop=True)

    print('result:', read_result)
    # print out: result: bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00')
    i2c.writeto_then_readfrom(0x28, test_read, read_result)
    print('result:', read_result)
    # print out: result: bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00')

if __name__ == '__main__':

1) The voltage between P1 (H1) and P4 (W1) on the DS1308-100 reads ~3V regardless of the data I send
2) The LED never turns on
3) The writeto_then_readfrom() function places nothing into the byte array I pass to it

Various Other Details:

From the DS1308 Datasheet:
"resolution of the potentiometer is defined as RTOT/255, where RTOT is the total resistor value of the potentiometer."

I am assuming here that this means that whatever the value of the data byte sent to the DS1308 should be the value of the potentiometer incremented by the resolution. The resolution should be 100kΩ/255 ~ 392Ω per bit value. I'd guess that sending either extreme should result in max resistance or minimum resistance for the wiper. I placed the LED so I could tell if one of the extremes actually worked, because the LED should at least show something with 392Ω resistor in line. I've also monitored voltage with a DMM and the voltage between the High and Wiper is consistantly around 3V without any change. I am not sure if I can measure resistance directly with the DMM or not, I tried without the P1 and P4 connected to Vcc or Ground and the number jumped around a lot so I guessed that it was not going to work from that.

I have tried sending the Data Byte as 0xFF, 0x01, and 0x00 and none of them change the voltage readings or light the LED. I get no errors during the process either so I'm assuming the DS1308 is sending an acknowledgement because I get that NACK error when I accidentally used the wrong I2C address.

If I don't connect the internal potentiometer to Vcc or Gnd, there is no voltage output with the DMM between pins 1, 3, or 4.

See for "Typo"
IMG_20210910_122958074_Cropped_for_relevence.jpg (502.45 KiB) Viewed 60 times

In the tutorial for using this breakout on Adafruit's website, they say to tie D1&D2 together for I2C SDA. On the board you can see there is a "+" between "MOSI" (D1) and "MISO" (D2) implying that these 2, D1 & D2, should get tied together to form SDA. But for some reason, right above it, the board specifically says "Connect D0 & D1 for I2C". D0 here is labeled as "SCK/SCL" which is where the clock should be. I can't imagine that anything should be tied to the clock and so I am assuming this is a typo on the board and it should actually say Connect D1 & D2 for I2C.
I have also tried using only a single pin between D1 and D2 as stated for the USB-C version (which I have) and there seems to be no difference in anything.

I'm really just looking for general advice on what I could try or if anything looks wrong from this setup or what I've done because I really am not sure of anything else except maybe trying to get a different library to try out I2C communication with. I've been working on this for around a week at the moment and I don't really know what else to try to make it work. Any advice on how to proceed from here would be appreciated. All I really need to do is be able to change the resistance value of the digipot and to have some sort of way to reliably measure it (at the very least measure a change in voltage with the changing resistance).

Datasheet for DS1308-100 (Mouser Product Link) https://www.mouser.com/ProductDetail/Maxim-Integrated/DS18030-050%2B?qs=wTZ%2FFzl837ax%252B5lTnnelAQ%3D%3D
Overview Page for Adafruit's guide on using the FT232H Breakout https://learn.adafruit.com/adafruit-ft232h-breakout

Posts: 6
Joined: Fri Sep 10, 2021 1:03 pm

Re: Failing to get I2C to work properly using FT232H, Python

by EE_ANGEL on Tue Sep 21, 2021 11:13 am

I was able to get answers to my questions so for anyone looking at this in the future this is what I did:
Code: Select all | TOGGLE FULL SIZE
import board
import busio

i2c = board.I2C()
address = 0x28  # Base address for this device is 0x28, with the option of changing the address by pulling any of the pins A2, A1, or A0 high
control_write = 0x50  # Specifies whether the action is read or write, 0x51 is read
command_both = 0xAF  # Command for writing to both devices, from datasheet for DS1308
data = 0xFF  # Set all the bits that control the potentiometers to 1

# What I tried that failed to work
# 1:
i2c.writeto(address, bytes([control_write]))
i2c.writeto(address, bytes([command_both]))
i2c.writeto(address, bytes([data]))
# 2:
i2c.writeto(address, bytes([control_write]), stop=False)
i2c.writeto(address, bytes([command_both]), stop=False)
i2c.writeto(address, bytes([data]), stop=True)
# 3:
i2c.writeto(address, bytes([control_write, command_both, data]))

# What ultimately worked for me:
i2c.writeto(address, bytes([control_write]))
i2c.writeto(address, bytes([command_both, data]))

# For reading from the device:
control_read = 0x51
read_response = bytearray(2)  # The DS1308 responds with a byte for the current values of each potentiometer, so I set the byte array to 2
i2c.writeto(address, bytes([control_read])
i2c.readfrom_into(address, read_response)
# Prompted response:
# bytearray(b'\xff\xff')  # This indicates that both potentiometers were set to their maximum values

I'm not really sure why, but for some reason I had to set up my writes in a specific way to make them work for the digipot I was trying to work with. As far as I could tell looking through the datasheet for the device I was using, there was nothing specific that indicated I had to write to the device this way. The examples just showed all the writes in binary one after the other.
I would really love if there were more examples from Adafruit available for using I2C on the FT232H to communicate with a generic device rather than a specific device that has a premade library like the BME280. As a pretty amateur programmer, this was by far the most difficult part to get working. Having two examples there would be a huge help to understanding how to use the FT232H. I wasn't sure what the problem was most of the time. I wound up looking through the busio.py to even found out what functions were available to me, which isn't necessarily a bad thing in and of itself, but it felt like there was a lack of assistance with explaining how to use the FT232H in this regard. With the GPIO I was able to make work it immediately but I just had no idea where to go with I2C on the FT232H unless I had another specific I2C device from Adafruit.

Posts: 6
Joined: Fri Sep 10, 2021 1:03 pm

Re: Failing to get I2C to work properly using FT232H, Python

by adafruit_support_carter on Fri Sep 24, 2021 1:51 pm

Agree that silk screen label is confusing. Opened an issue for that here:
https://github.com/adafruit/Adafruit-FT ... B/issues/3

For the V2 board, you can generally ignore that. Just use the I2C mode switch on top to set I2C mode. And then ref the pinout here:
https://learn.adafruit.com/circuitpytho ... 2h/pinouts

Posts: 21400
Joined: Tue Nov 29, 2016 2:45 pm

Please be positive and constructive with your questions and comments.