Translate

2015年5月27日水曜日

Arduino YUN上の温湿度センサデータをIBM IoT Foundation QuickStartへ送信する

MQTTを試そうといろいろ調べていくうちに、ふと次のIBM社のサイトが検索に引っかかった。

Arduino Uno と IBM IoT Foundation を利用してクラウド対応の温度センサーを作成する
第 1 回 回路を組み立てて環境を構築する
http://www.ibm.com/developerworks/jp/cloud/library/cl-bluemix-arduino-iot1/

第 2 回 スケッチを作成して IBM IoT Foundation Quickstart に接続する
http://www.ibm.com/developerworks/jp/cloud/library/cl-bluemix-arduino-iot2/


簡単にいえば、Arduino UNOにEthernetシールドと温湿度一体型センサDHT11をつないでIBM IoT FoundationのQuickStart(MQTTブローカ)にデータを送信するデモを作ることができるというもの。

で..どうせこれからもIoTデモを作っていくなら、EthernetとWiFi両方付いているArduino YUNのほうがすっきりするんじゃないの?とない頭をまわし、Arduino YUNを手に入れた。

 先の記事でWiFi設定したのはこのためだ。
 
 Arduino YUNのWiFi設定を有効にする
 http://fight-tsk.blogspot.jp/2015/05/arduino-yunwifi.html

SketchプログラムはYUNになるとEthernetライブラリ(EthernetクラスやEthernetClientクラス)は使わずにかわりにBirdgeライブラリ(BridgeクラスとYunClientクラス)に差し替えなければならない。

また、どうせセンサを入手するなら裸のセンサをダイレクトに繋がずに、Groveキットになっているものをつかえば、プルアップ抵抗も組み付けてくれているのでよいかな、しかもGroveキットにDHT22というDHT11より精度の上の製品が出ているので、こっちを使うことにした。

 GROVE - デジタル温度・湿度センサPro SEN51035P
 https://www.switch-science.com/catalog/819/
Arduino YUNとSEN51035Pは、赤・黒・黄のオス・オスのジャンパ線3本用意して、以下のように接続した。

  • SEN51035P GND(黒) と Arduino YUN GND
  • SEN51035P VCC(赤) と Arduino YUN 5V
  • SEN51035P SIG(黄) と Arduino YUN A0


SketchプログラムのほうもDHT11ライブラリではなく、製品Wiki  にのっていた以下のライブラリを使用した。

 Arduino library for the DHT series temperature&humidity sensors
 https://github.com/Seeed-Studio/Grove_Temperature_And_Humidity_Sensor

