5ドル!ラズパイ・ゼロ(Raspberry pi Zero)でIoT (23) ディジタル湿度センサ1 I2C SHT31

セラミック・タイプの湿度センサは最近実用化された

 マイコンにつないで利用できる湿度センサは各種あります。

  • DHT11、AM2322などの温湿度センサ。インターフェースは独自
  • HDC1000(後継HDC1010)やSHT31などの温湿度センサ。インターフェースはI2C
  • BME280の温湿度センサ+気圧計など複合タイプ

 ここではSHT31を使います。秋月電子通商から変換基板に実装されたモジュールを入手しました。セラミック・タイプのセンサに限らず、表面の汚れなどで性能自体に変化が出るので、はんだ付けや以後の取り扱いでは測定部が汚れないようにします。

SHT31のスペック

  • 電源電圧;2.4~5.5V
  • 通信方式;I2C(最大データ転送速度1MHz)
  • 温度;-40~+125℃(確度±0.2℃)、分解能0.015℃
  • 相対湿度;0~100%(0~90℃時)、分解能0.01%
  • データ・ビット長;16ビット
  • スレーブ・アドレス;ADDRピンをプルアップで0x45、GNDへつなぐと0x44

SHT31モジュールの構成

 モジュールには、チップ・コンデンサと三つのプルアップ抵抗が取り付けられています。ラズパイのI2Cバスにはすでにプルアップ抵抗が取り付けられているので、モジュール上のSDAとSCLのプルアップ抵抗を取り除きます。

 モジュールのデータシートによれば、SDA、SCL以外のプルアップ抵抗は、アドレスを設定するADDR端子用です。はんだゴテで温めて、ぜんぶ取り去ります。SHT31に一番近いところにあるチップ部品はコンデンサと思われるので、そのままにしておきます。

 ADDR端子はGNDにつなぎます。スレーブ・アドレスは0x44になります。ADDR端子をVddにつなぐと0x45です。モジュールのデータシートの表現ではオープンですが、プルアップしているので、Highです。ICのデータシートには、オープンにしたまま使わないように書かれています。

SHT31の動作モード

 シングル・ショット(単発測定)とピアリアディック・データ・アクイジション(周期的連続測定)の二つのモードがあります。省エネで利用したいときはシングル・ショット・モードが使われるようです。

 周期的連続測定は、最初に16ビット長のコマンドを送ると、あとは、16ビットの温度と湿度データを繰り返し送ってきます。

 コマンドは、繰り返し精度レベルおよび測定頻度によって次の表のように定義されています。

設定条件 コマンド(16進)
繰り返し精度レベル 測定頻度[mps] 上位 下位
0.5 0x20 32
24
2F
1

0x21

30
26
2D
2 0x22 36
20
2B
4 0x23 34
22
29
10 0x24 37
21
2A

 データシートでは、繰り返し精度レベルは高、測定頻度は 1mpsの条件で0x2130が掲載されているので、テスト時に利用します。

SHT31の読み出したデータ・フォーマット

 データ取り込みのコマンドは、0xe0と0x00の2バイトです。

 読み出したデータは、16ビットの温度データにCRC(チェックサム)、16ビットの湿度データにCRCという形式です。

16ビット長 温度測定値   16ビット長 相対湿度測定値  
温度測定値
(MSB部)
温度測定値
(LSB部)
チェックサム
(8ビット)
湿度測定値
(MSB部)
湿度測定値
(LSB部)
チェックサム
(8ビット)

 ラズパイのI2Cライブラリであるsmbusのブロック読み出し時に、引数として、

 「I2Cスレーブ・アドレス」、「何らかの1バイトのデータ」、「読み出すバイト数」

を指定します。けれど、SHT31のデータシートで読み出し時には、何らかの1バイトのデータが求められていません。そこでダミーの0を送っていますが、問題なく読み出せているように見えます。検証していませんが、1バイトのデータ、通常は読み出しコマンドもしくは読み出しレジスタのポインタを送るのですが、無視してくれているようです。

 また、ArduinoのWireライブラリを使ったときは、データ取り込みのコマンドを送らないでも、データが読み出せました。

 いずれも、イレギュラな読み出し方法ですから、デバイスの仕様が変更されると読めない可能性があります。

 正しく読むには、ioctlを使って、SHT31の読み出しフォーマットに合わせて6バイトを読むプログラムを作ることです。プログラムは研究中で、将来差し替えられればと思います。

 読み出した16ビットのデータは、測定データを符号なし整数型です。温度(摂氏)を求める換算式は次のとおりです。Stempは測定値です。

  T = -45 + 175 * Stemp / 2^16 - 1

 相対湿度の換算式は次のとおりです。SRHは測定値です。

  RH = 100 * SRH / 2^16 - 1

