電子工作 4 – 16F819 とLM35でLCD (液晶)上に温度を表示する実験

 

概要

    例によって割安パーツを用いた今回の実験では、10-bitのADCの入ったPIC16F819(\300)と温度センサLM35DZ (\200) を使って温度を測定し、それを液晶表示器(LCD SC16028、\700)上に表示しようというもの。ADCを使うための設定、液晶表示器と16F819とのピンの結線、取込んだ温度データを処理して、それを表示させる方法など結構複雑でした。現在の段階では、表示値の精度や安定度はイマイチです。

 

回路  

    一貫して使い続けているBasicコンパイラPicBasic Pro (PBP) のマニュアルに載っている回路図(そこでは16F84とLCDの組合わせ)を参考に、16F819とLCDを結線した。 温度センサ LM35DZは、レンジが0-100°C、変換率10.0 mV/°C、そして、精度が±1°C。つまり、1度温度が上る毎に10.0mVづつ直線的に出力されるという便利なものです。図中Vdd には、レギュレータ7805を使ってつくられた5.00Vが供給され、また、温度センサの電源は9Vの角型乾電池を使っています。消費電力は60uA です。 


        下の写真の液晶上に、センサからの電圧(1行目Volt=0.31V)と変換された温度(2行目 Temp=31C)が表示されているのが見えます。その下の3本足の黒いチップが温度センサLM35DZです。

    


 


プログラミング

目標は、16文字2行の液晶上に、1行目“Volt=0.xxV”とセンサからの電圧出力そのままを、そして、そのデータを用いて2行目には“Temp=xxC”と温度(摂氏)を2桁表示させることです。下のプログラムを見てください。 LCD表示のための様々な設定、8MHzの内部クロックを使うための設定(外付けいらずで簡単)、ADCを使うための結構厄介な設定をしています。次いで、外部からのアナログ入力(温度センサからの)(RA0-Pin17)を10個読込んで積算し、それから平均値を求める(バラツキを抑えるため)。ここで問題は、PBP では整数値しか扱えないので、小数点以下の表示が必要な場合は、工夫がいるということです。したがって、得られたVinという平均値(10-bit値)をLCD上の1行目に表示するには、Vin=(Vin*/500)>>2 とした後で、Lcdout $fe, 2, "Volt=",dec(Vin/100),".",DEC2 Vin と書きます。これで Volt=0.31 などと表示されます。この値を2行目に、2桁の温度として表示するには、 Lcdout "Temp=",Dec2 Vin,"C" と書きます。これで、Temp=31C などと表示することが出来ます。

 

プログラム

下の記述で分かるように、デバイスのピンの結線をはじめ、英語のコメント文がいっぱい入っていてかなり長く見えますが、実際のプログラムは、DEFINE LCD_DREG  PORTB  'Set LCD Data port で始まって、goto ADCLoop で終わります。最後の部分の”Note“にはAki Pic programmer configuration の設定項目が記してあります。内部クロックなどの選択はここでします。

 

'ADLC819h.bas - 16F819  2004.7.1 completed

'This time no digits below decimal point were used.

'Exp. to read a voltage value from PortA.0 which

'is connected to LM35DZ temp. sensor (10 mV/C),

'convert it to a voltage and a temperature and

'display both voltage (1-line) and temp. value

'on LCD(2-line display).

'Note: The points are the use of "Vin=(Vin*/500)>>2" ,

'Lcdout $fe, 2, "Volt=",dec(Vin/100),".",DEC2 Vin and

'Lcdout "Temp=",Dec2 Vin,"C"

'Here, Dec2 means to display the Vin value in a 2-digit

'number.

 

'Pin connections:

'LCD    PIC

'DB4     PortB.4

'DB5     PortB.5

'DB6     PortB.6

'DB7     PortB.7

'RS      PortB.1 (add 4.7K pullup resistor to 5 volts)

'E       PortB.0

'RW      Ground

'Vdd     5.00 volts (also used as +Vref)

'Vss     Ground

'Vo      Ground (or 20K potentiometer)

'DB0-3   No connect

'ADC input  PortA.0

 

'**New LCD connection setting** See p.88 in PBP Manual

DEFINE LCD_DREG PORTB  'Set LCD Data port

DEFINE LCD_DBIT 4      'Set starting Data bit

                       '(0 or 4) if 4-bit bus

