SpresenseでLチカから始める (9) Wireライブラリ SHT31
●クロック・ストレッチに対応しているか
Arduino UNOのWireライブラリは特に記述はありませんが、クロック・ストレッチに対応していました。クロック・ストレッチとは、センサなどのデバイスにデータを用意してほしいと要求した後、準備に時間がかかるときSCLをLOWのまま引き延ばす機能です。センサによっては、つねにクロック・ストレッチを要求するデバイスがありますが、温湿度センサのSHT31はクロック・ストレッチの有無をコマンドで指定できます。
マスタリングWireライブラリ その8 温湿度センサ SHT31 クロック・ストレッチ
この記事で、100kHzでは温度と湿度の読み出しは正常でしたが、転送速度を400kHzにすると温度は正常だが湿度は00の値が読み出されました。クロック・ストレッチを要求するコマンドに変更すると、湿度も正しく読み出せました。
SpresenseのWireライブラリを見てみます。
●接続
温湿度センサSHT31はebayで入手しました。電源電圧は2.4~5.5Vなので、Spresenseは3.3Vで動作させ、センサのVccへは3.3Vを供給しました。SHT31のスペックはこちらの記事を参照してください。インターフェースはI2Cです。スレーブ・アドレスを設定するADDR端子は10kΩでGNDにつながっているのでデフォルトの0x44です。
Spresense | SHT31 | Spresense | |
---|---|---|---|
3.3V | 1ピン(VIN) | - | - |
GND | 2ピン(GND) | - | - |
SCL | 3ピン(SCL) | 6ピン(ADDR) | - |
SDA | 4ピン(SDA) | 5ピン(RST) | - |
●スケッチ
#include <Wire.h>
#define SHT31_address 0x44
int Stemp;int SRH;
float temp;float RH;
byte readbuffer[6];
void setup() {
Wire.begin();
// Wire.setClock(4000000L);
Serial.begin(9600);
delay(10);
Serial.println("start ");
}
void loop() {
Wire.beginTransmission(SHT31_address);
Wire.write(0x24);
Wire.write((byte)0x00);
Wire.endTransmission();
Wire.requestFrom(SHT31_address, 6);
readbuffer[0] = Wire.read();
readbuffer[1] = Wire.read();
readbuffer[2] = Wire.read(); // CRC
readbuffer[3] = Wire.read();
readbuffer[4] = Wire.read();
readbuffer[5] = Wire.read(); // CRC
// Serial.println( "read CRC-temp "+String(readbuffer[2])+" "+String(crc8(readbuffer))+" <-calculatedCRC ");
if (readbuffer[2] == crc8(readbuffer)) {
Stemp = readbuffer[0] << 8 ;
Stemp = Stemp + readbuffer[1];
temp = -45 + Stemp * 175.0 / 65535.0;
}
// Serial.println( "read CRC-RH "+String(readbuffer[5])+" "+String(crc8(readbuffer+3))+" <-calculatedCRC ");
if (readbuffer[5] == crc8(readbuffer+3)) {
SRH = readbuffer[3] << 8 ;
SRH = SRH + readbuffer[4];
RH = 100.0 * SRH / 65535.0;
}
Serial.print(" temp= " + String(temp,1) + "'C ");
Serial.println(" RH%= " + String(RH,0));
delay(1000);
}
unsigned char table[256] =
{
0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65,157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220, 35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98, 190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255, 70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7, 219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154, 101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36, 248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185, 140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205, 17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80, 175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238, 50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115, 202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139, 87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22,233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168, 116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53
};
unsigned char crc8(const unsigned char * data) {
unsigned char crc = 0xff;
crc = table[reflect(data[0]) ^ crc];
crc = table[reflect(data[1]) ^ crc];
return reflect(crc);
}
unsigned char reflect(unsigned char c) {
unsigned char r=0;
for (int i=0;i<8;i++){
if (c&(1<<i)){
r=r|(1<<(7-i));
}
}
return r;
}
●転送速度100kHz時
スケッチを実行したときのシリアルモニタの出力です。正しくデータを読み出しています。
●転送速度400kHz設定時
スケッチを実行したときのシリアルモニタの出力です。湿度の値がおかしいです。
このときの波形です。読み出した後半の3バイトがおかしいのがわかります。
クロック・ストレッチを行うようにコマンドをWire.write(0x24);Wire.write((byte)0x00);からWire.write(0x2c);Wire.write(0x10);に変更した波形です。
変化はありません。
Arduino UNOの場合です。クロック・ストレッチが行われ、湿度の値も正しく読み出しています。
今回の条件範囲では、SpresenseのWireライブラリはクロック・ストレッチに対応していないことがわかりました。SHT31自体は転送速度100kHzで利用すれば、正しくデータを読み出せます。コマンドはいろいろな条件で用意できるため、400kHzでも湿度を正常に読み出せるコマンドを見つかるかもしれません。