{"id":8808,"library":"adafruit-circuitpython-busdevice","title":"Adafruit CircuitPython Bus Device","description":"Adafruit CircuitPython Bus Device provides helper classes, `I2CDevice` and `SPIDevice`, to simplify managing transaction state on I2C and SPI buses. It handles bus locking, device addressing for I2C, and chip select and protocol changes for SPI. The library is actively maintained by Adafruit, with frequent releases to address bug fixes and add minor enhancements. The current version is 5.2.16.","status":"active","version":"5.2.16","language":"en","source_language":"en","source_url":"https://github.com/adafruit/Adafruit_CircuitPython_BusDevice","tags":["circuitpython","adafruit","i2c","spi","bus","hardware","drivers","microcontroller"],"install":[{"cmd":"pip install adafruit-circuitpython-busdevice","lang":"bash","label":"Install for CPython (e.g., Raspberry Pi)"},{"cmd":"Download the Adafruit CircuitPython Library Bundle from circuitpython.org/libraries and copy the 'adafruit_bus_device' folder to the 'lib' directory on your CIRCUITPY drive.","lang":"text","label":"Install for CircuitPython (microcontrollers)"}],"dependencies":[{"reason":"Required for running CircuitPython libraries on single-board computers like Raspberry Pi (CPython).","package":"adafruit-blinka","optional":false},{"reason":"Provides low-level I2C and SPI bus access, used by `adafruit_bus_device` classes. Part of CircuitPython core or provided by `adafruit-blinka`.","package":"busio","optional":false},{"reason":"Used for managing chip select (CS) pins in SPIDevice. Part of CircuitPython core or provided by `adafruit-blinka`.","package":"digitalio","optional":false},{"reason":"May be required for SPIDevice initialization on certain Linux systems when hardware SPI is used directly (CPython).","package":"libgpiod bindings","optional":true}],"imports":[{"note":"The `I2CDevice` class is within the `i2c_device` submodule, not directly under `adafruit_bus_device`.","wrong":"from adafruit_bus_device import I2CDevice","symbol":"I2CDevice","correct":"from adafruit_bus_device.i2c_device import I2CDevice"},{"note":"The `SPIDevice` class is within the `spi_device` submodule, not directly under `adafruit_bus_device`.","wrong":"from adafruit_bus_device import SPIDevice","symbol":"SPIDevice","correct":"from adafruit_bus_device.spi_device import SPIDevice"}],"quickstart":{"code":"import board\nimport busio\nimport digitalio\nfrom adafruit_bus_device.i2c_device import I2CDevice\nfrom adafruit_bus_device.spi_device import SPIDevice\n\n# --- I2C Example ---\n# Replace with your actual I2C device address (e.g., 0x68 for DS3231)\nI2C_DEVICE_ADDRESS = 0x68\nI2C_REGISTER_ADDRESS = 0x0E # Example register\n\nprint(\"--- I2C Device Example ---\")\ntry:\n    # Initialize I2C bus\n    i2c = busio.I2C(board.SCL, board.SDA)\n    # Create an I2CDevice object\n    i2c_device = I2CDevice(i2c, I2C_DEVICE_ADDRESS)\n\n    # Perform an I2C transaction\n    with i2c_device:\n        i2c_device.write(bytes([I2C_REGISTER_ADDRESS]))\n        result = bytearray(1)\n        i2c_device.readinto(result)\n    print(f\"I2C read from 0x{I2C_DEVICE_ADDRESS:02X}, register 0x{I2C_REGISTER_ADDRESS:02X}: {result[0]:02X}\")\nexcept Exception as e:\n    print(f\"I2C Example Error: {e}\")\nfinally:\n    if 'i2c' in locals() and i2c.locked: i2c.unlock() # Ensure bus is unlocked\n\n# --- SPI Example ---\n# Replace with your actual SPI settings and CS pin\nSPI_REGISTER_ADDRESS = 0xD0 # Example register for BMP280\n\nprint(\"\\n--- SPI Device Example ---\")\ntry:\n    # Initialize SPI bus and Chip Select pin\n    spi_bus = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)\n    cs_pin = digitalio.DigitalInOut(board.D5) # Use an appropriate digital pin\n\n    # Create an SPIDevice object\n    spi_device = SPIDevice(spi_bus, cs_pin)\n\n    # Perform an SPI transaction\n    with spi_device as spi:\n        spi.write(bytes([SPI_REGISTER_ADDRESS]))\n        result = bytearray(1)\n        spi.readinto(result)\n    print(f\"SPI read from register 0x{SPI_REGISTER_ADDRESS:02X}: {result[0]:02X}\")\nexcept Exception as e:\n    print(f\"SPI Example Error: {e}\")\nfinally:\n    if 'spi_bus' in locals() and spi_bus.locked: spi_bus.unlock() # Ensure bus is unlocked\n\nprint(\"Examples complete.\")\n","lang":"python","description":"This quickstart demonstrates how to use `I2CDevice` and `SPIDevice` to perform basic read operations. It initializes the respective bus, creates a device object, and uses a `with` statement to manage bus locking and chip select automatically during transactions. Replace placeholder addresses and pins with your specific hardware configuration. For CPython, ensure `adafruit-blinka` is installed and GPIO/bus access is configured."},"warnings":[{"fix":"Check the CircuitPython 'module support matrix' for your board. If `adafruit_bus_device` is built-in, do not copy the library to your CIRCUITPY drive. If you encounter issues, try removing the `adafruit_bus_device` folder from 'lib'.","message":"On CircuitPython boards running v6.3.0 or newer firmware, `adafruit_bus_device` may be built-in. Installing an additional copy into the 'lib' directory can cause import conflicts and lead to unexpected errors in libraries that depend on it.","severity":"gotcha","affected_versions":"CircuitPython >= 6.3.0"},{"fix":"Ensure `adafruit-circuitpython-busdevice` and `adafruit-blinka` are installed via `pip` (e.g., `pip3 install adafruit-circuitpython-busdevice adafruit-blinka --upgrade`).","message":"`ImportError: No module named 'adafruit_bus_device'` in CPython (e.g., Raspberry Pi) often indicates the library or a core dependency like `adafruit-blinka` is missing.","severity":"gotcha","affected_versions":"All CPython versions"},{"fix":"This is an active issue (as of March 2026). A known workaround for specific debugging scenarios is to force the use of the pure Python `adafruit_bus_device` implementation, if available, by renaming library directories or adjusting import paths, though this is generally not recommended for production. Refer to GitHub issue `adafruit/circuitpython#10890` for the latest status and solutions.","message":"Encountering `AttributeError: 'DebugI2C' object has no attribute 'probe'` when using `DebugI2C` with `adafruit_bus_device` can occur due to an incompatibility between `DebugI2C` and the core CPython implementation of `adafruit_bus_device`.","severity":"gotcha","affected_versions":"Recent CircuitPython versions (e.g., CircuitPython 10.x with core busio)"},{"fix":"Always use the latest Adafruit CircuitPython Library Bundle corresponding to your CircuitPython firmware version. Replace all `.mpy` libraries on your `CIRCUITPY/lib` drive with the updated versions from the bundle.","message":"CircuitPython `.mpy` files (pre-compiled modules) are version-specific. An `ValueError: Incompatible .mpy file` will occur if `adafruit_bus_device` (or a library depending on it) was compiled for a different major CircuitPython version than currently running on your board (e.g., 6.x vs 7.x).","severity":"gotcha","affected_versions":"CircuitPython versions with `.mpy` format changes (e.g., 1.x->2.x, 2.x->3.x, 6.x->7.x)"},{"fix":"Ensure `libgpiod` development libraries and Python bindings are installed on your system if you encounter issues with `SPIDevice` on Linux (e.g., `sudo apt-get install libgpiod-dev python3-libgpiod`).","message":"The `SPIDevice` class might fail to initialize if `libgpiod` bindings are absent on certain Linux systems when using direct hardware SPI, as noted in release 5.2.15.","severity":"gotcha","affected_versions":"5.2.15 and later on specific CPython platforms (e.g., some Linux SBCs)"}],"env_vars":null,"last_verified":"2026-04-16T00:00:00.000Z","next_check":"2026-07-15T00:00:00.000Z","problems":[{"fix":"For CPython, run `pip install adafruit-circuitpython-busdevice`. For CircuitPython, ensure the `adafruit_bus_device` folder from the latest library bundle is copied to `CIRCUITPY/lib`, and check if your firmware has it built-in (see warnings).","cause":"The `adafruit_bus_device` library is not installed, or the `adafruit_bus_device` folder is missing from the `lib` directory on a CircuitPython board, or there's a conflict with a built-in version.","error":"ImportError: No module named 'adafruit_bus_device.i2c_device'"},{"fix":"Always interact with I2C devices through an `I2CDevice` instance and preferably within a `with` statement. Example: `with i2c_device: i2c_device.readinto(buf)`.","cause":"You are attempting to use `I2CDevice` methods directly on a `busio.I2C` object, or outside of its context manager (`with i2c_device:` block). `I2CDevice` provides these methods and manages bus locking.","error":"AttributeError: 'I2C' object has no attribute 'readinto' (or 'write', 'writeto_then_readfrom')"},{"fix":"This points to a known compatibility issue. Consult the Adafruit CircuitPython GitHub issues (specifically `adafruit/circuitpython#10890`) for the most up-to-date workarounds or fixes. Temporarily, some users have resorted to using the pure Python `adafruit_bus_device` implementation if debugging is critical.","cause":"This specific `TypeError` has been observed when using `DebugI2C` from `adafruit_debug_i2c` with the core `adafruit_bus_device` implementation, indicating a mismatch in expected arguments for certain internal methods, possibly related to `probe` or initialization.","error":"TypeError: function takes 1 positional arguments but 2 were given"},{"fix":"Update all CircuitPython libraries on your board using the latest Adafruit CircuitPython Library Bundle that matches your board's firmware version. This ensures all `.mpy` files are compatible.","cause":"The pre-compiled Python module (`.mpy` file) for `adafruit_bus_device` (or a library that depends on it) was created with a different major version of CircuitPython than what is currently running on the board.","error":"ValueError: Incompatible .mpy file"}]}