google-site-verification: google3bd66dd162ef54c7.html

I2Cアドレススキャナー (i2cdetectもどき)を作る

 久しぶりにArduinoのプログラムの話題です。

 ArduinoのIO機能を拡張する時にI2Cは欠かせません。

▼I2Cを使った回路の例(クリックで別窓に拡大)
使った回路図
 この記事の話に直接関係無いですが、この回路では3.3Vと5VのI2Cを混在させています。

▼ブレッドボードに組んだ回路
ブレッドボード
 I2Cの部品が3個あります。こういう回路を作ってうまく動かなかった場合の原因調査はかなりやっかいです。ロジックアナライザがあれば見通し良く調査出来ると思いますが、私を含めほとんどの人は持ってないでしょう。たぶん、不良原因をいろいろ想定して調べまくることになると思います。

 ところで、Raspberry Piの解説記事を読むと、I2Cのアドレスをスキャンして返事のあった(つまりデバイスが存在する)アドレスをメモリーマップで表示するi2cdetectというコマンドがあります。こういう便利なツールを作っちゃうのは、Linuxの文化なんでしょうね。

 で、これに相当するツールがArduinoに無いか探してみました。するとI2Cのアドレスをスキャンして反応があったアドレスを表示するツールはありました。でもi2cdetectのようにマップで結果を返すものは見つかりませんでした(世界中を探せばあるかも知れません)。だったら作っちゃいましょう、ということでコードを書いてみました。

/*
 I2Cアドレススキャナー
 
 I2Cのアドレスをスキャンしてデバイスが存在するアドレス
 をシリアルモニタに表示する。
 
 2014/12/23 ラジオペンチ
 http://radiopench.blog96.fc2.com/
 */

#include <Wire.h>

void setup()
{
  Wire.begin();
  Serial.begin(9600);
  Serial.println();
  Serial.println("I2C address checker"); // 開始メッセージ
}

void loop()
{
  Serial.println("     0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F");
  for(byte n = 0; n <= 0x7F; n++){    // I2Cアドレスを指定
    adrCheck(n);                      // デバイス有無を調べ結果を出力
  }
  Serial.println();                  // 1行空けて
  delay(2000);                        // 2秒待って繰り返す
}

void adrCheck(byte adr){
  byte    dummy;                      // Dummy
  if((adr & 0x0F) == 0){              // 行の先頭なら 
    print_hex2chr(adr);               // アドレスを出力
    Serial.print(":"); 
  }
  Serial.print(" ");                 // 区切り用に空白を入れる 

  if(adr < 8 || adr > 0x77){          // 予約アドレスの範囲はチェックしない
    Serial.print("xx");
  } 
  else{                               // アドレスにデバイスがあるか?
    Wire.beginTransmission(adr);
    Wire.write(&dummy, 0);
    if (Wire.endTransmission() == 0) { // 書き込みが正常終了していたら
      print_hex2chr(adr);             // そのアドレスを表示
    }
    else{
      Serial.print("--");            // 無効表示(--)
    }
  }
  if( (adr & 0x0F) == 0x0F){          // 行末なら改行
    Serial.println(); 
  }
}

void print_hex2chr(byte x){           // 16進2桁で出力
  Serial.print((x >> 4),HEX);        // 上位
  Serial.print((x & 0x0F),HEX);      // 下位
}
 このスケッチを上に示した回路の状態で動かすと、シリアルモニタに以下のような表示が出ます。

▼結果出力
出力画面
 シリアルモニタに2秒間隔でI2Cのアドレスマップを表示し続けます。このようにアドレス空間を一望できるのでとても使い易いです。と言ってもアイディアをパクッただけですが^_^;。
   なお、xx表示になっている部分はリザーブ領域なので触らないようにしています。情報源はnxpのI2C バス仕様およびユーザーマニュアル

 この出力結果では、51はRTCの8564、5Cは気圧センサーのLPS331、5Dは気圧センサーのLPS25Hが検出されています。ちなみに二つの気圧センサーはSD0ピンを電源/GNDに接続することでアドレスを変えています。
 また、2秒間隔で最新の状態を表示するので、チップや配線を外すことでそのデバイスが消える様子を直接確認することが出来ます。

 このコードはArduinoのI2Cのトラブルシューティング用に便利だと思います。今後使ってみて完成度を上げていきたいと思います。
関連記事

コメントの投稿

管理者にだけ表示を許可する

インクルードのファイル名

便利なスケッチをありがとう御座います。
macで試してみた所、#include <Wire.h>のWが小文字になっていたためファイルが見つからないとエラーになってました。修正して頂けるとありがたいです。Windowsだとファイル名の大文字小文字は区別しないのでエラーにならない様ですね。

re:インクルードのファイル名

まりすさん、今晩は。

プログラムをWebに上げる時、タグとみなされてしまう文字を安全な表現方法に変換(文字実態参照へ変換)するのを忘れてました。

修正版と差し替えましたので、現在のものをお使い下さい。

ご指摘ありがとうございました

助かりました

Arduinoオリジナルのスキャナーを使いましたがLCDのためにうまくいかなかったのですがラジオペンチさんのスキャナーはつながれたすべてのアドレスが明示されるので助かりました。
現在、温度、湿度をSDカードへタイムスタンプ付きでデータロギングを試みていますがなかなかうまくいきません。
フルセットで公開されている物はないでしょうか?

re:助かりました

そらまめさん、こんにちは。お役にたったようで嬉しいです。

タイムスタンプ付きデーターをSDカードに記録するものは、私のブログでは「気圧ロガー」の記事が近いと思います。
下記が「気圧ロガー」のカテゴリへのリンクなので、ここを読み進めると、お探しの情報(に近いもの)が出てくると思います。
http://radiopench.blog96.fc2.com/blog-category-25.html
カレンダー
10 | 2017/11 | 12
- - - 1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 - -
プロフィール

ラジオペンチ

Author:ラジオペンチ
電子工作を中心としたブログです。たまに近所(東京都稲城市)の話題など。60過ぎて視力や器用さの衰えを感じつつ日々挑戦!
コメントを入れる時にメールアドレスの記入は不要です。なお、非公開コメントは受け付けていません。

記事が気に入ったらクリックを!
最新記事
カテゴリ
最新コメント
リンク
FC2カウンター
検索フォーム
月別アーカイブ
RSSリンクの表示
QRコード
QRコード