接続

 GPIOのI2Cインターフェースは、3番ピンSDA、5番ピンSCLのバス1につなぎます。

  配線が終わってからラズパイの電源を入れます。ターミナルから i2cdetect -y 1 で配線が正しいかを確認します。44がSHT31です。

プログラム

 2017年11月12日現在のOSのバージョンです。

1
2
3
4
5
6
uname -a
4.9.61
python -V
2.7.13
i2cdetect -V
3.1.2

 テスト・プログラムです。センサに対して送るコマンドは、Arduinoのときにデータの欠落の少なかった0x23,0x34にしました。温度では符号のチェックをしていますが、このデバイスでは不要です。I2C用にはsmbusライブラリを利用します。変換待ちをするsleep()用にtimeライブラリを使います。

#!/usr/bin/env python
import smbus
import time
i2c = smbus.SMBus(1)
addr=0x44

def sign16(x):
return ( -(x & 0b1000000000000000) |
(x & 0b0111111111111111) )

#main
i2c.write_byte_data(addr,0x23,0x34)
time.sleep(0.5)
while 1:
i2c.write_byte_data(addr,0xe0,0x0)
data = i2c.read_i2c_block_data(addr,0x0,6)
rawT = ((data[0]) << 8) | (data[1])
rawR = ((data[3]) << 8) | (data[4])
# print (hex(data[0]));print(hex(data[1]));print(hex(rawT));print(bin(rawT))
raw_sT = sign16(int(hex(rawT),16))
temp = -45 + raw_sT * 175 / 65535
print (str(temp) +"C")
# print (hex(data[3]));print(hex(data[4]));print(hex(rawR));print(bin(rawR))
RH = 100 * rawR / 65535
print (str(RH) +"%")
time.sleep(1)
print ("---")

 コメントを外して実行した様子です。

Webに測定データを表示

 キャラクタ表示LCDに温度と湿度を表示するのではなく、家庭内LANの別のPCから見えるようにします。

 pythonには、Webサーバがあるので実行します。その前に、テキスト・ファイルのindex.htmlをテキスト・エディタで作成します。内容は次の1行で、保存場所は /home/piです。

  <h1>SHT31 Humidity & Temperature</h1> 

 新しくターミナルを立ち上げ、次の1行を入力します。

  python -m SimpleHTTPServer 

 別のPCを用意し、WebブラウザのURLに、

  http://ラズパイのIPアドレス:8000 

を入れてアクセスすると、「SHT31 Humidity & Temperature」が表示されます。動作が確認できました。

 テスト・プログラムに、index.htmlへの温度と湿度の書き込み部分をプログラムの最後に追加しました。

   f = open('index.html','w')
f.write(str(temp) +"C "+str(RH) +"%")
f.close()

 index.htmlは1秒ごとに更新されますが、PCから見ているブラウザは、再読み込みをしないと更新されません。

 クライアントPCからアクセスしたことは、pythonのサーバを立ち上げたターミナルに表示が出ます。192.168.111.114はPCのIPアドレスです。

※プログラム・リストは、表示の関係でTabキーが無視されます。スペースに代えてあります。また、リスト中を2回クリックすると、全選択になるので、CTRL-Cでコピーし、テキスト・エディタにCTRL-Vで貼り付けて利用してください。ラズパイに持っていくと、リターン・コードなどが化けていることがあるので、一度消して、ラズパイのテキスト・エディタで改行してください。

 プログラムを仮にSHT31.pyとすると、sudo chmod 755 SHT31.py で実行権を付け、ターミナルから、python SHT31.pyで実行します。I2CやSPIのグループにpiユーザが属しているので、sudoは不要です。

※I2Cの有効化は、1-Wireの説明を参照ください。1-Wireと同じく、I2CもEnableにチェックを入れています。

※参考;http://www.pibits.net/code/raspberry-pi-sht31-sensor-example.php