Arduinoで遊ぶページ

Arduinoで遊んだ結果を残すページです。
garretlab
温湿度センサモジュールの実験

概要

HDC1000というTexas Instrumentsの温湿度センサを使った実験です。温度センサと湿度センサの両方が入っています。

実際には、秋月電子通商で販売している、2.54mmピッチSIPモジュールを使用しました。

有機ELディスプレイに温湿度等を表示させてみました。こちらから。

Intel Edisonでも動作させてみました。こちらから。

データシート

HDC1000のデータシートを参照して、どのようなものかを調べました。

概要

HDC1000の仕様の概要は以下の通りです。

項目 内容
電源電圧(Vdd) 3V~5V
測定範囲(温度) -20℃~+85℃
精度(温度) ±0.2℃
測定範囲(湿度) 0%~100%
精度(湿度) ±3%
I2Cアドレス 0x40(0b1000000)

HDC1000は、5ピンのデバイスで各ピンの意味は以下の通りです。

ピン番号 内容
1 +V
2 SDA
3 SCL
4 RDY(データ変換終了後LOWになる)
5 GND

秋月電子通商で販売しているモジュールは、プルアップ抵抗が内蔵されています。

インタフェース

電源投入

電源投入後、最大15ミリ秒待つ必要があります。

レジスタ

HDC1000は、以下のレジスタを持っています(おそらく、全て2バイトと思います)。

ポインタ 名前 説明
0x00 温度 温度計測出力
0x01 湿度 湿度計測出力
0x02 設定 HDC1000の設定と状態
0xFB シリアルID シリアルID(最初の2バイト)
0xFC シリアルID シリアルID(真中の2バイト)
0xFD シリアルID シリアルID(最後の2バイト)
最後の1バイトは
0xFE 製造者番号 Texas InstrumentsのID(0x5449)
0xFF デバイスID HDC1000のデバイスID(0x1000)

0x03から0xFAは予約されていて、書き込んではいけません。

設定

上記に記載した設定レジスタを利用して、HDC1000の動作を設定することができます。

ビット 名前 説明
15 RST ソフトウェアリセットビット 0 通常動作
1 ソフトウェアリセット
14 Reserved 予約 0 予約ビット。0固定。
13 HEAT ヒーター(秋月電子通商の説明では、このビットは無効です) 0 ヒーター無効
1 ヒーター有効
12 MODE 計測モード 0 温度と湿度を個別に測定
1 温度と湿度を同時に測定
11 BTST バッテリー状態 0 バッテリー電圧 > 2.8V
1 バッテリー電圧 < 2.8V
10 TRES 温度測定精度 0 14ビット
1 11ビット
9:8 HRES 湿度測定精度 00 14ビット
01 11ビット
10 8ビット
7:0 Reserved 予約 0 予約ビット。0固定。

今回の実験では、以下の通り設定しました。

  • 計測モード:1(温度と湿度を同時に測定)
  • 温度測定精度:0(14ビット)
  • 湿度測定精度:00(14ビット)

上記の通りに設定レジスタに設定する値は、0b0001000000000000 = 0x1000 となります。

コマンド

設定レジスタの設定

設定レジスタに値を書き込むには、設定レジスタのポインタアドレス送信後、2バイトの設定値を1バイトずつ送信します。

温度・湿度変換の開始

温度・湿度変換を開始するには、温度レジスタのポインタアドレスを送信します。

温度・湿度とも変換精度を14ビットの場合は、温度変換に6.35ミリ秒、湿度変換に6.50ミリ秒かかるので、合計12.85ミリ秒必要です。また、変換後には、RDYピンがLOWになります。

このため、一定時間待つか、RDYピンがLOWになるのを検出する必要があります。今回の実験では、RDYピンがLOWになるのを検出するようにしました。ピンの数を減らしたい場合は一定時間待てばいいと思います。

温度・湿度の取得

変換終了後、4バイトのデータがHDC1000から送信されてきます。最初の2バイトが温度データ、その後の2バイトが湿度データです。

温度データ・湿度データから温度・湿度に変換するには、以下の式を用います。

温度[℃] = (温度データ / 216) * 165 - 40

湿度[%RH] = (湿度データ / 216) * 100

実験

HDC1000とArduinoとの接続

HDC1000とArduinoとを以下のように接続します。

HDC1000のピン Arduinoのピン番号
+V 5V
SDA SDA(A4)
SCL SCL(A5)
RDY A3
GND GND

A3・A4・A5はArduinoのアナログの3番・4番・5番です。

