マスタリングWireライブラリ その9 温湿度センサ SHT31 +LCD
●複数デバイスの接続
温湿度センサSHT31にI2C接続のLCD AQM1602をArduino UNOのI2Cバスにつなげます。SHT31のスレーブ・アドレスは0x44、LCDは0x3eです。プルアップ抵抗は低い値だとAQM1602がACKをLOWにできません。これは、AQM1602自体が1mA程度と消費電流が低いデバイスだからです。
プルアップ抵抗が820Ωのとき、LOWが1Vを少し超えていましたが、I2CバスのLOW規格を満たしていなくても正常に読み書きできました。しかしギリギリなので8.2kΩに変更し、LOWの電圧を十分低くしました。データ転送は400kHzです。
データ転送速度の異なるデバイスが同じI2Cバスにつながっているとき、どのような波形になるかを確かめたかったのですが、今回の実験では、どちらも約400kHzに対応していたので、特徴がわかりませんでした。ラズパイを使ったときのデータ転送速度の記事はこちらを参照ください。NXPの資料では表8に異なる速度の相互間の転送速度が掲載されています。
#include <Wire.h>
#include <i2clcd.h>
unsigned char SHT31_address = 0x44;
unsigned char AQM1602_address = 0x3e;
int Stemp;unsigned int SRH;
float temp;float RH;
byte readbuffer[6];
i2clcd lcd(0x3e, 5);
void setup() {
Wire.begin();
Wire.setClock(400000L);
Wire.beginTransmission(SHT31_address);
Wire.write(0x30);Wire.write(0xa2); //reset
Wire.endTransmission();
Serial.begin(9600);
delay(10);
Serial.println("start ");
lcd.init_lcd();
}
void loop() {
lcd.lcdclear();
Wire.beginTransmission(SHT31_address);
Wire.write(0x2c);Wire.write(0x10);
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
if (readbuffer[2] == crc8(readbuffer)) {
Stemp = readbuffer[0] << 8 | readbuffer[1];
temp = -45 + Stemp * 175.0 / 65535.0;
}
if (readbuffer[5] == crc8(readbuffer+3)) {
SRH = readbuffer[3] << 8 | readbuffer[4];
RH = 100.0 * SRH / 65535.0;
}
Serial.println(" temp= "+String(temp,1)+"'C");
Serial.println(" RH%= "+String(RH,0));
lcd.i2cprint( "temp="+String(temp,1) +"'C" );
lcd.lcdcu_set(0, 1);
lcd.i2cprint( "RH%="+String(RH,0) );
delay(300);
}
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;
}
●I2Cのやり取り
スケッチの最初はLCDの画面クリアです。ここでオシロスコープのトリガを掛けています。次に、STH31のデータの読み出しⒶです。この後、LCDへデータを送ります(temp=Ⓑ)。拡大している0x40はLCDへのデータ書き込みコマンド、0x78は小文字の't'です。2行目の先頭へカーソルを動かしてⒸ、RH%Ⓓを送ります。スケッチどおりにI2Cのやり取りが行われていることがわかります。