クラス I2C -- 2線式シリアルプロトコル

I2C は、デバイス間通信のための2線式プロトコルです。物理レベルでは、クロックラインである SCL とデータラインである SDA の2本のワイヤで構成されています。

I2C オブジェクトは特定のバスに接続して作成されます。作成時に初期化することも、後で初期化することもできます。

I2Cオブジェクトを print() で表示すると、その設定に関する情報が得られます。

ハードウェア I2C の実装は machine.I2C クラス、ソフトウェア I2C の 実装は machine.SoftI2C クラスにより利用できます。ハードウェア I2C は、システムの基盤ハードウェアサポートを使って読み書きします。たいていは効率的で高速ですが、利用できるピンに制限のある場合があります。ソフトウェア I2C はビットバンギングによって実装されており、どのピンでも利用できますが、効率的ではありません。両クラスとも利用可能なメソッドは同じで、構築方法が異なるのが大きな違いです。

注釈

I2Cバスは、その動作のために SDA と SCL の両方にプルアップ回路を必要とします。通常は 1 - 10 kOhm 程度の抵抗で SDA/SCL それぞれから Vcc に接続します。これがないと動作が不定になり、ブロッキングや予期せぬウォッチドッグ・リセット、不正な値になるなど、さまざまな問題が発生します。このプルアップ回路は MCU ボードやセンサーブレークアウトボードにすでに内蔵されていることが多いですが、そのようになっているという保証はありません。そのようなことから、トラブルが発生した場合にはプルアップ回路を確認してみてください。I2C の配線については、Adafruit の ラーニングガイド も参照してください。

使用例:

from machine import I2C

i2c = I2C(freq=400000)          # ポートに依存して 400kHz の周波数でI2Cペリフェラルを
                                # 作成します。使用するペリフェラルやピンを選択するために
                                # 追加のパラメータが必要になる場合があります

i2c.scan()                      # ペリフェラルをスキャンし、7ビットアドレスのリストを返します

i2c.writeto(42, b'123')         # 7ビットアドレス 42 のペリフェラルに3バイトを書き込みます
i2c.readfrom(42, 4)             # 7ビットアドレス 42 のペリフェラルから4バイトを読み込みます

i2c.readfrom_mem(42, 8, 3)      # スレーブ 42 のメモリから、ペリフェラルのメモリアドレス 8 で
                                #   始まる3バイトを読み込みます
i2c.writeto_mem(42, 2, b'\x10') # スレーブ 42 のメモリの、ペリフェラルのメモリアドレス 2 で
                                #   始まるところに2バイトを書き込みます

コンストラクタ

class machine.I2C(id, *, scl, sda, freq=400000)

以下のパラメータを使用して、新しい I2C オブジェクトを構築して返します。

  • id は特定の I2C ペリフェラルを識別します。指定できる値はポートやボードに依存します
  • scl は SCL に使用するピンを指定するピンオブジェクトでなければなりません。
  • sda は SDA に使用するピンを指定するピンオブジェクトです。
  • freq は SCL の最大周波数を設定する整数です。

ポートやボードによっては、このコンストラクタで指定する sclsda のデフォルト値を持っていることに注意してください。 sclsda が固定で変更できないこともあります。

class machine.SoftI2C(scl, sda, *, freq=400000, timeout=50000)

