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

Warning

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

The EasyMCP2221.Device constructor will try to prevent conflicts by caching and returning the same Object if the same initialization parameters are given, instead of two different objects.

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=1, force=False, VID=1240, PID=221, usbserial=None, clock=100000, mcp=None)

Initialize and open an I2C bus connection. See EasyMCP2221.Device initialization for details.

Parameters:
  • bus (int, optional) – Device index starting by 1. Default is to use the first device (index 1).

  • force (bool, optional) – For compatibility only, not used.

  • VID (int, optional) – Vendor Id (default is 0x04D8)

  • PID (int, optional) – Product Id (default is 0x00DD)

  • usbserial (str, optional) – Device’s USB serial ID to open.

  • clock (int, optional) – I2C clock frequency (default to 100kHz).

  • mcp (EasyMCP2221 object, optional) – An already initialized EasyMCP2221.Device object to use.

Returns:

SMBus object.

Example

from EasyMCP2221 import SMBus

bus = SMBus()

or

from EasyMCP2221 import smbus

bus = smbus.SMBus()
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