SMBus compatible class

Usage

This is a smbus compatibility class. You can use it to run any I2C Python library for Raspberry Pi or micropython just using MCP2221’s I2C device interface.

Usage:

from EasyMCP2221 import SMBus

bus = SMBus()

or

from EasyMCP2221 import smbus

bus = smbus.SMBus()

Note

To use other mcp functions in addition to SMBus, do not create a new MCP Device. It will interfere with existing bus resulting in unpredictable behavior. Always re-use bus.mcp object (see example 2).

Example 1: Basic weather station

In this example, we are using a library from Pimoroni/BME280 to read Temperature, Barometric Pressure and Relative Humidity from a BME280 sensor.

That library is designed for Raspberry Pi or any other system that supports SMBus protocol. It works together with EasyMCP2221 via SMBus class.

Install:

pip install pimoroni-bme280 EasyMCP2221

Example code:

import time
from EasyMCP2221 import SMBus
from bme280 import BME280

bus = SMBus(1)
bme280 = BME280(i2c_dev=bus)

while True:
    temperature = bme280.get_temperature()
    pressure = bme280.get_pressure()
    humidity = bme280.get_humidity()
    print('{:05.2f}*C {:05.2f}hPa {:05.2f}%'.format(temperature, pressure, humidity))
    time.sleep(1)

Output:

17.93*C 933.76hPa 51.57%
17.92*C 933.76hPa 51.57%
17.91*C 933.77hPa 51.53%
17.91*C 933.77hPa 51.50%
17.91*C 933.77hPa 51.54%
...

Example 2: Real Time Clock with LCD

This is a digital clock with two I2C chips:

  • DS1307 as RTC

  • LCD display based on with PCF8574 I2C adapter.

It also shows how to re-use mcp object to further configure MCP2221.

Main loop:

  • DS1307 is configured as 1Hz square oscillator.

  • MCP2221’s GP2 is configured as Interrupt on Change.

  • The rising edge of DS1307’s output triggers the update cycle.

Full code on EasyMCP2221 examples/clock

from EasyMCP2221 import SMBus
from lcd_driver import LCD
from DS1307 import DS1307

# Create SMBus and instances
bus = SMBus()
lcd = LCD(bus, addr=0x3F)
ds = DS1307(bus, addr=0x68)

bus.mcp.I2C_speed(100_000) # DS1307 only supports 100kHz

bus.mcp.set_pin_function(
    gp0 = "GPIO_IN",  # unused
    gp1 = "IOC",      # trigger update LCD each second
    gp2 = "DAC",      # simulate backup battery
    gp3 = "LED_I2C")  # i2c traffic indicator

bus.mcp.DAC_write(21) # about 3.28V with 5V Vcc
bus.mcp.IOC_config(edge = "rising")

# Initialization after a complete power loss
if ds.halted():
    ds.write_now()
    ds._write(0x07, 0b0001_0000) # sqwe 1Hz
    print("RTC initialized with current timestamp")
else:
    print("RTC was already initialized")

lcd.clear()

# Update only when GP1 changes using Interrupt On Change
while True:
    if bus.mcp.IOC_read():
        bus.mcp.IOC_clear()
        (year, month, day, dow, hours, minutes, seconds) = ds.read_all()

        lcd.display_string("%02d/%02d/20%02d" % (day, month, year), 1)
        lcd.display_string("%02d:%02d:%02d" % (hours, minutes, seconds), 2)

Full reference

Based on kplindegaard/smbus2 interface.

See The SMBus Protocol for more information.

class SMBus(bus=None, force=False, VID=1240, PID=221, devnum=0, clock=100000)

Initialize and open an i2c bus connection.

Parameters:
  • bus (int or str) – (for compatibility only, not used) i2c bus number (e.g. 0 or 1) or an absolute file path (e.g. /dev/i2c-42). If not given, a subsequent call to open() is required.

  • force (boolean) – (for compatibility only, not used) force using the slave address even when driver is already using it.

  • VID – Vendor Id (default to 0x04D8)

  • PID – Product Id (default to 0x00DD)

  • clock – I2C clock frequency (default to 100kHz)

block_process_call(i2c_addr, register, data, force=None)

Executes a SMBus Block Process Call, sending a variable-size data block and receiving another variable-size response

Parameters:
  • i2c_addr (int) – i2c address

  • register (int) – Register to read/write to

  • data (list) – List of bytes

  • force (Boolean) –

Returns:

List of bytes

Return type:

list

close()

(For compatibility only, no effects) Close the i2c connection.

open(bus)

(For compatibility only, no effects) Open a given i2c bus.

Parameters:

bus (int or str) – i2c bus number (e.g. 0 or 1) or an absolute file path (e.g. ‘/dev/i2c-42’).

Raises:

TypeError – if type(bus) is not in (int, str)

process_call(i2c_addr, register, value, force=None)

Executes a SMBus Process Call, sending a 16-bit value and receiving a 16-bit response

Parameters:
  • i2c_addr (int) – i2c address

  • register (int) – Register to read/write to

  • value (int) – Word value to transmit

  • force (Boolean) –

Return type:

int

read_block_data(i2c_addr, register, force=None)

Read a block of up to 32-bytes from a given register.

Parameters:
  • i2c_addr (int) – i2c address

  • register (int) – Start register

  • force (Boolean) –

Returns:

List of bytes

Return type:

list

read_byte(i2c_addr, force=None)

Read a single byte from a device.

Return type:

int

Parameters:
  • i2c_addr (int) – i2c address

  • force (Boolean) –

Returns:

Read byte value

read_byte_data(i2c_addr, register, force=None)

Read a single byte from a designated register.

Parameters:
  • i2c_addr (int) – i2c address

  • register (int) – Register to read

  • force (Boolean) –

Returns:

Read byte value

Return type:

int

read_i2c_block_data(i2c_addr, register, length, force=None)

Read a block of byte data from a given register.

Parameters:
  • i2c_addr (int) – i2c address

  • register (int) – Start register

  • length (int) – Desired block length

  • force (Boolean) –

Returns:

List of bytes

Return type:

list

read_word_data(i2c_addr, register, force=None)

Read a single word (2 bytes) from a given register.

Parameters:
  • i2c_addr (int) – i2c address

  • register (int) – Register to read

  • force (Boolean) –

Returns:

2-byte word

Return type:

int

write_block_data(i2c_addr, register, data, force=None)

Write a block of byte data to a given register.

Parameters:
  • i2c_addr (int) – i2c address

  • register (int) – Start register

  • data (list) – List of bytes

  • force (Boolean) –

Return type:

None

write_byte(i2c_addr, value, force=None)

Write a single byte to a device.

Parameters:
  • i2c_addr (int) – i2c address

  • value (int) – value to write

  • force (Boolean) –

write_byte_data(i2c_addr, register, value, force=None)

Write a byte to a given register.

Parameters:
  • i2c_addr (int) – i2c address

  • register (int) – Register to write to

  • value (int) – Byte value to transmit

  • force (Boolean) –

Return type:

None

write_i2c_block_data(i2c_addr, register, data, force=None)

Write a block of byte data to a given register.

Parameters:
  • i2c_addr (int) – i2c address

  • register (int) – Start register

  • data (list) – List of bytes

  • force (Boolean) –

Return type:

None

write_word_data(i2c_addr, register, value, force=None)

Write a single word (2 bytes) to a given register.

Parameters:
  • i2c_addr (int) – i2c address

  • register (int) – Register to write to

  • value (int) – Word value to transmit

  • force (Boolean) –

Return type:

None