ラズパイとプローブ型の防水温度センサー(DS18B20)での温度測定 | そう備忘録

ラズパイとプローブ型の防水温度センサー(DS18B20)での温度測定

プローブ型温度センサー

ラズパイ(Raspberry Pi 4B)でプローブ型の防水温度センサー(DS18B20)を使って温度測定をしてみた時の記事。

LXTerminal からのコマンドと Python のスクリプトの両方で測定してみた。

2022/06/25 追記

センサーを複数(2台)付けた時の Python スクリプトを記事の最後に追記した。

ラズパイと温度センサー

尚、同じ温度センサーを ESP32 で試して見たことがあるので、その時の記事はこちらを参照して欲しい。

温度センサーは以前に購入した下記の製品を使用している。

※同型のセンサーは品切れの為、類似の商品のリンクに変更している。

主な仕様

センサー部分(DS18B20)の主な仕様は以下の通り。

  • 測定可能温度範囲:-55℃ ~ +125℃
  • 精度範囲:-10℃ ~ +85℃ の時 ± 0.5℃
  • 長さ:1m
  • プローブサイズ: 6 × 50 mm
  • 電源電圧範囲:3.0 V ~ 5.5V(今回は3.3Vで使用した)
  • 出力リード線:赤(VCC)、黄色(DATA / MCU )、黒(GND)

準備したモノ

ラズパイ本体

以前に購入した Raspberry Pi 4B スターターキットを使用した。

尚、ラズパイの基本的なセットアップの記事へのリンクを書いておく。

ブレッドボード

配線テスト用のブレッドボード。

直接、ラスパイに接続するのであれば不要だ。

ジャンパーワイヤーコネクタ

以前に購入したジャンパーワイヤーのコネクタの制作キット。

ブレッドボードで配線を組み替える時に使用した。

抵抗

プルアップ用に以前に購入した 10kΩ の抵抗を使用した。

大体 4K ~ 10K の範囲の抵抗であれば良いと思う。

事前準備

1-Wireを有効にする

ラズパイで1-Wire を有効にする。

1-Wire は一本の信号線だけで低速なデータ通信を行うバス規格で、デフォルトでは無効になっているので有効化する。

複数のやり方があるが、デスクトップ表示(GUI)であれば、スタートボタンー>設定ー>Raspberry Piの設定ー>インターフェースタブで 1-Wire を有効にして再起動するのが簡単だ。

1-Wireの有効化

CLI(Command Line Interface)環境であれば、

sudo raspi-config

でRaspberry Pi Software Configuration Tool を起動して Interface Optionsー>P7 1ーWireー>Enabled を「はい」で再起動しても同じことが行われる。

上記いずれの方法でも実際に行われことは、/boot/config.txt に以下の行が追加される。

dtoverlay=w1-gpio

よって、下記のコマンドで直接エディターでconfig.txt を開いて、

sudo vi /boot/config.txt

で上記の行を追記しても良い。

信号線のGPIO

尚、温度センサーの信号線を GPIO4(後述の配線図参照)に接続する場合は、dtoverlay=w1-gpio の指定だけで良いが、異なる GPIO(例えばGPIO23)に接続する時は以下のように指定する。

dtoverlay=w1-gpio,gpiopin=23

今回は GPIO23 に接続している。

/boot/config.txt

配線図

ラズパイとプローブ型温度センサーの配線図は以下の通り。

プローブ型温度センサーとラズパイの配線図

コマンドで確認

最初に LXTerminal からのコマンドで温度を測定してみる。

以下のコマンドでデバイスの一覧を表示する。

ls /sys/bus/w1/devices/

すると devices ディレクトリの下に 28 で始まるディレクトリ(デバイスID)があるので、そのディレクトリ配下にある w1_slave ファイルの中身を cat コマンドで表示する。

自分の環境では 28-012059e8da3a という ID のデバイスが認識された。

cat /sys/bus/w1/devices/28-012059e8da3a/w1_slave

何回か cat コマンドで表示してみた。

w1_slave ファイルの中身を表示する

t=21312 となっているが、摂氏21.312度を表している。

Pythonスクリプト

続いて Python スクリプトから温度を取得してみる。

