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

最終更新時間:2008年03月27日 15時33分14秒

[公開:any]

[電子工作/PIC]
[湿度計,PIC,PIC16F88,LM35DZ,CHS-UGR,HS-15P,LM358,mikroC]

origin 2008-03-10
fix1 2008-03-27
fix2 2008-04-07

3月から4月は1年のうちでもっとも空気が乾燥する時期です。体質的に乾燥した空気に弱いため加湿器を使用していますが、内蔵された湿度センサーが、どうもあやしい・・・・・・。

秋月電子で湿度センサーのHS-15Pを入手したのでLM35DZもつかってワンチップマイコンのPICにより温度計と湿度計を作ってみました。

秋月電子 湿度センサー HS-15P

湿度センサーは、秋月電子でHS-15Pを500円で購入しました。このセンサーは、1KHz程度の交流を加えたときに湿度によってインピーダンスが変化するようです。しかもその変化を対数変換すると湿度が求まるらしい・・・・・・。難しそうです。

とりあえず、購入した袋に入っていたデータシートにあるサンプル回路でテストします。

DSC01482.jpg

センサーに息を吹きかけたりしながら、出力電圧をテスターで見てみると微妙に変化しているようです。でも、これが正しいのかどうか確認する方法がありません。この出力をさらにLOGアンプ(対数アンプ)に入力するとリニアに変化する湿度が得られるようです。

インターネットであちこち検索すると、e電子工房さんでオリジナルな回路が紹介されています。この回路ではLOGアンプまで含めたものになっています。

DSC01520.jpg

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

TDK 湿度センサー CHS-UGR

HS-15Pを使う回路が複雑なので製作を躊躇しているところで、新たな湿度センサーを入手することが出来ました。TDKのCHS-UGRというものです。
インターネットで調べると、CHS-UGSという角型のものは、2000円程度で入手できるようです。

DSC01484.jpg

この湿度センサーは、+5Vを加えると湿度1%あたり10mVの電圧が出力されるようになっています。つまり、50%の時は500mVの出力となります。温度センサーのLM35DZと同じように使えます。

DSC01489.jpg

上の画像は、湿度27.4%を示しています。湿度に対する反応も早く、息を吹きかけると即座に出力電圧が上昇します。

DSC01516.jpg

湿度が直読できるので、先ほどのHS-15Pを使ったものと反応や湿球温度計でもとめた湿度を比較したところ、やっぱり値段なりにCHS-UGRが優れているようです。

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

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


ブレットボードでテスト

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

DSC01529.jpg

温度と湿度の表示には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を使用しています。

temp_hum_meter.PNG

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

最上位桁がゼロの場合に点灯なしにする条件判断を修正(2008-04-06)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/*
* 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個使います。
そのままユニバーサル基板に実装すると配線が大変なので、あらかじめ加工します。

DSC01524.jpgDSC01525.jpg

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

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

DSC01534.jpgDSC01535.jpg

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

ディスプレイ加工

パソコンの上におく予定なので、電源+5Vは、USBから取り出します。100円均一ショップで携帯充電用USBケーブルを買ってきて接続しました。

当然のことながら密閉されたケースに組み込んでしまうと温度や湿度が正確に測れません。そこで、今回は、アクリル写真立てをつかって基板ごとディスプレイに仕立てます。写真立ては、100円均一ショップで買ってきました。

DSC01536.jpg

通常は、2枚のアクリル板の間に写真を挟むようになっていますが、このようにプラスペーサで基板を保持しています。

DSC01537.jpg

この状態なので、前面パネルに穴がなくても、空気の対流は問題ないと思われます。
また、アクリル(プラスチックかもしれないけど)は、熱伝導率が低いと思われるので、今回の用途にぴったりです。

DSC01538.jpg

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

このテンプレートをデザインした者がへたれなので IE6 には非対応です。IE7FirefoxSafariOperaChrome など、モダンなブラウザを利用して下さい。


▲ページ Top へ...