RaspberryPi
EnOcean
SORACOM
SoracomHarvest
Pi-field

Pi-FieldとEnOceanを使って電源レスの温度測定システム

EnOceanとPi-FieldとSORACOM Airを使って電源不要の温度測定システム

こんにちは、木内です。この記事では、「Raspberry Pi」+「Pi-field(ラズパイ屋外稼働キット)」+「SORACOM Air」+「EnOcean」の組み合わせで電源レスの温度測定デモシステムを構築する方法について解説しています。


1.はじめに

メカトラックス社様からRaspberry Piのための屋外稼働キットである「Pi-field」をお借りすることができましたので、「EnOcean」と「Pi-field」と「SORACOM Air」を組み合わせが電源レスの温度計測システムを構築しました。

エネルギーハーベストにより蓄積した微細な電力を使っって通信を行うEnOcean搭載のセンサーデバイスからの情報をソーラーパネル搭載のPi-fieldで動作しているRaspberry Piで受信し、SORACOM Airを使用して、SORACOMが提供するSORACOM Harvestサービスにデータを転送します。EnOceanセンサー(STM-431J)および「Pi-field」は、それぞれ光発電により動作可能ですので、完全な電源レス環境を構築することができます。「slee-Pi」を使用してRaspberry Piを間欠動作させることにより省電力で動作させます。今回構築するデモシステムの大まかなシステム構成は次の通りです。

このデモシステムを構築するために必要な機材を以下に一覧にしましたのでご参考にしてください。


2.メカトラックス社Pi-Fieldについて

このデモシステムで使用するメカトラックス社社様からラズベリーパイ屋外稼働キット「Pi-field」を紹介します。pi-fieldを取り付けている黒いシャーシは今回のデモ用に取り付けたもので、キットには含まれません。

Pi-fieldは電源やネットワーク環境がない屋外でもRaspberry Piを使用した環境モニタリングが可能となる屋外稼働キットになります。ソーラーパネル、防水ボックス、鉛蓄電池、太陽電池充放電コントローラと、メカトラックス社の3G通信モジュール(3GPi)、電源管理・死活監視モジュール(slee-Pi)、Raspberry Piが含まれたキットになっています。防水ボックスを開くと次のようになっています。

Pi-fieldは、鉛蓄電池が含まれているため約18Kgぐらいの重量があり、縦置きする必要があります。背面のアルミフレームを使用して屋外に設置できるようになっています。しかし、筆者の環境では適当な外部に取り付ける場所が準備できなかったため、ホームセンターで入手したL型フレームを使ってシャーシを作りました。このL型フレームは本来は棚を作るフレームで、キャスタ(車輪)込みで2,500円ぐらいで作ることができました。

Pi-fieldに含まれているメカトラックス社のRaspberry Pi用の拡張ボードについても触れておきます、

ラズベリーパイ用電源管理/死活監視モジュール「slee-Pi」

Raspberry Pi専用に開発された電源管理・死活監視モジュールであり、搭載されたRTC内蔵マイコンにより時間管理を行い、Raspberry Piの間欠動作やウォッチドック(死活監視)などが可能です。Raspberry Pi向けのライブラリがオープンソースで提供されています。

ラズベリーパイ用3G通信モジュール「3GPi」

Raspberry Pi専用に開発された3G通信(携帯電話通信)モジュールであり、対応したSIMカードを使用して3G回線によりインターネット接続が可能になります。Raspberry Pi向けのライブラリや設定ファイルが提供されていますので、Raspberry Piを簡単にインターネットへ接続させることができます。


3.EnOceanとは

EnOceanは、太陽光や照明光、機械の発する振動、熱などのエネルギーを採取し、電力を得るエネルギーハーベストを利用した無線通信技術です。例えばスイッチを押す力を電気に変えたり、光発電パネルで起こした電気をコンデンサーに蓄積し、この電力で各種センサーのデータを送信するといった使い方ができます。
EnOceanの最も大きな特徴は、バッテリ不要で動作する無線通信になります。日本国内向けには928MHz帯の周波数帯を使用しており、通信到達距離は使用周波数や周辺環境に応じて30m〜300mとなっています。今回のデモシステムで使用したモジュールやデバイスを簡単に紹介します。

