温湿度センサー(SHT31)をESP32開発ボードから使ってみた時の記録 | そう備忘録

温湿度センサー(SHT31)をESP32開発ボードから使ってみた時の記録

SHT31

秋月電子通商で購入した高精度温湿度センサーモジュール(SHT31)を ESP32 開発ボードから制御して温湿度を取得した時の記事。

通常の温湿度センサーモジュールだと誤差が ±0.5℃ の製品が多いが、こちらの製品は ±0.3℃ とあったので試してみる事にした。

ESP32とSHT31

スペック

SHT31 の主なスペックは以下の通り。

  • センサー部分はSensirion(センシリオン)社の高精度温湿度センサ SHT31-DIS を使用している
  • 電源電圧:DC2.4V ~ 5.5V(今回は3.3Vで使用した)
  • 通信方式:I2C(最大1MHz)
  • I2Cアドレス:0x45 or 0x44
  • 温度:-40℃ ~ +125℃、±0.3℃(@0℃ ~ 90℃)
  • 湿度:0% ~ 100%、±2%(@0℃ ~ 90℃)
  • 分解能:0.015℃(温度)、0.01%(湿度)
  • 5ピン(2.54mmピッチ)
  • サイズ:12mm(縦) × 14mm(横)

外観

表面

中央上部にあるのが外気取り込み口。

L字型のピンヘッダーが付属しているので自分ではんだ付けする必要があり、ピンは向かって左から 1 ~ 5 番ピンとなっている。

SHT31モジュール 表面

裏面

ピンアサインは右から、

  • 1番ピン:VDD(電源+)
  • 2番ピン:SDA(データ出力)
  • 3番ピン:SCL(クロック入力)
  • 4番ピン:ADR(アドレス選択)※
  • 5番ピン:GND

※ I2C アドレスは ADR(4番ピン)と GND(5番ピン)がオープンで 0x45、ショートで 0x44 になる。説明書には4番ピンと5番ピンをハンダでブリッジして 0x44 にする例が載っていた。

SHT31モジュール 裏面

また説明書では裏面でのはんだ付けを推奨していた。

というのも表面の外気取り込みがフラックス等の飛散で汚染される可能性を低くした方が良いとの事だ。

用意したモノ

温湿度センサーモジュール(SHT31)以外では以下のモノを用意した。

ESP32 開発ボード

ESP32-WROOM-32 チップモジュールを内蔵した開発ボード。

ピン配置が40ピンでは無く30ピンの ESP32 DEVKIT V1のピン配置になっているので注意が必要だ。

ブレッドボード

配線テスト用のブレッドボード。

通常のブレッドボードは左右に5ピン(ABCDE-FGHIJ)づつだが、こちらのブレッドボードは左右に6ピン(ABCDEF-GHIJKL)と幅広になっている。

今回使用した ESP32開発ボードは横幅が広いので左右のピンが確保できるこちらのブレッドボードの方が使いやすい。

配線図

ESP32開発ボートと SHT31 との配線は以下の通り。

SHT31配線図
  • VCC は 3.3V に接続
  • SDA は D21、SCL は D22 に接続
  • ADR はオープンなので I2Cのアドレスは 0x45 になる
  • ADR を GND とショートさせればアドレスは 0x44

開発環境

スケッチの開発環境は以下の通り。

パソコン

DELL G7 15 7588

CPU:CoreTM i7-8750H

メモリ:16GB

OS

Windows 11 Home(64 Bit)

スケッチ開発

Arduino IDE Ver 1.8.19

事前準備

プログラム(スケッチ)の開発環境は Arduino IDE を使用する。

Arduino IDE のダウンロードとインストールは以前の記事を参照して欲しい。

秋月電子通商のホームページにArduino IDE 用のライブラリーとサンプルスケッチがあったのでインストールを行った。

AE_SHT31.zip

こちらのページから “Arduinoスケッチ” のリンクをクリックして AE_SHT31.zip をダウンロードする。

秋月電子通商からArduinoスケッチのダウンロード

Arduino IDE を起動してスケッチー>ライブラリをインクルードー>.ZIP形式のライブラリをインストール を選択して、先程ダウンロードした AE_SHT31.zip を指定する。