書き換えたScketctプログラムは、以下のとおり。


 #include <SPI.h>
 #include <Bridge.h>
 #include <Console.h>
 #include <YunClient.h>
 #include <DHT.h>
 #include <PubSubClient.h>
 /*
  * Arduino YUN
  * + 温湿度センサ DH22 (SIG -> A0)
  *
  * IBM IoT Foundation
  * https://internetofthings.ibmcloud.com/
  * -> Try QuickStart
  * -> MAC:b4218af800a8
  */

 // Arduino YUN

 // MAC アドレス(要書き換え)
 byte mac[]    = {0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX };
 char macstr[] = "xxxxxxxxxxxx";

 // クライアントオブジェクト
 YunClient c;

 // 温湿度センサ

 // DHT sig ピン
 #define DHTPIN A0

 // センサ種類
 //#define DHTTYPE DHT11 // DHT 11
 #define DHTTYPE DHT22 // DHT 22 (AM2302)
 //#define DHTTYPE DHT21 // DHT 21 (AM2301)

 // センサオブジェクト
 DHT dht(DHTPIN, DHTTYPE);

 float tempF = 0.0;
 float tempC = 0.0;
 float humidity = 0.0;

 // MQTTブローカ

 // PC (mosquitto)
 //byte localserver[] = {192, 168, 1, 13 };
 // IBM IoTF quickstart
 char servername[]="messaging.quickstart.internetofthings.ibmcloud.com";

 String clientName = String("d:quickstart:arduino:") + macstr;
 String topicName = String("iot-2/evt/status/fmt/json");

 // MQTTクライアントオブジェクト
 //PubSubClient client(localserver, 1883, 0, c);
 PubSubClient client(servername, 1883, 0, c);

 void setup() {
   // シリアル初期化
   Serial.begin(9600);
   while (!Serial) {
     ; // 待機
   }
   Serial.println("Start serial");

   // センサオブジェクト初期化
   dht.begin();
   Serial.println("Start dht");
  
   // Bridge 初期化
   Bridge.begin();
   Serial.println("Start bridge");
  
   // 待機
   delay(2000);
 }

 void loop() {
   char clientStr[34];
   clientName.toCharArray(clientStr,34);
   char topicStr[26];
   topicName.toCharArray(topicStr,26);
   getData();
   if (!client.connected()) {
     Serial.print("Trying to connect to: ");
     Serial.println(clientStr);
     client.connect(clientStr);
   }
   if (client.connected() ) {
     String json = buildJson();
     char jsonStr[200];
     json.toCharArray(jsonStr,200);
     boolean pubresult = client.publish(topicStr,jsonStr);
     Serial.print("attempt to send ");
     Serial.println(jsonStr);
     Serial.print("to ");
     Serial.println(topicStr);
     if (pubresult)
       Serial.println("successfully sent");
     else
       Serial.println("unsuccessfully sent");
   }
   delay(5000);
 }

 String buildJson() {
   String data = "{";
   data+="\n";
   data+= "\"d\": {";
   data+="\n";
   data+="\"myName\": \"Arduino DHT22\",";
   data+="\n";
   data+="\"temperature (F)\": ";
   data+=(int)tempF;
   data+= ",";
   data+="\n";
   data+="\"temperature (C)\": ";
   data+=(int)tempC;
   data+= ",";
   data+="\n";
   data+="\"humidity\": ";
   data+=(int)humidity;
   data+="\n";
   data+="}";
   data+="\n";
   data+="}";
   return data;
 }

 void getData() {
   humidity = dht.readHumidity();
   tempF = dht.readTemperature(true);
   tempC = dht.readTemperature(false);
 }



YUNに書き込んで、シリアルコンソールを開いた後、IBM IoT FoundationのQuickStartサイトにMACアドレスを入力するとグラフが表示される。

MQTTブローカへ接続するためのライブラリだが、PubSubClientライブラリのほうがPahoライブラリより軽いので、Arduinoにはこっちのほうがよいかもしれない。

Arduinoを使ってみて気づいたが、メモリを75%以上使ったプログラムは、複数回実行しても同じ動作をしてくれないことがあり、開発者をこまらせてくれる。
回路側の合計アンペア数はこえるとピタッと止まるが、途中まで通信できていたのに途中からエラーになったりする。

メモリ潤沢なWebアプリ開発者がArduino快活すると、これまで使ったことのない筋肉を突然使って筋肉痛起こしているような感覚になる..

6 件のコメント:

aramon さんのコメント...

はじめまして。突然のコメントすみません。
現在、arduino yun mini +流量センサー(流量アナログ入力DC0~5Vとセンサー判定デジタル入力無電圧接点入力)でIBM Bluemixへデータを上げ、
グラフ化、流量監視、異常流量時はメール送信などをしたいと取り組んでいます。
アップされているyunのスケッチを参考に、クィックスタートにデータをあげてみようと思っているんですが、Bridgeのところがうまくうごきません。接続されません。
IDEのツール・ポートのところからは見えています。
yun miniの初期設定は終わっているんですが、yunのスケッチってyun miniでも動くでしょうか?
アドバイス頂けたら幸甚に存じます。

ton さんのコメント...

コメントに気づくのが遅れてスミマセン。

