I2Cインターフェースのセンサを接続する(1)温度センサTMP102
■I2Cインターフェースの温度センサTMP102を接続
I2CインターフェースのLCDモジュールに表示する関数ができました。今回からは、I2Cインターフェースをもったデバイスを利用します。最初に、デバイスとして手元にあるI2Cインターフェースの温度センサTMP102を接続します。
●TMP102はI2Cのインターフェースをもったディジタル温度センサ
TMP102はテキサスインスツルメンツ社から発売されている温度センサで、パッケージは2mm角以下の超小型SOT563というパッケージです。手作業ではんだ付けしなくてもよいように、Sparkfunから、次に示すように10×12mmの基板に搭載し2.54mmピッチのピンヘッダを取り付けられようにしたモジュールが発売されています。
次に示すのは、手元にあるSparkfunのTMP102です。現在はこのモデルは販売終了ですが、同じ6ピンヘッダのモジュールでマウント用の穴が二つ追加され使いやすい形状になったものが後継モデルとして販売されています。形状が違うだけで同じように利用できます。
●センサ・モジュールの各ピンの機能
6ピンあるこのモジュールの各ピンの機能は、次のようになります。
- GND、V+は電源ピンで、GND(0V)とV+には3.3Vのプラス電源を接続する。実際はArduinoのGNDと3.3Vの電源を接続する
- SCLとSDAはI2Cの信号ライン。3.3V電源のそれぞれのI2C信号ラインに接続する
- ALTはアラートの出力信号。今回は利用しないので何も接続しない
- ADD0は、I2Cのスレーブ・アドレスを0x48から0x4Bのいずれかのアドレスを選択するための入力端子
●電源電圧の最大定格は3.6V
TMP102のデータシートは、TIのWebページから日本語のデータシートをダウンロードできます。動作電源範囲は1.4~3.6Vです。3.3V電源のI2C接続LCDモジュールのI2Cの信号線に接続できます。
3.3V駆動のArduinoとは直接接続できますが、5V動作のArduinoとは直接接続することはできません。
●I2Cのバスに複数のデバイスを接続する
I2Cバスはクロック信号(SCL)とデータ信号(SDA)の2本の信号線を利用して、マスタとスレーブの間でデータの受け渡しを行います。マスタから、スレーブに対して次の命令を用い、通信開始するためにスレーブのアドレスを指定して通信の確立を要求します。
Wire.beginTransmission(0x49); // 0x49はスレーブ・アドレス |
このTMP102のアドレスは、次に示すようにADD0ピンをどこへ接続するかにより、0x48~0x4Bの値を設定できます。
設定されるアドレス |
ADD0の接続先 |
---|---|
0x48 | グラウンド |
0x49 | V+ |
0x4A | SDA |
0x4B | SCL |
今回のテストでは、ADD0をV+に接続しアドレスを0x49に設定します。
●センサの内部レジスタ
TMP102には、温度レジスタ、コンフィグレーション・レジスタ、アラートの下限温度、アラートの上限温度のレジスタが用意されています。このレジスタの選択はポインタ・レジスタに0x00から0x03の値を書き込み、選択します。このポインタ・レジスタの値は一度設定されると新たに書き込まれるまで変更されません。
また、電源投入後のデフォルトの値は温度レジスタに設定されます。そのため、温度の読み取りしか行わないのであれば、電源投入後、温度を測定したデータを上位バイト・下位バイトの順番に読み取るだけで温度測定が行えます。
●温度の読み出し
温度の測定だけであれば、電源投入後このTMP102のレジスタを読み出すだけで温度を知ることができます。温度データは12ビットで、最初に読み出したバイトは上位8ビットで、次に読み出したバイトの上位4ビットが、温度データの下位4ビットになります。
そのため、
読み取った上位バイト×16 + 読み取った下位バイト/16 |
で12ビットのレジスタの内容となります。
●TMP102の各レジスタ
各レジスタは、D2からD7が0で、D0、D1が次の0から3の各レジスタのポインタを示す値を書き込むことで、それぞれのレジスタの読み書きできるようになります。
ポインタ・レジスタ | レジスタ |
---|---|
0x00 | 温度レジスタ(R/W) |
0x01 | コンフィグレーション・レジスタ(R/W) |
0x02 | 下限温度(R/W) |
0x03 | 上限温度(R/W) |
各レジスタは12ビットで、読み出しは上位、下位バイトの順番になります。
●アラート機能をもつI2Cインターフェース
このディジタル温度センサは、アラート機能をもったディジタル・センサです。このアラート機能は内部のレジスタで読み込むほかに、ALT端子に出力することもできます。このALT端子はSMBusのアラート機能に対応しています。SMBusのアラート機能は、オープン・ドレインのALT出力をSMBusのアラート・ラインに接続します。アラートが発生するとこのラインを“L”にします。
マスタは、ALTラインの“L”を検出するとアラート・コマンドをI2Cのバスに送信します。ALTをアクティブにしているデバイスは、このアラート・コマンドを検出してスレーブ・アドレスをマスタに返送します。アドレス・バイトのビット8にアラートの原因を反映させています。今回はこのアラート端子は使用していないので、接続はしていません。
TMP102のデータシートは18ページにわたり詳しい説明があり、このセンサを利用するためには大いに役立ちます。
●TMP102から温度を読み取る関数
TMP102からの温度の読み取り関数は、次のようになります。tmp_adrは0x49の今回セットしたTMP102のI2Cのスレーブ・アドレスがセットされています。
この関数get_tmp()の戻り値が単位℃の温度となります。Wire.requestFrom(tmp_adr, 2); の命令でTMP102に温度の測定データを送信してくることを要求します。次のWhile文で2バイトの受信データが受信バッファに送られてくるのを待ちます。
float get_tmp102() { Wire.requestFrom(tmp_adr, 2); while (Wire.available() < 2) { } |
整数変数tmpinに上位バイトを読み込み4ビット・シフトします。ここでは16倍しています。次は下位バイトを読み取り4ビット右シフトし、上位バイトと加算します。
int tmpin = Wire.read() * 16; tmpin = tmpin + (Wire.read() >> 4); |
I2C受信の処理を終え、受信データから温度の値に変換し、戻り値にセットします。
Wire.endTransmission(); float tmpdata = 0.0625 * tmpin; return tmpdata; } |
以上の関数を用いて、前回作成したI2C接続のLCDモジュールの温度を表示するプログラムは、次のようになります
void loop() { lcdclear(); i2cprint("temp="); // 見出しを表示 float tdata = get_tmp102(); // 測定値を変数にセット i2cprint(String(tdata)); // 変数をLCDに表示 delay(1000); } |
プログラムは次のようになります。
tmp_adrの温度センサのI2Cスレーブ・アドレスは、プログラムの初めに定義しています。
TMP102に関連する部分を以下に示します。
プログラムの実行結果は次に示すようになります。実際の温度より少し高い温度が表示されています。
5、6年も部品箱に放り込んでいたためなのかまだわかりません。新しいTMP102を取り寄せ確認してみます。また、I2Cバスのプルアップ抵抗がレベル変化モジュールとTMP102のモジュールでダブってセットされています。次回これらの問題の検討を行います。
(2016/9/6 V1.0)
<神崎康宏>
バックグラウンド
マスタとスレーブ;転送などを要求するのがマスタ、自分のアドレス宛かを待っていて、アドレスが一致したら返答するのがスレーブです。複数のマスタが存在することも考慮されています。
SMBus;PCのマザーボードで温度管理など使われるときの名称で、I2Cと同じものです。