PICを使った温度計・湿度計の製作

 3月から4月は1年のうちでもっとも空気が乾燥する時期です。体質的に乾燥した空気に弱いため加湿器を使用していますが、内蔵された湿度センサーが、どうもあやしい・・・・・・。
 秋月電子で湿度センサーのHS-15Pを入手したのでLM35DZもつかってワンチップマイコンのPICにより温度計と湿度計を作ってみました。このセンサーは、1KHz程度の交流を加えたときに湿度によってインピーダンスが変化するようです。しかもその変化を対数変換すると湿度が求まるらしい・・・・・・。難しそうです。
 とりあえず、購入した袋に入っていたデータシートにあるサンプル回路でテストします。

 センサーに息を吹きかけたりしながら、出力電圧をテスターで見てみると微妙に変化しているようです。でも、これが正しいのかどうか確認する方法がありません。この出力をさらにLOGアンプ(対数アンプ)に入力するとリニアに変化する湿度が得られるようです。
 インターネットであちこち検索すると、e電子工房さんでオリジナルな回路が紹介されています。この回路ではLOGアンプまで含めたものになっています。

 ブレットボードに組み込んでテストします。オペアンプLM358の反転増幅回路を通して出力をテスターで見ると、湿度に反応した出力が得られます。秋月電子のサンプル回路よりは使いやすくて安定しているようです。

 HS-15Pを使う回路が複雑なので製作を躊躇しているところで、新たな湿度センサーを入手することが出来ました。TDKのCHS-UGRというものです。インターネットで調べると、CHS-UGSという角型のものは、2000円程度で入手できるようです。
 この湿度センサーは、+5Vを加えると湿度1%あたり10mVの電圧が出力されるようになっています。つまり、50%の時は500mVの出力となります。温度センサーのLM35DZと同じように使えます。

 上右の画像は、湿度27.4%を示しています。湿度に対する反応も早く、息を吹きかけると即座に出力電圧が上昇します。
 湿度が直読できるので、先ほどのHS-15Pを使ったものと反応や湿球温度計でもとめた湿度を比較したところ、やっぱり値段なりにCHS-UGRが優れているようです。

 ・・・ということで、今回はTDKの湿度センサーを使うことにします。

HS-15Pを使った湿度計を「AVRを使った温度計・湿度計の製作」で作成しました。(2008-04-07)

 いきなり製作するとハードウェアが悪いのかソフトウェアが悪いのか判別付かない状態に陥る可能性があるので、ブレットボードで開発します。

 温度と湿度の表示には7セグメントLEDを使いダイナミック点灯方式とします。ブレットボードでは多数の7セグメントLEDをつなぐのは大変なので、実験用安定化電源を製作してからお蔵入りしている「PICを使った電流計の製作」で作った4桁のダイナミック点灯用のものを暫定的に使用して実験します。

 完成した回路図です。PICは18ピンDIPのPIC16F88を使用します。PICのAD変換のリファレンス電圧は、シャントレギュレータICのTL431を使用して2.5Vとしています。温度センサーLM35DZと湿度センサーCHS-UGRは、ともに0~100℃が0~1V、0~100%が0~1Vとなっているので、フルスケールになるようにオペアンプLM358で2.5倍に増幅しています。
 6個の7セグメントLEDをダイナミック点灯するには、PICのIOポートが足りませんので、3-8デコーダーの74HC138を使用しています。

 プログラムは、mikroCを使用します。HEXファイルは600Byte程度になります。PICのAD変換で最小桁(小数点以下)がバラつくので10回の単純平均で温度と湿度を求めています。

/*
* Temperature and Humidity Meter for 7segment LED multiplex
* PIC16F88 Device Flags:
* _CP_OFF _CCP1_RB3 _DEBUG_OFF _WRT_ENABLE_OFF
* _CPD_OFF _LVP_OFF _BODEN_OFF _MCLR_OFF _PWRTE_ON
* _WDT_OFF _INTRC_IO _IESO_ON__CFG2 _FCMEN_ON__CFG2
*/

unsigned short seg[6];
unsigned short v;

unsigned short mask(unsigned short num) {
switch (num) {
case 0 : return 0xc0;
case 1 : return 0xf9;
case 2 : return 0xa4;
case 3 : return 0xb0;
case 4 : return 0x99;
case 5 : return 0x92;
case 6 : return 0x82;
case 7 : return 0xf8;
case 8 : return 0x80;
case 9 : return 0x90;
case 10 : return 0xff; // all clear
case 11 : return 0x86; // E
case 12 : return 0xAF; // r
}
}