USB受送信モジュール「USB-400J」

USB 400Jは、USB接続によりEnOceanを使用した無線機器と受送信が可能なUSBドングルです。EnOceanで使用されているEnOcean Equipment Profile(EEP)の全メッセージフォーマットをサポートしており、Raspberry PiやPCからはUSB-Serialとして認識され、EnOceanの無線信号のテレグラムデータの送受信が可能になっています。

温度センサーモジュール「STM-431J」

今回のデモ構築に使用したSTM-431Jというデバイスは、光発電(ソーラーパネル)の搭載により、屋内の微弱な光でも発電して蓄電キャパシタに電気を蓄え、電池レスで動作可能な温度センサ無線モジュールです。マイコンを内蔵していますのでコンフィグレーションの変更や独自のファームウェアの搭載が可能です。

EnOcean プログラミングボード「EOD350」

STM-431Jや他のモジュールのコンフィグレーションの変更や独自のファームウェアの書き換えを行うためのプログラミングモードになります。今回のデモシステムではSTM-431Jのコンフィグレーションを変更するために使用します。EOD350ボードは、現在は単体での販売はされていないようで、EnOcean開発キット:EDK 400Jに含まれています。


4.SORACOM SIMのアカウント登録

このデモシステムで収集したデータをSORACOM Airを利用して、3G/LTEによりSORACOM Harvestにデータを蓄積させます。そのために、SORACOM AirのSIMを調達して、アカウント登録する必要があります。SORACOM Air for セルラー(SIM)は、アマゾンSORACOMコンソールから購入が可能です。今回はアマゾンから購入しました。

SORACOM AirのSIMを使用するためにSORACOMのアカウントの設定を行います。SORACOMのサイト:https://console.soracom.ioにアクセスします。

「アカウント作成」をクリックするとSORACOMオペレータ登録画面が表示されます。ここで使用するSIMは日本国内用のSIMなので、「カバレッジタイプJapan」を選択します。

氏名、メールアドレス、パスワードなど必要な情報を入力し、SORACOM利用規約を確認の上「アカウントを作成」をクリックします。

登録するSIMカードのIMSIコード(15桁)とパスコード(5桁)を入力します。名前はSIMカードにつける任意の名称です。ここでは「46Lab-SIM01」という名前で登録しました。「登録」をクリックするとSIMが登録されます。

SIMカードにIMSIコードとパスワードが記載されています。



SIMの登録が完了するとSORACOM コンソール画面で確認ができます。

以上でSORACOM Airのアカウント作成、およびSIMの登録は終了です。


5.Raspberry Pi3起動イメージ作成

Raspbianイメージのダウンロード

今回構築する環境では、GUIなどは使用しませんので、GUI環境などが含まれていないRaspbian Stretch Liteを使用します。Raspbianのサイト
からイメージファルをダウンロードします。

※注) 「Pi-field」には、メカトラックス社のSDカードが付属していますので、そのまま使用することも可能です。この付属SDカードには、Raspianに、 「3GPi」ユーティリティ、「slee-Pi」ユーティリティが追加されたイメージが書き込まれています。付属SDカードをそのまま使用する場合は、この記事の「5.Raspberry Pi3起動イメージ作成」、「7.slee-Piの設定」、「8.3GPiの設定」のステップは必要ありません。

イメージのSDカードへの書き込み

ダウンロードしたイメージファイルをmicroSDカードに書き込みます。Windows10、Linuxそれぞれの環境を使用したSDカードへのイメージ書き込み方法を説明します。


Windows10環境の場合:

etcher.ioを使用してイメージファイルをSDカードの書き込みます。etcher.ioのサイトにアクセスして書き込みソフトウエアをダウンロードします。ここでは「Etcher for Windows x64 (64-bit) (Portable)」を選択しててダウンロードします。

Etcher-Potable-1.4.3-x64.exeを実行すると、次のようにEtcherが起動されます。

