Skip to main content
Skip table of contents

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:

  1. Initial configuration.

  2. Transmit load data.

  3. Specify the number of bytes to read.

  4. Execute the I²C operations.

  5. Read the data that was read from the slave device, if any.

  6. 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.

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:

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).

Note: When writing the TX and RX data, LJM functions eWriteNameArray and eReadNameArray functions are recommended for ease of use.

I2C FAQ/Common Questions

Q: Why are no I2C ACK bits being received?

  • Double check to make sure pull-up resistors are installed.  A general rule for selecting the correct size pull-up resistors is to start with 4.7kΩ and adjust down to 1kΩ as necessary.  If necessary, an oscilloscope should be used to ensure proper digital signals are present on the SDA and SCL lines.

  • Double check to make sure the correct I/O lines are being used.  It is preferred to do I2C communication on EIO/CIO/MIO lines instead of the FIO lines due to the larger series resistance (ESD protection) implemented on the FIO lines.

  • Use an oscilloscope to verify the SDA and SCL lines are square waves and not weird arch signals (see "I2C_SPEED_THROTTLE" or use EIO/CIO/MIO lines).

  • Use a logic analyzer (some oscilloscopes have this functionality) to verify the correct slave address is being used.  See this EEVblog post on budget-friendly options.  It is common to not take into account 7-bit vs 8-bit slave addresses or properly understand how LabJack handles the defined slave address and the read/write bits defined by the I2C protocol to perform read and write requests.

  • Make sure your sensor is being properly powered.  The VS lines of LJ devices are ~5V and the I/O lines are 3.3V.  Sometimes this is a problem.  Consider buying a LJTick-LVDigitalIO or powering the sensor with an I/O line or DAC channel.

Q: I've tried everything, still no I2C Ack Bits...

  • Try slowing down the I2C bus using the "I2C_SPEED_THROTTLE" register/option.   Reasons:

  • Not all I2C sensors can communicate at the full speed of the LabJack.  Check the I2C sensor datasheet.  

  • The digital signals could be getting corrupted due to the series resistors of the I/O lines on the LabJack.

  • Consider finding a way to verify that your sensor is still functioning correctly using an Arduino and that it isn't broken.

  • Try to establish communications with an LJTick-DAC to ensure the DIO are operating properly and that you are configuring I2C properly.

Q: Why is my device not being found by the I2C.search function?

  • See information on I2C ACK bits above.

Q: What are I2C Read and Write functions or procedures?

Q: 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.

Files

I2C_Test_Utilities.zip

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.