PR

I2Cアドレス重複を抵抗とダイオードだけで解決する方法

I2C接続の7セグディスプレイを2つ同時に使いたいって案件がありまして。 
当然同じデバイスなので、同じI2Cアドレスなんです。
で、バスセレクタ的な物を挟むしかないかなぁと思いながらググってたら、 頭良い人を発見しました。

以下、対策方法を記載します。

記事内の一部に広告を含みます。

参考にした解決法

非アクティブなデバイスのSDAライン上の抵抗はバスのプルアップとして機能するため、正確な値はデバイスの数とバスに必要なプルアップに依存します。したがって、10Kの抵抗を選択すると、3つの非アクティブデバイスが3K3プルアップを提供します。
ショットキーダイオードにより、デバイスがホストにデータを送り返すときにSDAラインを十分に低く引き下げることができます。 
<下図参照>
マイクロコントローラーのI / Oラインを使用して、アドレス指定したくないデバイスのSDAラインを強制的にハイにし、ターゲットのデバイスのI / Oラインを入力として設定することです(高インピーダンス)。これは、ターゲットデバイスのみがそのI2Cアドレスと一致し、他のデバイスは後続のデータを無視することを意味します。

 https://qastack.jp/electronics/5096/how-to-resolve-i2c-address-clashes
z7npQ.png
 https://qastack.jp/electronics/5096/how-to-resolve-i2c-address-clashes

実際にやってみるとこんな感じです。↓

IMG_1658.jpg

以下、arduinoのサンプルコード作ってみました。
こんな感じで関数作っておけば、すぐ切り替えられます。
(2個切り替えなのでbool使ってますが、2個以上ならcharとか、short int とかで)

void setI2CAddressMode(boolean mode) {
  if (mode == HIGH) {   //LOW側のSDLをVccに固定し、HIGH側をハイインピーダンスにする
    pinMode(SET_LOWER_PIN, OUTPUT);    digitalWrite(SET_LOWER_PIN, HIGH);
    pinMode(SET_UPPER_PIN, INPUT);
  } else {             //HIGH側のSDLをVccに固定し、LOW側をハイインピーダンスにする
    pinMode(SET_UPPER_PIN, OUTPUT);    digitalWrite(SET_UPPER_PIN, HIGH);
    pinMode(SET_LOWER_PIN, INPUT);
  }
}

で、作った直後に気づいたのですが、写真に写ってる7セグLED、実は裏のパッドをショートするとアドレス変えられたと言うオチ。

写真に写っている7セグLEDの>Amazonの商品ページ