「Select image」をクリックして、先ほどダウンロードした2018-XX-XX-raspbian-stretch-lite.imgを選択します。USB経由のSDドライブにmicroSDカードを挿入すると、自動的に認識します。「Flash!」ボタンをクリックするとmicroSDへのイメージの書き込みが行われます。Etcher.ioは本当に簡単にイメージ書き込みができるツールです。


Linux環境の場合:

ダウンロードしたイメージファイルを次のように解凍します。

$ unzip 2018-xx-xx-raspbian-stretch-lite.zip

LinuxホストPCにSDカードを挿入し、次のコマンドを実行します。of=/dev/sde の部分は、それぞれの環境により異なりますので注意してください。

$ dd if=2018-03-13-raspbian-stretch-lite.img of=/dev/sde bs=1M

シリアルコンソールのための設定

今回の環境では、Raspberry PiにHDMIモニターやUSBキーボードを使用しないため、USB-Serial(TTL)変換ケーブルを使用してシリアルコンソールを使用します。Raspberry Pi3の場合、シリアルコンソールを使用するためにコンフィグレーションの変更が必要です。Raspberry Pi3では、今まで使えていたUARTのピンをBluetoothが使用していますので、UARTのための変更が必要になります。イメージが書き込まれたmicroSDカードの設定ファイルを直接、Windows10やLinuxホストで変更します。

イメージが書き込まれたmicroSDカードを一度抜いて、再度、Windows10 PC(あるいはLinux PC)に挿入してマウントします。イメージが正常に書き込まれているmicroSDカードは、/bootパーティションがFATフォーマットになっていますので、Windows10、Linuxのどちらでも自動的に認識してマウントされるはずです。

マウントされたSDカードの/boot/config.txtというファイルをテキストエディタなどで変更します。このconfig.txtファイルは、改行がLF(Unix系改行)になっていますので、Windows系の標準のエディタでは一行で表示されてしまい上手く編集ができませんのでご注意ください。sakura editorなど改行をLFに変更できるようなエディタを使用してください。

/boot/config.txtの最後の行に以下の行を追加して、ファイルを保存してください。

/boot/config.txt
# 最後の行に追加します。
dtoverlay=pi3-miniuart-bt

microSDカードのアンマウントしてPCから取り出し、Raspberry Pi3に挿入します。

Raspberry Pi3起動

Raspberry Pi3を起動する前に、USB-Serialケーブルと有線のネットワークケーブルを接続します。USB-Serialが接続されているPCには、USB-Serialケーブルのためのデバイスドライバのインストールが必要な場合もあります。USB-Serialケーブルの設定に従ってあらかじめドライバーなどをWindows10やLinuxPCにインストールしておいてください。PC側は、TeraTermやminicomといった通信ターミナルソフトウエアを使用して、ボーレート:115200で接続します。


6.Raspbianの設定

Raspberry Pi3でRaspbianが起動しましたので、追加ソフトのインストールや各種設定を行います。インターネットから追加のソフトウエアなどのダウンロードを行いますので、有線Ethernetを接続して、作業を行います。

Raspbianのアップデート

まずは次のコマンドでRaspbianを最新の状態にアップデートします。

$ sudo apt-get update 
$ sudo apt-get upgrade

SSHの設定

シリアルコンソールで操作はできますが、sshによりログインできた方が作業はしやすいので、sshdを有効にします。この作業は任意です。
コンソールから次のコマンドを実行してsshを有効にします。

$ sudo raspi-config

これで他のホストからssh でログインできるはずです。

他のホストからsshでログインする場合は次のようなコマンドで行います(Linuxの場合)。

$ ssh -l pi <ipaddress>
 SSHの補足

“Read from socket failed: Connection reset by peer”などとでてsshでの接続ができない場合、次のような手順でsshが使えるようになります。
  (1) raspi-config で SSH をオフ
  (2) sudo rm /etc/ssh/ssh_host_* && sudo dpkg-reconfigure openssh-server
  (3) sudo touch /boot/ssh
  (4) raspi-config で SSH をオン
これでできるようになるはず。

Timezone変更

