電子工作 5 –アンプLM358を使って“電子工作4”の温度表示の精度を1桁上げる
概要
前の電子工作4の温度を液晶に表示する実験では、2桁の精度(例
32°C)を確保するのが限界でした。これを実用精度3桁まで(例32.4°C)にするため、温度センサの出力をオペアンプLM358で増幅し、また、プログラムにも若干の改良を加えて、安定した3桁表示が出来るようにした。
回路
下に示した図のように、温度センサLM35DZの出力端子に、新たにオペアンプLM358をつなぎ、そのオペアンプの出力端子を16F819のPin17 (PortA.0、前の電子工作4を参照)につないだ。このオペアンプLM358は、分圧器(Standard
Voltage Generator)の作りだす1.000V(DMM表示値)を使って、正確に5倍の増幅をするように、VRfとVRsで調整した。したがって、LM35DZから500
mV(temp=50°Cに相当)の入力があると、オペアンプLM358は0.500x5=2.50Vの出力を16F819に供給することになる。また、1000mV(temp=100°Cに相当)の場合は、1.00x5=5.00Vの出力を16F819に供給することになる。オペアンプLM358の電源(電圧:6.50V)はLM317を使った可変電源から(この電圧以下だと、出力5.00Vが得られない)、また、16F819には、7805を用いた電源から、5.00Vを供給した。なお、この電圧5.00Vは、内臓のADコンバータ(10-bit)の基準電圧としても使われている。
プログラミング
今回の目標は、16文字2行の液晶上に、1行目“Volt=x.xxV”とセンサからの電圧出力をアンプで5倍に増幅した値を、そして、そのデータを用いて2行目には“Temp=xx.xC”と温度(摂氏)を3桁表示させることです。しかも、いずれの値も、最小の桁がスムーズに増減しなければいけません。下のプログラムを見てください。電子工作4のものを一部変更してあります。
Result=Vin*/12500 'Scale 1024 to 50000
Result=(Result+5)/10 'Round the result
読み込んだデータを、整数値しか扱えないPICBasic Proに理解できるようにするトリックで、この場合の12500はscaling factor と呼ばれ、50000/1024*256を指し、(Result+5)/10は四捨五入のためのものです。
次の部分は、Volt=x.xxV、Temp=xx.xCと液晶に表示させるためのものです。
Lcdout $fe, 1
'Clear LCD
Lcdout $fe, 2, "Volt=",dec1 Result DIG
3,".",DEC1 Result DIG 2,DEC1 Result DIG 1,"V"
Lcdout $fe,$c0 'Jump to second line
Lcdout "Temp=",dec1 ResultT DIG 3,dec1
ResultT DIG 2,".",DEC1 ResultT DIG 1,"C"
プログラム
'ADLC819j.bas -
16F819 2004.8.16 completed
'This time the
input was amplified by 5 times with
‘a home-made
OpAmp LM358N so that 100°C equated to 5.00V
'(+Vref) and 3 decimal figures were used.
'Exp. to read a
voltage value from PortA.0 which
'is connected
to LM35DZ temp. sensor (10 mV/C), via the
'OpAmp LM358N, convert
it to a voltage and a temperature and
'display both
voltage (1-line) and temp. values
'on LCD(2-line
display).
'Note: The
points are the use of "Result=Vin*/12500 'Scale
'1024 to
50000", "dec1 Result DIG 3,".",DEC1 Result DIG 2,
'DEC1 Result
DIG 1,"V" and Lcdout "Temp=", dec1 Result DIG 3,
'dec1 Result
DIG 2,".",DEC1 Result DIG 1,"C"
'Here, Dec1
means to display the Result DIG 2 value in 1 digit
'number (DIG 2
- 3rd digit from LSB).
'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 (Pin 17)
'**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
Result VAR
WORD 'Result is variable
ResultT VAR
WORD
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
Result=Vin*/12500
'Scale 1024 to 50000
Result=(Result+5)/10 'Round the result
ResultT=Result*2
Lcdout $fe,
1 'Clear LCD
Lcdout $fe, 2,
"Volt=",dec1 Result DIG 3,".",DEC1 Result DIG 2,DEC1 Result
DIG 1,"V"
lcdout
$fe,$c0 'Jump to second line
Lcdout
"Temp=",dec1 ResultT DIG 3,dec1 ResultT DIG 2,".",DEC1
ResultT DIG 1,"C"
Samples=0
goto ADCLoop
'Note: Aki Pic
programmer configuration for 16F819:
'Basically 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桁目が、市販の液晶温度計並みの、大変安定した増減をするようになった (少なくとも常用温度で)。 Cooler/heater box の中に、この装置の温度センサと市販のデジタル温度計(NT-301)の針状検出部を入れ比較してみたところ、少なくとも実験した10
- 55°Cの区間では大変直線性が良く、±0.5°C程度の精度はあることが分かった。ただ、電源やオペアンプの追加が必要であった。温度の精度を1桁上げるのも結構大変であることが理解できた。