I2C Implementation in Python - cu-ecen-aeld/buildroot-assignments-base GitHub Wiki

I2C Implementation in Python

What is I²C?

  • I²C, pronounced I-squared-C or I-2-C, is a popular serial communication protocol initially developed by Phillips Semiconductor (now NXP Semiconductor).
  • It is widely used by major IC manufacturers for a variety of devices like microcontrollers, ADCs, DACs, EEPROMs, I/O devices, and real-time clocks.
  • I²C is a multi-slave, half-duplex bus, meaning a master device communicates with multiple slave devices on the same bus, but communication occurs in only one direction at a time.
  • On the Raspberry Pi, the Pi acts as the master while connected devices act as slaves.

Key Features:

  • Two Wires:
    • SDA (Serial Data): Carries data packets between the master and slave devices.
    • SCL (Serial Clock): Synchronizes the data packets via a clock signal generated by the master.
  • Pull-Up Resistors:
    • SDA and SCL are connected to the +Vdd power wire via pull-up resistors, defaulting the bus to a high state.
    • Typical voltages are 3.3V or 5V.

I²C in Python

There are multiple ways to implement I²C in Python. This documentation focuses on using low-level system calls.

Linux I2C Interface:

  • I²C buses are represented as device files (e.g., /dev/i2c-1) in Linux.
  • Tools like i2cdetect can identify the unique address of connected I²C devices.

Python Modules for I²C:

  • fcntl: For file descriptor I/O control operations.
  • struct: For packing and unpacking data in binary formats.
  • ctypes: For low-level memory and data type operations.

Configuring I²C on Raspberry Pi

If you are using a Raspberry Pi, you must configure its I²C hardware to enable communication. Follow the steps in the Raspberry Pi Hardware Hints - I²C section for detailed instructions.

Note: This guide for enabling I²C is tailored for Raspberry Pi. If you're using a different platform, you may need to adapt the configuration to match your hardware's requirements.

Implementation Steps

Step 1: Initialize I²C Device

Open the I²C device file and set the slave address:

import fcntl

# I²C Settings
DEVICE = 0x27  # Replace with your device's I²C address
I2C_SLAVE = 0x0703  # I²C_SLAVE operation code

# Open the I²C bus
i2c_file = open('/dev/i2c-1', 'rb+', buffering=0)
fcntl.ioctl(i2c_file, I2C_SLAVE, DEVICE)  # Set the I²C device address

Step 2: Create Utility Functions

Writing Data:

Write a single byte to the I²C device:

def write_byte(data):
    """Write a single byte to the I²C device."""
    i2c_file.write(bytearray([data]))

Reading Data:

Read a sequence of bytes starting from a specific register:

def read_bytes(register, length):
    """
    Read a sequence of bytes from the I²C device.

    :param register: Starting register address.
    :param length: Number of bytes to read.
    :return: List of bytes read.
    """
    i2c_file.write(bytearray([register]))  # Set the register pointer
    return list(i2c_file.read(length))  # Read the data

Step 3: Example Applications

Example 1: BMP180 Sensor Communication

The BMP180 sensor is used to read temperature , altitude and pressure data over I²C.
Refer to the BMP180 I2C interface for full implementation details.

Example 2: I²C LCD Communication

The I²C-enabled LCD is controlled to display strings using specific commands.
Refer to the I2C LCD Interface for complete code.


References

  1. Linux I²C Interface Documentation
  2. BMP180 I²C Interface
  3. Circuit Basics: Raspberry Pi I²C LCD
  4. Raspberry Pi Hardware Hints - I²C