ESP-WROOM-02で二次元温度センサ(ROBOBA041, Grid-EYE)を使ってみる 中編

th_grid_eye_6

前回で、とりあえずGrid-EYE (ROBOBA041)をESP-WROOM-02で動かすことには成功しました。一応これでタイトルの内容は達成済みなのですが、せっかくWi-Fiに繋がるWROOM-02を使っているので、クラウド上にデータをアップロードするところまでやってしまいたいと思います。

クラウドとは言いつつも、単にデータを記録していくだけならとりあえずGoogle スプレッドシートがお手軽かなーということで、以下の先人の方の知恵を拝借して、まずはIFTTTを使う方法を試してみました。

IFTTTを介することで、通常、APIをダイレクトに叩くときに面倒な(でも必要な)認証周りを気にしなくて良くなるのでとてもラクです。。。が。

自分が試したところ、スプレッドシートに実際に値が反映されるまでに恐ろしく遅延が発生してしまいました。数分とかではなく、数十分というレベルです。

これではさすがにちょっと使いものにならないので、何か別の手段はないかと色々探してみたところ、ThingSpeakというサービスに行き当たりました。そんなにやたらめったらデータをアップロードしないのであれば登録だけで無料で使えますし、簡単なグラフ化も勝手にやってくれます。何より、ArduinoとESP8266(ESP-WROOM-02)向けのライブラリとサンプルを用意してくれているのは素晴らしいです。蓄積したデータをCSVでエクスポートすることも可能です。

実際にThingSpeakとそのライブラリを使ってESP-WROOM-02向けに開発する方法は、以下の記事が大変参考になります。

以下の内容は、上記の記事とほぼ同じようなことをやっているだけです。

 

ThingSpeakの登録およびチャンネル作成の基本的な方法は上記記事のとおりですので、省略します。以下が実際に作成したチャンネルです。

thingspeak

 

三つのフィールドを設定していて、一つ目はサーミスタ温度、二つ目はGrid-EYEの8×8ピクセルの内の1〜32番まで、三つ目はその33番〜64番までという形にしています。ThingSpeakでは一つのチャンネルにアップロードできる値の種類(フィールド)は八つと決まっているので、8×8の一つずつに個別のフィールドを割り当てることはできません。そのため、ESP-WROOM-02側でで、”20.3:20.4:20.5: …”のように32個分のデータをコロン区切りで連結した文字列の形にして、1〜32番分と33〜64番分の二つのフィールドに格納しています。後でデータを分析するときには、これをプログラム側でコロンでスプリットするイメージです。ちなみにフィールドを一つではなくわざわざ二つに分けている理由は、一つだと文字列が長くなり過ぎる為か、うまくアップロードできなかったためです。

ESP-WROOM-02側のソースコードは以下のようになります。先ほどご紹介した記事の内容をベースにしていますが、元のソースからかなり簡略化してしまっています。スリープ制御やら再送処理やらをしっかり入れ込みたい方は、是非元記事の方をご参照ください。

#include <Wire.h>
#include <GridEye.h>
#include <ESP8266WiFi.h>
#include <ThingSpeak.h>

// Wifi設定
const char ssid[] = "YourSSID";
const char pass[] = "YourPass";

// ThingSpeak設定
const unsigned long myChannelNumber = xxxxxx;
const char * myWriteAPIKey = "YourApiKey";

// ThingSpeak接続用
WiFiClient  client;

GridEye myeye = GridEye(GridEye_DeviceAddress_1);

// ピクセル温度データ保存用
int pixel[64];

void setup(void)
{
  // 起動メッセージ出力
  Serial.begin(115200);
  Serial.println("Hello GridEye!");

  // 接続開始
  WiFi.begin(ssid, pass);
  Serial.print("Wifi connect...");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");  
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  // I2Cバスに参加
  Wire.begin();
}

void loop(void)
{
  // サーミスタ温度読み出し
  int temp = myeye.thermistorTemp();
  Serial.print(F("Thermistor Temp: "));
  Serial.println(temp * 0.065); // 1単位 = 0.065度

  // ピクセル温度データ読み出し
  myeye.pixelOut(pixel);
  Serial.println(F("Pixel Output: "));
  for (int i = 0; i < 64; i++) {
    if (i && ((i % 8) == 0)) {
      Serial.println();
    }
    Serial.print(pixel[i] * 0.25); // 1単位 = 0.25度
    Serial.print(' ');
  }
  Serial.println();

  // センサーデータアップロード開始
  ThingSpeak.begin(client);

  // フィードに値を設定
  String pixelString_1 = String(pixel[0]*0.25);
  for(int i=1;i<32;i++){
    pixelString_1 += ":" + String(pixel[i]*0.25);
  }
  String pixelString_2 = String(pixel[32]*0.25);
  for(int i=33;i<64;i++){
    pixelString_2 += ":" + String(pixel[i]*0.25);
  }
  ThingSpeak.setField(1, float(temp*0.065));
  ThingSpeak.setField(2, pixelString_1);
  ThingSpeak.setField(3, pixelString_2);

  // ThingSpeakに送信
  Serial.println();
  Serial.print("Write fields...");
  ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
  Serial.println("done");

  // 1分間隔で繰り返し
  delay(60000);
}

これでとりあえずクラウド側にデータをアップロードすることができるようになりました。一分間隔で上げたデータをCSVでエクスポートすると、以下のような感じになります。

thingspeak2

ということで、一応無事にクラウド側にデータを保存していくことはできるようになりました。最後に、これを可視化するプログラムを書いて終わりにしようと思います。