DS18B20温度センサーをラズパイで使ってみた

#本記事のサマリー
Raspberry Pi3B+にDB18B20センサを接続し、Pythonスクリプトで温度を取得した後、crontabで定期的に温度を取得した。
#DB18B20センサとは
DB18B20センサは安価でアナログコンバータをセンサとラズパイの間に介さずに、温度を取得できるセンサー。情報量的に、価格的に空気中の温度（もしくは湿度も）図るのならdht11センサか、この上位互換のdht22センサのほうがオヌヌメといえる。
ただ、DB18B20の最大のメリットは防水タイプが販売されており、水温等図れることにある。ちなみに、筆者はHiLetgo社という中華製？、５つで1000円程度のものをAmazonで購入した。
#環境
devices: Raspberry Pi3B+
OS: Rasbian NOOBS_ver_3_5_1
言語：Python 3系
#回路
回路に関しては、下記のURLを参考にした。
http://aba.doorblog.jp/archives/55110922.html
回路を載せてくれてありがとうございます。
といっても、プルダウン抵抗を介するだけです。ポイントは信号線（概ね黄色かな）をGPIO4に接続すること！変更できますが、今回はこれで行った。
筆者の場合、手元に2kΩしかなかったので、これを使用したが測定結果に誤差は見られなかった。
なお、ラズパイには本体に抵抗がついているから、この抵抗を介さなくてもいけそうである。
#下準備
このセンサは1-wireというインターフェイスをつかった通信方式を使うらしい。なのでこれをONにする。
まず、ターミナルで下記のコマンドを入力する。

```
$sudo nano /boot/config.txt
```

ここのnanoはエディターの指定ですが、もちろんお好みで違うエディターをつかってもらってかまわないです。
エディターが開くので、最下部に下記を加える。

```
$dtoverlay=w1-gpio
```

この動作をすれば、sudo rebootでラズパイを再起動。なお、上記の作業はラズパイのデスクトップ>Raspberry Piの設定>インターフェイスで1-wireをONにすれば、すべてGUIで完結します（はよ、いえ）。

次に、同じくターミナルで

```
$lsmod
```

を入力する。ここで、下から十数行目の次を確認。

```
w1_therm               24576  0
w1_gpio                16384  0
fixed                  16384  0
wire                   36864  2 w1_gpio,w1_therm
cn                     16384  1 wire
uas                    24576  0
uio_pdrv_genirq        16384  0
uio                    20480  1 uio_pdrv_genirq
i2c_dev                20480  0
ip_tables              28672  0
x_tables               32768  1 ip_tables
ipv6                  458752  46
```

正直、へっぽこ筆者はこれが何を意味してるのかあんまりよくわかんねぇんだが、w1_therm, w1_gpioの記載があれば、OKってことらしい。
これが出現しないなら、1-wireのインターフェイスがきちんとONになっているか、プルダウン抵抗をきちんとかませているか、を確認です。筆者は、回路がまちがってて1時間飛びました。

次に、下記をターミナルで実行する。

```
$sudo modprobe w1-gpio
$sudo modprobe w1-therm
```

次に、センサのIDみたいなのを確認しに行く。ターミナルで下記のパスを入力してディレクトリの移動をする。

```
$ cd /sys/bus/w1/devices/
```

移動したら、次を実行。

```
$ ls -la
```

すると、下記の情報を得る。

```
drwxr-xr-x 2 root root 0 12月 30 10:20 .
drwxr-xr-x 4 root root 0 12月 30 10:20 ..
lrwxrwxrwx 1 root root 0 12月 30 10:26 28-3c01b5564493 -> ../../../devices/w1_bus_master1/28-3c[貴方の画面に表示されている数字列]
lrwxrwxrwx 1 root root 0 12月 30 10:20 w1_bus_master1 -> ../../../devices/w1_bus_master1
```

ここで、28-3c・・・・のところの番号を読み取ります。後で使うのでメモメモ。
28なんて番号ねぇよって方は、回路図でGPIO4に信号線を指しているか、1-wireをONにしているかを再確認するところに戻ります。

次にようやく動作試験です。ターミナルに下記のパスを記入してください。

```
$/sys/bus/w1/devices/28-[上記でメモをとった番号]
```

