前回は、センシリオン社製温湿度センサーSHT31をArduinoで制御する時の注意点を紹介しました。
Part3で述べた様に、測定開始コマンドを送った直後、SHT31のデータシートに記載された測定時間分(表1参照)の待ち時間をdelay()を使って決め打ちで指定しないと、マスター(Arduino)が温湿度データを受け取れませんでした。
表1 SHT31の測定時間一覧
しかしながら、SHT31が持つ「クロックストレッチ」機能を使うと、delay()を使ってその待ち時間を決め打ちで指定する必要はありません。
I2Cの「クロックストレッチ」とは、マスターからのコマンドに対して、スレーブの処理が間に合わない時、スレーブがクロックライン(SCL)を強制的にLOWにしてマスター側からのクロック送信を待たせる機能です(図1参照)。
図1 クロックストレッチの説明(NXPセミコンダクタのI2C仕様書から引用)
スレーブ側の処理が終了すると、クロック送信が再開され、マスターはスレーブからのデータを受信できるようになります。
SHT31の場合、表2に示すコマンドを送ることでクロックストレッチを実現できます。
表2 SHT31測定コマンド一覧
例えばクロックストレッチ有効かつ繰り返し精度「高」とするには、
「0x2C06」をSHT31に送る。
早速クロックストレッチ機能を使って、SHT31で温湿度を測定してみましょう。スケッチは以下。
// SHT31から温度と湿度を読み出し、COMに表示する。
// クロックストレッチ機能を使って、測定終了を知る。//Wireライブラリ読み込み
#include <Wire.h>
//変数定義
int SHT31_Address = 0x45;// SHT31のI2Cアドレス(7ビット)
int Ta_MSB,Ta_LSB,Ta_CRC,RH_MSB,RH_LSB,RH_CRC;
float Ta, RH;
// Taは温度データ変数、RHは、相対湿度データ変数void setup()
{
Wire.begin(); //Wireライブラリを使って、I2Cの有効化
Serial.begin(9600); //シリアル通信スピードを9600bpsに設定//ソフトウエアによるデバイスリセット
Wire.beginTransmission(SHT31_Address);
Wire.write(0x30);
Wire.write(0xA2);
Wire.endTransmission();
delay(1);//ステータスレジスタクリア
Wire.beginTransmission(SHT31_Address);
Wire.write(0x30);
Wire.write(0x41);
Wire.endTransmission();
delay(1);//内部ヒーターOFF
Wire.beginTransmission(SHT31_Address);
Wire.write(0x30);
Wire.write(0x66);
Wire.endTransmission();
delay(1);}
void loop() {
//SHT31にI2C経由でコマンド送信開始
Wire.beginTransmission(SHT31_Address);
//シングルショットモードで測定
//MSB部のコマンド。0x2Cはクロック・ストレッチ有効
Wire.write(0x2C);//LSB部のコマンド。0x06は繰り返し精度「高」
//ここを0x0Dとすると、繰り返し精度「中」、
//0x10とすると、繰り返し精度「低」となる。
Wire.write(0x06);//コマンド送信終了
Wire.endTransmission();
//ここにdelay();を入れる必要はない//SHTー31に対して、I2C経由で6バイト分のデータを読むようにリクエスト
Wire.requestFrom(SHT31_Address,6);
//6バイト準備されるまで待つ
while (Wire.available()<6){
}
//読み込み開始
Ta_MSB=Wire.read();
Ta_LSB=Wire.read();
Ta_CRC=Wire.read();
RH_MSB=Wire.read();
RH_LSB=Wire.read();
RH_CRC=Wire.read();//得られたデータから、温度と湿度を計算する
//温度は、Tc=-45+175*(Ta_MSB+Ta_LSB)/(2^16-1) 単位は摂氏
Ta = -45 + 175 * ((Ta_MSB * 256.0) + Ta_LSB)/(pow(2,16)-1);Serial.print(“Temperature :”);
Serial.print(Ta,1);
Serial.println(” *C”);//湿度は、RH=100*(RH_MSB+RH_LSB)/(2^16-1) 単位は%
RH = 100 * ((RH_MSB * 256.0) + RH_LSB)/(pow(2,16)-1);Serial.print(“Relative Humidity :”);
Serial.print(RH,0);
Serial.println(” %”);
Serial.println(” “);delay(1000);
}
上記スケッチを使った時のI2C波形を図2−1,図2−2に示します。
図2−1 クロックストレッチ機能を使った時のI2C波形(測定開始コマンド送出部)
この波形を見ると、クロックストレッチ有効で繰り返し精度「高」の測定開始コマンド(0x2C06)をアドレス45のSHT31に送っていることが分かります(「45Wa 2Ca 06a」)。さらにアドレス45のSHT31からデータを読むために「45Ra」が送られています。
注目すべきは「45Ra」直後のSCLの挙動です。クロックストレッチがスタートし、SCLがLOWレベルに落ちます。このSCLがLOWレベルに落ちている期間、SHT31は温湿度データの測定を行います。
図2−2 クロックストレッチが終了し、SHT31からArduinoへ測定データが送られている様子
繰り返し精度「高」で温湿度データを測定するために必要な時間(図3−2に示した「12ms」)経過すると、自動的にSCLが再開し、測定データをArduinoに送っています(「5Da DFa OCa B9a ADa 63~a」)。
図3−2で観測されたように、測定にかかる時間が経過するとSCLが自動的に再開するので、スケッチの中にdelay()を入れる必要はありません。
参考までに、繰り返し精度「中」に設定した場合のI2C波形を図3−1,3−2に、繰り返し精度「低」に設定した場合のI2C波形を、図4−1,4−2に示します。
図3−1 繰り返し精度「中」でのI2C波形(コマンド送出部)
図3−2 繰り返し精度「中」でのI2C波形(温湿度データ受信部)
図4−1 繰り返し精度「低」でのI2C波形(コマンド送出部)
図4−2 繰り返し精度「低」でのI2C波形(温湿度データ受信部)
温湿度センサーSHT31で、クロックストレッチを有効にしたときの挙動を示しました。
クロックストレッチ機能、便利ですね。決め打ちでdelay()を入れる必要がなく、スケッチがすっきりします。他のI2Cデバイスでクロックストレッチ機能があるものは積極的にその機能を使ってみたいと思います。