🌡️

ラズパイ3とDS18B20で温度を測定してFirestoreにアップする

2023/05/07に公開

概要

お古のラズパイ3を譲り受けたので折角なら何か電子工作始めてみようと思い、飼育しているペットのケージ内の温度を測定できたらなあとやってみました。。
取得までの手順は以下のページをとても参考にさせていただきました。ありがとうございます。

https://101010.fun/iot/raspi-water-temp.html

上記サイト様を参考にpythonで温度取得をできるようにし、その後データをFirestoreに保存するようにします。

準備したもの

電子工作自体が初めてのため、基本的に参考サイト様で紹介されていたものを購入しています。

やってみた

1-Wireの有効化

/boot/config.txtに下記の値を追記します。
iniファイルのようになっていますが、セクション無しの箇所に追記しました。

dtoverlay=w1-gpio,gpiopin=4,pullup=y

以下のmodprobeコマンドでカーネルモジュールをロードします。

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

lsmodでロード済みを確認します。

$ lsmod | grep w1
w1_therm               28672  0
w1_gpio                16384  0
wire                   36864  2 w1_gpio,w1_therm

配線

ラズパイの電源を切り、参考サイト記載のように配線を行います。

初めてで非常に汚いんですが....以下のようになりました。

疎通確認

ラズパイに再び電源を入れsshし、疎通確認をしていきます。

DS18B20のディレクトリの場所を確認します。
28-から始まるセンサデバイスUIDのシンボリックリンクがあればok

$ ls /sys/bus/w1/devices/
28-03009779ec2d  w1_bus_master1

ディレクトリ内のw1_slaveファイルをcatして、温度を確認します。
t=の値が摂氏温度で1000倍にされた温度になっており、今回はt=23187でおよそ23.1℃とのことでした。5月初旬の室内なので確からしい値です。

$ cat /sys/bus/w1/devices/28-03009779ec2d/w1_slave 
73 01 55 05 7f a5 a5 66 02 : crc=02 YES
73 01 55 05 7f a5 a5 66 02 t=23187

Pythonで温度取得する

先ほどのファイルからではなく、pythonでライブラリを使用して取得してみます。
w1thermsensorというライブラリで、pipでインストールができます。

$ pip install w1thermsensor

参考サイト様の実装を参照しつつ、問題なく摂氏と華氏を表示させることができました。

main.py
from w1thermsensor import W1ThermSensor, Unit
import time

sensor = W1ThermSensor()

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(1.0)
$ python main.py 
celsius:    22.125
fahrenheit: 72.050
celsius:    22.188
fahrenheit: 72.050
...

Firestoreにデータを保存する

今後の学習等で別のクライアントからデータを取得できるように、Firestoreに温度データを打ち上げるようにします。

Firestore初期設定

Firebaseでプロジェクトを作成 > Cloud Firestore > 本番モードでDBを作成します。
(プロジェクトは今回はそれっぽくThermWatcherとかつけておきました。)
statというコレクションを作成しておきます。

ラズパイからFirestoreにアクセスできるように、サービスアカウントを利用します。
Cloud Firestoreサイドメニュー > ギアアイコン > プロジェクトの設定 > サービスアカウント で設定画面に移動し、Firebase Admin SDKのPythonにチェックを入れて「新しい秘密鍵の生成」でJSONをダウンロードします。
ダウンロードしたJSONはラズパイにscpで送りました。

Firestoreへの書き込み

以下のコードで取得と書き込みを行います。
温度データに加え、センサーIDとタイムスタンプをDBに保存するようにしました。
実行時には、ダウンロードしたサービスアカウントのJSONファイルのパスをSA_FILE_PATHで指定します。

main.py
import os
import time

from w1thermsensor import W1ThermSensor, Unit
import firebase_admin
from firebase_admin import credentials
from firebase_admin import firestore


# Firestoreクライアント生成
cred = credentials.Certificate(os.getenv('SA_FILE_PATH'))
app = firebase_admin.initialize_app(cred)
db = firestore.client()

# センサークライアント生成
sensor = W1ThermSensor()


while True:
    # 摂氏と華氏の取得
    temperature_in_celsius = sensor.get_temperature()
    temperature_in_fahrenheit = sensor.get_temperature(Unit.DEGREES_F)
    # 保存するドキュメントの生成
    data = {
        'sensor_id': sensor.id,
        'reporting_time': int(time.time()),
        'temperature': {
            'celsius': sensor.get_temperature(),
            'fahrenheit': sensor.get_temperature(Unit.DEGREES_F),
        }
    }
    # DBに保存
    doc_ref = db.collection('stat').document()
    doc_ref.set(data)

    time.sleep(1.0)

JSONのファイルパスを指定して実行します。

$ SA_FILE_PATH=$HOME/sa.json python main.py

Firestoreを確認すると、無事書き込みができていました!

最後に

無事測定ができたので、今度はペットのケージに温度計入れて、取得したデータをDB経由でモバイルから参照...とかしていきたいです。
また今回は1つのセンサーのみでしたが、複数センサーを並列で扱うことも試せたらなと思います。
最後まで読んでいただき、ありがとうございました。

Discussion