Arduinoプログラミング

Wireライブラリを利用して、ArduinoとHDC1000との通信を行います。

初期化

congigure()という関数を作成しました。

設定する値は、HDC1000_CONFIGURE_MSBとHDC1000_CONFIGURE_LSBというマクロに8ビットずつ分割して定義しています。

今回は、温度と湿度を同時に取得し、温度・湿度ともに14ビットの精度で取得するように設定しています。

温度・湿度の取得

getTemperatureAndHumidity()という関数を作成しました。

温度と湿度を両方取得するため、ポインタ渡しの関数としました。(C++/C言語では、複数の値をreturnで返すことはできません)。

スケッチ

温度と湿度を取得するスケッチです。最初に製造者番号(0x5449)を取得して表示しています。

注意:久しぶりに、このプログラムを動かしたら、バグを発見しました…73行目の変数の宣言が間違っており、湿度が高くなると(たぶん、50%以上くらい)、値がマイナスになってしまいました。温度も42.5℃くらいを過ぎると、マイナスになってしまうと思います。2015年5月30日以前にこのプログラムを参考にされた方は注意してください。

誤:int tData, hData; 正:unsigned int tData, hData; です。

#include <Wire.h>

#define HDC1000_ADDRESS 0x40 /* or 0b1000000 */
#define HDC1000_RDY_PIN A3   /* Data Ready Pin */

#define HDC1000_TEMPERATURE_POINTER     0x00
#define HDC1000_HUMIDITY_POINTER        0x01
#define HDC1000_CONFIGURATION_POINTER   0x02
#define HDC1000_SERIAL_ID1_POINTER      0xfb
#define HDC1000_SERIAL_ID2_POINTER      0xfc
#define HDC1000_SERIAL_ID3_POINTER      0xfd
#define HDC1000_MANUFACTURER_ID_POINTER 0xfe

#define HDC1000_CONFIGURE_MSB 0x10 /* Get both temperature and humidity */
#define HDC1000_CONFIGURE_LSB 0x00 /* 14 bit resolution */

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Wire.begin();
  pinMode(HDC1000_RDY_PIN, INPUT);

  delay(15); /* Wait for 15ms */
  configure();

  Serial.print("Manufacturer ID = 0x");
  Serial.println(getManufacturerId(), HEX);
  
  Serial.println();
}

void loop() {
  // put your main code here, to run repeatedly:
  float temperature, humidity;

  getTemperatureAndHumidity(&temperature, &humidity);
  Serial.print("Temperature = ");
  Serial.print(temperature);
  Serial.print(" degree, Humidity = ");
  Serial.print(humidity);
  Serial.println("%");

  delay(1000);
}

void configure() {
  Wire.beginTransmission(HDC1000_ADDRESS);
  Wire.write(HDC1000_CONFIGURATION_POINTER);
  Wire.write(HDC1000_CONFIGURE_MSB);
  Wire.write(HDC1000_CONFIGURE_LSB);
  Wire.endTransmission();
}

int getManufacturerId() {
  int manufacturerId;

  Wire.beginTransmission(HDC1000_ADDRESS);
  Wire.write(HDC1000_MANUFACTURER_ID_POINTER);
  Wire.endTransmission();

  Wire.requestFrom(HDC1000_ADDRESS, 2);
  while (Wire.available() < 2) {
    ;
  }

  manufacturerId = Wire.read() << 8;
  manufacturerId |= Wire.read();

  return manufacturerId;
}

void getTemperatureAndHumidity(float *temperature, float *humidity) {
  unsigned int tData, hData;

  Wire.beginTransmission(HDC1000_ADDRESS);
  Wire.write(HDC1000_TEMPERATURE_POINTER);
  Wire.endTransmission();

  while (digitalRead(HDC1000_RDY_PIN) == HIGH) {
    ;
  }

  Wire.requestFrom(HDC1000_ADDRESS, 4);
  while (Wire.available() < 4) {
    ;
  }

  tData = Wire.read() << 8;
  tData |= Wire.read();

  hData = Wire.read() << 8;
  hData |= Wire.read();

  *temperature = tData / 65536.0 * 165.0 - 40.0;
  *humidity = hData / 65536.0 * 100.0;
}

実行の様子

上記のスケッチを実行している様子です。ちょっと寒い。

バージョン

Arduino 1.5.8/Arduino Uno



メニューを表示するためにJavaScriptを有効にしてください。

Arduinoで遊ぶページ
Copyright © 2015 garretlab all rights reserved.
inserted by FC2 system