電子工作12 - デジタル温度計チップDS1820/DS18B20出力を液晶に表示

 

概要

  今回は、温度がデジタル信号で出力されるというMAXIM社製の one-wire デジタル温度計を液晶に表示させる実験を試してみることにした。最初は、正直言ってどんなものか全く分からず、ただ、PICBasic Pro(現在の小生のものはV 2.46)で開発された関連プログラムがいくつか Web上で見つかったので、とにかく、自分流に回路を組んで実験してみた。

  通常の3ピンのトランジスタのような外観のこのチップは、実は仲々の優れもので、次ぎのような特徴を持つ。

1)      この温度計チップには、温度センサ、メモリ、制御回路など、すべて入っているので、マイクロプロセッサにつないで、プログラムを作成すれば温度測定ができる。

2)      その動作には、3本線(電源、GND、信号)をつなぐか、または2本線(信号、GND)ですむ。

3)      2本線接続モードを使うと、一本の線(正確には、GNDを含めて2本)に複数のこの温度計チップや、同社のone-wire 製品がつなげられる。

4)      しかし、1本の信号線を通して、コントロール指令、温度情報のやり取りなどを行うので、タイミングの取り方やプログラミングそのものが易しくない。

 

差当たって、手元にあるDS1820 (生産中止になり、現在は同等品DS18S20が多く出回っているようだ)を、関連ソフトが結構あるので使ってみることにした。また、3、4年以上前から販売されているDS18B20という温度計チップも試してみた。

 

DS1820: -55°C ßà +125°C   精度±0.5°C (高精度表示の方法もあり) 分解能 1/80°C    9-bit digital word

DS18S20: -55°C ßà +125°C  精度±0.5°C (高精度表示の方法もあり) 分解能 1/16°C    9-bit digital word

DS18B20: -55°C ßà +125°C 精度±0.5°C (高精度表示の方法もあり)  分解能 1/16°C  12-bit digital word

DS1820 と DS18S20 との差: 温度変換速度の差があり、500 msec VS 750 msec

 

回路

  PIC16F877と今回のデジタル温度計チップを組み合わせ、結果を液晶20文字X4行(または、16文字X2行)に表示させることにした。下図に示すように、液晶とPIC16F877の間の接続では、制御線2本(RSとE)、データ線4本(DB4-DB7)の合計6本と、温度計チップから信号線が1本がPIC16F877に入るだけの、シンプルなものである。

 

                                                                          Fig. 1


 


Photo 1は上の回路で組込んだボードを示す(後述のプログラム(A)で動いている)。一番上に20文字x4行の液晶、その下にPIC16F877、更に下に小さいトランジスタのような黒いDS1820チップが、黄色い小さいリセットスイッチの左側に見える。右下に見える小さいボードはDC5V電源である。

Photo 1


 

 


  Photo 2では、DS18B20PIC16F87716文字x2行の液晶を使い、DS1820の場合とは違う後述のプログラム(B)で動かしている。プログラムリストで分かるように、PIC16F877と液晶との結線もDS1820の場合とは多少異なる。ここでは温度の表示精度は±0.5°Cなので、小数点以下1桁目は、0か5になる。液晶の右下に見えるのがDS18B20。

                                                          Photo 2


 


プログラム

    

プログラム(A): DS1820 を使う場合の例 Fig. 1、Photo 1

このプログラムの要点、 順を追って、

1)     LCD表示のための設定

2)     各種パラメータの設定

3)     OWOutOWIn (one-wire 製品のためのPBPコマンド) を使って、PORTC.2 (DQ) を通じ、$CCと$44(one-wire 製品特有のコマンド)を温度計チップに送って、温度変換を指令。そして、$CCと$BEを送って、スクラッチパッドというメモリから温度を読込む。

4)     読込んだ温度 temperature (16-bitの2進数)を、適当に算術処理してLCDの表示させる。

 

'****************** プログラミング備忘録 ********************

[DS18877x.bas] '06.3.21, based on "Basic for PIC Microcontrollers On-line" p.25/26 (Reference) 

'This PBP program works on the new board made up of DS1820 and 20x4 LCD.

' The program reads DS1820 1-wire temperature unit and displays the temperature on LCD.

‘Temperature has reached to 127.68°C and stopped when heated with a soldering iron and was ‘measured down to 8.0°C in my refrigerator (06.5.11-12).

 

'************** LCDと PIC16F877のピン結合 *****************

'Pin connections for LCD (SC2004CS*B, 20x4)

'Pin 1 - Vss (GND)  (for 20x4 LCD)

'Pin 2 - Vdd (+5V)  (for 20x4 LCD)

'Pin 3 - Vo (Contrast adj.)

'Pin 4 - RS (Register select) to RD2 (PIC)

'Pin 5 - R/W (Read/Wrire input) -> GND here

'Pin 6 - E (Enable) to RD3 (PIC)

'Pin 11 - RD4 (PIC)

'Pin 12 - RD5 (PIC)

'Pin 13 - RD6 (PIC)

'Pin 14 - RD7 (PIC)

 

'Pin connections for 16F877

'Pin 11 - Vdd (+5V)

'Pin 12 - Vss (GND)

'Pin 15 (RC2) - DS1820 (DS18S20 or DS18B20)

'Pin 21 (RD2) - RS (Pin 4 of LCD)

'Pin 22 (RD3) - E (Pin 6 of LCD)

'Pin 27 (RD4) - Data (Pin 11 of LCD)

'Pin 28 (RD5) - Data (Pin 12 of LCD)

'Pin 29 (RD6) - Data (Pin 13 of LCD)

'Pin 30 (RD7) - Data (Pin 14 of LCD)

 

'*************** ここからがプログラム本体 ***************

' Define LCD registers and bits

Define LCD_DREG PORTD     ‘Connect data pins to PORTD

Define LCD_DBIT 4                ‘Using DB4 – DB7 (4 bits)

Define LCD_RSREG PORTD    ‘Connect RS to PORTD

Define LCD_RSBIT 2               ‘Connect RS to PORTD.2

Define LCD_EREG PORTD      ‘Connect E to PORTD

Define LCD_EBIT 3                 ‘Connect E to PORTD.3

Define LCD_BITS 4                 ‘4-bit dara bus

Define LCD_LINES 4               ‘No. of LCD lines

 

‘---- 各種パラメータの設定 ----

DQ var PORTC.2        ' One-wire data pin

temperature var Word  ' Temperature storage

count_remain var Byte  ' Count remaining

count_per_c var Byte   ' Count per degree C

 

ADCON1 = 7               ' Set all PORTs to digital

Pause 100

 

‘---- PICとDS1820とのデータやり取り ----

Main: OWOut DQ,1,[$CC,$44]          ' Start temperature conversion

Waitloop: OWIn DQ,4,[count_remain]  ' Check for still busy converting

If count_remain = 0 Then Waitloop

OWOut DQ,1,[$CC,$BE]                  ' Read the temperature

OWIn DQ,0,[temperature.LOWBYTE,temperature.HIGHBYTE,Skip 4,count_remain,count_per_c]

 

‘---- LCDへの温度表示 (高精度モード) ----

'Display temperature in DEC

' (not valid for negative temperature)

temperature = (((temperature >> 1) * 100) - 25) + (((count_per_c - count_remain) * 100)/count_per_c)  ‘温度データの処理

Lcdout $fe,1, “Temp.DS1820=”, DEC (temperature/100),".",DEC2 temperature," C"  ‘LCDへ温度10進、小数点2桁表示

Pause 1000     ' Display about once a second

Goto Main      ' Do it forever

End

‘************* プログラム本体はここまで ***************

 

‘********** 秋月のプログラマで焼く時の設定 ***********          

'Note: AKI Programmer's configs. - FOSC: XT, WDTE: Enable,

'PWRTE: Enable, BODEN: Enable, LVP=RB3=I/O,

'CPD: Not protect, WRT=Enable, DEBUD=Disable, CP=Not protect

 

‘****:上記プログラムのHex File (DS18877x..HEX) の内容 ****

    今回は、省略した。 DS18877x..HEX の大きさは3,132 バイトであった。

 

 

プログラム(B): DS18B20 を使う場合の例 (Photo 2

サブルーチンを多用してのビット操作によるコマンドやデータの転送、マイクロ秒まで指定できるPauses を使った微妙なタイミング取りが、このプログラムのポイントのようです。

 

'****************** プログラミング備忘録 ********************

'[DS18877b.bas], ’06.5.29, based on http://www.renton.com/PICX4.htm (Reference)

'Found to work when changed like "temp >> 1" -> "temp >> 4" in the line "Lcdout $fe, 1, dec ‘(temp >> 4),".", 'dec (temp.0 * 5)," degrees C" in the program shown below – Important!

'Temperature has reached 127.5C and stopped when heated by a soldering iron.

'This program reads temperature data from DS18B20 as digital data and display it on LCD.

 

'************** LCDと PIC16F877のピン結合 *****************

 DS1820の場合と多少違う。

'Pin connections for LCD (SC16028B, 16x2)

'Pin 1 – Vdd (+5V)  (for 16x2 LCD)   

'Pin 2 - Vss (GND)  (for 16x2 LCD)

'Pin 3 - Vo (Contrast adj.)

'Pin 4 - RS (Register select) to RE0 (PIC)

'Pin 5 - R/W (Read/Wrire input) -> GND here

'Pin 6 - E (Enable) to RE1 (PIC)

'Pin 11 - RD4 (PIC)

'Pin 12 - RD5 (PIC)

'Pin 13 - RD6 (PIC)

'Pin 14 - RD7 (PIC)

 

'Pin connections for 16F877

'Pin 8 (RE0) - RS (Pin 4 of LCD)

'Pin 9 (RE1) - E (Pin 6 of LCD)

'Pin 11 - Vdd (+5V)

'Pin 12 - Vss (GND)

'Pin 15 (RC0) - DS18B20

'Pin 27 (RD4) - Data (Pin 11 of LCD)

'Pin 28 (RD5) - Data (Pin 12 of LCD)

'Pin 29 (RD6) - Data (Pin 13 of LCD)

'Pin 30 (RD7) - Data (Pin 14 of LCD)

 

'*************** ここからがプログラム本体 ***************

' Define LCD pins

Define  LCD_DREG        PORTD

Define  LCD_DBIT          4

Define  LCD_RSREG      PORTE

Define  LCD_RSBIT        0

Define  LCD_EREG        PORTE

Define  LCD_EBIT          1

Define  LCD_BITS          4

Define  LCD_COMMANDUS   2000  ‘Set command delay time in ms

Define  LCD_DATAUS      50          ‘Set data delay time in ms

 

‘---- 各種パラメータの設定 ----

' Allocate variables

command var    byte            ' Storage for command

i           var     byte             ' Storage for loop counter

temp     var     word             ' Storage for temperature

DQ        var     PORTC.0       ' Alias DS18B20 data pin

DQ_DIR  var     TRISC.0         ' Alias DS18B20 data direction pin

 

        ADCON1 =%10000111     '= 135 Close-up to Right and all PORTs to digital

        Low PORTE.2               ' LCD R/W line low (W)

        Pause 100                   ' Wait for LCD to start

 

‘---- PICとDS1820とのデータやり取り ----

        Lcdout $fe, 1, "Temp degrees C"  ' Display sign-on message

 

' Mainloop to read the temperature and display on LCD

mainloop:

        Gosub init1820           ' Init the DS18B20

 

        command = $CC           ' Issue Skip ROM command

        Gosub write1820

 

        command = $44           ' Start temperature conversion

        Gosub write1820

 

        Pause 2000           ' Wait 2 seconds for conversion to complete

 

        Gosub init1820           ' Do another init

 

        command = $CC           ' Issue Skip ROM command

        Gosub write1820

 

        command = $BE           ' Read the temperature

        Gosub write1820

        Gosub read1820

 

‘---- LCDへの温度表示 (通常モード) ----

       ' Display the decimal temperature

      

        Lcdout $fe, 1, dec (temp >> 4),".", dec (temp.0 * 5)," degrees C"  ‘Changed from the original’s “temp>>1” to “temp>>4” (4-bit shift)  

        Goto mainloop         ' Do it forever

 

' Initialize DS18B20 and check for presence

init1820:

        Low DQ                  ' Set the data pin low to init

        Pauseus 500            ' Wait > 480us

        DQ_DIR = 1          ' Release data pin (set to input for high)   

 

        Pauseus 100             ' Wait > 60us

        If DQ = 1 Then

                Lcdout $fe, 1, "DS1820 not present"

                Pause 500

                Goto mainloop    ' Try again

        Endif

        Pauseus 400             ' Wait for end of presence pulse

        Return

 

' Write "command" byte to the DS18B20

write1820:

        For i = 1 to 8                  ' 8 bits to a byte

                If command.0 = 0 Then

                        Gosub write0    ' Write a 0 bit

                Else

                        Gosub write1    ' Write a 1 bit

                Endif

                command = command >> 1  ' Shift to next bit

        Next i

        Return

 

' Write a 0 bit to the DS18B20

write0:

        Low DQ

        Pauseus 60            ' Low for > 60us for 0

        DQ_DIR = 1              ' Release data pin (set to input for high)

        Return

 

' Write a 1 bit to the DS18B20

write1:

        Low DQ                  ' Low for < 15us for 1

@       nop                       ' Delay 1us at 4MHz

        DQ_DIR = 1              ' Release data pin (set to input for high)

        Pauseus 60            ' Use up rest of time slot

        Return

 

' Read temperature from the DS18B20

read1820:

        For i = 1 to 16          ' 16 bits to a word

        temp = temp >> 1        ' Shift down bits

                

                Gosub readbit   ' Get the bit to the top of temp

        Next i

        Return

 

' Read a bit from the DS18B20

readbit:

        temp.15 = 1             ' Preset read bit to 1

        Low DQ                 ' Start the time slot

@       nop                       ' Delay 1us at 4MHz

        DQ_DIR = 1              ' Release data pin (set to input for high)

        If DQ = 0 Then

                temp.15 = 0      ' Set bit to 0

        Endif

        Pauseus 60             ' Wait out rest of time slot

        Return

        End

‘************* プログラム本体はここまで ***************

 

結果、課題、分かったことなど

1)         市販の温度計と比較して、DS1820/DS18B20の温度はほぼ正しかった(差1°C内)。DS1820を使った場合(高精度温度表示モード)では、少なくとも、表示の少数点以下1桁までの上下動はスムーズであった。半田ゴテを当てて加熱すると、+127.68°Cまで上昇して止まった。あまり冷えない冷蔵庫で8.0°Cまで下がるのを確認した。一方、DS18B20を使った場合(通常温度表示モード)では、最高温度は+127.5°Cまで上昇して止まった。

