M5Stackで始めるセンサ・インターフェーシング (2) ディジタル温湿度センサSHT35を利用
筆者が東京に出てきた1974年、通勤電車の多くに冷房は入っていませんでした。その前の世代、通勤電車は色分けされてなかったので、飲み会の後に東京駅や新宿などで乗り替えで間違えることが多かったようです。1974年当時、緑色の山手線の車両にはすでに冷房が入っていたと思います。暖房は、速度可変などのために抵抗器が使われ、その排熱を利用していたようで、寒い思いをした記憶はありません。サイリスタの制御に代わった後も、ヒータが座席の下に入っていました。
地下鉄や黄色の総武線の車両に冷房が入って、東京近郊の通勤は快適になりました。
通勤電車は頻繁にドアが開閉するので、温度管理をしていても、ほとんど意味がないような気がしますが、ポリマを利用した湿度計がある時期に車両に設置されました。それまで、振動の多い場所などで利用できる湿度計はありませんでした。その湿度計がどのように活用されているかは不明ですが、この20年の間に、コンパクトなセンサで湿度を正確に測れるようになりました。
<ポリマ湿度センサ部分。ebayで購入>
●相対湿度
通常、湿度は相対湿度を指します。温度によって大きく変わる値です。そのため、湿度センサは温度による補正を行うので、温度の値も出力できます。
相対湿度は、空気中に存在できる水蒸気の最大値に対して何%の水分が存在するかを表しています。温度が上がると、空気中に存在できる水蒸気の最大値が増加するので、水分の絶対量が同じであれば、相対的に湿度の値は下がります。
●温湿度センサ
本Webサイトでもいくつかの温湿度センサを扱っています。
型名 | 相対湿度の確度 | センサの材質 | 記事 | そのほかの測定項目 | 温度の確度 | インターフェース | 電源電圧[V] |
---|---|---|---|---|---|---|---|
DHT11 | ±5%RH | ポリマ | MKR ZERO ラズパイ |
温度 | ±2℃ | 独自シリアル | 3.3~5.5 |
AM2322 | ±2%RH | ポリマ | ラズパイ | 温度 | ±2℃ | I2C | 3.1~5.5 |
SHT-35 | ±1.5%RH | ポリマ。静電容量式 | MKR ZERO | 温度 | ±0.1°C | I2C | 2.4~5.5 |
SHT-31 | ±2%RH | ポリマ。 静電容量式 | ラズパイ Arduino Micro:bit Trinket M0 |
温度 | ±0.2°C | I2C | 2.4~5.5 |
BME280 | ±3%RH | MEMS? | Arduino ラズパイ |
温度、気圧 | ±0.5°C | I2C、SPI | 1.71~3.6 |
SHT-35とSHT-31は、同じデータシートにレジスタやI2Cの通信手順、温度や湿度の変換式が書かれているので、スケッチはまったく同じです。
ここでは、比較的新しいSHT-35(Seeed、Groveコネクタ付き)を利用します。
●SHT-35のライブラリを利用
ライブラリ管理の検索欄にSHT-35と入れると、一つ見つかります。Seeed_SHT35-master.zipを利用する事例は、こちらで解説しました。ここでは、ClosedCube SHT31Dをインストールしました。
SHT-35/31のスレーブ・アドレスは0x45と0x44のどちらかです。最初にI2CScannerで確認します。0x45に見つけました。
スケッチ例->ClosedCube SHT31D->periodicmodeを読み込み、sht3xd.begin(0x44)を0x45に変更し、コンパイル、実行します。温度が高く、湿度が低いですね。
singleshotmodeを動かします。こちらの測定値は妥当な値が出ています。
ClockStrechというのは、I2Cの通信時、スレーブ・デバイスのセンサが、変換要求を受けて最新データを用意するのに時間がかかるとき、SCL信号をLOW状態のまま維持し、データが用意できたらHIGHに戻すという通信手順です。
●LCDディスプレイを活用
前回の距離センサVL53L1Xと同様に、LCDディスプレイに温度と湿度を表示します。
/*
This is example for SHT3X-DIS Digital Humidity & Temperature Sensors Arduino Library
ClosedCube SHT31-D [Digital I2C] Humidity and Temperature Sensor Breakout
Initial Date: 06-Oct-2015
Last Updated: 12-Oct-2016
MIT License
*/
#include <Wire.h>
#include "ClosedCube_SHT31D.h"
#include <M5Stack.h>
ClosedCube_SHT31D sht3xd;
void setup()
{
Wire.begin();
Serial.begin(9600);
Serial.println("ClosedCube SHT3X-D Single Shot Mode Example");
Serial.println("supports SHT30-D, SHT31-D and SHT35-D");
sht3xd.begin(0x45); // I2C address: 0x44 or 0x45
Serial.print("Serial #");
Serial.println(sht3xd.readSerialNumber());
M5.begin();
M5.Lcd.setCursor(10, 10);
M5.Lcd.print("SHT-35 start");
}
void loop()
{
printResult("ClockStrech Mode", sht3xd.readTempAndHumidity(SHT3XD_REPEATABILITY_LOW, SHT3XD_MODE_CLOCK_STRETCH, 50));
delay(250);
printResult("Pooling Mode", sht3xd.readTempAndHumidity(SHT3XD_REPEATABILITY_HIGH, SHT3XD_MODE_POLLING, 50));
delay(250);
}
void printResult(String text, SHT31D result) {
if (result.error == SHT3XD_NO_ERROR) {
Serial.print(text);
Serial.print(": T=");
float temp = result.t;
int rh = result.rh;
Serial.print(temp,1);
Serial.print("C, RH=");
Serial.print(rh);
Serial.println("%");
M5.Lcd.setCursor(10, 20);
M5.Lcd.print(temp);
M5.Lcd.setCursor(50, 20);
M5.Lcd.print(rh);
} else {
Serial.print(text);
Serial.print(": [ERROR] Code #");
Serial.println(result.error);
}
delay(2000);
}
実行中の様子です。文字、小さいですね。
●グラフィック描画機能を使う
M5StackのLCDディスプレイは、四角形や直線を描画できるコマンドをもっています。温度計を描画しました。
setup()内で外形を描き、loop()内で真ん中の棒を温度に合わせて動かしています。室温付近でほぼ正しく動作することを確認しました。
/*
This is example for SHT3X-DIS Digital Humidity & Temperature Sensors Arduino Library
ClosedCube SHT31-D [Digital I2C] Humidity and Temperature Sensor Breakout
Initial Date: 06-Oct-2015
Last Updated: 12-Oct-2016
MIT License
*/
#include <Wire.h>
#include "ClosedCube_SHT31D.h"
#include <M5Stack.h>
ClosedCube_SHT31D sht3xd;
void setup()
{
Wire.begin();
Serial.begin(9600);
Serial.println("ClosedCube SHT3X-D Single Shot Mode Example");
Serial.println("supports SHT30-D, SHT31-D and SHT35-D");
sht3xd.begin(0x45); // I2C address: 0x44 or 0x45
Serial.print("Serial #");
Serial.println(sht3xd.readSerialNumber());
M5.begin();
M5.Lcd.setCursor(10, 10);
M5.Lcd.print("SHT-35 start");
M5.Lcd.fillRoundRect(80, 180, 60, 60, 32, WHITE);
M5.Lcd.fillRoundRect(96, 60, 30, 150, 12, WHITE);
M5.Lcd.fillRoundRect(85, 186, 50, 50, 24, RED);
M5.Lcd.drawRect(100, 70, 20, 118, BLUE);
}
void loop()
{
printResult("ClockStrech Mode", sht3xd.readTempAndHumidity(SHT3XD_REPEATABILITY_LOW, SHT3XD_MODE_CLOCK_STRETCH, 50));
delay(250);
printResult("Pooling Mode", sht3xd.readTempAndHumidity(SHT3XD_REPEATABILITY_HIGH, SHT3XD_MODE_POLLING, 50));
delay(250);
}
void printResult(String text, SHT31D result) {
if (result.error == SHT3XD_NO_ERROR) {
Serial.print(text);
Serial.print(": T=");
float temp = result.t;
int rh = result.rh;
Serial.print(temp,1);
Serial.print("C, RH=");
Serial.print(rh);
Serial.println("%");
M5.Lcd.setCursor(10, 20);
M5.Lcd.print(temp);
M5.Lcd.setCursor(50, 20);
M5.Lcd.print(rh);
int tempY = 50-temp;
M5.Lcd.fillRoundRect(101, 70, 18, 140, 4, RED);
M5.Lcd.fillRoundRect(101, 71, 18, 100-temp, 4, WHITE);
M5.Lcd.fillRoundRect(60, 65, 34, 120, 0, BLACK);
M5.Lcd.setCursor(60, 160-temp);
M5.Lcd.print(temp);
} else {
Serial.print(text);
Serial.print(": [ERROR] Code #");
Serial.println(result.error);
}
delay(2000);
}
実行している様子です。色は、REDやWHITEの原色だけが指定できるようです。オレンジ色に見えているはREDの指定です。肉眼で見た目は赤色です。
湿度計も作りました。LCDライブラリには円を描く関数などはないので、動きのある絵にできませんでした。水滴の中央付近に湿度を表示しただけです。円は四角形の角を大きめにとることで実現しています。
void setup()
{
Wire.begin();
Serial.begin(9600);
Serial.println("ClosedCube SHT3X-D Single Shot Mode Example");
Serial.println("supports SHT30-D, SHT31-D and SHT35-D");
sht3xd.begin(0x45); // I2C address: 0x44 or 0x45
Serial.print("Serial #");
Serial.println(sht3xd.readSerialNumber());
M5.begin();
M5.Lcd.setCursor(10, 10);
M5.Lcd.print("SHT-35 start");
M5.Lcd.fillRoundRect(80, 180, 60, 60, 32, WHITE);
M5.Lcd.fillRoundRect(96, 60, 30, 150, 12, WHITE);
M5.Lcd.fillRoundRect(85, 186, 50, 50, 24, RED);
M5.Lcd.drawRect(100, 70, 20, 118, BLUE);
M5.Lcd.fillRoundRect(180, 130, 100, 100, 48, BLUE);
M5.Lcd.fillTriangle(228, 100, 182, 164, 275, 160, BLUE);
M5.Lcd.fillTriangle(228, 90, 210, 144, 255, 144, BLUE);
}
void loop()
{
printResult("ClockStrech Mode", sht3xd.readTempAndHumidity(SHT3XD_REPEATABILITY_LOW, SHT3XD_MODE_CLOCK_STRETCH, 50));
delay(250);
printResult("Pooling Mode", sht3xd.readTempAndHumidity(SHT3XD_REPEATABILITY_HIGH, SHT3XD_MODE_POLLING, 50));
delay(250);
}
void printResult(String text, SHT31D result) {
if (result.error == SHT3XD_NO_ERROR) {
Serial.print(text);
Serial.print(": T=");
float temp = result.t;
int rh = result.rh;
Serial.print(temp,1);
Serial.print("C, RH=");
Serial.print(rh);
Serial.println("%");
M5.Lcd.setCursor(10, 20);
M5.Lcd.print(temp);
M5.Lcd.setCursor(50, 20);
M5.Lcd.print(rh);
int tempY = 50-temp;
M5.Lcd.fillRoundRect(101, 70, 18, 140, 4, RED);
M5.Lcd.fillRoundRect(101, 71, 18, 100-temp, 4, WHITE);
M5.Lcd.fillRoundRect(60, 65, 34, 120, 0, BLACK);
M5.Lcd.setCursor(60, 160-temp);
M5.Lcd.print(temp);
M5.Lcd.setCursor(218, 168);
M5.Lcd.print(rh);
M5.Lcd.setCursor(232, 168);
M5.Lcd.print("%RH");
} else {
Serial.print(text);
Serial.print(": [ERROR] Code #");
Serial.println(result.error);
}
delay(2000);
}
(※)現在の開発環境では、LCDディスプレイへ文字を出すと、シリアルモニタの文字が文字化けしています。