Arduino Nano R4の活用 ⑩ I2C 湿度・温度センサHS3003 Wire①
Arduino Nano R4のI2Cバスに気圧センサLPS22HBをつないで、Wireライブラリを使って気圧データを読みだしました。
Arduino Nano R4の活用 ⑥ I2C LPS22HB Wire①
Arduino Nano R4の活用 ⑧ I2C LPS22HB Wire②
このI2Cバスは、センサ類のデバイスを数珠つなぎにできます。今回、ルネサスの湿度・温度センサHS3003をつなぎます。
(※)HS3003は執筆している2025年で製造中止が決まっています。流通在庫はあると思われます。
●環境
- Arduino IDE;2.3.5
- Windows11;24H2
- Arduino Nano R4 1.5.1 PCはマザーボードのUSBポートから直接つなぐ。
●接続
Arduino Nano R4のQWIICコネクタにつなぎます。単独でもよいのですが、ここではLPS22HBボードのコネクタにつなぎます。どちらのボードも二つのコネクタを搭載しています。
scannerで、デバイスを検索します。
(引用)How to Scan and Detect I2C Addresses
// SPDX-FileCopyrightText: 2023 Carter Nelson for Adafruit Industries
//
// SPDX-License-Identifier: MIT
// --------------------------------------
// i2c_scanner
//
// Modified from https://playground.arduino.cc/Main/I2cScanner/
// --------------------------------------
#include <Wire.h>
// Set I2C bus to use: Wire, Wire1, etc.
#define WIRE Wire1
void setup() {
WIRE.begin();
Serial.begin(9600);
while (!Serial)
delay(10);
Serial.println("\nI2C Scanner");
}
void loop() {
byte error, address;
int nDevices;
Serial.println("Scanning...");
nDevices = 0;
for(address = 1; address < 127; address++ )
{
// The i2c_scanner uses the return value of
// the Write.endTransmisstion to see if
// a device did acknowledge to the address.
WIRE.beginTransmission(address);
error = WIRE.endTransmission();
if (error == 0)
{
Serial.print("I2C device found at address 0x");
if (address<16)
Serial.print("0");
Serial.print(address,HEX);
Serial.println(" !");
nDevices++;
}
else if (error==4)
{
Serial.print("Unknown error at address 0x");
if (address<16)
Serial.print("0");
Serial.println(address,HEX);
}
}
if (nDevices == 0)
Serial.println("No I2C devices found\n");
else
Serial.println("done\n");
delay(5000); // wait 5 seconds for next scan
}
実行すると、0x5dはLPS22HBで、0x44はHS3003です。
●湿度・温度センサHS3003のボード
利用したHS3003のボードはArduinoの製品で、スイッチサイエンスから入手しました。
●湿度・温度センサHS3003の主なスペック
- 湿度測定範囲 0~100% RH
- 確度 ±1.5% RH, typical (HS3x01,10~90% RH, 25℃)
- 解像度 0.01% RH, typical (セットできるのは8, 10, 12, 14ビット)
- レスポンス 1秒
- 温度測定範囲 -40~125℃
- 確度 ±0.25℃(0~70°C )
- 解像度 14ビット;0.015℃
- レスポンス 2秒
- I2Cバス 20~400kHz
- スレーブ・アドレス 0x44
●Arduino Plug and Make Kit
このセンサ・ボードは単独でも入手できますが、Arduino Plug and Make Kitを購入しました。
Arduino Plug and Make Kit スイッチサイエンスのチュートリアル
専用のライブラリ Arduino_Modulino
専用の解説ページ Plug and Make Kit
Arduino_Modulinoライブラリのソースには、Hexダンプが書かれていて、C言語のソースは読めません。
●HS3003のコマンド
ArduinoのライブラリはNano 33 BLE Sense R2用があります。
ここではWireライブラリで湿度と温度を読みだします。
電源ON時にはスリープ・モードになっています。
スリープから測定に移行するためには、MRコマンドを送ります。これはスレーブ・アドレス7ビットの後に0を送ることで実現します。つまり、何かのコマンドを書き込めば変換を開始し、14ビットのデータが出力レジスタに入ります。
新しいデータを読み取るには14ビットのときに34msかかります。そのため、新しいデータかどうかを確認する必要があります。湿度データの上位2ビットがステータス・ビットになっており、'01'では前のデータで、'00'では新しくなったデータです。ただし、パワー・オン・リセット直後に'01'が返りますが、無効なデータです。
測定データの読み取りは、次のようにします。2バイトのデータは、上位、下位の順番で送られます。
スレーブ・アドレスをリードで送ると、湿度が2バイト送られてきます。先頭の2バイトはステータス・ビットなので捨て去り、14ビット・データを得ます。
続いて温度データが2バイト送られてきます。末尾2ビットは不要ビットなのでマスクして、14ビットのデータを得ます。
読みだしたデータは、次の変換式で、湿度と温度になります。
湿度は、(14ビット・データ /( 2^14 - 1))* 100
温度は、(14ビット・データ / (2^14 - 1))* 165 - 40
●スケッチ
ステータスのチェックでは、いつも00だったので、古いデータである01になったときの処理を記述していません。
#include <Wire.h>
const uint8_t HS3003_address = 0x44;
uint8_t result[4];
float humidity, temperature;
uint8_t status;
void setup() {
Wire1.begin();
Serial.begin(9600);
delay(1000);
Serial.println("\nstart ");
}
void loop() {
Wire1.beginTransmission(HS3003_address);
Wire1.write((uint8_t)0); // dummy
Wire1.endTransmission();
delay(35); // 14bit
status = readSensor();
Serial.print(status);Serial.print(" ");
// need SENSOR_BUSY delay
Serial.print(result[0],HEX);Serial.print(" ");
Serial.print(result[1],HEX);Serial.print(" ;");
Serial.print(humidity);
Serial.print("\t\t\t");
Serial.print(result[2],HEX);Serial.print(" ");
Serial.print(result[3],HEX);Serial.print(" ;");
Serial.println(temperature);
delay(3000);
}
uint8_t readSensor(){
Wire1.requestFrom(HS3003_address, 4);
result[0] = Wire1.read();
result[1] = Wire1.read();
uint16_t raw_humidity = ((result[0] & 0x3f) << 8 | result[1]);
humidity = (raw_humidity / (pow(2,14) - 1)) * 100.0;
result[2] = Wire1.read();
result[3] = Wire1.read();
uint16_t raw_temperature = ((result[2]) << 8 | result[3] & 0xFC) >> 2;
temperature = (raw_temperature / (pow(2,14) - 1)) * 165.0 - 40;
return (result[0] >> 6);
}
実行している様子です。左が湿度、右が温度です。