2010年2月21日日曜日

Arduinoで湿度・温度を計測する SHT-71使用

この投稿は、建築発明工作ゼミ2009 『温・湿度センサ SHT-71』をもとに、新しく書き直したものです。

図1 温度・湿度センサ SHT-71 データシート

SHTシリーズのセンサをArduinoに接続し、温度と湿度を両方計測してみます。

センサはSHT-71を使いました。SHTシリーズではSHT-11が有名なのですが、小型の基盤にセットしなければ使いづらそうなので、ちょっと値段は高くなりますが4本のピンが並んでいるこちらを使う事にします。
センサとしての性能は全く同じですが、SHT-11とはピンの配置が異なるので注意が必要です。

このセンサの利点はまずその小ささです。センサ部分が4mm×5mmしかありません。
あと、Arduinoへの入力はデジタルインピンを使うので貴重なアナログインピンを節約できます。この小ささで正確な温度と湿度が計測できます。

まずここからライブラリをダウンロードします。 解凍後、「sht1x」というフォルダを以下に設置します。

(Macの場合)
○○○(ユーザディレクトリ)/書類/Arduino/library/

これでライブラリのインストールは完了です。


回路図
VDDからプルアップ抵抗をSCKとDATAに挟まないと正しく計測できません。
SHT-11センサは、参考リンク先のエレキジャックさんがとても詳しく書かれているので、大変参考になります。
SCKピンとDATAピンを差し込む箇所はデジタル2ピン、デジタルD3ピンと決まっているらしいです。
ダウンロードしたライブラリの sht1x_hw.h というファイルのline 26,27 に以下のような記述があります。

# define SHT1X_CLOCK_LINE PD2
# define SHT1X_DATA_LINE PD3

Arduino Duemilanove 168(Atmega168)の場合、'PD2'と'PD3'という定数は読み込まないらしいので、
これを適当なエディタで開き、以下のように書き換えて保存します。

# define SHT1X_CLOCK_LINE PORTD2
# define SHT1X_DATA_LINE PORTD3

これで、Arduino (Atmega328)以降でも読み込むようになります。
ちなみにArduino MEGAの場合、

SCKピン -> デジタル19ピン
DATAピン -> デジタル18ピン

に指す必要があります。

Board sht1x_hw.h line 26,27の記述 ピン番号
Arduino Duemilanove 168 # define SHT1X_CLOCK_LINE PD2
# define SHT1X_DATA_LINE PD3
SCK -> デジタル2ピン
DATA -> デジタル3ピン
Arduino Duemilanove 328 # define SHT1X_CLOCK_LINE PORTD2
# define SHT1X_DATA_LINE PORTD3
SCK -> デジタル2ピン
DATA -> デジタル3ピン
Arduino MEGA # define SHT1X_CLOCK_LINE PORTD2
# define SHT1X_DATA_LINE PORTD3
SCK -> デジタル19ピン
DATA -> デジタル18ピン


SHT-71センサを導線にハンダ付けし、防水用にエキポシ樹脂で固めます。


スケッチ
#include <sht1x.h>
#include <sht1x_hw.h>

void setup()
{
  int timeout = 0;

  Serial.begin(9600);
  delay(11);
  sht1x_init();

  if (sht1x_read_humidity() < 0) {
    Serial.println("soft reset");
    sht1x_reset();
  }
}

void loop()
{
  unsigned int h = sht1x_read_humidity();
  unsigned int t = sht1x_read_temp();

  while (millis() % 1000);

  Serial.print("hum : ");
  Serial.print(-4.0 + 0.0405 * h - 2.8e-6 * h * h, DEC);
  Serial.print(" ");
  Serial.print("temp : ");
  Serial.println(-40.0 + 0.01 * t, DEC);
}


スケッチを実行し、Arduino IDE のシリアルモニタで表示させます。左の値が湿度、右が温度になっています。

