Open ElmarJongerius opened 3 years ago
@nonNoise Could you point me in the right direction on how to implement longer reads and writes? I think at this moment the code is limited to single block transfers; and still it does crash a lot of times for me. (reading more than 20 bytes is almost impossible it seems).
I would like to add reliable read/write functions but cannot even find doc`s on microchips website. Hoe should I for example do a status check/read within the transfer?
Hello. thank you for contacting. I don't know the target because there is no scene to communicate more than 20 bytes. If you are assuming EEPROM etc., how about reading it in pieces?
Thanks for using it.
Hi @nonNoise, The reason we are communicating longer transactions is speed and compatibility.
Points 1 and 2 are most important to me.
If you could help me on some tips on implementing I would be very grateful.
Hmm? I checked the contents of MCP2221A, but I think the maximum number of bytes that can be transferred at one time is 59. (63 - 4 = 59Byte) I have a problem where it crashes at 20 bytes.
Do you know the target sensor or IC? I want to buy and try it.
Located in PyMCP2221A.py def _i2c_write (self, addrs, data, buf): in There is time.sleep (0.008).
This "time.sleep" is included to improve PC (or USB) speed and IC compatibility.
Number entered by experience.
Please adjust it.
I am happy if you can see the waveform during communication.
Thank you,
I forgot to tell you. PyMCP2221A Certainly slow. There are times when I can't stand it. Is there a problem with Python? Is there a problem with HID-API? Is there a problem with the MCP221A that uses HID in the first place? I don't know, but it's very slow. Especially when I read the accelerometer, I can't stand it. Temperatures and pressures of 1 second to 100 milliseconds are acceptable.
This area is quite difficult. It may not be possible to solve it.
The target is a self developed ARM micro controller configured as I2C slave. Playing with the delay`s will not help; I do need to adjust how the library transfers I2C data.
Semicode:
Write address
Get status (ACK/NACK)
While data available
Write data
Get status (ACK/NACK/BUSY)
Do you think this is a "library" problem? I am going according to the command of MCP2221A. Check the specifications of the MCP2221A. Please let me know if there is anything you want. https://www.microchip.com/wwwproducts/en/MCP2221A
Thank you,
Well, the datasheet states: "Supports block reads/writes up to 65535 bytes long". Clearly that would need to be multiple USB block transfers; but I would really like to have this implemented :)
I have searched for a way how to use it (probably needs some status checking and extended data sending) but I couldn't figure out from the available documentation yet). I have requested support at Microchip so I'm hopeful they will send me some details which will help to bring these together.
Checking the I2C status might also make your sensors read out faster; as this delay is probably unnecessary when using status readback.
@ElmarJongerius , @nonNoise ,
I found "TABLE 3-2: RESPONSE 1 STRUCTURE" (page 25 of the datasheet pdf) has a great hint. in the table, byte index from 9 to 17:
index | description |
---|---|
9 | Lower byte (16-bit value) of the requested I2C transfer length |
10 | Higher byte (16-bit value) of the requested I2C transfer length |
11 | Lower byte (16-bit value) of the already transferred (through I2C) number of bytes |
12 | Higher byte (16-bit value) of the already transferred (through I2C) number of bytes |
13 | Internal I2C data buffer counter |
14 | Current I2C communication speed divider value |
15 | Current I2C time-out value |
16 | Lower byte (16-bit value) of the I2C address being used |
17 | Higher byte (16-bit value) of the I2C address being used |
Hi was this ever figured out? For my project I really need to read more than 60 per block, and I am struggling to make it work.
Hi I'm a little interested. "read more than 60 per block" What model number of IC are you using?
I'm using the MCP2221A and trying to read 68 bytes
Also, do you mind explaining what this portion of your code in the _i2c_read function is doing?
buf[1 + 1] = (size & 0x00FF) # Read LEN
buf[2 + 1] = (size & 0xFF00) >> 8 # Read LEN
buf[3 + 1] = 0xFF & (addrs << 1) # addrs
self.mcp2221a.write(buf)
rbuf = self.mcp2221a.read(PACKET_SIZE)
if (rbuf[1] != 0x00):
# print("[0x91:0x{:02x},0x{:02x},0x{:02x}]".format(rbuf[1],rbuf[2],rbuf[3]))
self.I2C_Cancel()
self.I2C_Init()
raise RuntimeError("I2C Read Data Failed: Code " + rbuf[1])
time.sleep(self.MCP2221_I2C_SLEEP)
buf = self.compile_packet([0x00, 0x40])
buf[1 + 1] = 0x00
buf[2 + 1] = 0x00
buf[3 + 1] = 0x00
self.mcp2221a.write(buf)
rbuf = self.mcp2221a.read(PACKET_SIZE)
The I2C functions do not handle writes and reads which are longer than 1 block (60 bytes?).
I have hacked it into the _i2c_write function as follows, as I was not able to find a way to do this cleaner. I would be glad to help implement and test this; it seems there is a status read required to see if we can already write the next block.
#Support for longer I2C write packets
def _i2c_write(self, addrs, data, buf):
buf = buf + [0 for i in range(65 - len(buf))]
buf[1 + 1] = (len(data) & 0x00FF) # Cancel current I2C/SMBus transfer (sub-command)
buf[2 + 1] = (len(data) & 0xFF00) >> 8 # Set I2C/SMBus communication speed (sub-command)
# The I2C/SMBus system clock divider that will be used to establish the communication speed
buf[3 + 1] = 0xFF & (addrs << 1)
while (len(data)):
for i in range(min(len(data), 60)):
#print ("{:d}: 0x{:02x}".format(i,data[i]))
buf[4 + 1 + i] = data[i] # The I2C/SMBus system clock divider that will be used to establish the communication speed
self.mcp2221a.write(buf)
rbuf = self.mcp2221a.read(65)
time.sleep(0.08)
#print("\n\n")
data = data[min(len(data), 60):]