Raspberry Pi に温度センサDS18B20を接続する（パラサイトパワーモード）

# はじめに

温度センサは、ざっくり分けるとアナログ出力タイプのと、デジタル通信で読み取るタイプの2種類があります。

アナログ出力タイプのは、配線の良し悪しで精度が劣化しそうな気がします。

デジタルなやつは値を読み取ることができたら、配線による劣化は無いと判断できるので、電子工作初心者としては取得した値について安心感・信頼感があると思います。

割とよく使われるのが**1-wire**というバス規格で接続できる**DS18B20**です。

**ほとんどのサイト**では、電源・GND・信号線の**3本で配線**している例が紹介されています。

しかし、**パラサイトパワーモード**(寄生電源モード)というのがあり、**GNDと信号線の2本だけで配線**できます。

「部屋の天井付近と床付近の温度を取りたい」 という場合などに必要な**配線コストが33%低減！！**

ということで **DS18B20 のパラサイトパワーモードでの使い方を紹介**します。

# ハードウェア

## 部品
・DS18B20
　　DS18B20とDS18B20+があるみたいですが、どっちでも構いません。
　　+がつく方は鉛フリー品です。　
・抵抗 4.7kΩ
・Raspberry Pi

## 配線

初めて [Fritzing](http://fritzing.org/home/) で書いてみました。すごい便利ですね。。。

![ds18b20_raspi_ブレッドボード.png](https://qiita-image-store.s3.amazonaws.com/0/104360/f7defdeb-19c4-28b7-26a2-622d34eb76d4.png)


ブレッドボードの上半分・下半分に分けて配線してますが、**温度センサへの配線が2本で済む**ことを強調するための配線になっています。実験する分にはもうちょっとコンパクトに配線することもできるでしょう。

並列で複数接続できることも示しています。

無限に個数を増やしたり配線長を伸ばしたりできるわけではありませんが、数個、数ｍオーダーならパラサイトパワーモードで行けると思います。

# ソフトウェア

raspbian には 1-wire のドライバがあるので、それを利用します。

/boot/config.txt に下記の行を追加します。

```ini:/boot/config.txt
dtoverlay=w1-gpio,gpiopin=4,pullup=y
```

gpiopin=4 のところは、接続したGPIOピンを指定するところです。デフォルト値が4なのでそれに倣っていますが、配線と設定が一致していれば別のピンでも構いません。
（ただし、GPIO2,GPIO3 はラズパイのボード上で1.8kΩのプルアップ抵抗がついているので適しません。）

追加したらリブートします。

確認のため、lsmod コマンドでドライバが存在することを確認します。

```
pi@raspberrypi:~ $ lsmod | grep w1
w1_therm                3584  0
w1_gpio                 3657  0
wire                   25219  2 w1_gpio,w1_therm
```

w1_gpio がない場合は、/boot/config.txt の記述が間違っていると思われます。
w1_therm がない場合は、配線が間違っていると思われます。

設定・配線が間違ってなければ、温度センサの数だけ /sys/bus/w1/devices/ の下に 28- で始まるディレクトリが出現しているはずです。

```
pi@raspberrypi:~ $ ls /sys/bus/w1/devices/
28-00000647c928  28-00000723c733  w1_bus_master1
```

28-以降の16進数は、それぞれのDS18B20が持つ固有のIDです。

これらの中の w1_slave ファイルを読むと、温度を1000倍した数値を取得することができます。

```
pi@raspberrypi:~ $ cat /sys/bus/w1/devices/28-00000647c928/w1_slave
b6 01 7f 80 7f ff 0a 10 2d : crc=2d YES
b6 01 7f 80 7f ff 0a 10 2d t=27375
pi@raspberrypi:~ $ cat /sys/bus/w1/devices/28-00000723c733/w1_slave
ad 01 4b 46 7f ff 03 10 ab : crc=ab YES
ad 01 4b 46 7f ff 03 10 ab t=26812
```

どっちの値がどっちのセンサだか分からないよ～ という場合はセンサを指でつまむと温度が上がるので、それで確認できます。ブレッドボードから引っこ抜いて反応がないほう、という判別方法もあります。

この先の応用については他のページを参照してください。

**以上、使い方の話は終わり**

# /boot/config.txt の設定の詳細について

ここからは調査経緯の話になります。

/boot/config.txt に書くべき内容の一次ソースはどこなんだー！？ と思ってよく見たら、/boot/config.txt の最初に

```
# For more options and information see
# http://www.raspberrypi.org/documentation/configuration/config-txt.md
# Some settings may impact device functionality. See link above for details
```

と書いてあります。

そこで http://www.raspberrypi.org/documentation/configuration/config-txt.md を見るわけですが、w1-gpio についての記述はありません。

しかし、/boot/config.txt の下の方を見ると

```
# Additional overlays and parameters are documented /boot/overlays/README
```

と書いてあるではありませんか！

**この探検感がLinuxっぽい**ですね。

ということで、ラズパイにログインして /boot/overlays/README を見てみます。

```
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


Name:   w1-gpio-pullup
Info:   Configures the w1-gpio Onewire interface module.
        Use this overlay if you *do* need a GPIO to drive an external pullup.
Load:   dtoverlay=w1-gpio-pullup,<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

        extpullup               GPIO for external pullup (default "5")
```

詳細が簡単に書いてありました。

## pullup=y の意味

pullup=y （あるいは pullup=on や pullup=1） は parasitic power の場合に指定するようです。

殆どのサイトで3本配線なのにpullup=yを指定しているみたいですが、それは誤りのようです。。。
（まあpullupというパラメータ名も誤解を招く表現のような気がしますが。）

pullup=y を指定すると、連続して読み込むときにキャパシタチャージ用のディレイがかかるものと想像します。3本配線なのにpullup=yを指定した場合は、余計なディレイがかかっちゃうものの、値は読み取れるという結果になりそうです。

## w1-gpio か w1-gpio-pullup か？

external pullup が必要な場合に w1-gpio-pullup を使うみたいです。

ここで言う "external pullup" とは何なんでしょうか。

2本配線でも、3本配線でも、プルアップが必要なことには変わりありません。

w1-gpio-pullup には extpullup という引数があります。

もしかして、「ラズパイ内蔵プルアップは抵抗値が高くて弱いので、2つのポートの内蔵プルアップを合わせて4.7kΩ相当のプルアップにしてしまおう」ということなのかな？ と考えて試してみましたが、うまく動きませんでした。

DS18B20 のデータシートを見ると、こんな配線例があります。

![DS18B20_fig6.png](https://qiita-image-store.s3.amazonaws.com/0/104360/2664fa2a-f723-9148-f244-e370dc85b942.png)

（μP はマイクロプロセッサーの略でしょうか。）

この場合、GPIOが2本必要であることから、w1-gpio-pullup を使うということなのでしょう。extpullup には MOSFET を接続したGPIOピン番号を指定することになります。

配線が長い場合や、DS18B20の接続デバイス数を増やした場合などで、不安定になる場合に、この接続方法と w1-gpio-pullup の利用が必要になってくるのでしょう。

なお、3本配線の方がさらに安定するはずです。


pullup パラメータは parasitic という名前にして、external pullup は MOSFET pullup と書いてくれれば分かりやすいのになーと思いました。

英語力の貧弱な私が勘違いしている可能性も否定できませんが。

# さらに調査が必要なこと

DS18B20はデジタルで値が取れて便利なのですが、読み取り時間(ADCの変換待ち時間)が750msも掛かってしまうというちょっとした短所があります。

その短所を解決する手段として、精度を落として9bit(0.5℃ステップ)とすることで93.75msにするというモードもあります。

![DS18B20_tbl2.png](https://qiita-image-store.s3.amazonaws.com/0/104360/6008f9cc-aaa4-99c2-eb06-2f7f35760c11.png)

しかし、raspbianのドライバにはその設定がないようです。

そもそもカーネルドライバでやる必要があるのかという疑問があり、ユーザーランドで動くDS18B20のサンプルは無いのかなーと思っています。
（ユーザーランドでμ秒オーダーの通信は難しいのでしょうか？）

# まとめ
- DS18B20 のパラサイトパワーモードでの使い方を紹介した
- 設定方法について調べて思ったことをグチった
- ユーザーランドで動くサンプルがあったら教えてください