IoT実験:ラズパイで温度取得しグラフ表示 (1)ラズパイで温度取得
概要
Raspberry Pi(ラズベリーパイ、本記事では略して「ラズパイ」と呼ぶ)は、元々教育用に開発されたシングルボードコンピュータです。センサ等を接続して使用できるマイコン的な要素と、OSを搭載しネットワーク機能やPythonなどのプログラミング言語が使用できるPC的な要素をあわせ持っています。しかも、比較的安価に入手することができるため、様々な場面で用いられます。
今回は、ラズパイを使用してIoTの実験を行います。記事は何回かに分かれますが、最終目的は、ラズパイで温度取得したデータを、下図のように温度の時間的な変化としてグラフで見られるようにすることで、しかも、なるべく出来合いのソフトウエアを使用して、労力と時間を最小限に抑えます。(ラズパイで温度取得する部分は、プログラムが必要です。)
グラフによる可視化の例
この温度データの可視化ができれば、これを応用して、他のセンサから取得したデータの可視化も、同じように行うことができます。
システム内の大まかな機能は以下の通りです。
- ラズパイ:温度センサから温度データを取得
- ラズパイ:取得した温度データをネットワークを介してサーバへ送信
- サーバ:受信した温度データをデータベースへ保存
- サーバ:ユーザの要望に応じて温度データを可視化
システム内の大まかな機能
本記事では、このうちの1番目「ラズパイ:温度センサから温度データを取得」を行います。
実験環境
ラズパイ
項目 | 内容 |
---|---|
本体 | Raspberry Pi 3B+ |
OS | Raspberry Pi OS Lite Release date: May 3rd 2023 System: 64-bit Kernel version: 6.1 Debian version: 11 (bullseye) |
開発言語 | Python 3.9.2 |
ホスト名 | raspi01.local |
IPアドレス | DHCP (192.168.130.0/24) |
ラズパイ本体は 3B+ を使用しました。特に負荷はかからないので、Zeroでも充分です。
OSは Lite版の64bitを使用しました。Lite版以外(デスクトップ版など)でも、32bitでも構いません。
Zeroは64bitが使用できませんので注意してください(Zero2は使用可)。
温度取得プログラムは、Python3 を使用しました。
ホスト名は「raspi01.local」としました。特にこの名前にこだわる必要はありませんが、データをデータベースに保存する際、ホスト名も同時に保存されますので、必ず自身で見分けられる名前にしてください。
IPアドレスは、自動取得(DHCP)としています。
温度センサ
項目 | 内容 |
---|---|
型番 | DS18B20 |
通信方式 | 1-wire |
抵抗 | 4.7kΩ(プルアップ用) |
温度センサは、1-wire方式のDS18B20というものを使用しました。センサやケーブルが防水処理がされているものでした。
使用した温度センサ
温度センサの信号線はプルアップする(信号線を抵抗を介して電源に接続する)必要があります。マニュアルでは5kΩ程度とのことで、今回は 4.7kΩの抵抗を使用しました。
サーバ
次回以降となりますが、サーバOSはLinux(Ubuntu MATE)を使用し、データベースや可視化はInfluxDBというソフトウエアを使用します。
今回の実験では、「社内からしかアクセスしない」、「セキュリティをあまり考慮しなくてもよい」などの理由から、サーバマシンをLAN内に設置し、インターネットは使わないことを想定しています。もしインターネット上のクラウドにサーバを用意する場合は、そちらでも構いませんが、セキュリティを考慮したり、ラズパイからhttpやhttpsで通信ができる必要があります。
また、サーバとして別のマシンが用意できない場合、温度データを取得するラズパイにてデータベースソフトウエア(InfluxDB)を使用することも可能です(あまりお勧めはできませんが)。この場合、温度取得~可視化まで1台のラズパイで完結できます。
なお、本実験では、Windows 10上の仮想マシンをサーバとして利用しました。
接続
ブレッドボードを使用して、温度センサや抵抗を接続しました。
ブレッドボードでセンサや抵抗を接続
今回は、ラズパイのGPIO 26に温度センサの信号を入力しています。ラズパイの初期状態でGPIO 4が入力端子となりますので、GPIO 26を使う場合は設定変更が必要です。GPIO 4で問題なければ設定変更は不要です。(変更して使う場合はこうしましょう、という例となります。)
また、温度センサの電源は3.3Vを使用しますが、ラズパイから供給します。
今回使用したセンサは、赤、黄、黒の3本の線が出ていました。マニュアルより、次の意味となります。
- 赤 ... 電源
- 黄 ... 信号線
- 黒 ... GND
ここから、下図のように接続しました。
温度センサの接続先
実際の接続の様子(あらかじめブレッドボードの赤線部は3.3V、青線部はGNDに接続済みです)
Raspberry Pi OS のインストール
Raspberry Pi OS のインストールに関しては、インターネット上に多くの記事がありますので、それらを参照してください。ここでは省略します。
参考:
Raspberry Pi OS – Raspberry Pi (https://www.raspberrypi.com/software/)
ラズパイの設定
1-wireの有効化
1-wireを有効化するには、raspi-config
コマンドなら、以下のように実行し、
$ sudo raspi-config
以下のメニューをたどって有効化します。
「3 Interface Options」→「I7 1-Wire」→「はい」
また、デスクトップ環境なら「Raspberry Piの設定」ツールを使用します。
「Raspberry Piの設定」ツール
入力を GPIO26 へ
初期状態では、1-wire の入力は、GPIO 4 です。今回は、GPIO 26 を使用しようと思いますので、この変更が必要です。もし、GPIO 4 をそのまま使用する場合、この手順は不要です。
(GPIO 4 を別の用途で使用しないのであれば、GPIO 4 のままで問題ありません。変更する場合は、このようにしてください、という例となります。)
1-wireで使用する入力ポートの指定は、/boot/config.txt
に記述します。このファイルへの書き込みは管理者権限が必要ですので、管理者権限を指定して、エディタで開きます。
以下は、エディタ vi にて、ファイル /boot/config.txt
を、管理者権限で開いている例です。
$ sudo vi /boot/config.txt
ファイルを開いたら、以下の行を探してください。
dtoverlay=w1-gpio
そして、行の末尾に ,gpiopin=26
を追記します。
dtoverlay=w1-gpio,gpiopin=26
ファイルを上書き保存して終了したら、ラズパイを再起動してください。
$ sudo reboot
温度データの取得
上記設定を行うことで、1-wireのドライバが自動的に読み込まれます。1-wireのドライバでは、ファイルを経由してデータの読み取りが可能です。
以下では、1-wire用のファイルが作成されているか、そしてそのファイルを開いて温度が取得できるかの確認を行います。
なお、ファイルは /sys/bus/w1/devices/デバイスID/w1_slave
となります。
/sys/bus/w1
の確認
(1) $ ls /sys/bus
... w1 ...
w1
ディレクトリが存在すれば、コマンドの実行結果に w1
が含まれます。
/sys/bus/w1/devices
の確認
(2) $ ls /sys/bus/w1
... devices ...
devices
ディレクトリが存在すれば、コマンドの実行結果に devices
が含まれます。
(3) デバイスID の確認
$ ls /sys/bus/w1/devices
28-3c01d60775b9 w1_bus_master1
今回使用した温度センサ DS18B20 は、デバイスIDが「28-3c01d60775b9」でした。
/sys/bus/w1/devices/デバイスID
の確認
(4) 上でデバイスIDが確認できたので、以下を実行します。
$ ls /sys/bus/w1/devices/28-3c01d60775b9
... w1_slave ...
w1_slave
が存在すれば、それが温度センサからデータ取得するファイルとなります。
/sys/bus/w1/devices/デバイスID/w1_slave
の内容表示
(5) /sys/bus/w1/devices/デバイスID/w1_slave
の内容を表示してみましょう。
これにより、温度データが取得できます。
$ cat /sys/bus/w1/devices/28-3c01d60775b9/w1_slave
88 01 55 05 7f a5 a5 66 ca : crc=ca YES
88 01 55 05 7f a5 a5 66 ca t=24500
ここで、末尾が「t=24500」と表示されていますが、これが取得した温度データとなります。実際には、下3桁が小数点以下となり「24.500℃」を意味します。
プログラム
実際のコード
以下は、上記のファイル /sys/bus/w1/devices/28-3c01d60775b9/w1_slave
を読み込み、「t=xxxxx」の部分を温度として画面上に表示するPythonスクリプトです。
#!/usr/bin/env python
import os
import glob
BASE_DIR = "/sys/bus/w1/devices"
TEMP_FILE = "w1_slave"
DIR_HEAD = "28-"
TEMP_RATE = 1000
def read_temp_raw(temp_file):
if not os.path.isfile(temp_file): return None
f = open(temp_file, 'r')
lines = f.readlines()
f.close()
return lines
def read_temp(temp_file):
lines = read_temp_raw(temp_file)
if lines is None: return None
if len(lines) < 2: return None
if lines[0].strip()[-3:] != 'YES': return None
t_pos = lines[1].find('t=')
if t_pos < 0: return None
t_str = lines[1][t_pos+2:]
try:
t_val = float(t_str) / TEMP_RATE
return t_val
except Exception:
return None
def main():
base_subdir = BASE_DIR + "/" + DIR_HEAD + "*"
ds_dirs = glob.glob(base_subdir)
if len(ds_dirs) == 0:
print("0.0")
else:
temp_file = ds_dirs[0] + "/" + TEMP_FILE
temp_val = read_temp(temp_file)
if temp_val is None: print("0.0")
else: print(temp_val)
if __name__ == '__main__':
main()
実行例
これを、たとえば「w1_temp.py」というファイル名で保存し、実行すると次のようになります。
$ python3 w1_temp.py
24.875
簡単な解説
関数 read_temp_raw(temp_file)
は、引数で受け取ったファイル名のファイルの内容を読み込み、行ごとのリストとして返します。
関数 read_temp(temp_file)
は、引数で受け取ったファイル名のファイル内容から、温度データを抽出し値を返します。
関数 main()
は、スクリプト実行時に呼び出される関数で、read_temp(temp_file)
を呼び出して温度データを取得後、画面上に出力します。
誰でも実行できるように
最後に、このスクリプトを誰でも実行できるように、別のディレクトリへコピーし、実行権を与えます。
$ sudo mkdir -p /usr/local/bin
$ sudo cp w1_temp.py /usr/local/bin/w1_temp.py
$ sudo chmod +x /usr/local/bin/w1_temp.py
実行してみます。
$ w1_temp.py
25.0
次回
今回は以上で終了です。
次回は、データを保存するサーバの構築を行います。
Discussion