13.3 I2C [T-Series Datasheet]
I²C or I2C is a two-wire synchronous serial protocol typically used to send data between chips. I2C is considered an advanced topic. A good knowledge of the protocol is recommended. Troubleshooting may require a logic analyzer or oscilloscope. We recommend users inexperienced with I2C purchase our LJTick-DAC and get I2C working with it before attempting configuration with a third-party sensor. LabJack does not typically provide support for specific I2C sensors beyond clarifying the necessary I2C configuration steps. Some general troubleshooting guidance can be found below, including two useful troubleshooting utilities. See the attached "I2C_Test_Utilities.zip" at the bottom of the page (Windows only).
Subsections
T-series I2C Support
T-series devices support master-mode Inter-Integrated Circuit (I²C or I2C) communication. Two digital IO are required to act as clock (SCL) and data (SDA). Any T-series digital I/O line can be SDA or SCL.
The I²C bus generally requires pull-up resistors of perhaps 4.7 kΩ from SDA to VS and SCL to VS.
EIO and CIO digital I/O lines should be used, instead of the FIO lines, due to the extra lower output impedances on those lines. Look at the Digital I/O Specifications page for more details.
Lua scripting is often convenient for serial applications. For example, a script can run the serial communication at a specified interval, and put the result in USER_RAM registers. The host software can read from the USER_RAM registers when convenient. This puts the complications of serial communication in a script running on the T-series device. The I²C Sensor Lua examples contain several serial communication examples.
This I²C bus is not an alternative to the USB connection. Rather, the host application will write/read data to/from the LabJack, and the LabJack will communicate with some other device using I²C.
Data Rates
I²C is done in command-response mode, either from a host application or an on-board Lua script. Throughput can be estimated by looking at the bit rate and number of bits to transfer, and for external host communication adding the packet overhead estimates from the beginning of Appendix A-1. A further consideration is how much you can fit in 1 packet or whether multiple packets will be required.
I2C is implemented in software rather than with hardware. As a result, the I2C clock timing can vary somewhat depending on the T-series device processor load, and there is not any precise formula to calculate the bus speed based off of I2C_SPEED_THROTTLE.
Clock Stretching
T-Series devices support clock stretching. When a slave device needs more time to complete an operation it can use clock stretching to pause the bus. T-Series devices will allow up to 1000 clock periods of clock stretching. If a slave device needs more time, a slower clock speed should be used.
How-To
Device Control Basics
All T-series device features are controlled by reading and writing Modbus TCP registers via Modbus TCP (either directly or through our LJM library).
We have register descriptions throughout documentation detailing relevant register names, starting addresses, types, and access permissions (read/write).
See Section 3.0 Communication for other detailed communication information.
Process
Running an I2C operation on a T-series device requires:
Initial configuration.
Transmit load data.
Specify the number of bytes to read.
Execute the I²C operations.
Read the data that was read from the slave device, if any.
Debugging (optional): Read the acknowledgement array to determine which bytes were acknowledged by the slave device.
Steps 2-5 can be repeated as long as I²C has not been used to communicate with a different device.
When writing/reading the TX and RX data using LJM, we recommend using the functions eWriteNameArray and eReadNameArray for ease of use.
When writing/reading the TX and RX data using direct Modbus TCP communications, you should process data as a raw byte array rather than casting each byte as a 16-bit value. This means there will be two data bytes in each Modbus register written/read.
Initial Configuration
Several registers need to be written to configure the T-series device.
Digital IO lines need to be selected to act as SDA and SCL. The directions of these lines will be configured automatically.
Set the clock speed:
The options register controls several compatibility settings:
For example, setting bit 1 of I2C_OPTIONS to true supports the repeated start condition.
Load the address of the slave device:
Transmit load data.
Load an array of bytes to send to the slave device. This array does not include the device address.
Specify the number of bytes to read.
Write the number of bytes to be read from the slave device. Read operations will always be performed after any write operations.
Execute the I²C operations.
Instruct the T-series device to run the write and read operations specified in the last two steps.
Read the data that was read from the slave device, if any.
Data received from the slave device will be saved in buffer on the T-series device. Use the I2C_DATA_RX to read the buffer:
Debugging: Read the acknowledgement array to determine which bytes were acknowledged by the slave device.
The below register can help troubleshoot I²C issues. The ACKs register will record all Acknowledgement signals transmitted from the slave device to the master (master is the T-series device). Data is always transmitted over I²C in the following sequence: Slave Address, Write data, Slave Address, Read data. After each byte sent to the slave device an acknowledgement will be stored in bit 0. A 1 indicates that the bytes was acknowledged, a 0 indicates no acknowledgement. Before saving the an ACK or no-ACK the register is shifted left.
For example, if two bytes are transmitted and three are read there will be four ACKs. Bit 3 represents the acknowledgement to the first slave address which starts the write operation, bit 2 is the first data byte, Bit 1 is the seconds data byte, bit 0 is the second slave address which starts the read operation.
Example
This demonstrates I²C communications with an LJTick-DAC connected to FIO0/FIO1.
First, configure the I²C settings:
I2C_SDA_DIONUM = 1 // Set SDA pin number = 1(FIO1)
I2C_SCL_DIONUM = 0 // Set SCL pin number = 0 (FIO0)
I2C_SPEED_THROTTLE = 0 // Set speed throttle = 0 (max)
I2C_OPTIONS = 0 // Set options = 0
I2C_SLAVE_ADDRESS = 80 // Set 7-bit slave address of the I²C chip = 80 (0x50)
Read from EEPROM bytes 0-3 in the user memory area. We need a single I²C transmission that writes the chip's memory pointer and then reads the data.
I2C_NUM_BYTES_TX = 1 // Set the number of bytes to transmit to 1
I2C_NUM_BYTES_RX = 4 // Set the number of bytes to receive to 4
I2C_DATA_TX = {0} // Set the TX data. byte 0: Memory pointer = 0.
I2C_GO = 1 // Do the I²C communications.
I2C_DATA_RX = {?, ?, ?, ?} // Get the RX data (4 bytes).
Write EEPROM bytes 0-3 in the user memory area, using the page write technique. Note that page writes are limited to 16 bytes max, and must be aligned with the 16-byte page intervals. For instance, if you start writing at address 14, you can only write two bytes because byte 16 is the start of a new page.
I2C_NUM_BYTES_TX = 5 // Set the number of bytes to transmit to 5
I2C_NUM_BYTES_RX = 0 // Set the number of bytes to receive to 0 (not receiving data)
I2C_DATA_TX = {0, 156, 26, 2, 201} // Set the TX data. byte 0: Memory pointer = 0, bytes 1-4: EEPROM bytes 0-3.
I2C_GO = 1 // Do the I²C communications.
If using multiple I²C busses, just include writes to set the DIONUMs each time you want to communicate on a different bus. Other configuration is global also, so if different busses need different configuration include those writes also:
I2C_SDA_DIONUM = 2 // Set SDA pin number = 2 (FIO2)
I2C_SCL_DIONUM = 3 // Set SCL pin number = 3 (FIO3)
I2C_SPEED_THROTTLE = 65516 // Set speed throttle for ~100 kbps
I2C_NUM_BYTES_TX = 1 // Set the number of bytes to transmit to 1
I2C_NUM_BYTES_RX = 4 // Set the number of bytes to receive to 4
I2C_DATA_TX = {0} // Set the TX data. byte 0: Memory pointer = 0.
I2C_GO = 1 // Do the I²C communications.
I2C_DATA_RX = {?, ?, ?, ?} // Get the RX data (4 bytes).
I2C Troubleshooting
See our I2C Resources App Note.
Why am I getting a I2C_BUS_BUSY (LJM Error code 2720) error?
See information on I2C ACK Bits above. Try different pull-up resistor sizes.
Testing Utilities
The following zip archive contains a couple of basic Windows programs to help identify your sensor slave address and troubleshoot some I2C signal issues.