I2C

The serbus.I2CDev class provides an API for interfacing with standard GNU/Linux spidev devices. It is instantiated with a bus number corresponding to the I2C bus device file it will use - to communicate with devices on the I2C bus connected to /dev/i2c-0 you could create the instance bus = serbus.I2CDev(0).

Note

For more info on I2C (Inter-Integrated Circuit) see https://en.wikipedia.org/wiki/I%C2%B2C

API

class serbus.I2CDev(bus)
Parameters:bus (int) – The bus number to use, e.g. 0 for /dev/i2c-0
close()

Close the I2C bus interface.

open([use_10bit_address=False])
Parameters:use_10bit_address (bool, optional) – True for 10-bit address mode, False for 7-bit address mode (default)

Initialize the I2C bus interface, selecting whether the bus will use 10-bit slave addresses or the standard 7-bit addresses. Must be called before any other methods.

read(slave_addr, n_bytes)
Parameters:
  • slave_addr (int) – The address of the slave to read from
  • n_bytes (int) – The number of bytes to read
Returns:

A list of ints of the bytes read

Reads and returns n_bytes words from the I2C slave device with the given address.

readTransaction(slave_addr, tx_byte, n_bytes)
Parameters:
  • slave_addr (int) – The address of the slave to read from
  • tx_byte (int) – The byte to write before reading
  • n_bytes (int) – The number of bytes to read
Returns:

A list of ints of the bytes read

Writes tx_byte then immediately reads n_bytes bytes from the I2C slave device with the given address and returns them as a list. This is useful for things like reading register values from memory mapped devices.

write(slave_addr, bytes)
Parameters:
  • slave_addr (int) – The address of the slave to write to
  • n_bytes (list) – A list of bytes to write

Writes the given list of bytes to the I2C slave device with the given address.

Examples

These are a few examples of using the I2CDev object. They will only work if you have the proper hardware connected to the system running them and your I2C kernel driver loaded. Depending on the system there may be additional required setup as well, such as configuring pin multiplexers on embedded GNU/Linux systems like the BeagleBone Black.

Reading data

This example shows how to read a single byte from an I2C device. It is not specific to any particular device.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import serbus

# Create an I2CDev instance for interfacing to /dev/i2c-1:
bus = serbus.I2CDev(1)
bus.open()

# Read a single byte from the slave device with address 0x50:
data = bus.read(0x50, 1)
print "byte received: {:x}".format(data[0])

bus.close()

EEPROM memory

In this example, a sequence of bytes are written to a 24LC256 (or equivalent) I2C EEPROM, then reading them back to verify they have been written.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import serbus, time

eeprom_addr = 0x50 # I2C slave address of EEPROM
start_msb   = 0x00 # High byte of location in EEPROM to write/read
start_lsb   = 0x00 # Low byte of location in EEPROM to write/read

data_to_write = range(10)

# Create an I2CDev instance for interfacing to /dev/i2c-2:
bus = serbus.I2CDev(2)
bus.open()

print "Writing data: {}".format(data_to_write)
# Write the data to the EEPROM:
bus.write(eeprom_addr, [start_msb, start_lsb] + data_to_write)
# The I2C write is asynchronous - give it a bit of time to complete:
time.sleep(0.01) # 10ms should be more than enough

# Read the data from the EEPROM:
bus.write(eeprom_addr, [start_msb, start_lsb])
read_data = bus.read(0x50, len(data_to_write))
print "Data read: {}".format(read_data)

if read_data == data_to_write:
  print "EEPROM write successful!"
else:
  print "EEPROM write failed, is WP enabled?"

bus.close()

For this to work, the EEPROM’s WP (write protect) pin must be pulled down to GND to allow writing.

HTU21D humidity sensor

This example shows how the I2CDev class can be used to measure relative humidity and temperature from the HTU21D I2C humidity sensor.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import serbus, time

htu21d_bus      = 1    # Connected to /dev/i2c-1
htu21d_addr     = 0x40 # HTU21D slave address
htu21d_cmd_temp = 0xe3 # Command to read temperature
htu21d_cmd_rh   = 0xe5 # Command to read relative humidity

bus = serbus.I2CDev(1)
bus.open()

def getTemp():
  # Read the 3 bytes of data:
  msb, lsb, crc = bus.readTransaction(htu21d_addr, htu21d_cmd_temp, 3)
  # The crc (cyclic redundancy check) can be used to verify the data was 
  # received without error - ignore it here
  # Combine the high and low bytes:
  raw_value = (msb<<8) | lsb
  # Clear the two status bits (see datasheet):
  raw_value &= ~0b11
  # Convert to Celsius and return (conversion from datasheet):
  return -46.85 + 175.72 * (raw_value/65536.0)

def getRH():
  msb, lsb, crc = bus.readTransaction(htu21d_addr, htu21d_cmd_rh, 3)
  raw_value = (msb<<8) | lsb
  raw_value &= ~0b11
  # Convert to %RH and return (conversion from datasheet):
  return -6.0 + 125.0 * (raw_value/65536.0)

try:
  while True:
    print
    print "Temperature:       {:0.2f}C".format(getTemp())
    print "Relative humidity: {:0.2f}%".format(getRH())
    time.sleep(1)

except KeyboardInterrupt:
  bus.close()