次に、Raspberry Piのtimezoneの設定を行います。
コンソールから次のコマンドを実行してtimezoneを変更します。

$ sudo raspi-config

raspi-configの以下のところにtimezoneの設定がありますので、「Asia ---- Tokyo」を選択します。
  4.Localisation Options ---- I2 Change Timezone
    Asia ---- Tokyo

不必要なサービスの無効化

今回使用しているRaspbian Stretch Liteは、GUIなどが含まれてませんので、フルセットのRaspberianより起動されているサービスは少ないのですが、このデモシステムで明らかに使用しないいくつかのサービスを無効化します。

$ sudo systemctl disable Bluetooth
$ sudo systemctl disable hciuart
$ sudo systemctl disable triggerhappy
$ sudo systemctl disable apt-daily.timer

7.「slee-Pi」の設定

次にslee-Piの設定を行います。slee-Piで使用するライブラリやユーティリティは、メカトラックス社のgithubで公開されています。次の手順で、slee-Pi関連のソフトウエアをRaspberry Piにインストールします。インストールは外部のサイトよりファイルをダウンロードしますので、Raspberry Piを有線のEthernetや無線LAN環境に接続しておく必要があります。ここでは有線のEthernetケーブルをRaspberry Piに接続してインストールを行っています。

メカトラックス社のレポジトリなどの情報を追加します。

$ sudo bash -c 'echo "deb http://mechatrax.github.io/raspbian/ stretch main contrib non-free" > /etc/apt/sources.list.d/mechatrax.list'
$ wget http://mechatrax.github.io/raspbian/pool/main/m/mechatrax-archive-keyring/mechatrax-archive-keyring_2016.12.19.1_all.deb
$ sudo dpkg -i mechatrax-archive-keyring_2016.12.19.1_all.deb

次にslee-Piに関連するパッケージをインストールします。

$ sudo apt-get update
$ sudo apt-get install sleepi2-firmware sleepi2-utils sleepi2-monitor

slee-Piに関連するパッケージのインストール時に、/boot/config.txtにDevice TreeのOverlayを有効にする記述が追加されます。このDevice Tree Overlayを有効にするために、slee-Piに関連するパッケージをインストール後に次のようなコマンドでRaspberry Pi3を再起動します。

$ sudo shutdown -r now

Raspberry Piが再起動されたら、再度ログインして、次のコマンドを実行してシステム時刻をリアルタイムクロックに反映します。

$ sudo hwclock -w

sleep-Piの動作をテストしてみます。次のコマンドを使用して一定時間後に起動させます。

$ sudo sleepi2alarm -set “+5min”
$ sudo poweroff

5分後にraspberry Piが起動されてばsleep-Piのセットアップは終了です。


8.「3GPi」の設定

3GPi向けのユーティリティと設定ファイルをインストールします。すでに、slee-Piのセットアップ時にメカトラックス社のレポジトリを追加してあるので、次のコマンドでインストールすることができます。

$ sudo apt-get install 3gpi-utils
$ sudo apt-get install 3gpi-network-manager

次に、3GPIでSORACOM Airが使えるようにAPNを設定します。

$ sudo nmcli con add type gsm ifname "*" con-name SORACOM apn soracom.io user sora password sora

SORACOM Air SIMを3GPiに挿入して、再起動すると自動的にSORACOMに接続されます。SORACOMコンソールにログインすると登録されているSIMがオンライン表示になることが確認できます。


9.EnOcean USB400Jの設定

EnOceanの受送信モジュールであるUSB400Jは、Raspberry Piに接続するとUSB-Serialとして認識され、デバイスファイルとして/dev/ttyUSBXXXといった名称が割り当てられます。このシステムでは「3GPi」などもUSB-Serialを使用していますので、デバイス名を固定化しておく必要があります。

udevによるデバイスファイル名の固定化は、/etc/udeb/rules.d/xxxxxx.rulesで行います。まず、今回使用するUSB400JのベンダーIDとプロダクトIDを調べます。

USB400Jを挿入していない状態で、Raspberry Piのコンソールでlsusbを実行します。

