i2c通信 アドレスが重複した場合

adコンバータのads1115をi2c通信を使ってデータのやり取りを行おうと思っているのですが複数のadsとやり取りをするときにスレーブアドレスが重複してしまい苦戦しております。

初歩的なことで申し訳ないのですがどなたか解決方法を教えていただけないでしょうか。

Parents
  • ADS1115はADDRピンの接続先で4つのアドレスを選択可能になっています。
    いくつのADS1115がつながっているのでしょうか?
  • Higetakaさん回答ありがとうございます。
    5つのads1115がつながっております。
  • Higetakaさん回答ありがとうございます。
    RX65Nを使用しております。
  • RX65Nなら、I2Cが3ch使えるので、複数chにデバイスを分散させてみてはいかが?
    1chで使えるのは4つまでです。
    通信速度はFast Mode (400kbps)までは大丈夫そうです。
  • Higetakaさん回答ありがとうございます。
    同じチャンネルではやはりアドレスを変更しないといけないのでしょうか?
    初歩的なことですみません。
  • その通りです。
    以下のページは参考になりますか?
    ADS1115を搭載したブレークアウトボードでアドレスを変更したり、複数の接続をしている例が出ています。
    learn.adafruit.com/.../assembly-and-wiring
    「I2C Addressing」と「Multiple Boards」のところ。
  • Higetakaさん回答ありがとうございます。
    返信が遅くなり申し訳ございません。

    アドレスの変更の仕方はわかりました。しかし5つのADS1115を使用するのでアドレスが一つは重複してしまいます。その時に他のチャンネルを使えばいいとのことでしたがプログラム上で重複したアドレスを指定したときに2つのチャンネルが動くような気がします。その時にどのようにして差別化できるか教えていただけないでしょうか?(分かりずらくてすみません)
  • たむらさん
    「重複したアドレスを指定したときに2つのチャンネルが動く」ことは動くのではと思います、ただし正常に動作できるのは送信のみだと思います、A/Dコンバータはデータの受信が重要で1チャンネルがFF00を送信して2チャンネルが00FFを送信したときSDAはオープンコレクタでドライブして来るのでたぶん受信できるのは0000となるのではないかと思います、差別化するということではチャンネル毎に電源ON/OFFできるようにするか(OFFでハイインピーダンスになる場合)、SDAをアナログスイッチで区切る、ADDR端子を区切る等ですがBGAのICでもありシャットダウン端子も無いようですからパターン幅も細ければ難航を極めると思いますよ。
  • IKUZOさん回答ありがとうございます。

    なるほど...ちょっと難しそうですが提案された通りにやってみます。
    またわからないことがあれば質問しますのでその際はよろしくお願いします。
  • ハードウェアとソフトウェアに分けて説明します。

    ハードウェアでは、I2Cバスを2ch分(2セット)用意します。
    例としてch0に4つ、ch1に1つのデバイス(ADS1115)を接続します。
    アドレス(7bit)はch0が0x48,0x49,0x4A,0x4B、ch1は0x48にします。
    ch0とch1はI2Cバスが別のため、0x48からの応答は衝突しません。

    ソフトウェアでは、論理アドレスと物理アドレスを導入します。
    論理アドレスとして0〜4の5つでデバイスを識別するようにします。
    物理アドレスはch番号とデバイスアドレスの組です。
    I2C通信を行う関数は、論理アドレスを受け取り、物理アドレスに変換してデバイスにアクセスするようにデザインします。
    この時、I2C通信は対象となるchのみで行うようにします。
  • Higetakaさん回答ありがとうございます。

    関数をデザインするのが難しそうですがイメージはできたのでやってみます。
  • ちなみにスマートコンフィグレータのI2C通信を用いることは可能でしょうか?
Reply Children
  • 可能ですよ。スマートコンフィグレータのAPIにひと皮被せるような形でI2C関数をデザインすることになります。
  • Higetakaさん回答ありがとうございます。
    頑張ってデザインします。
  • Higetakaさん、何度もすみません。

    物理アドレスはどのようにして確認することができるのでしょうか?あとスレーブアドレスの0x48〜などは論理アドレスでしょうか?

    簡単なことで申し訳ないのですが教えていただけるとありがたいです。
  • 質問の意図がつかみづらいのですが...

    以下がイメージしていたコードの骨子です。このままではコンパイルは通りません。適宜補ってください。
    (C99スタイルで書いています)

    ---

    // 物理アドレス (ch番号, I2Cアドレス)

    typedef struct {
      uint8_t ch;
      uint8_t i2c_addr;  // 7-bit
    } PhysicalAddr_t;

    const PhysicalAddr_t phy_addrs[] = {{0, 0x48}, {0, 0x49}, {0, 0x4A}, {0, 0x4B}, {1, 0x48}};

    main()
    {
      // 5台分のAD値を順次取得 (論理アドレス 0~4)
      for (uint32_t log_addr = 0; log_addr < 5; log_addr++) {
        uint16_t value = GetAdc(log_addr);
      }
    }

    uint16_t GetAdc(uint32_t log_addr)
    {
      // 論理アドレスを物理アドレスに変換
      PhysicalAddr_t pa = phy_addrs[log_addr];

      // pa.ch番号に応じたI2C APIを使用する。
      // I2C APIにpa.i2c_addrを指定する。
    }

  • Higetakaさん、回答ありがとうございます。
    返信が遅くなり申し訳ございません。

    わざわざプログラムを作成してくださってありがとうございます。
    これを改良してI2C通信させてみたいと思います。