ライブラリーのインストール

“ライブラリが追加されました” のメッセージが表示されて \ドキュメント\Arduino\libraries\AE_SHT31 にライブラリが追加された。

  • AE_SHT31.cpp
  • AE_SHT31.h
ライブラリが追加された

スケッチ

以下、上記ライブラリに付いていたサンプルプログラムを多少手を加えて動かしてみた。

SHT31_Sample.ino

//---------------------------------------------------//
//  AKIZUKI DENSHI TSUSHO CO.,LTD.
//  Version 1.0  2017-06-20
//---------------------------------------------------//


#include <Arduino.h>
#include <Wire.h>
#include <AE_SHT31.h>


//---------------------------------------------------//
// AE-SHT31    ------     Arduino UNO                //
//                                                   //
//   V+        ------        5.0V                    //
//  SDA        ------        A4                      //
//  SCL        ------        A5                      //
//  ADR        ------       (Open = 0x45)            //
//  GND        ------        GND                     //
//---------------------------------------------------//

// SHT31のアドレスを設定
AE_SHT31 SHT31 = AE_SHT31(0x45); // Open
//AE_SHT31 SHT31 = AE_SHT31(0x44); // Short


void setup() {
  // シリアル通信を9600bpsに設定
  //Serial.begin(9600);
  Serial.begin(115200);
  // シリアルに文字を出力
  Serial.println("SHT31 Test!!");
  // SHT31をソフトリセット
  SHT31.SoftReset();
  // 内蔵ヒーター 0:OFF 1:ON
  SHT31.Heater(0);
}



void loop()
{
  // SHT31から温湿度データを取得
  SHT31.GetTempHum();
  
  Serial.println("--------------------------");
  // SHT31.Temperature() より温度データ取得
  Serial.println("Temperature ('C)");
  Serial.println(SHT31.Temperature());
  // SHT31.Humidity() より相対湿度データ取得
  Serial.println("Humidity (%)");
  Serial.println(SHT31.Humidity());
  // 待ち時間
  delay(10000);
}

補足説明

V+

サンプルプログラムのコメントでは V+ は 5.0V に接続となっているが 3.3V でも問題なく動作した。

仕様上は、DC2.4V ~ 5.5V となっている。

loop()

先程インストールしたライブラリ(AE_SHT31.cpp)の SHT31.GetTempHum() を10秒間隔でループしながら呼び出してシリアル表示している。

ライブラリの修正

上記サンプルプログラムは通常時は問題なく動作したのだが SHT31 の破損やコネクターの接触不良の際にプログラムが停止(無限ループ)に陥ってしまう事が判明した。

破損や接触不良の際には温度湿度が取得できないのは仕方が無いのだが、その際はエラーを返して後続の処理を実行するようにしたい。

インストールしたライブラリ(AE_SHT31.cpp)を確認すると while で無限ループに陥る部分があったので一部修正をしている。

尚、ライブラリのバージョンアップをすると修正した分が上書きされてしまうので AE_SHT31.cpp とAE_SHT31.h をスケッチと同じフォルダーにコピーした上で修正した。

ライブラリの include 時に、

#include "AE_SHT31.h"

の様に “(ダブルクオーテーション)で囲めばスケッチと同じフォルダーにあるライブラリが優先してインクルードされる。

修正後 AE_SHT31.cpp

元のライブラリから多少程を加えている。

//---------------------------------------------------//
//  AKIZUKI DENSHI TSUSHO CO.,LTD.
//  Version 1.1  2018-07-29
//---------------------------------------------------//


#include "AE_SHT31.h"

AE_SHT31::AE_SHT31(uint8_t i2caddr) {
  _i2caddr = i2caddr;
  Wire.begin(); 
}