$ lsusb
Bus 001 Device 004: ID 05c6:9000 Qualcomm, Inc. SIMCom SIM5218 modem
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp. SMC9514 Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

次にUSB400Jを挿入して、lsusbを実行します。

$ lsusb
Bus 001 Device 004: ID 05c6:9000 Qualcomm, Inc. SIMCom SIM5218 modem
Bus 001 Device 006: ID 0403:6001 Future Technology Devices International, Ltd FT232 USB-Serial (UART) IC
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp. SMC9514 Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

USB400Jの挿入前後で変わった
Bus 001 Device 006: ID 0403:6001 Future Technology Devices International, Ltd FT232 USB-Serial (UART) IC
がUSB400Jの情報になります。

ID 0403:6001の内、ベンダーIDが0403、プロダクトIDが6001になります。この情報を元に、/etc/udev/rules.d/99-local.rulesに下記の設定を追加します。デフォルトでは/etc/udev/rules.d/99-local.rulesというファイルはありませんので、viエディタなどで新規に次のように作成します。

$ sudo vi /etc/udev/rules.d/99-local.rules`


/etc/udev/rules.d/99-local.rules
# For EnOcean USB400J
KERNEL=="ttyUSB*",  ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", SYMLINK+="ttyUSB400J"

ここでのシンボリックリンク名:ttyUSB400Jは任意の名前です。

USB400Jを外して、挿入し直します。/dev/ttyUSB400Jが認識した/dev/ttyUSBXXにシンボリックリンクしていることが確認できます。

$ ls -al /dev/ttyUSB400J
lrwxrwxrwx 1 root root 7 Apr 20 10:16 /dev/ttyUSB400J -> ttyUSB4

10.EnOcean STM-431Jの設定

EnOceanの温度センサーモジュール:STM-431Jのコンフィグレーションを変更します。STM-431Jのデフォルトの設定では、蓄積されている電力量などによりランダムに温度データを送信しているようです。これだと一定時間後のデータ測定が困難なので、一定時間ごとに温度データを送信するようにコンフィグレーションの変更を行います。コンフィグレーションの変更には、EnOceanプログラムボード:EOP350とEnOcean開発者向けのツールが必要になります。

EnOceanのサイト:https://www.enocean.com/jp/download/から次の2つのツールをダウンロードしてインストールします。サポートしているホスト環境はWindowsだけです。

  • EnOcean Dolphin V4 Suite
  • EnOcean DoplhinView Basic

EnOceanプログラムボードEOP350にSTM-431J(温度センサーモジュール)を取り付け、USBケーブルでWindows環境に接続します。

Dolphin V4 Suiteに含まれているDolphine V4 Module Configuratorを起動します。EOP350が接続されているポートとコンフィグレーションを行うSTM-431Jを選択します。

Dolphin V4 Module Configuratorの上段にある「Read configuration from flash」をクリックして、現在のSTM-431Jに書き込まれているパラメータを読み込みます。

変更するパラメータは次の3箇所になります。

  • Cyclec wake-up
  • Redundant retransmission(cyclic wake-up): Min
  • Redundant retransmission(cyclic wake-up): Max

「Cyclec wake-up」はSTM-431Jがウェイクアップされる周期を秒数で指定します。デフォルト値は65535となっておりハードウェアの設定となっています。これを60秒に指定します。
「Redundant retransmission(cyclic wake-up) Min/Max」は、Wake-up何回に1度データを送信するかを設定するパラメータになります。MinとMaxで指定した間のランダム回数ごとに送信するといった設定を行います。これをMax/Min共に「1」と設定することで、Wake-up毎に毎回データを送信するようにします。

STM-431Jは、小さな蓄電キャパシタ(電池)を内蔵していますので、昼間にソーラーパネルで発電した電力を蓄えることができ、光発電ができない夜間も動作することが可能です。しかし、この蓄電キャパシタは非常に小さな電力しか蓄えられませんので、どれぐらいの周期でWake-upさせて、どれぐらいの頻度でデータ送信するかが重要になります。STM-431Jのマニュアル(ここからダウンロードできます)にWake-up周期とデータ送信の頻度の関係についてのデータが提供されています。

「STM 431J User Manual | v2.0 | Nov 2017」 www.enocean.comより抜粋

60秒毎にWake-upし、毎回データ送信をする設定にしたSTM-431Jを室内に置いた状態で実際に試したところ、24時間稼働できていることを確認できました。

EnOcean STM-431Jが実際にどのようなデータを送信しているかについては、DolphinView Basicツールを使って確認することができます。USB400JをWindowsホストに挿入し、DolphineView Basicツールを起動します。USB400Jが挿入されているポートを指定すると、EnOceanのデータをモニタリングすることができます。


11.SORACOM Harvest設定

SORACOM Harvestは、SORACOMプラットフォームが提供するデータ収集・蓄積サービスです。SORACOM Harvestを利用することで別途サーバーやストレージを準備することなくデータの収集と保存、データの可視化を行うことができます

SORACOM Harvestを使用するには、SORACOMコンソールから設定します。SORACOM Harvestの設定は、SIMのグループ毎に行います。SIMに対してグループを設定し、そのグループに対してSORACOM Harvestを有効化します。

指定するSIMを選択して、「操作」→「所属グループ変更」 を選択します。

「新しい所属グループ」をクリックして、「新しいグループを作成….」を選択します。

グループ名入力のウィンドウが表示されますので、任意のグループ名を入力して「グループ作成」をクリックします。ここではHarvest01というグループ名を作りました。

SIMの一覧から今作成した「Harvest01」というグループ名をクリックするとグループ毎の設定が表示されます。この中の「SORACOM Harvest設定」をクリックします。SORACOM Harvest のスイッチを「ON」にして「保存」をクリックします。以上でSORACOM Harvestの有効化は終了です。

SORACOM Harvestにデータを送信するにはHTTPあるいはTCP/UDPによって行います。HTTPでデータを送信する場合は、Raspberry Piのコンソールから次のようなコマンドで行うことができます。実際にSORACOM Harvestにデータ送信する場合、有線のEthernet接続や、WiFi接続などは切ってください。SORACOM Harvestは、登録されているSORACOM Air SIM経由のデータしか受け付けません。有線のEthernet接続を行なっている場合、Defalt Gatewayの設定によっては、Ethernet経由で送信してしまいますので、データを受け取ってくれません。

$ curl -v -X POST -H 'content-type:application/json' -d '{"temperature01":25}' http://harvest.soracom.io
$ curl -v -X POST -H 'content-type:application/json' -d '{"temperature01":21,"temperature02":18}' http://harvest.soracom.io

12. SORACOM Harvestへの送信プログム

いよいよ実際にEnOceanの温度センサーから受け取ったデータをSORACOM Harvestへ送信するプログラムを作成します。プログラムはpythonで作りました。このプログラムに依存するpythont追加パッケージをインストールします。Raspberry Piのコンソールから次のコマンドでインストールを行います。

$ sudo apt-get install python-serial
$ sudo apt-get install python-requests

※注)$ sudo pip install serial これだとpython で/dev/ttyUSBXXXがオープンできなかった。原因はまだ調べていません。

実際のプログラムは次のようになっています。このプログラム作成にあたり「PythonでEnOceanの電文を読み取る」を参考にさせていただきました。

import requests
import json
import serial
from sys import exit
from datetime import datetime

PORT = '/dev/ttyUSB400J'              # USB400Jが接続されているデバイス名
URL = 'http://harvest.soracom.io/'    # SORACOM HarvestのURL
SENSORID1 = '04:01:53:e1'             # 1つ目のSTM-431JのID
SENSORID2 = '04:00:6f:e5'             # 2つ目のSTM-431JのID

# この関数でSORACOM HarvestにHTTPによりデータを送信しています。
def sendData(strings, temp_data):
        headers = {'content-type': 'application/json'}
        payload = {strings:temp_data}
        print payload
        req = requests.post(URL, data=json.dumps(payload), headers=headers)

# この関数はシリアルポートから1バイトづつデータを読み込み、EnOceanのテレグラムを解析しています。
# テレグラムを解析後、デバイスIDが一致した場合だけSORACOM Harvestにデータを送っています。
def EnoceanSensor(s_port):
    sensor1_rdy = False
    sensor2_rdy = False
    cnt = 0
    dataLen = 0
    optLen = 0
    telegraph,headList,dataList,optList = [],[],[],[]
    ready = True

    while True:
        if sensor1_rdy and sensor2_rdy:
            break

                # 1byteつづシリアルポートからデータを読み込みます。
        s_data = s_port.read().encode('hex') # read 1byte

                 # Sync-Byteの0x55をからテレグラムデータの開始を認識します。
        if s_data == '55' and ready: # Telegram start
            # valuable reset
            cnt = 0
            dataLen = 0
            optLen = 0
            ready = False
            telegraph,headList,dataList,optList = [],[],[],[]

        cnt += 1
        telegraph.append(s_data)

                # テレグラムデータを解析しています。
        if 2 <= cnt <= 5: # header
            headList.append(s_data)
        if cnt == 5: # header end, get data length
            dataLen = int(headList[1],16)
            optLen  = int(headList[2],16)
        if 7 <= cnt <= (6+dataLen): # data
            dataList.append(s_data)
        if (7+dataLen) <= cnt <= (6+dataLen+optLen): # optional data
            optList.append(s_data)
        if cnt == (6+dataLen+optLen+1): # Telegram end
            ready = True
            sensorId = ':'.join(dataList[1:5]) # Sensor ID
            timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')

            # デバッグ用にデータを表示させています。
            print "========"
            print timestamp
            print 'telegraph...:', ':'.join(telegraph)
            print 'head...', ':'.join(headList)
            print 'data...', ':'.join(dataList), '(length=%d)' % dataLen
            print 'opt ...', ':'.join(optList),  '(length=%d)' % optLen
            print 'sensorID...', sensorId


            # Temp sensor1 センサーIDが一致したらデータ送信します。
            if sensorId == SENSORID1 and sensor1_rdy == False:
                val = int(dataList[7],16)
                sensor1_temp = round((255.0-val)/255.0*40.0, 2)
                sendData('temperature01', sensor1_temp)
                sensor1_rdy = True

            # Temp sensor2  センサーIDが一致したらデータ送信します。
            elif sensorId == SENSORID2 and sensor2_rdy == False:
                val = int(dataList[7],16)
                sensor2_temp = round((255.0-val)/255.0*40.0, 2)
                sendData('temperature02', sensor2_temp)
                sensor2_rdy = True

            # Other sensors, ignore ID
            else:
                continue

# main関数です。シリアルポートを開いて上記のEnoceanSensor関数を実行しているだけです。
if __name__ == '__main__':
        # Open serial port
        try:
                s_port = serial.Serial(PORT, 57600)
                print('open serial port: %s' % PORT)
        except:
                print('cannot open serial port: %s' % PORT)
                exit(1)

        EnoceanSensor(s_port)

print "Done!"

STM-431J温度センサーモジュールを2個使用しています。プログラムの中でそれぞれのIDを定義していますが、これらのIDはEnOceanデバイス毎にあらかじめ設定されているIDになります。

SENSORID1 = '04:01:53:e1'
SENSORID2 = '04:00:6f:e5'

この関数で、温度データと文字列をJSON形式に変更し、HTTPプロトコルでSORACOM Harvestに送信しています。

import requests
import json

#......一部省略.....
def sendData(strings, temp_data):
        headers = {'content-type': 'application/json'}
        payload = {strings:temp_data}
        print payload
        req = requests.post(URL, data=json.dumps(payload), headers=headers)

13.自動実行、定周期起動

このシステムは「slee-Pi」を搭載していますので、この機能を利用してRaspberry Piを間欠動作させます。作成したPythonのプログラムの自動実行とslee-Piとcronサービスを使用した間欠動作の設定を行います。

プログラムの自動起動

Linux(Raspbian)が起動した時に自動的にプログラムを実行する方法は色々ありますが、ここではsystemdによるサービス起動方法を利用して、作成したプログラムを起動毎に実行させます。次のようなファイルを新規に作成します。

/etc/systemd/system/enocean.service
#  File:/etc/systemd/system/enocean.service
[Unit]
Description=EnOceanTempuratureSensor
After=syslog.target

[Service]
Type=simple
WorkingDirectory=/home/pi
ExecStart=/usr/bin/python /home/pi/enocean-soracom.py 
TimeoutStopSec=5
#StandardOutput=null
StandardOutput=/home/pi/enocean.log

[Install]
WantedBy = multi-user.target

次のコマンドで設定したサービスを起動することができます。

$ sudo systemctl start enocean

動作確認ができたので、自動起動するように設定します。

$ sudo systemctl enable enocean

自動起動をやめるときは次のコマンドで設定します。

$ sudo systemctl disable enocean

自動起動については「Raspberry Piでプログラムを自動起動する5種類の方法を比較・解説』を参考にさせていただきました。

定周期起動

一定周期でのRaspberry Piの起動(間欠動作)は、slee-Piの機能とcronサービスを利用します。一定周期毎にcronによりRaspberry Piをシャットダウンさせます。シャットダウンさせる寸前にslee-Piにアラームを設定し、再起動させます。

Raspberry Piでcronを使用する場合、パッケージの追加が必要です。cronではエラー処理でメール送信を行うためpostfixをあらかじめインストールする必要があります。

$ sudo apt-get install postfix

インストール時にConfigrationメニューが出ますが、ここでは実際にメール送信は行わないのでLocal onlyを選択します。

次に、cronが実行するシェルスクリプトを作成します。このシェルスクリプトでは、slee-Piに10分後のアラーム(再起動をセット)の設定を行い、シャットダウンさせるだけになります。このシェルスクリプト はrootユーザで実行させます。次のようなコマンドでシェルスクリプト を作成します。

$ sudo su
$ cd
$ vi sleepi2pon.sh
/root/sleepi2poff.sh
# !/bin/sh
/usr/sbin/sleepi2alarm –set “+10m”
/sbin/poweroff

次にcronの設定を行います。cronで毎時05、20、35、50に作成したシャットダウンスクリプトを実行させます。slee-Piで10分後に再起動させるので、およそ毎時0、15、30、45分に再起動されます。

次のコマンドでcronの設定を行います。

$ sudo crontab -u root -e

次のように起動させる時間と起動するプログラムを設定します。

# m h  dom mon dow   command
05,20,35,50 * * * * /bin/sh /root/sleepi2poff.sh

これで毎時、5分、20分、35分、50分にsleepi2poff.shスクリプトが実行されます。


14.稼働

これで電源レス温度測定システムが構築できましたので、実際に運用してみます。「Pi-field」はソーラ発電を行う必要がありますので、自宅マンションの庭に設置しました(家族には邪魔扱いされましたが....)。

温度センサーモジュール:STM-431Jが2個ありますしたので、屋外のマンションの壁と室内にそれぞれ両目テープで貼り付けました。

設置後、「Pi-field」の電源を投入し1週間ほど運用させました。収集されたEnOceanの温度センサーデータは、SORACOMコンソールから確認することができます。
SORACOM コンソールでSIMを選択します。「操作」->「データを確認」を選択します。

SORACOM Harvestで収集したデータをグラフ化して表示することができます。

今回は温度センサーを2箇所に設置したデータとなっています。赤色のグラフ(temperature01)が屋外に設置したセンサーデータ、青色のグラフ(temperature02)が屋内に設置したセンサーデータになります。設置した自宅はマンションですので、屋内の温度変化が少ないことがわかります。屋外のデータで30℃を超えている時間帯がありますね。実際の気温はそこまで上がってはいなかったので、直射日光がセンサーに当たってしまったのかもしれません。


15.終わりに

盛りだくさんの内容となってしまいましたが、「Raspberry Pi」+「Pi-fiels(ラズパイ屋外稼働キット)」+「SORACOM Air」+「EnOcean」を組み合わせたシステムの構築の雰囲気がわかってもらえたかと思います。エネルギーハーベストは、これから色々と応用がききそうな分野です。新しいアイデアが生まれてきそうです。


参考記事