温湿度センサーSHT31を使う場合の注意点(パート2)

センシリオン製温湿度センサーSHT31を使う上での注意点その2です。

待ち時間の妥当性を検証する前に、待ち時間を入れないとWriteコマンドが実行されないことを実証しておきたいと思います。

具体的には、ステータスレジスタ消去コマンド(0x3041)が実行されていないことを確かめます(図1の「45Wa 30a 41~a」部分) 。

I2C通信で失敗した例図1 Writeコマンドを連投したときのI2C波形
ステータスレジスタ消去コマンド(0x3041)を送ってもNACKを返している


● ステータスレジスタ消去コマンドを送っても、待ち時間を入れないとそのコマンドは実行されていなかったことが確認できた

SHT31のデータシートによると、ステータスレジスタの内容は図2のようになっており、電源投入時のデフォルト値は、ビット15とビット4がそれぞれ1で、他は0になります。16進で表すと0x8010。

図2 ステータスレジスタの内容

ステータスレジスタの消去コマンド(0x3041)を送ると、ビット15、11、10、4の内容が消去されて0になります(図3)。従ってステータスレジスタの各ビットは全て0、16進だと0x0000になります。

図3 ステータスレジスタ消去コマンド送った時の挙動

ステータスレジスタの内容を読むためには、マスター(Arduino)から、SHT31に対して0xF32Dを送り、その後Readコマンドでその値を読みます。出力される値は3バイトですが、最後の1バイトがチェックサムなので、最初の2バイトのみに注目すれば良いことになります(図4参照)。

図4 ステータスレジスタ値を読み出すコマンドとそのデータ構造

Arduinoのスケッチは以下の通り。

// SHT31のステータスレジスタを連続で読む

//Wireライブラリ読み込み
#include <Wire.h>
//各種変数
int SHT31_Address = 0x45;// SHT31のI2Cアドレス(7ビット)
int Status_MSB,Status_LSB,Status_CRC;//ステータスレジスタデータ

void setup() {
Wire.begin(); //Wireライブラリを使って、I2Cの有効化
Serial.begin(9600); //シリアル通信スピードを9600bpsに設定
}

void loop() {
//ソフトウエアによるデバイスリセット
Wire.beginTransmission(SHT31_Address);
Wire.write(0x30);
Wire.write(0xA2);
Wire.endTransmission();

//ステータスレジスタクリア
Wire.beginTransmission(SHT31_Address);
Wire.write(0x30);
Wire.write(0x41);
Wire.endTransmission();

//内蔵ヒーターOFF
Wire.beginTransmission(SHT31_Address);
Wire.write(0x30);
Wire.write(0x66);
Wire.endTransmission();

//ステータスレジスタ読み出しコマンドの送出
Wire.beginTransmission(SHT31_Address);
Wire.write(0xF3);
Wire.write(0x2D);
Wire.endTransmission();
delay(500);

//SHTー31に対して、I2C経由で3バイト分のデータを読むようにリクエスト
Wire.requestFrom(SHT31_Address,3);
//3バイト準備されるまで待つ
while (Wire.available()<3){
}
//読み込み開始
Status_MSB = Wire.read();
Status_LSB = Wire.read();
Status_CRC = Wire.read();
Serial.print(Status_MSB,HEX);
Serial.println(Status_LSB,HEX);

delay(1000);
}

 

上記スケッチを動作させたときのI2C波形を図5に示します。

図5 ステータスレジスタ消去コマンド(0x3041)が正常に受信されていない。

図5を観ると、ステータスレジスタ消去コマンド(0x3041)を送っているところは、「45Wa 30a 41~a」となってNACKが返ってきており、このコマンドを受け付けていないことがうかがえます。

図6は、ステータスレジスタの内容を読むコマンド(0xF32D)を送っている部分で、「45Wa F3a 2Da」と、SHT31が正常にコマンドを受け付けていることが分かります。

図6 ステータスレジスタの内容を読むコマンド(0xF32D)が正常に受信されている。

続いて、図7は、ステータスレジスタの内容を読んでいる部分です。

図7 ステータスレジスタの読み値。
デフォルト値の0x8010が読み出され、レジスタの内容が消去されていないことが分かる。

本来ならば、ステータスレジスタは消去されているので、0x0000が返ってくるはずですが、電源投入時のデフォルト値、0x8010が返ってきています。つまり、ステータスレジスタ消去コマンドを受け付けていなかったことが分かりました。

ステータスレジスタの消去を行うためには、そのコマンド、0x3041をSHT31に正常に受信させなければなりません。そこで、以下のようにスケッチを書き換えました。

void loop() {
//ソフトウエアによるデバイスリセット
Wire.beginTransmission(SHT31_Address);
Wire.write(0x30);
Wire.write(0xA2);
Wire.endTransmission();
delay(500);

//ステータスレジスタクリア
Wire.beginTransmission(SHT31_Address);
Wire.write(0x30);
Wire.write(0x41);
Wire.endTransmission();
delay(500);
(以下略)

上記の様にスケッチを変更してそのスケッチを動作させたときの波形を図8と図9に示します。

図8 ステータスレジスタ消去コマンドを送っているところ。
「45Wa 30a 41a」とACKが返ってきており、コマンドが正常に受信されていることが分かる

図9 ステータスレジスタ消去コマンドが正常に受信されたので、
ステータスレジスタの内容が消去され、その内容を読むと、0x0000となっている。

ここまでで、Writeコマンドを送るときには待ち時間を設けないと、そのコマンドをSHT31が正常に受信できないことが実証できました。

続いて、この待ち時間の妥当性を検証します。Part3に続く。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください