5ドル!ラズパイ・ゼロ(Raspberry pi Zero)でIoT (16) ディジタル温度センサ1 1-Wire DS18B20

ディジタル出力の温度センサは用途に合わせて選べる

 ラズパイにはI2CやSPIのライブラリが整っているので、それらのインターフェースが用意された温度センサを利用すると便利です。大きく分類して市販品には次のインターフェースがあります。

  • 1-Wire 信号線は1本
  • I2C 信号線は2本
  • SPI 信号線は3本。高速
  • 独自

1-WireのDS18B20はドライバ入っている

 信号線が1本のDS18B20は、低価格で、複数をつないで利用できる便利な温度センサです。アマゾンでも購入できます。ほかのインターフェースがプリント基板上で接続するのを前提としているのに比べて、複数のDS18B20をじゅずつなぎにすることもでき、ラズパイとの距離を伸ばすことができるのも大きなメリットです。

 センサ単体をブレッドボード上に配線して利用しますが、金属のケースに入って防水処理されたケーブルが付いた製品もあるので、部屋の外や水中の温度も測れます。

  • 温度測定範囲:-55℃~+125℃
  • 精度:±0.5℃(-10℃~+85℃)
  • 電源:3~5.5V

 node-REDで利用した例はこちらを参照してください。

 ラズパイの/boot/overlaysには、w1-gpio.dtboというドライバが入っています。READファイルには、使い方が書かれています。

Name:  w1-gpio
Info:  Configures the w1-gpio Onewire interface module.
    Use this overlay if you *don't* need a GPIO to drive an external pullup.
Load:  dtoverlay=w1-gpio,<param>=<val>
Params: gpiopin    GPIO for I/O (default "4")

  pullup       Non-zero, "on", or "y" to enable the parasitic
            power (2-wire, power-on-data) feature

1-Wireを有効にする

 I2CやSPIと同様な手順で1-Wireを有効にします。メニューのPreferencesから、Raspberry Pi Configurationを開きます。

 1-WireのEnabledにチェックを入れ、再起動します。

 sudo nano /boot/config.txtでconfig.txtを開きます。上記の設定変更で、dtoverlay=w1-gpioが1行見つかります。デフォルトでGPIO4、7番ピンにDS18B20がつながっているという前提です。

 今回、温度を表示するためにキャラクタLCD表示器AQM0802のソケットが挿さっていて使えないので、センサの出力DQの接続はGPIO5、29番ピンに変更しました。

 dtoverlay=w1-gpio,gpiopin=5

と修正し、CTRL-O、リターン、CTRL+Xで変更を書き込みます。再起動します。

 上記の記述は、上記の接続(Non-Parasitic Power Mode)に対応しています。

 VDDをGNDに接続するParasitic Power Modeのときは、接続ケーブルが2本になり便利ですが、実験していません。

dtoverlay=w1-gpio,pullup=1,gpiopin=5

接続

 LCD表示器を1番ピンから11番ピンへ接続しますが、実際はソケットを挿し込むだけです。温度センサのDQピンを29番ピンへ接続します。複数のDS18B20があっても、すべて29番ピンへつなぎます。

 lsmodでデバイス・ドライバが読み込まれているのを確認します。

読み出したファイルの中身

 常時温度は読み込まれ、/sys/bus/w1/devicesに28-から始まるディレクトリができていて、/sys/bus/w1/devices/28-xxxxx/w1_slave というファイルに温度が書き込まれています。接続しているDS18B20の個数分、ディレクトリができていて、ファイル名w1_slaveは同じです。28が温度センサ DS18B20の識別数字で、xxxxxの部分がセンサの個別の認識数字です。現在マキシム・インテグレーテッドの製品ですが、元はダラスセミコンダクタが世の中に出しました。

 2個のDS18B20をつないだときのディレクトリの状態です。

 センサがつながっているときにYESです。t=に続く数字が、温度が1000倍されて書かれています。摂氏です。

プログラム

 I2C接続のキャラクタLCD表示器はsmbusライブラリを利用します。変換待ちをするsleep()用にtimeライブラリを使います。

 シェルで実行するcatの標準出力を得るためにsubprocessライブラリを、ディレクトリに存在するファイル数を得るためにosライブラリを、ファイル一覧をリスト形式で得るglobライブラリを使います。

 LCDcommand()とwriteLCD()はLCD用の関数です。LCDcommand()は、LCDへ直接命令を送信します。writeLCD()は、引数に入っている文字列を表示します。initLCD()はLCDの初期化コードを送信します。利用しているのはAQM0802です。

 プログラムは、DS18B20が3個までつないでテストをしました。3個つないだ後、いずれかが取り外されたときは、プログラムは途中で止まりますが、少し時間が経過したのちに再度実行すると、少なくなったセンサの個数で正常に表示をします。

 表示は小数点第2位まで出していますが、センサの精度は±0.5℃です。

 LCDへは、最初は1行目、2回目は2行目、3回目は1行目のように、表示を繰り返します。

 プログラム・リストは、表示の関係でTabキーが無視されます。スペース8個に代えてあります。また、リスト中を2回クリックすると、全選択になるので、CTRL-Cでコピーし、テキスト・エディタにCTRL-Vで貼り付けて利用してください。ラズパイに持っていくと、リターン・コードなどが化けていることがあるので、一度消して、ラズパイのテキスト・エディタで改行してください。

 プログラムを仮にDS18B20a.pyとすると、sudo chmod 755 DS18B20a.py で実行権を付け、ターミナルから、python DS18B20a.pyで実行します。

#!/usr/bin/env python
import smbus
import time
import subprocess
import os
import glob
i2c = smbus.SMBus(1) # 1 is bus number
addr = 0x3e #lcd
_command=0x00;_data=0x40;_clear=0x01;_home=0x02;display_On=0x0f;LCD_2ndline=0x40+0x80

#LCD AQM0802
def LCDcommand( code ):
i2c.write_byte_data(addr, _command, code)
time.sleep(0.1)

def writeLCD( message ):
mojilist=[]
for moji in message:
mojilist.append(ord(moji))
i2c.write_i2c_block_data(addr, _data, mojilist)
time.sleep(0.1)

def initLCD():
LCDcommand(0x38);LCDcommand(0x39);LCDcommand(0x14);LCDcommand(0x73);LCDcommand(0x56);LCDcommand(0x6c);LCDcommand(0x38);LCDcommand(_clear);LCDcommand(display_On)

#main
initLCD()

dir1 = os.listdir("/sys/bus/w1/devices")
counter = 0
for D in dir1:
if "28-" in D:
counter += 1
files = glob.glob('/sys/bus/w1/devices/28-*')
# print files
print(D)
tfiles = subprocess.check_output(['cat','/sys/bus/w1/devices/' + D + '/w1_slave'])
# print tfiles
if tfiles.find("YES",30,60) != -1 :
nannmojime = tfiles.find("t=",50,80)
print (str(tfiles[nannmojime:]) + " " + str(int(tfiles[nannmojime+2:])/1000.0))
if counter % 2 == True :
LCDcommand( _home )
else:
LCDcommand(LCD_2ndline)
writeLCD("T" + str(counter) +"="+ str(int(tfiles[nannmojime+2:])/1000.0))
time.sleep(1)

実行例

参考文献;http://www.jumpnowtek.com/rpi/Using-DS18B20-1-wire-Temp-Sensors-with-the-Raspberry-Pi.html