追記
Arduino Duemilanove 328だと正常に動かないみたいです。
Atmega168に乗せ変えて、ボードの指定をAtmega168に設定すると動きます。
謎。

Arduino 328、Arduino MEGAでの動かし方は、KOUSAKUさんのアドバイスによりできるようになりました。ありがとうございます。
上記参照。

19 コメント:

Lucellino さんのコメント...

windowsでsht1xライブラリを入れたのですが、上手く動きませんでした。
どうやら、macとwindows間で文字化けしてライブラリのエラーが生じるようです。
windows版のライブラリもないかな。

Daisuke En さんのコメント...

ライブラリの文字コードがUNICODE(UTF-8)でないと動かないかもしれません。
http://mkmqwerty.hp.infoseek.co.jp/programing/tips/tips_string_convert.html
僕もwindowsで使ったスケッチをMacで開いたら文字化けしていて、アップするとエラーが出た時がありました。

ちょっと面倒かもしれませんが、ダウンロードしたsht1xライブラリ内の三つのファイル
sht1x.c,sht1x.h,sht1x_hw.hを適当なエディタで開き、文字コードにUTF-8を指定して保存し直してみてください。「BOM」を付けるか付けないかの指定があったら「付けない」、で。もちろん作業前にバックアップをとっておいてください。
それでもういちどトライしてみてもらえますか。

Lucellino さんのコメント...

エディタで開いて、文字コードをUTF-8にしたのですが、うまくいきませんでした…。UTF-8じゃないかもしれません。うーん、何が悪いのか…。

Daisuke En さんのコメント...

IDEの下部のシリアルモニタにはどんなエラーメッセージが出ていますか?
エラーメッセージをアップしてもらえますか。

それと、エラーメッセージそのものをググってみると、結構検索されたりします。

それと、これは関係ないかもしれませんが、僕の持っているArduino Duimilanove はAtmega168で、それだと動くんです。しかし、スイッチサイエンスで買ったAtmega328に交換して動かそうとするとなぜかエラーがでて動きませんでした。しかたなく、168に戻した記憶があります。

もしかしたら328自体に対応していないのかもしれません。

Daisuke En さんのコメント...

追記
試しに、windowsXP環境で、Duemilanove にAtmega168を乗せ変えて上記のスケッチをアップしてみると動きました。湿度、温度ともにシリアルモニタに表示されます。
なぜでしょう…。
ブートローダーのせい?

Lucellino さんのコメント...

いろいろすいません。アップロードまでたどり着いていないのですが、コンパイルが上手くいかず、下記メッセージが表示されます。

D:\91_App\arduino-0018\libraries\sht1x\._sht1x.c:1: error: stray '\2' in program

unicodeに関連するエラーみたいなのですが…。
ちなみに、エディターは「Emeditor」で保存しなおしたのですが上手くいきませんでした。

さらに、._shix.cファイル内容です。
' 'が怪しそうですね。

Mac OS X 2 R TEXT

Lucellino さんのコメント...

._shix.cファイルのないようですが、文字で表現されないところが消えてしまいました。
ペーストすると変な記号で表示されたのですが、アップしたら消えてしまいました。

Daisuke En さんのコメント...

使った事がないんですが、

http://www.arduino.cc/playground/Main/InterfacingWithHardware#Input

ページの

Environmental>Temperature 項目に、

Extremely easy-to-use Arduino library for the Sensirion SHT1x temperature and humidity sensor, which also calculates the dew point (sensor available at nuelectronics).

といって、Sensironというライブラリがあります。
これはどうでしょうか。

mirrorn さんのコメント...

「sht1x」ライブラリの方ですが:
「sht1x_hw.h」内の26~27行目の

# define SHT1X_CLOCK_LINE PD2
# define SHT1X_DATA_LINE PD3

を、

# define SHT1X_CLOCK_LINE PORTD2
# define SHT1X_DATA_LINE PORTD3