必要ライブラリー

事前に以下のコマンドで Python から1-Wire を扱うためのライブラリ(w1thermsensor)をインストールする。

このライブラリーは以下の 1-Wire の温度センサーに対応している。

  • DS18S20
  • DS1822
  • DS18B20
  • DS28EA00
  • DS1825/MAX31850K
pip3 install w1thermsensor

Python3.x にインストールしたかったので明示的に pip3 を使ったがデフォルトが Python3.x 環境なら pip コマンドでも同じ様にインストールされる。

w1thermsensorのインストール

コード(ds18b20.py)

5秒間隔で温度を測定して摂氏と華氏を取得して表示するコード。

# -*- coding: utf-8 -*-
"""
Created on Sat Jun 11 07:59:57 2022

 DS18B20 Test Program
 
@author: Souichirou Kikuchi
"""

from w1thermsensor import W1ThermSensor, Unit
import time

sensor = W1ThermSensor()
# sensor.set_resolution(12)

#main
try:
    while True:
        # 摂氏、華氏のみを取得
        temperature_in_celsius = sensor.get_temperature()
        temperature_in_fahrenheit = sensor.get_temperature(Unit.DEGREES_F)
        print("celsius:    {0:.3f}".format(temperature_in_celsius))
        print("fahrenheit: {0:.3f}".format(temperature_in_fahrenheit))

        time.sleep(5.0)
except KeyboardInterrupt:
    pass

実行結果

上記のスクリプトの実行結果は以下の通り。

5秒間隔で

  • celsius:摂氏
  • fahrenheit:華氏

で温度が表示される。

摂氏と華氏の表示

補足説明

停止方法

Ctrl+c でスクリプトは停止する。

w1thermsensor

10行目で 1-Wire の w1thermsensor モジュールをインポートしている。

set_resolution

コメントアウトしているが温度取得時の解像度を 9~12 の値で指定することが可能だ。

  • 数字が大きい方が高解像度(小数点以下の細かい数字まで取得できる)
  • 設定可能なセンサーと不可能なセンサーがある模様
  • 自分が購入した機器はデフォルトで12(最高解像度)が設定されていた
  • 解像度の変更は管理者権限でスクリプトを実行する必要がある
  • 試しに9を設定したら小数点以下が0(低解像度)になった

先程の w1_slave ファイルが格納されているディレクトリに resolution ファイルがあるので中身を見ると 12 が入っていた。

set_resolution はこのファイルの中身を(管理者権限で)書き換えていた。

解像度

摂氏と華氏

日本では摂氏の方が一般的だがアメリカなどで表記の多い華氏を表示する機能もある。

摂氏から華氏への変換式は以下の通り。

(摂氏°C × 9 ÷ 5) + 32 = 華氏°F
  • get_temperature():摂氏を取得する
  • get_temperature(Unit.DEGREES_F):華氏を取得する

絶対温度を取得するコード(ds18b20_2.py)

以下の様に摂氏、華氏、絶対温度(kelvin)を配列で取得する事もできる。

※絶対温度とは物理的に考えられる最低温度(摂氏-273度)を零度として摂氏で表した温度。

# -*- coding: utf-8 -*-
"""
Created on Sat Jun 11 07:59:57 2022

 DS18B20 Test Program
 
@author: Souichirou Kikuchi
"""

from w1thermsensor import W1ThermSensor, Unit
import time

sensor = W1ThermSensor()
# sensor.set_resolution(12)

#main
try:
    while True:
        temperature_in_all_units = sensor.get_temperatures([
            Unit.DEGREES_C,
            Unit.DEGREES_F,
            Unit.KELVIN])    
        print("celsius:    {0:.3f}".format(temperature_in_all_units[0]))
        print("fahrenheit: {0:.3f}".format(temperature_in_all_units[1]))
        print("kelvin: {0:.3f}".format(temperature_in_all_units[2]))
    
        time.sleep(5.0)
except KeyboardInterrupt:
    pass

実行結果

実行結果は以下の通り。

5秒間隔で、

  • celsius:摂氏
  • fahrenheit:華氏
  • kelvin:絶対温度

が表示される。

実行結果

