(注:XOceanは販売を終了しています。そのほかの受信モジュールでも同様の電子工作は制作可能ですので、ご自身で取り組まれる際の参考にしてください。)
みなさん、はじめまして。新米ライターの小西と申します。私、組み込み系の知識はあるものの電子工作の経験が浅いのですが、Makersブームの波にのって電子工作にチャレンジしたいと思います!
というのも、先日、上司に「君にEnOceanを扱えるかな……?フッフッフ」とバカにされちゃったのです。
「な、なんだ!EnOceanって!汗」と思いつつも、彼にギャフンと言わせるべく、そして最後には「Good Job!」が聞きたい、という不純な動機で、この「超入門」の場をお借りして、記事を書き始めたのであります……。
そもそもEnOcean通信って、なんだろう……
http://www.enocean.com/jp/home/
http://www.rohm.co.jp/web/japan/enocean
EnOcean通信とは、エナジーハーベスト(環境発電)と無線通信が組み合わされた技術だそうです。スイッチを押す力を電気エネルギーに変換したり、室内照明の光を電気エネルギーに変換して、その電力をセンシングや無線通信に使うのだそうです。要するに、発電機構を内蔵した、無線センサなのですね。自分で発電して動くので、電池交換が不要。すなわち、一度置いたらほったらかしにしても良いということです。おもしろい技術ですね。
ググってみると、いろんな製品があります。
温度センサと湿度センサが環境測定としてはわかりやすそう。組み込みケースも用意されているのですね。これなら実際に設置も可能です。
というわけで、みなさんもお馴染みのArduinoと、ニューカマーのEnOceanで、温湿度センサを2回に渡って作ってみましょう。
今回はセンサ情報の収集をやってみたいと思います。
今回の電子工作レシピ
完成までの時間目安:120分 難易度:(★★★★☆)
必要なパーツ
- Arduino本体(Arduino Uno R3) http://www.switch-science.com/catalog/789/
- XOcean(EnOcean送受信モジュール) ※XOceanは販売を終了しています。その他の受信モジュールで代用ください。
- XBeeシールド http://www.switch-science.com/catalog/1262/
- EnOcean温湿度センサ(STM431J+HSM100) http://www.zaikostore.com/zaikostore/itstoreWireless?cid=3
- カラー漢字LCDシールド http://www.switch-science.com/catalog/1427/
- USBケーブル http://www.switch-science.com/catalog/1033/
さっそくコアスタッフで温湿度センサを買ってみました。
ケースに入った状態手に入れましたが、温湿度センサがどういった構成になっているか確認しましょう。中身の大きさは5cmくらい。意外と小さい印象。
温度センサモジュールと、湿度センサを接続します。
コネクタを合わせてあるので、ブスっと挿すだけで簡単に接続できます。
次にケースに組み込んでみました。これも、簡単に組めました。
意外とコンパクトで、存在感なくセンサが置けそうな気がします。
センサは、送信側になるので、受信側も準備が必要なのですね。Gateway開発KITのようなKITも出ているようですが、今回はArduinoを使います。
色々とネットで探していると、EnOceanが乗っている新しいモジュールが出るみたいです。それが題名にもある「XOcean」という、EnOcean通信モジュールです。こちらは2015年7月末よりコアスタッフで販売開始しているようなので、さっそくできたてホヤホヤを入手しちゃいました。(XOcean世界最速レポートなるか?)
XBee®コネクタにそのまま挿せるタイプなのですね。
黄色い配線は、アンテナか。TELECマークもついているので、電波法も問題なし、と。
持っていたArduino基盤に、XBeeコネクタがついていなかったので(汗)、まずはXBeeシールドに接続します。XBeeシールドのシルクに合わせて接続すれば良いようです。
続いてXBeeシールドをArduinoに接続しました。こちらもピンをArduinoのシールド用コネクタに合わせて接続するだけです。
さらに同じようにLCDシールドを接続します。
これで、ハードウェアはそろいました!非常に簡単で、作業時間は5分もかかりませんでした。
それでは、さっそくソフトウェアの開発に移りましょう。いきなりLCDシールドまで接続して動作させようと思うとやることが多すぎて大変なので、ArduinoとXOceanでPCのディスプレイ上に温湿度センサのデータ表示をしましょう。一歩ずつ着実に……。
さて、EnOcean通信が電池不要で動くのはわかりましたが、実際どのようなデータが送られているかわからないので規格やプロファイルを調べました。
EnOceanの無線通信とシリアル通信規格、機器情報プロファイル
無線通信とシリアル通信の規格および機器情報プロファイルが決められています。
センサも色々あるので、無線データの配列を決めておかないと、無意味なデータになってしまいます。また、データ配列をいちいち覚えてられないので、機器情報も決められているのですねー。(EnOcean通信に限らず、無線としては、当たり前か…)
無線通信はEnOcean Radio Protocol(ERP)、シリアル通信はEnOcean Serial Protocol(ESP)、機器情報プロファイルはEnOcean Equipment Profile(EEP)という名称で規定されていて以下URLからドキュメントをダウンロードできます。
ERP:http://www.enocean.com/erp2/
ESP:http://www.enocean.com/esp
EEP:http://www.enocean-alliance.org/eep/
ArduinoとXOceanはシリアル接続となるのでESP3の内容がわかればArduinoでEnOcean製品のセンサ情報が取得できますね。
XOceanのデータを受信する
XOceanはArduinoの1,2番ピンと接続されているようなので、Arduinoのハードウェアシリアルを使ってXOceanのデータを受信しました。
void setup() { Serial.begin(57600); // 57600bps-EnOcean Serial Protocol 3 }
ハードウェアシリアルのボーレート変更
EnOceanの製品はUARTというシリアル通信で接続されるみたいなので、このようにボーレートをEnOceanの製品に合わせ込みます。ボーレートの合わせ込みができればデータを受信できるようになりそうです。
それでは受信したデータを確認してみましょう。受信したデータをそのままArduino IDEのシリアルモニタ上に表示させています。
void loop() { unsigned char dataReceive = 0 ; //受信確認フラグ unsigned char aChar = 0 ; //データ格納用変数 char buf[1] ; while(Serial.available()>0){ // XOcean受信したか? delay(5); aChar = Serial.read(); // シリアルデータ取得 // シリアルモニタ出力 sprintf(buf, "%02X", aChar); Serial.print(buf); Serial.print(" "); dataReceive = 1 ; } if(dataReceive ==1){ Serial.println(""); }
受信したデータを変数であるaCharに格納し、取得したデータを16進数の文字列としてArduino IDEのシリアルモニタを使ってディスプレイ上に出力させました。ちなみにArduinoのIDEのシリアルモニタはメニューバーの「ツール > シリアルモニタ」を選択して立ち上げることができます。
シリアルモニタを立ち上げた際、画面右下にあるボーレートを57600bpsへ変更するのを忘れずに!最初変な文字が出てきて焦りました…
ボーレートを変更してEnOceanからデータが送られてきました。
こんな感じでEnOceanの製品からデータが送られてきてるんですね。データが受信できただけでなんとなく出来た感がでます。うれしいです。
データ解釈~ESP3編
ただし、このままではただの文字列なのでどこにどんなデータが入っているかわかりません。文字列の解釈をするため、ESP3のドキュメントを読み解きます。
ESP3のシリアル信号(ドキュメントのP.13)、EnOceanのシリアル信号は一つのかたまりで「パケット」と呼ばれているようで構造は下の図のようになっています。
この図を読み解くと、主に“Header”、“Data”、“Optional Data”という3つの要素で構成されているようです。それでは先ほどのデータを当てはめてみましょう。
このようにHeaderとDataとOption Dataの切り分けができました。
パケットタイプとデータを確認することでセンサの情報を取得することができます。
温湿度センサが送信するデータはパケットタイプが0x0A→10なのでパケットタイプ10を見てみましょう。
Option DataはTelegram NumberとRSSIであることがわかりました。欲しいデータは温度と湿度の情報なので今はそれほど必要ではないですね。肝心のデータについてはERPに従うようです。次はERPのドキュメントを確認しましょう。
データ解析~ERP2編
ERP2のドキュメントを読み進めていきますと、データ構造について書かれているページがありました。
図の内容を確認していくと温湿度センサは送信元IDが4バイト、信号の種類が4BS(4バイトのテレグラム)といった内容がわかりました。シリアル通信のようにこちらもデータを割り当ててみます。
4バイトのデータ(4BS)の中に温度と湿度の情報が入っています。4バイトのデータのうち、どの部分に入っているかはEEPのドキュメントと照らし合わせる事が必要です。この温湿度センサのEEPは製品を購入したコアスタッフさんより”A5-04-01”と伺ったので、該当部分を確認します。
データ解析~EEP編
EEPのドキュメントを確認して”A5-04-01”のプロファイルを確認しましょう。
この図に従って取得したデータを温度、湿度の値に変換します。
00 : Not use
78 : 湿度 123(0x7B) × (100-0)/(250-0) = 49.20 %
A2 : 温度 159(0x9F) × (40-0)/(250-0) = 25.44 ℃
0A : Data Telegram ,Temperature sensor available
これで無事温湿度センサのデータ内容が把握できました!
あとはこの解析した内容をプログラムにするだけです。
ポイントは温湿度データを取得したいので、EnOceanから送られてくるデータの順番を把握してどのデータなのかを確認しています。
#define TEMPID 0x0040179BD // EnOceanモジュールID #define SYNC 0x55 // SYNCバイト void setup() { //Pin 0/1 Serial.begin(57600); // 57600-EnOcean Serial Protocol 3 Serial.println("Working"); } void loop() { unsigned char dataReceive = 0 ; //受信確認フラグ unsigned char aChar = 0 ; //データ格納用変数 unsigned char pos = 0 ; //ESPデータ位置 unsigned long senderID = 0 ; //温湿度モジュールのID unsigned short dataLength = 0 ; //データ長 unsigned char optLength = 0 ; //オプションデータ長 unsigned char packettype = 0 ; //パケットタイプ float Temp = 0 ; //温度データ float Hum = 0 ; //湿度データ char buf[1] ; while(Serial.available()>0){ // XOcean受信したか? aChar = Serial.read(); switch(pos){ case(0): if( SYNC == aChar){ // SYNCバイトだったら受信開始 delay(5); pos++; // pos移動 SYNC -> dataLength dataReceive = 1 ; } break; case(1): dataLength = 0x00FF & aChar ; // dataLength 上位1バイトです。 pos++; // pos移動 dataLength -> dataLength break; case(2): dataLength = (dataLength<<8) + aChar ; // dataLength 下位1バイトです。 pos++ ; // pos移動 dataLength -> optLength break; case(3): optLength = aChar ; // optionLength pos++ ; // pos移動 optLength -> packet type break; case(4): packettype = aChar ; // packettype pos++; // pos移動 packet type -> crc break; case(5): pos++; // pos移動 crc -> header break; case(6): pos++; // pos移動 header -> ID1 break; case(7): senderID = 0x0000FF & aChar ; // ID1バイト pos++; // pos移動 ID1 -> ID2 break; case(8): case(9): case(10): senderID = (senderID<<8) + aChar ; // ID2-4バイト pos++; // pos移動 ID2 -> ID4 -> data1 break; case(11): pos++; // pos移動 data1 -> data2 break; case(12): Hum = (float)aChar * 100/250 ; // humdata pos++; // pos移動 data2(hum) -> data3(temp) break; case(13): Temp = (float)aChar * 40/250 ; // Tempdata pos++; break; default: break; } } if(dataReceive ==1){ if(TEMPID == senderID ){ Serial.print("Temperature = "); Serial.print(Temp , 2); Serial.println( " (deg)"); Serial.print("Humidity = "); Serial.print(Hum , 2); Serial.println( " (%)"); Serial.println(""); } dataReceive = 0 ; } }
posという変数で位置を確認し、EnOceanから送られてくるデータを取得してみました。また、受信した後、モジュールが持っているIDの値と比較し、一致していたら値を表示させています。これで例え同じようなセンサがたくさんあっても確認したいセンサのみの情報を取ることができますね。いずれ来るEnOcean時代(?)のために対策しました。
これで前半戦が終了です。
ふう……これまでのArduinoの連載よりかなりの上級編と感じたのですが、「これも上司をギャフンと言わせるためだ」と自分に鞭を打ちつつなんとかデータ内容の把握/表示までやってやりました。
次回はここにLCDシールドを接続し、機器として自立した、「Arduino×EnOcean」で電池不要の温湿度センサモニタ機器を作っちゃいます!
今回の連載の流れ
第1回:番外編① XOceanを使ってみた〜ArduinoとEnOceanを使用した温湿度表示(今回)
第2回:番外編② XOceanを使ってみた~ArduinoとEnOceanを使用した温湿度表示(その2)