に書き換えてもだめでしょうか?
そのセンサーを持っていないので確認はできないのですが。

mirrorn さんのコメント...
このコメントは投稿者によって削除されました。
Daisuke En さんのコメント...

Atmega328に乗せ変えて、

# define SHT1X_CLOCK_LINE PORTD2
# define SHT1X_DATA_LINE PORTD3

に書き換えで動きました!
Windowsでは未確認ですが、多分いけるのではないでしょうか。

mirrorn さんのコメント...

大丈夫でしたか。よかったです。
PD2やPD3(ATmegaのピン番号)は168では読み取ってくれるようですが、なぜか328だとだめみたいですね。
PD2=PORTD2=0x02、PD3=PORTD3=0x03ということになりますね。

mirrorn さんのコメント...

Mega上でも動かないようですが、
2番ピンをMegaの19番ピンへ
3番ピンをMegaの18番ピンへ
つないでもだめでしょうか?
Megaのピン配置図が、
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1245229578
ここにのっています。

Daisuke En さんのコメント...

>Mega上でも動かないようですが、
>2番ピンをMegaの19番ピンへ
>3番ピンをMegaの18番ピンへ
>つないでもだめでしょうか?

すごい、動きました。
SHTシリーズをMEGAで使えれば、いろいろ可能性がつながります。ありがとうございます。

mirrorn さんのコメント...

Sensironライブラリの方がピン指定できるので使いやすいかもしれませんが、サンプルをコンパイルしてみたらエラーがでました。
サンプル内の

#define dataPin 2
#define clockPin 3
...
Sensirion tempSensor = Sensirion(dataPin, clockPin);



#define DATAPIN 2
#define CLOCKPIN 3
...
Sensirion tempSensor = Sensirion(DATAPIN, CLOCKPIN);

などと書き換える必要がありそうです。
dataPinやclockPinだと、ArduinoのC言語ファイル内にも同じ変数名が使われているためかエラーがでてしまいます。
たぶん、上記のようにすべて大文字にする(あるいは異なる変数名)などすれば大丈夫なはずです。
それから、Megaとイーサネットシールドについてはこっちに書いておきました。

Daisuke En さんのコメント...

Arduino 328、Arduino MEGAともにSensirionライブラリでも動作確認できました。

ただ、Arduino MEGA の場合、指定したピン番号

#define DATAPIN 3
#define CLOCKPIN 2

とした場合、shtx1ライブラリと異なり、そのまま

DATAピン デジタル3ピン
CLOCKピン デジタル2ピン

とやる必要がありました。

Sensirionライブラリの方が使いやすそうですね。
デジタルピンで好きにピンを指定できれば、MEGAの場合、かなりの数のSHTセンサを接続できることになります。

アドバイスありがとうございました。

Daisuke En さんのコメント...

Arduino MEGAの場合、galileo7からちょっと前までMEGA専用のEthernet Shieldシールドが出ていたので油断していましたが、いつのまにか商品リストから消えていました。
参考にさせていただきます。

mirrorn さんのコメント...

PD2やPORTD2のような表記はATmegaのピン番号で、Arduinoボード上のピン番号とは必ずしも一致しません。例えばDuemilanove328ならPB0~5(PORTB0~5)はデジタルピン8~13に対応します。PORTDとはデジタルピン0~7までのひとグループで、PORTBはデジタルピン8~13までのグループ、PORTCはアナログインピン0~5までのグループです。ピンマッピング(図面)を見ると書いてあります。あるいは、PortManipulationを見てみるといいかもしれません。

Lucellino さんのコメント...

Sensironライブラリを使ったところ無事動きました。

サンプルファイルだとDATAはDIN2へクロック(SCK)はDIN3に接続になっています。
最初ブログの接続ピン番号と違っていたので動かず、よくよくサンプルコードを見てみるとピン番号が逆でしたね。
いろいろありがとうございました。
みごと、湿度も測定できるようになりました。

コメントを投稿