void interrupt() {
if(INTCON.T0IF) {
INTCON.T0IF = 0; // Timer0 Interrupt flag clear
PORTB = seg[v];

switch(v) { // for 74HC138 drive
case 0: PORTA.F7 = 0; PORTA.F0 = 0; PORTA.F1 = 0; break;
case 1: PORTA.F7 = 0; PORTA.F0 = 0; PORTA.F1 = 1; break;
case 2: PORTA.F7 = 0; PORTA.F0 = 1; PORTA.F1 = 0; break;
case 3: PORTA.F7 = 0; PORTA.F0 = 1; PORTA.F1 = 1; break;
case 4: PORTA.F7 = 1; PORTA.F0 = 0; PORTA.F1 = 0; break;
case 5: PORTA.F7 = 1; PORTA.F0 = 0; PORTA.F1 = 1; break;
}
v++;
if(v > 5u)
v = 0;
}
}

unsigned int read_adc(unsigned short p)
{
unsigned int data;
unsigned int i;

data = 0;
for(i = 0; i < 10; i++) { // 10 count avg.
data += Adc_Read(p);
Delay_ms(100);
}
return data / i;
}

void main()
{
unsigned int temp, humd;
unsigned short i;

OSCCON = 0b01110000; // 8MHz internal clock
PORTB = 0b00000000;
PORTA = 0b00000000;
TRISA = 0b00011100; // RA2,RA4 is AD input. RA3 is Vref+
TRISB = 0b00000000; // 7SegLED

ANSEL = 0b00010100; // AN2,AN4 AD input

ADCON0 = 0b11100001; // Fosc/32 AN6
ADCON1 = 0b10100000; // ADFM Right and Vref+,AVss

OPTION_REG = 0b10000011; // PORTB pull-up,PSA set 100=1/16

INTCON.T0IE = 1; // Timer0 Interrupt Enable
INTCON.GIE = 1; // General Interrupt Enable

i = 0;
v = 0;

while(1) {
temp = read_adc(4);
humd = read_adc(2);

if(temp > 999 || temp < 0) {
seg[3] = mask(11);
seg[4] = mask(12);
seg[5] = mask(12);
} else {
i = (temp / 100u) % 10u;
if(i == 0)
i = 10;
seg[3] = mask(i);
i = (temp / 10) % 10u;
seg[4] = mask(i);
i = temp % 10u;
seg[5] = mask(i);
}
if(humd > 999 || humd < 0) {
seg[0] = mask(11);
seg[1] = mask(12);
seg[2] = mask(12);
} else {
i = (humd / 100u) % 10u;
if(i == 0)
i = 10;
seg[0] = mask(i);
i = (humd / 10) % 10u;
seg[1] = mask(i);
i = humd % 10u;
seg[2] = mask(i);
}
}
}

 7セグメントLEDは、秋月電子で10個100円で入手したGL9A040Gをそれぞれ3個使います。
そのままユニバーサル基板に実装すると配線が大変なので、あらかじめ加工します。

 すべての部品を1枚のユニバーサル基板上に実装します。配線スペースが不足するので、裏でKQE線を使ってジャンパーを飛ばします。7セグメントLEDの電流制限抵抗を330Ωにしたのですが、ダイナミック点灯では、日中は、ちょっと暗く感じます。

 校正は各センサーの出力電圧を測定して表示を合わせるようにオペアンプの半固定VRを調整します。乾球と湿球を持つ寒暖計で絶対値を求めて校正するのが正しい方法だと思いますが、湿度については、ほぼ合っていることを確認済みなのでこのまま使用します。

 左が気温、右が湿度ですが、ご覧のとおりかなり乾燥しています。

 パソコンの上におく予定なので、電源+5Vは、USBから取り出します。100円均一ショップで携帯充電用USBケーブルを買ってきて接続しました。当然のことながら密閉されたケースに組み込んでしまうと温度や湿度が正確に測れません。そこで、今回は、アクリル写真立てをつかって基板ごとディスプレイに仕立てます。写真立ては、100円均一ショップで買ってきました。

 通常は、2枚のアクリル板の間に写真を挟むようになっていますが、このようにプラスペーサで基板を保持しています。この状態なので、前面パネルに穴がなくても、空気の対流は問題ないと思われます。また、アクリル(プラスチックかもしれないけど)は、熱伝導率が低いと思われるので、今回の用途にぴったりです。

 PCの上においてみました。このPCは、ここが吸気口なので強制対流となり気温や湿度の変化をレスポンス良く捕らえるようです。

6件のピンバック

コメントは現在停止中です。