2)    OWOut や OWIn を使わずに、サブルーチンを沢山使って温度計チップに指令を出し、温度を読込む方式のプログラム(DS18B20使ったプログラム(B))は、長めになるが、理解し易いようだ。

3)    上述のプログラムでは、マイナスの温度範囲(-55°Cまで)をカバーしていない。カバーするには、”+”や”-“記号添付を含めた、更なるプログラムの追加や変更が必要である。

4)    DS1820などを複数個つなぐ、いわゆるパラサイト接続(電源線不要、信号線とGND線の2本線でOK)にはどんなプログラムが必要なのか、興味あり。

5)    DS18B20(12-bitの温度データ)を走らせることにも成功した。正しく温度を表示させるには、オリジナルプログラム(See Reference)の温度表示行"Lcdout $fe, 1, dec (temp >> 1),".", dec (temp.0 * 5), “degrees C"の中の "temp >> 1"部分を"temp >> 4"(4ビット右へシフト)に変えることがポイントであった。上のプログラム(B)で、16-bit長の2進温度データの内、温度に関係する真中の 8 bits を抽出(実際には温度データの下12 bits を抽出して 4 bits shift させる)して10進数で表示させている(精度±0.5°C)

 

余談

いじくっていた温度計チップがDS18S20だとばかり思っていて、いくつか公開されているプログラムをPICに組込んでみても動作しない。悶々とすること3カ月。外国のホーラムに質問しても、返答なし。止めようかと、何気なしに虫眼鏡で型番を確認したら、DS18B20ではないか。“S”と”B”を見間違っていたのである。視力低下−ジジイになると良いことなし。

単純明快、外付けなしで直接PICにつなげられる簡便さは良い。あとはソフト次第である。one-wire 製品が結構出回っているようで、うまく使えれば、いろんなことが出来そうである。

やっと、このデジタル温度計チップを使って温度を表示させることに成功した。と言ってもプログラムやチップの使い方を完全に理解しているわけではない。正直、ややこしく、難しい。

それにしても、エレキのメッカ秋葉原でDS18S20など入手出来ないのはどうしたことだろう。

その後、マイクロテクニカでDS18S20 (正真正銘のDS18S20 だが、現在のものは“S”記号がないという)が、1個650円で購入出来た。

 

Menu Pageへ戻る    

Topへ戻る