業界(学界というべき?)内で、このブログを見てくれている人が少しずつ増えてきてくれているようです。更新もやる気がおきます。

 

 前回はI2C通信でデジタル化されたデータを返す水圧計を紹介しました。ところで、第5回で、I2Cというものについて簡単に説明しました。センサー自体が固有のアドレスを持っているので、異なるセンサーを複数、芋づる式に同じ端子(具体的にはA4 – SDAとA5 – SCL)につないでも、センサーのほうで自分が呼ばれているのかどうか判別して応答してくれるというものです。ところがこの方式の問題として、同じアドレスを持った複数のセンサーをつなげないということがあります(アドレスの競合)。つまり、前回紹介した水圧計MS5837-30BAは、そのままでは2個以上同じマイコン(Arduino)に繋げないことになります。この問題を解決するのがI2Cマルチプレクサーです。

 

 アナログのマルチプレクサーについては第10回で紹介しました。役割としては似ています。要は交換機で、マルチプレクサーという一つのモジュールを通して複数のスレーブ(と呼んではいけないんでしたっけ)と通信できます。ここではTCA9548AというI2Cマルチプレクサーを紹介します。

 

 

写真の2つは同じものです。Adafruit社製のものと(右)、そのジェネリック製品?(左)です。価格はいろいろですが、1000円はしないことが多いです。Adafruitのウェブサイト上では$6.95とあります。見てなんとなくわかるように、ここから複数のI2Cセンサーにつなげるように、SD0, SC0, SD1, SC1, …と端子があります。そして、このマルチプレクサー自体が固有のアドレスを持っており、ArduinoのA4(SDA)、A5(SCL)につなぐのはこのマルチプレクサーだけです。

 

 説明するよりも接続図を見たほうが早いです。水圧計MS5837-30BAを4つつなぎ、それらから圧力・温度を読む例を示します。ここでのポイントとして、

・TCA9548AのI2Cアドレスはデフォルトで0x70ですが、TCA9548A上のA0-A2ピン(Arduino上のA0-A2ではないです)をVINに短絡(つまり、直結)することで、0x70-0x77の範囲で変えられるようです。Adafruitのウェブサイトを読む限り、たとえばA0がVINにつながれた状態をA0=1、つながれていない状態をA0=0とし、A1・A2も同様とすると、アドレスの最後のケタはA0+A1×2+A2×4となるようで、A0=A1=A2=1のとき、アドレスが0x77になります。

・スケッチではsensor[4]とあるように、4つのMS5837-30BAのそれぞれに対し、sensorというインスタンスを生成しています。どれかが初期化に失敗すると”Init failed!”と出ます。第26回にしたがって自作した場合、このシグナルは、作製失敗(MS5837-30BAの基板パッド部がうまくはんだ付けされていないなど)を意味することが多いです。

・特段のライブラリは使っていません。最後のほうにvoid TCA9548A()という関数がありますが、この関数だけでI2Cマルチプレクサー上の接続チャネルを切り替えています。

 

 

 



#include <Wire.h>

#include "MS5837.h"

 

MS5837 sensor[4];

const int CHNUM=4;

 

void setup()

  Serial.begin(9600);

  Wire.begin();

 

  int cnt1;

  for(cnt1=0; cnt1<CHNUM; cnt1++)

  {

    TCA9548A(cnt1);

    if(!sensor[cnt1].init())

    {

      Serial.print("Ch");Serial.print(cnt1);Serial.println(": Init failed!");Serial.println("\n\n\n");

      delay(1000);

    }

    sensor[cnt1].setModel(MS5837::MS5837_30BA);

    sensor[cnt1].setFluidDensity(997); // kg/m^3 (freshwater, 1029 for seawater)

    delay(200);

  }

}

 

void loop()

{

  /* Pressure sensor MS5837 */

  float temperat[CHNUM];

  float pres[CHNUM];

  int cnt1;

 

  for(cnt1=0;cnt1<CHNUM;cnt1++)

  {

    TCA9548A(cnt1);

    sensor[cnt1].read();

    temperat[cnt1]=sensor[cnt1].temperature();

    pres[cnt1]=0.1*sensor[cnt1].pressure(); //kPaに直す

    Serial.print("CH");Serial.print(cnt1);Serial.print(": ");Serial.print(pres[cnt1]); Serial.print(" kPa, ");

    Serial.print(temperat[cnt1]);Serial.println(" oC");

  }

 

  delay(1000);

}

 

void TCA9548A(uint8_t bus)

{

  Wire.beginTransmission(0x70);  // TCA9548A address is 0x70

  Wire.write(1 << bus);          // send byte to select bus

  Wire.endTransmission();

}