移動先で、下記を実行

```
/sys/bus/w1/devices/28-3c01b5564493 $ cat w1_slave
```

そすると、こんな感じ↓のを得ます。

```
a7 00 55 05 7f a5 a5 66 a5 : crc=a5 YES
a7 00 55 05 7f a5 a5 66 a5 t=10437
```

t=10437が温度です。1000で除した値が温度になります。
10.437℃。うん、うちの家、寒いですね笑笑。

これで、下準備は終了です。
詰まった場合は、
（１）1-wireの設定を確認。rebootを忘れてないか。
（２）回路の確認。今回の流れだとGPIO4を通信線に選ぶ必要がある。
（３）温度センサ自体が逝っている。中華製なので、ままあることなので、センサごと変えてみる。

#Pythonスクリプトを作る
次に、上述の下準備が終わったのでPythonで温度を測定して、その測定データをcsvファイルに日付と時間入りで記録するプログラムを作成する。作成したプログラムが下記の通り。

```
import datetime
import os　

#ここのファイルpassは貴方の任意のユーザ名や希望のファイル保管場所等に変えてください（pi→tarou）
fileName = '/home/pi/waterTemp/waterTemp.csv'

#with文で書いてますが、別にこれである必要はないです
with open('/sys/bus/w1/devices/28-[貴方の数列]/w1_slave') as f:
    #print(type(f))
    data = f.read()
    waterTemp = float(data[data.index('t=')+2:])/1000
    
#print(waterTemp)

#もし該当箇所にファイルがないなら作る処理
if not os.path.exists(fileName):
    thData = open(fileName,'w')
    thData.write('date_time,waterTemp\n')
    thData.close()

#温度データを時間とともに記録する処理
while True:
    now = str(datetime.datetime.now())[0:16]
    data = [now,waterTemp]
    if waterTemp == 0:
        continue
    thData = open(fileName, 'a')
    thData.write(','.join(map(str,data))+'\n')
    thData.close()
    print(','.join(map(str,data)))
    break
```

なお、今回、筆者はThonnyで書きました。

#cronで定期的に温度データを取得する
最後に、上記で作成したPythonスクリプトをcronで定期的に実行します。
cronはわりと簡単そうなんですが、バリバリ初心者の私は意外と詰まったので、詳しい記事はまた書けたらと思います。今回は、簡単に流れを記載しておきます。

ターミナルで下記を入力。

```
crontab -e
```

好きなエディターを選んで（わてくしはnanoがオヌヌメ。簡単な気がする。）最下部に下記のように記載。

```
# Edit this file to introduce tasks to be run by cron.
# 
# Each task to run has to be defined through a single line
# indicating with different fields when the task will be run
# and what command to run for the task
# 
# To define the time you can provide concrete values for
# minute (m), hour (h), day of month (dom), month (mon),
# and day of week (dow) or use '*' in these fields (for 'any').
# 
# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.
# 
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
# 
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
# 
# For more information see the manual pages of crontab(5) and cron(8)
# 
# m h  dom mon dow   command
#下記の項目を追加！！
*/1 * * * * /usr/bin/python3 /home/pi/waterTemp/waterTemp.py
```

パスは各位が当該スクリプトを置かれている場所を指定してください。
これでctrl-xでyを押して終了です。
今回は*/1 * * * *の部分で1分おきに取得していますが、適当に変えてください。

#終わりに
今回は、DS18B20センサをラズパイに接続して、温度を定期的にcsvに保存するDIYをしました。これで、観賞魚の水温や水耕栽培の養液温度の見える化等IoT工作に使えて楽しそうです。
へっぽこ理系大学生の手探り工作ですので、間違い箇所やこうしたほうがもっとスマートだよっていうあれば共有していただけると幸いです。
#参考文献
下記のサイト・書籍にに大いにお世話になりました。ありがとうございます。
https://www.taneyats.com/entry/raspi-smart-aquarium-2
https://dkpyn.com/blog/2344
https://kookye.com/ja/2017/06/01/desgin-a-temperature-detector-through-raspberry-pi-and-ds18b20-temperature-sensor/
ゼロからよくわかる！ラズベリー・パイで電子工作入門ガイド　初版　タトラエディット著p189,p190