ラズパイでセンサーのデータを継続的に記録する(ソフトウェア編)
前回の続きで、Raspberry pi 2に接続した温度センサーから繰り返しデータを取得して、自室の気温の変化を見てみたいと思います。SPIデバイスの準備から、Pythonモジュールの準備など、いろいろ大変でした。忘れてしまってここに書き切れていない部分があるかもしれません。以下順を追って説明します。
SPIデバイスを使える状態にする
Raspberry pi 2のSPIバスは、最初封印された状態なので使えません。/boot/config.txtに以下の記載を追加して、ラズパイごと再起動する必要があります。以下の記載は本家のフォーラムに出ていた話題なのですが、Raspberry pi 2とカーネル3.18が出てから必要になったんだとか。ついでにI2Cバスも有効にしていますが、ここでは説明はしません。
# Added by myself # http://www.raspberrypi.org/forums/viewtopic.php?p=675658#p675658 dtparam=i2c_arm=on dtparam=spi=on
ネットを探すと/etc/modprobe.d/raspi-blacklist.confを編集する必要がある、というような記載も多々見つかるのですが、私の環境にはこのファイルはありませんでした。でも、この設定で動いています。
実際にSPIが有効になったかどうかどうかは、以下のコマンドでspidev0.0とspidev0.1のデバイスファイルが存在しているかどうかで確認できます。
pi@raspberrypi:~/work$ ls -l /dev/spi* crw-rw---T 1 root spi 153, 0 1月 1 1970 /dev/spidev0.0 crw-rw---T 1 root spi 153, 1 1月 1 1970 /dev/spidev0.1 pi@raspberrypi:~/work$
Pythonモジュールpy-spidevの準備
SPIバスからデータを取得するプログラムをPythonで書くわけですが、それにはpy-spidevというモジュールが必要です。だいたい以下のような手順です(おおざっぱですが)。
$ cd ~ $ git clone git://github.com/doceme/py-spidev $ cd py-spidev $ sudo python setup.py install
Pythonスクリプトから呼び出せるようになったかどうか確認するには、以下のようにPythonをインタラクティブに呼び出してエラーがでなければOKです。
pi@raspberrypi:~$ python Python 2.7.3 (default, Mar 18 2014, 05:13:23) [GCC 4.6.3] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import spidev >>> >>> pi@raspberrypi:~$
Pythonスクリプトを書こう
さて、いよいよ本番、センサーを読むプログラムを書きます。実はこちらのサイトにあるスクリプトを参考にさせてもらいました。ただ、最終的にはかなり書き換えています。
- 使っている温度センサーは別物ですので、計算を書き換え
- Ctrl+Cで終了したときにSPIバスが開かれたままになってしまうことを避けるため、最後の掃除用の処理を追加
- 温度センサーMCP9700の精度はかなり悪い(±4℃)ので、毎秒1回センサーのデータを読んで、60回分の平均をとり、それを室温として記録
- 室温の記録はカレントディレクトリのdata.tsvにタブ区切り(Tab Separated Value)形式で保存
- ついでに明度センサ(CDSセンサ)の値もとっていますが、変換式は適当です
pi@raspberrypi:~/work$ cat my_mcp3008_tmp36.py #!/usr/bin/python # -*- coding: utf-8 -*- import spidev import time from collections import deque import signal import sys import RPi.GPIO as GPIO from datetime import date from datetime import datetime # センサーがつながっているMCP3008のチャネル cds_channel = 0 temp_channel = 1 # LEDが接続されているGPIOポートの番号 led = 18 # キューに保存するデータの最大数 max_data = 60 # SPIバスへのアクセスを開く spi = spidev.SpiDev() spi.open(0,0) def ReadChannel(channel): """ MCP3008経由でアナログセンサからのデータを受け取る。 channelはMCP3008の入力チャンネルで、0から7の値 """ adc = spi.xfer2([1,(8+channel)<<4,0]) data = ((adc[1]&3) << 8) + adc[2] return data def ConvertVolts(data, places): """ MCP3008から受け取ったデジタルデータを、アナログセンサの 出力電圧に変換する計算をする。placesは有効桁数。 """ volts = (data * 3.3) / float(1023) volts = round(volts, places) return volts def ConvertTemp(volts, places): """ 電圧をセンサーが検知した温度に変換する。 """ temp = ( 100 * volts ) - 50.0 temp = round( temp, places ) return temp def exit_handler(signal, frame): """ Ctrl+Cが押されたときにデバイスを初期状態に戻して終了する。 """ print("\nExit") spi.close() GPIO.cleanup() sys.exit(0) # # メインルーチン # # 終了時に処理するシグナルハンドラを準備 signal.signal(signal.SIGINT, exit_handler) # LEDを点灯するためのGPIOを用意 GPIO.setmode(GPIO.BCM) GPIO.setup(led, GPIO.OUT) # データ保管用のキューを用意 queue = deque() # ログファイルの用意 # tsvfile = open('data'+datetime.now().strftime("%Y%m%d_%H%M%S")+'.tsv', 'a') tsvfile = open('data.tsv', 'a') data_count = 0 while True: # LEDを点灯する GPIO.output(led, True) time.sleep(0.2) # 温度センサーを読む temp = ConvertTemp( ConvertVolts( ReadChannel( temp_channel ), 4), 4) # 明度センサーを読む cds = ConvertTemp( ConvertVolts( ReadChannel( cds_channel ), 4), 4) # 平均値を出すためにデータを保存しておく # 一定の数データが溜まったら、古い物から削除 queue.append((temp, cds)) if len(queue) > max_data: queue.popleft() # 平均値を求める sum1 = 0.0 sum2 = 0.0 for d in queue: sum1 += d[0] sum2 += d[1] ave_temp = sum1 / len(queue) ave_cds = sum2 / len(queue) # コンソールへ結果を表示 print "(温度, 明度)=(%6.2f, %6.2f) 平均 = (%6.2f, %6.2f)" % (temp, cds, ave_temp, ave_cds) # 一定の回数ごとに平均値を記録 data_count += 1 if data_count == max_data: d = datetime.now() tsvfile.write("%s\t%6.2f\t%6.2f\n" % (datetime.now().strftime("\"%Y/%m/%d %H:%M:%S\""), ave_temp, ave_cds)) tsvfile.flush() data_count = 0 # LED消灯する GPIO.output(led, False) time.sleep(0.8) pi@raspberrypi:~/work$
さて、実行
前回も書きましたが、ハードウェアに直接アクセスするプログラムを実行するには、管理者権限が必要です。sudoして実行しましょう。
pi@raspberrypi:~/work$ chmod +x my_mcp3008_tmp36.py pi@raspberrypi:~/work$ sudo ./my_mcp3008_tmp36.py
明度(CDS)センサが気になる人がいるかもしれないので一応写真を挙げておきます。
取得された室温データは、以下のような形式になっていて、Excelなどで利用することもできます。
pi@raspberrypi:~/work$ more data20150304_153031.tsv "2015/03/04 15:31:30" 23.92 247.36 "2015/03/04 15:32:30" 23.86 246.96 pi@raspberrypi:~/work$
次回は取得したデータをグラフにするところを書こうと思います。
- 出版社/メーカー: Raspberry Pi
- メディア: エレクトロニクス
- この商品を含むブログ (3件) を見る