DEFINE LCD_RSREG PORTB 'Set LCD Register Select port

DEFINE LCD_RSBIT 1     'Set LCD Register Select bit

DEFINE LCD_EREG PORTB  'Set LCD Enable port

DEFINE LCD_EBIT 0      'Set LCD Enable bit

DEFINE LCD_BITS 4      'Set LCD bus size (4 or 8 bits)

DEFINE LCD_LINES 2     'Set number of lines on LCD

DEFINE LCD_COMMANDUS 2000 'Set command delay time in us

DEFINE LCD_DATAUS 50   'Set data delay time in us

 

'**Setting for ADC of 16F819**

Define ADC_BITS 10     '10-bit ADC used

Define ADC_CLOCK 3     'Internal clock used

Define ADC_SAMPLEUS 50 'Sample timing

 

OSCCON=%01110100  '=100 (decimal) - Internal OSC setting

'bit7=0(unimplemented), bit6-5-4=111(internal OSC 8MHz),

'bit3=0(unimplemented), bit2=1(frequency stable?),

'bit1-0=00(unimplemented)

 

ADCON0=%10000101  '=5 (decimal) - ADC setting

'bit7-6=01(Fosc/32 atADSC2?),'bit5-4-3=000(channel 0 (RA0/AN0),

'bit2=1(Ad conversion in progress at ADOn=1),

'bit1=0(unimplemented), bit0=1(AD module is operating)

 

ADCON1=%10001110  '=142 (decimal) - ADC and pin setting

'bit7=1 (right justified), bit6=0 (disable), bit5-4=00

'(unimplemented), bit3-2-1-0=1110 (AN4-3-2-1-0=DDDDA,

'+Vref-AVdd(supply power), -Vref-AVss(GND))

 

TRISA=%00100001   'PortA.0-analog input, PortA.5-input,

                  'all others-output

TRISB=%00000000   'All PortBs are output

Samples var word 'Samples

Sample var byte  'Sample

Vin var Word     'Vin is variable

 

Samples=0

 

ADCloop:

For Sample=1 to 10 'Take 10 samples (changed from 20)

ADCIN 0, Vin   'Read ADC ch-0 and save in Vin

               '(range 0-1023)

Samples=Samples + Vin

Pause 200      'Wait for LCD to startup

               'Seems to be appropriate.

Next sample

 

Vin=Samples/10 'Mean of 10 Vin values

Vin=(Vin*/500)>>2

Lcdout $fe, 1  'Clear LCD

Lcdout $fe, 2, "Volt=",dec(Vin/100),".",DEC2 Vin

LCDOUT $FE,$C0 'Jump to second line

Lcdout "Temp=",Dec2 Vin,"C"

 

Samples=0

 

goto ADCLoop

 

'Note: Aki Pic programmer configuration for 16F819:

'Same as those on 04.2.13

'FOSC-INTRC__RA6=I/O, WDTE-Enable, PWRTE-Enable, MCLRE-RA5=I/O,

'BODEN-Enable, LVP-RB3=I/O, CPD-Disable, WRT-All-Enable,

'DEBUG-Disable, CCPMX-CCPI=RB2, CP-Disable

 

余談

        今回の実験で、液晶に表示される温度の小数点以下1桁目は不安定で、その増減が連続的でなく(数値が飛ぶ)、市販の液晶温度計のようではありませんでした。 従って、2桁表示を採用することにしました。 Cooler/heater box の中に温度センサと市販のデジタル温度計(NT-301)の針状検出部を入れ比較してみたところ、少なくとも実験した7 - 55°Cの区間では大変直線性が良く、±0.5°C程度の精度はあることが分かりました。小数点以下1桁目まで安定した温度を得るには、12-bit ADC (0-4095=4096) 内臓のフラッシュタイプPIC(未発売)、プログラミングの工夫、それに、より精度の高い温度センサが必要のようです。巷で\1500-2000 位で売られている様々な液晶温度計の、あの桁上がりのズムーズさ、設計した人、創った人、プロとは凄いものだと脱帽してしまいます。

 

―間違い―

回路図の液晶(SC1602)のピン表示に誤り見つかりました。

      誤   正

Pin 1 VDD  -> VDD

Pin 2 VO   -> VSS

Pin 2 VSS  -> VO

 

Menu Pageへ戻る    

Topへ戻る