ソフトウェア I2C オブジェクトを新規に構築します。パラメータは次のとおりです:

  • scl は SCL に使用するピンを指定するピンオブジェクトでなければなりません。
  • sda は SDA に使用するピンを指定するピンオブジェクトです。
  • freq は SCL の最大周波数を設定する整数です。
  • timeout は、クロックストレッチ(clock stretching: (バス上の相手のデバイスが SCL を LOW にしている状態)を待つ最大時間(マイクロ秒)です。この時間を経過すると OSError(ETIMEDOUT) 例外が発生します。

一般的なメソッド

I2C.init(scl, sda, *, freq=400000)

与えた引数で I2C バスを初期化します。

  • scl は SCL ラインのピンオブジェクトです
  • sda は SDA ラインのピンオブジェクトです
  • freq は SCL のクロックレートです
I2C.deinit()

I2C バスをオフにします。

可用性: WiPy

I2C.scan()

0x08 から 0x77 までのすべてのI2Cアドレスをスキャンし、応答したもののリストを返します。デバイスは、アドレス(書き込みビットを含む)がバスに送信された後に SDA ラインをローに引き下げると応答します。

プリミティブ I2C 操作

以下のメソッドは、プリミティブな I2C コントローラのバス操作を実装しており、任意の I2C トランザクションを作成するために組み合わせることができます。標準的なメソッド(下記参照)では足りない制御する必要があるなら、これらのメソッドを使います。

これらのメソッドは machine.SoftI2C クラスでのみ利用できます。

I2C.start()

バス上で START 条件を生成します(SCL がハイの間に SDA がローに遷移します)。

I2C.stop()

バス上で STOP 条件を生成します(SCL がハイの間に SDA がハイに遷移します)。

I2C.readinto(buf, nack=True, /)

バスから bytes 型オブジェクトを読み込んで buf に格納します。読み取るバイト数は buf の長さ分です。ACK は最後のバイトを除くすべてを受信した後にバス上に送信されます。最後のバイトが受信した後、 nack が true の場合は NACK が送信され、それ以外の場合は ACK が送信されます(この場合、ペリフェラルは後の呼び出しでさらに bytes 型オブジェクトが読み取られると想定します)。

I2C.write(buf)

buf からバスに bytes 型オブジェクトを書き込みます。各バイトの後に ACK が受信されたことを確認し、NACK が受信された場合は残りのバイト列の送信を停止します。この関数は受信した ACK の数を返します。

標準バスオペレーション

以下のメソッドは、特定のペリフェラルデバイスをターゲットとした標準 I2C コントローラの読取り/書込み操作を実装しています。

I2C.readfrom(addr, nbytes, stop=True, /)

addr で指定されたペリフェラルから nbytes 分を読み取ります。 stop が True の場合、転送終了時に STOP 条件が生成されます。読み込んだデータを持つ bytes 型オブジェクトを返します。

I2C.readfrom_into(addr, buf, stop=True, /)

addr で指定されたペリフェラルから buf に読み込みます。読み取られるバイト数は buf の長さ分になります。 stop が True の場合、転送終了時にSTOP条件が生成されます。

このメソッドは None を返します。

I2C.writeto(addr, buf, stop=True, /)

buf から addr で指定されたペリフェラルに bytes 型オブジェクトを書き込みます。 buf からの bytes 型オブジェクトの書き込みに続いて NACK を受信した場合、残りのバイトは送信されません。もし stop が True であれば、たとえ NACK が受信されたとしても、転送の終わりに STOP 条件が生成されます。この関数は受信した ACK の数を返します。

I2C.writevto(addr, vector, stop=True, /)

vector に指定した bytes 型オブジェクトを addr に指定したペリフェラルに書き込みます。vector はバッファプロトコルを持つオブジェクトのタプルかリストであるべきです。addr が1回送信され、その後 vector 内の各オブジェクトからの bytes 型オブジェクトを順次書き込みます。 vector 内のオブジェクトは長さが0バイトであるかもしれませんが、その場合には出力しません。

vector 内のオブジェクトの1つから、あるバイトの書き込みの後に NACK が受信された場合、残りのバイトおよび残りのオブジェクトは送信されません。 stop が真の場合、たとえ NACK が受信されても、転送の終わりに STOP 条件が生成されます。この関数は受信した ACK の数を返します。

メモリ操作

一部の I2C デバイスは、読み書き可能なメモリデバイス(またはレジスタセット)として機能します。この場合、I2C トランザクションに関連付けられた2つのアドレスがあります。ペリフェラルアドレスとメモリアドレスです。以下のメソッドは、そのようなデバイスと通信するための便利な機能です。

I2C.readfrom_mem(addr, memaddr, nbytes, *, addrsize=8)

addr で指定したペリフェラルより、 memaddr で指定したメモリアドレスから nbytes 分を読み込みます。引数 addrsize はアドレスサイズをビット数で指定します。この関数は読み込んだデータを持つ bytes 型オブジェクトを返します。

I2C.readfrom_mem_into(addr, memaddr, buf, *, addrsize=8)

addr で指定したペリフェラルより、 memaddr で指定したメモリアドレスから buf に読み込みます。読み取られるバイト数は buf の長さです。引数 addrsize はアドレスサイズをビット数で指定します(ESP8266ではこの引数は認識されず、アドレスサイズは常に8ビットです)。

このメソッドは None を返します。

I2C.writeto_mem(addr, memaddr, buf, *, addrsize=8)

addr で指定したペリフェラルに、 memaddr で指定したメモリアドレスへ buf を書き込みます。引数 addrsize はアドレスサイズをビット数で指定します(ESP8266ではこの引数は認識されず、アドレスサイズは常に8ビットです)。

このメソッドは None を返します。