非同期で温度を取得するコード(ds18b20_async.py)

あまり使用する事はないと思うが W1ThermSensor には非同期で温度を取得する機能も用意されていたので試してみた。

使用例としては時間の掛かる処理を並行して動作させている時に、その処理終了を待たずに一定間隔で温度を取得したい場合などが考えられる。

# -*- coding: utf-8 -*-
"""
Created on Sat Jun 11 07:59:57 2022

@author: Souichirou Kikuchi
"""

import asyncio
from w1thermsensor import AsyncW1ThermSensor, Unit
import time

sensor = AsyncW1ThermSensor()

async def temp_get():
        temperature_in_all_units = await sensor.get_temperatures([
            Unit.DEGREES_C,
            Unit.DEGREES_F,
            Unit.KELVIN])    
        print("celsius:    {0:.3f}".format(temperature_in_all_units[0]))
        print("fahrenheit: {0:.3f}".format(temperature_in_all_units[1]))
        print("kelvin: {0:.3f}".format(temperature_in_all_units[2]))

#main
try:
    while True:
        asyncio.run(temp_get())
        time.sleep(5.0)
except KeyboardInterrupt:
    pass

実行結果

実行結果は以下の通り。

非同期で温度を取得
2022/06/25 追記

複数センサーの接続

配線図

配線図は以下の通り。

信号線は共通にしている。

複数の温度センサーを接続する時の配線図

複数センサーの時のコード(ds18b20-multiple.py)

センサーを複数接続(2台)した時のコードを追記する。

# -*- coding: utf-8 -*-
"""
Created on Sat Jun 11 07:59:57 2022

 DS18B20 Test Program
 
@author: Souichirou Kikuchi
"""

from w1thermsensor import W1ThermSensor
import time

sensor = W1ThermSensor()

#main
try:
    while True:
        for sensor in W1ThermSensor.get_available_sensors():
            print("Sensor %s has temperature %.2f" % (sensor.id, sensor.get_temperature()))

        time.sleep(5.0)
except KeyboardInterrupt:
    pass

補足説明

get_available_sensor() 関数をfor 文で回して利用可能なセンサーのセンサーIDを取得する。

接続してセンサーの数だけセンサーIDが取得される。

取得したセンサーIDに対して get_temperture() 関数で温度を取得する。

実行結果

実行結果は以下の通り。

センサーID:012059e8da3a と 01205a884473 の2つのセンサーの温度を表示している。

複数センサーの実行結果

最初は両方共に摂氏27.44度を測定している。

片方だけ手で掴んで温度を上げた所、28.00→30.56→31.44 と温度が上昇した事が分かる。

以上で今回の記事は終了とする。

最後に

この記事が何処かで誰かの役に立つことを願っている。

尚、当記事中の商品へのリンクはAmazonアソシエイトへのリンクが含まれています。Amazonのアソシエイトとして、当メディアは適格販売により収入を得ていますのでご了承ください。

souichirou

やった事を忘れない為の備忘録 同じような事をやりたい人の参考になればと思ってブログにしてます。 主にレゴ、AWS(Amazon Web Services)、WordPress、Deep Learning、RaspberryPiに関するブログを書いています。 仕事では工場に協働ロボットの導入や中小企業へのAI/IoT導入のアドバイザーをやっています。 2019年7月にJDLA(一般社団法人 日本デイープラーニング協会)Deep Learning for GENERALに合格しました。 質問は記事一番下にあるコメントかメニュー上部の問い合わせからお願いします。

4件のフィードバック

  1. より:

    すごい丁寧な記事でよかったです。
    IoTにも興味があるので、また読ませてもらいます!

  2. nobby より:

    参考にしております。現在はパンを作るときの発酵器内の温度管理で利用させていただいています。
    燻製器の温度管理もデジタルやりたいので、この記事の内容を利用させていただこうと思っています。

    • souichirou より:

      nobbyさん
      コメントありがとうございます。
      パンと燻製器の温度管理とは良いですねー!ベストな温度管理で発酵したパンは美味しいでしょうね?

へ返信する コメントをキャンセル

名前、メール、サイト欄は任意です。
またメールアドレスは公開されません。