I'm debugging both python host code (ethernet) and microcontroller firmware (I2C), with a labjack T7 in between.
I'm using I2C clock stretching to hold the I2C bus while the uC is preparing a response from incoming T7 commands. The T7 is the master, the uC is the slave. The uC invokes clock-stretching by holding SCL low.
Sometimes, if my poorly-written uC firmware takes too long, and LJM returns with an "I2C_BUS_BUSY" error.
For example:
Bytes_To_Read = write_device(daq, sout, verbose=verbose) #updates Bytes_To_Read with length-to-read
File ".\sc_NERDAQ_I2C.py", line 261, in write_device
ljm.eWriteName(daq, "I2C_GO", 1)
File "C:\Python27\lib\site-packages\labjack\ljm\ljm.py", line 530, in eWriteName
raise LJMError(error)
labjack.ljm.ljm.LJMError: LJM library error code 2720 I2C_BUS_BUSY
This particular instance happened when my uC was holding SCL low for ~280 mSec (delaying the ACK of the address byte). Yes, I know that this is slow, and something is broken.
However, I'm wondering:
- What determines this I2C "GO" Timeout?
- Is the timeout value readable/setable?
- Am I correct that Ethernet Transaction Timeout is a default of 2600 mS (or thereabouts), so it's probably not that?
I2C Setup:
# Configure the T7 for I2C-serial
my_list = [
"I2C_SDA_DIONUM",
"I2C_SCL_DIONUM",
"I2C_SPEED_THROTTLE",
"I2C_OPTIONS",
"I2C_SLAVE_ADDRESS",
]
my_data = [
int(SDA_pin),
int(SCL_pin),
65516, # Speed Throttle 65,516 is ~100 kHz, min is 46,000 (per LJM library)
0b00000000, #I2C options B2: disable clock stretching, B1: No STOP with RESTART, B0: Reset Bus
int(MIN_I2C_ADDRESS), # junk, default I2C_address of a widget
]
ljm.eWriteNames(daq, len(my_list), my_list, my_data)
Trace results of writing to I2C widget at address 0x14 "X\0x10", followed by a Read request to the same address, with clock stretching (delaying the ACK of the Address-Read byte) starting at ~390 uS:
See Attachment.
Sending code:
ljm.eWriteName(daq, "I2C_NUM_BYTES_TX", len(bytes_in)) # number of bytes in the original data
ljm.eWriteName(daq, "I2C_NUM_BYTES_RX", 1) # read-back the length of any response, 0-128
ljm.eWriteNameByteArray(daq, "I2C_DATA_TX", len(bytes_in), [ord(ch) for ch in bytes_in]) #convert string to list of ints
ljm.eWriteName(daq, "I2C_GO", 1)
< I2C Busy Error Here >
#Get the LabJack buffer contents, that was updated from "I2C_GO".
resp = read_LabJack_I2C_buffer(daq, 1, verbose=verbose)
Thank you for your attention.
-Chris
**Latest firmware and LJM used.**
The T7 has an internal watchdog that will trip if any operation takes longer than 256 ms. This timeout cannot be changed.
When the T7 receives a request to start an I2C communication, it checks the states of the I2C lines. If one or both of the lines are low then the I2C_BUS_BUSY error is thrown. Clock stretching should only be used to stall a communication in progress. For instance, if the master addresses the slave and sends an instruction asking for a specific result, then the clock can be stretched for a short time while the result is fetched. For very long sensor operations separate start_reading and read_result functions are usually used (two separate communications).
The good news is that if you know your device will eventually be ready to send data you can ignore I2C_BUS_BUSY and just keep attempting the I2C operation. Eventually the request will go through.
Communication timeouts can be modified:
https://labjack.com/support/software/api/ljm/function-reference/library-...
https://labjack.com/support/software/api/ljm/constants/timeout-configs
Thanks for the quick reply.
This the direction that I'm going in. It's good to be aware of the 256mS boundary as well.
Regards,
Chris