void AE_SHT31::i2c_write(uint16_t data)
{
  Wire.beginTransmission(_i2caddr);
  Wire.write(data>>8); 
  Wire.write(data&0xFF);
  Wire.endTransmission();
}
int AE_SHT31::i2c_read(uint8_t data[],uint8_t num) // 2022/06/21 エラー処理の追加
// void AE_SHT31::i2c_read(uint8_t data[],uint8_t num)
{
  short int loop_cnt = 0; // 接続試行回数
  const short int MAX_LOOP = 20; // 最大試行回数

  Wire.requestFrom(_i2caddr,(uint8_t)num);
  while ((Wire.available() != num) and (loop_cnt < MAX_LOOP)){
    delay(100);
    loop_cnt++;
  }
  if (loop_cnt >= MAX_LOOP) { // MAX_LOOP回数接続出来なかった
    return 0;
  } else {
    for (int i=0; i<num; i++) {
      data[i] = Wire.read();
    }
    return 1;
  }
}

void AE_SHT31::BussReset(void)
{
  Wire.beginTransmission(_i2caddr);
  Wire.write(0x00); 
  Wire.write(0x06);
  Wire.endTransmission();
}

void AE_SHT31::SoftReset(void)
{
  i2c_write(0x30A2);
  delay(500);
  i2c_write(0x3041);
  delay(500);
}

void AE_SHT31::Heater(uint8_t onoff)
{
  if(onoff==1)i2c_write(0x306D);
  else i2c_write(0x3066);
  delay(500);
}


uint16_t AE_SHT31::ReadStatus(void) // 2022/06/21 エラー処理の追加
{
  uint8_t data[3];
  i2c_write(0xF32D);
  if (i2c_read(data,3)){
    //Serial.println(data[0]<<8|data[1], HEX);
    return (data[0]<<8|data[1]);
  } else{
    return 0;
  }
}

//void AE_SHT31::GetTempHum(void)
int AE_SHT31::GetTempHum(void) // 2022/06/21 エラー処理の追加
{
  uint8_t data[7];
    
  i2c_write(0x2400);
  delay(300);
  if (i2c_read(data,6)) {
    temperature = -45.0 + (175.0 * ((data[0] * 256.0) + data[1]) / 65535.0);
    humidity = (100.0 * ((data[3] * 256.0) + data[4])) / 65535.0;
    return 1;
  } else {
    temperature = 0;
    humidity = 0;
    return 0;
  }
}

float AE_SHT31::Temperature(void)
{
 return temperature;
}

float AE_SHT31::Humidity(void)
{
 return humidity;
}

補足説明

i2c_read

元々のロジックだと、

  while (Wire.available() != num);

の部分で SHT31が接触不良(コネクタが抜けている等)の際に無限ループに陥ってしまい後続の処理が実行されなかった。

よって最大試行回数を設定してその回数をオーバーした時は戻り値を返すように修正した。

ReadStatus

i2c_read を呼び出した後のエラー処理を追加した。

GetTempHum

i2c_read を呼び出した後のエラー処理を追加して、値が取得できなかった際には温湿度共に 0 を返すようにした。

呼び出し側

呼び出し側の SHT31_Sample.ino も多少手を入れる。

温湿度の取得の際に、

  SHT31.GetTempHum();

と戻り値を考慮していないが、以下のように戻り値を考慮する。

  if (SHT31.GetTempHum()) { }

動作結果

動作結果は以下の通り。

10秒間隔で温度と湿度がシリアルモニターに表示される。

SHT31 実行結果

以上で今回の記事は終了とする。

最後に

この記事が何処かで誰かの役に立つことを願っている。

尚、当記事中の商品へのリンクはAmazonアソシエイトへのリンクが含まれています。Amazonのアソシエイトとして、当メディアは適格販売により収入を得ていますのでご了承ください。

souichirou

やった事を忘れない為の備忘録 同じような事をやりたい人の参考になればと思ってブログにしてます。 主にレゴ、AWS(Amazon Web Services)、WordPress、Deep Learning、RaspberryPiに関するブログを書いています。 仕事では工場に協働ロボットの導入や中小企業へのAI/IoT導入のアドバイザーをやっています。 2019年7月にJDLA(一般社団法人 日本デイープラーニング協会)Deep Learning for GENERALに合格しました。 質問は記事一番下にあるコメントかメニュー上部の問い合わせからお願いします。

質問やコメントや励ましの言葉などを残す

名前、メール、サイト欄は任意です。
またメールアドレスは公開されません。