:mod:`i2cperipheral`
====================
.. py:module:: i2cperipheral
.. autoapi-nested-parse::
Two wire serial protocol peripheral
The `i2cperipheral` module contains classes to support an I2C peripheral.
Example emulating a peripheral with 2 addresses (read and write)::
import board
from i2cperipheral import I2CPeripheral
regs = [0] * 16
index = 0
with I2CPeripheral(board.SCL, board.SDA, (0x40, 0x41)) as device:
while True:
r = device.request()
if not r:
# Maybe do some housekeeping
continue
with r: # Closes the transfer if necessary by sending a NACK or feeding dummy bytes
if r.address == 0x40:
if not r.is_read: # Main write which is Selected read
b = r.read(1)
if not b or b[0] > 15:
break
index = b[0]
b = r.read(1)
if b:
regs[index] = b[0]
elif r.is_restart: # Combined transfer: This is the Main read message
n = r.write(bytes([regs[index]]))
#else:
# A read transfer is not supported in this example
# If the microcontroller tries, it will get 0xff byte(s) by the ctx manager (r.close())
elif r.address == 0x41:
if not r.is_read:
b = r.read(1)
if b and b[0] == 0xde:
# do something
pass
This example sets up an I2C device that can be accessed from Linux like this::
$ i2cget -y 1 0x40 0x01
0x00
$ i2cset -y 1 0x40 0x01 0xaa
$ i2cget -y 1 0x40 0x01
0xaa
.. warning::
I2CPeripheral makes use of clock stretching in order to slow down
the host.
Make sure the I2C host supports this.
Raspberry Pi in particular does not support this with its I2C hw block.
This can be worked around by using the ``i2c-gpio`` bit banging driver.
Since the RPi firmware uses the hw i2c, it's not possible to emulate a HAT eeprom.
.. raw:: html
Available on these boards
- AITHinker ESP32-C3S_Kit
- ATMegaZero ESP32-S2
- Adafruit EdgeBadge
- Adafruit Feather ESP32-S2 TFT
- Adafruit Feather ESP32S2
- Adafruit Feather M4 CAN
- Adafruit Feather M4 Express
- Adafruit FunHouse
- Adafruit Grand Central M4 Express
- Adafruit Hallowing M4 Express
- Adafruit ItsyBitsy M4 Express
- Adafruit MagTag
- Adafruit Matrix Portal M4
- Adafruit Metro ESP32S2
- Adafruit Metro M4 Airlift Lite
- Adafruit Metro M4 Express
- Adafruit Monster M4SK
- Adafruit PyGamer
- Adafruit PyPortal
- Adafruit PyPortal Pynt
- Adafruit PyPortal Titano
- Adafruit Pybadge
- Adafruit QT Py ESP32S2
- Adafruit Trellis M4 Express
- AloriumTech Evo M51
- Artisense Reference Design RD00
- BDMICRO VINA-D51
- BastWiFi
- CP32-M4
- Capable Robot Programmable USB Hub
- CircuitBrains Deluxe
- CrumpS2
- DynOSSAT-EDU-OBC
- ESP 12k NodeMCU
- Feather ESP32S2 without PSRAM
- FeatherS2
- FeatherS2 Neo
- FeatherS2 PreRelease
- Franzininho WIFI w/Wroom
- Franzininho WIFI w/Wrover
- Gravitech Cucumber M
- Gravitech Cucumber MS
- Gravitech Cucumber R
- Gravitech Cucumber RS
- HMI-DevKit-1.1
- Kaluga 1
- LILYGO TTGO T8 ESP32-S2 w/Display
- MORPHEANS MorphESP-240
- MicroDev microC3
- MicroDev microS2
- Mini SAM M4
- Oak Dev Tech PixelWing ESP32S2
- PyCubedv04
- PyCubedv04-MRAM
- PyCubedv05
- PyCubedv05-MRAM
- Robo HAT MM1 M4
- S2Mini
- S2Pico
- SAM E54 Xplained Pro
- SAM32v26
- Saola 1 w/Wroom
- Saola 1 w/Wrover
- Seeeduino Wio Terminal
- Silicognition LLC M4-Shim
- SparkFun MicroMod SAMD51 Processor
- SparkFun Thing Plus - SAMD51
- Sprite_v2b
- TG-Boards' Datalore IP M4
- Targett Module Clip w/Wroom
- Targett Module Clip w/Wrover
- The Open Book Feather
- Thingz - Galaxia
- TinyS2
- UARTLogger II
- nanoESP32-S2 w/Wrover
- nanoESP32-S2 w/Wroom
.. py:class:: I2CPeripheral(scl: microcontroller.Pin, sda: microcontroller.Pin, addresses: Sequence[int], smbus: bool = False)
Two wire serial protocol peripheral
I2C is a two-wire protocol for communicating between devices.
This implements the peripheral (sensor, secondary) side.
:param ~microcontroller.Pin scl: The clock pin
:param ~microcontroller.Pin sda: The data pin
:param addresses: The I2C addresses to respond to (how many is hw dependent).
:type addresses: list[int]
:param bool smbus: Use SMBUS timings if the hardware supports it
.. py:method:: deinit() -> None
Releases control of the underlying hardware so other classes can use it.
.. py:method:: __enter__() -> I2CPeripheral
No-op used in Context Managers.
.. py:method:: __exit__() -> None
Automatically deinitializes the hardware on context exit. See
:ref:`lifetime-and-contextmanagers` for more info.
.. py:method:: request(timeout: float = -1) -> I2CPeripheralRequest
Wait for an I2C request.
:param float timeout: Timeout in seconds. Zero means wait forever, a negative value means check once
:return: I2C Slave Request or None if timeout=-1 and there's no request
:rtype: ~i2cperipheral.I2CPeripheralRequest
.. py:class:: I2CPeripheralRequest(peripheral: I2CPeripheral, address: int, is_read: bool, is_restart: bool)
Information about an I2C transfer request
This cannot be instantiated directly, but is returned by :py:meth:`I2CPeripheral.request`.
:param peripheral: The I2CPeripheral object receiving this request
:param address: I2C address
:param is_read: True if the main peripheral is requesting data
:param is_restart: Repeated Start Condition
.. py:attribute:: address
:annotation: :int
The I2C address of the request.
.. py:attribute:: is_read
:annotation: :bool
The I2C main controller is reading from this peripheral.
.. py:attribute:: is_restart
:annotation: :bool
Is Repeated Start Condition.
.. py:method:: __enter__() -> I2CPeripheralRequest
No-op used in Context Managers.
.. py:method:: __exit__() -> None
Close the request.
.. py:method:: read(n: int = -1, ack: bool = True) -> bytearray
Read data.
If ack=False, the caller is responsible for calling :py:meth:`I2CPeripheralRequest.ack`.
:param n: Number of bytes to read (negative means all)
:param ack: Whether or not to send an ACK after the n'th byte
:return: Bytes read
.. py:method:: write(buffer: _typing.ReadableBuffer) -> int
Write the data contained in buffer.
:param ~_typing.ReadableBuffer buffer: Write out the data in this buffer
:return: Number of bytes written
.. py:method:: ack(ack: bool = True) -> None
Acknowledge or Not Acknowledge last byte received.
Use together with :py:meth:`I2CPeripheralRequest.read` ack=False.
:param ack: Whether to send an ACK or NACK