・Yun miniへBridgeライブラリプログラムを動作させる前に
 WiFi設定はできていますか?

 できていない場合は、まず以下の記事を参考にWiFi設定を完了させてください。
 https://fight-tsk.blogspot.jp/2015/08/arduino-yun-mini-wifi.html

 企業で使用している場合はproxy設定がある場合があります
 その際はかならずproxyなしで繋がる環境を用意してください。

・WiFiルータ側のポート番号1833は開放されていますか?

 たとえばWiMAXルータ HWD15 だと
 https://codezine.jp/article/detail/9233
 の4ページ目にあるように
 デフォルトでは1833がブロックされています。
 このようにデフォルトではブロックされている
 機種も多いので注意してください。
 設定を見ただけでは開放されているように見えることもあるので
 マニュアルで確認することをおすすめします。

 ArduinoIDEのスケッチの例>Bridge>HttpClient
 が正常動作するのにIoT foundationへつながらない場合は
 ルータが1883ポートを遮断している可能性が高いです。

・arduino.ccではなくarduino.org/softwareから落としたArduinoIDEを使っていますか?

 .cc側はstableな開発環境です。Yun/Yun mini上の開発は
http://www.arduino.org/software
のIDEで開発する必要があります。

ton さんのコメント...

あと1点
上記プログラムは
ArduinoIDE>ツール>シリアルモニタ
を選択してコンソールを表示させないと開始しません。
ご注意ください。

aramon さんのコメント...

ton様
ご返事ありがとうございます。
教えて頂いたことを参考にやってみます。
本当にありがとうございます。
やってみて何かありましたらまた教えて頂けたら幸甚に存じます。
取り急ぎお礼まで。

aramon さんのコメント...

ton様
お世話になります。
上記の件、漏水監視(流量センサー+yunで流量グラフ化・指定水量超過で警報メール送信)成功しました。
ありがとうございます。
ただ、yunから無線LANでクラウド上へパブリッシュしていますが、yunを設置しているポンプ室までが遠いのもあり、
通信が不安定でたまに切れてしまいます。
通信が切れたとき、IDEのツール→ポートからIPアドレスのポートが見えない状態です。
yunの電源リセットをすると、ポートも見れるようになり、通信が再開、パブリッシュも再開します。
距離も遠く、Wifi子機、孫機運用でもダメなので、最悪、LANケーブルを配線、arduino uno+イーサネットシールドに載せ替えも考えていますが、yunのスケッチで通信停止を回避する方法等あるでしょうか?
すみませんが、ご教授頂けたら幸甚に存じます。

ton さんのコメント...

コメントに気づくのが遅れてスミマセン。

1. WiFi中継器を配置する
YUN と WiFi ルータの間に 中継器を置くことができればそれが一番良いと思います。
家庭用のものもあるそうです。WiFi 中継器 で検索すると出てくると思います。
WiFi中継器は電源が必要になるので、給電できる環境でなくてはなりませんが..

2. ロガー型にする
あとで通信ミスデータを補填してもよい業務であれば、送信データをSDカードにも書き込んでおき、途絶したデータは後でSDカードから取得する方向もあります。
YUNの SDカードスロットはLininoの更新用なのでSketch操作できないため、SDカードを搭載したシールドが必要になります。
ただしどの通信データがミスしたものかを調べることができるように、経過時間などをJSONデータに追加しておく必要があります。以下のサイトを参考にされるとよいとおもいます。
http://arms22.blog91.fc2.com/blog-entry-502.html

既存アプリケーションをK8s上でコンテナ化して動かす場合の設計注意事項メモ

既存アプリをK8sなどのコンテナにして動かすには、どこを注意すればいいか..ちょっと調べたときの注意事項をメモにした。   1. The Twelve Factors (日本語訳からの転記) コードベース   バージョン管理されている1つのコードベースと複数のデプロイ 依存関係 ...