MKR1000からGoogleスプレッドシートへ:WiFiでセンサーデータをシームレスにアップロード
必要なパーツと用品
| パーツ | 数量 |
|---|---|
| Arduino MKR1000 | 1 |
| DHT11 温湿度センサー(4ピン) | 1 |
| ジャンパーワイヤー | 1 |
| ブレッドボード | 1 |
使用するアプリとオンラインサービス
- Arduino IDE
- Google スプレッドシート
プロジェクト概要
このプロジェクトでは、MKR1000でデータを処理し、WiFi経由でクラウド上のGoogleスプレッドシートに送信します。クレジットカード登録やプロプライエタリなブラックボックスAPIを一切使用せずに実現できます。この例では安価で広く普及しているDHT11環境センサーを使用しますが、同梱のArduinoコードを簡単に変更すれば、あらゆるセンサーやデバイスに対応可能です。なお、このプロジェクトは、DHT11データをThingspeak.comにアップロードしてグラフ化する関連プロジェクトと組み合わせることも容易です。
全4部構成の第1部です。第1部では、同梱のGoogle Apps Scriptコードを使用して、独自のGoogleスプレッドシートをセットアップし、WiFiデータを受信できるように設定します。
パート1:Googleスプレッドシートの作成とデプロイ
- Googleアカウントをお持ちでない場合は、無料で登録してください。
- Googleアカウントにログインし、新しい「Googleスプレッドシート」を作成します。これがDHTセンサーの値でWiFi経由で埋め込まれるスプレッドシートです。この時点で、スプレッドシートのURLキーをコピーして保存しておいてください。このキーは、新しいスプレッドシートのURLの「/d/」と「/edit」の間に記載されています(青丸部分)。
- スプレッドシートに「環境データ」などわかりやすい名前を付け、Google Apps Script(JavaScriptに類似)を作成してデータを処理し、スプレッドシートに正しく書き込めるようにします。スクリプトエディターを開くには:
ツール → スクリプト エディタ
Googleスクリプトエディターページが開きます。GScriptに「環境データ用GScript」などの名前を付けます。ここで残り4つの作業を行います:
- 同梱のGoogleスクリプトコードをエディターにコピー&ペースト
- 手順2で保存したスプレッドシートURLキーを、Googleスクリプトコードの正しい行(引用符の間)に貼り付け:
var id = ' '; // Spreadsheet ID - スクリプトを保存:ファイル → すべて保存
- ウェブアプリとしてデプロイ:公開 → ウェブアプリとして導入…
- 最終ステップ: ウェブデプロイのパラメータを設定します。すべてのフィールドを正しく設定することが重要です。4つのフィールドを完全に正しく設定しないと、スプレッドシートが正常に動作しません。
フィールド1) 今生成された「現在のウェブアプリのURL:」をコピーして保存。後でPushingBoxのAPI設定で必要になります。
フィールド2) プロジェクトバージョンを各反復で「新規」として保存。スクリプトを改訂するたびに新しいプロジェクトバージョンを作らないと、改訂がウェブに反映されません。直感的ではありませんが、現在のGoogleの仕様です。
フィールド3) 「アプリを実行するユーザー: 」を「自分(あなたのGmail)」に設定。
フィールド4) 「アプリにアクセスできるユーザー:」を「全員(匿名ユーザーを含む)」に設定。
パート2:PushingBoxの設定
PushingBox.comは、DHTデータをGoogleスプレッドシートが受け入れ可能な形式に変換する、シンプルで無料、簡単なAPIミドルウェアとして機能します。PushingBox APIの中継が必要な理由は、HTTPで送信されるデータをGoogle準拠のHTTPS暗号化データに変換するためです。独自の暗号化アルゴリズムで標準要件を満たすことも可能ですが、PushingBoxを使う方が簡単で、1日1,000リクエストまで無料です。また、「パラメータを入力するだけで内部動作が見えない」ブラックボックスAPIを扱う必要もありません。以下はPushingBoxをデータ用に設定する手順です:
- GmailでPushingBoxアカウントを作成
- 上部の「My Services」をクリック
- 「My Services」内の「Add a service」ボックスで「Add a service」をクリック
- サービス一覧の最後の項目「
CustomURL、独自のサービスを設定!」を選択 - 以下の3項目を入力して送信:
CustomURL設定の名前: 任意
Root URL: このURLはhttps://script.google.com...で始まり、パート1で保存したGoogleスクリプトのアドレスになります
Method: GET
- サービス送信後、そのサービスのシナリオを作成。ページ上部の「My Scenarios」を選択
- 「Create a scenario or add a device」ボックスに適切なシナリオ名を入力し、右の「add」ボタンをクリック
- 「Add an action for your scenario」で、前ステップで作成したサービス名の横にある「Add an action to this service」ボタンを選択。これで新しいシナリオが新しいサービスに割り当てられます
- データボックスが開くので、「Get」または「Post」メソッドを選択(直感に反しますがGetメソッドを使用)。DHTの全データ(5データポイント)をGoogleスプレッドシートに記録するため、Google Apps Scriptの変数名とArduinoスケッチの変数名をリンクさせます。PushingBox APIで名前を正しくフォーマットすることでこのリンクが完了します。以下の文字列をコピー&ペースト:
?humidityData=$humidityData$&celData=$celData$&fehrData=$fehrData$&hicData=$hicData$&hifData=$hifData$
注意: 文の先頭に「?」「を付けて「GET」を示します。
結果は以下のようになります(シナリオ名とDevice ID番号はあなたのものになります):
必ず「DeviceID」文字列をコピーして保存してください。 次のステップでの予備テストと、パート4のArduinoスケッチで必要になります。
3. APIのテスト
最後のステップ(MKR1000をプログラミングしてDHTデータをウェブ経由で送信)に進む前に、ここまでの設定が正しいかテストすると便利です。ハードウェア部分を完了してからエラー原因を特定するのは困難だからです。幸い、簡単なテスト方法があります。ブラウザのアドレスバーにハードコードされた疑似データを直接入力し、Googleスプレッドシートが正しく更新されるか確認できます。以下をブラウザのアドレスバーにコピー&ペーストしてください:
https://api.pushingbox.com/pushingbox?devid=(YOUR-DEVID-HERE)&humidityData=33&celData=44&fehrData=111&hicData=22&hifData=77
その後、異なる値で再度実行して後続行にデータを追加することもできますが、PushingBoxは1日1,000リクエストまでなのでやりすぎないでください。この手順でスプレッドシートが更新されない場合は、パート1〜3を見直してエラーを修正してからパート4に進んでください。
パート4:MKR1000からGoogleスプレッドシートへデータ送信
ブラウザからハードコードされた疑似データをGoogleスプレッドシートに正常にプッシュできたら、次はMKR1000からPushingBox経由でWiFiを通じてGoogleスプレッドシートにデータを直接送信するステップに進みます。同梱のArduinoスケッチをMKR1000にアップロードして実行する前に、以下の3ステップを完了してください。
ハードウェア
- MKR1000とDHTの配線: 簡単な作業です。特にMKR1000を使用する場合は容易です。DHTには5Vで電源供給することを推奨します(MKR1000の5Vピンで利用可能)。DHTは3.3Vでも動作するとされていますが、低電圧では読み取りが信頼できないことが多いです。DHTからMKR1000へのデータ入力ピンはいくつか選択肢がありますが、このスケッチではピン5(MKR1000基板上部のピンD5にマッピング)を使用します。
ソフトウェア(1)
- Arduino IDEをMKR1000用に設定: 2つのライブラリのダウンロードと、Arduino IDE(1.6.4以降)への正しいMKR1000ボードパッケージの設定(ツール → ボード → ボードマネージャー)が必要です。多くの方は必要なソフトウェアをすでにインストール済みでしょう。未インストールの方は以下のリンクから必要なライブラリとMKR1000ボードサポートパッケージを取得してください。なお、最新のMKR1000ボードサポートパッケージが正しく動作しなかったため、以前のバージョンを使用しました。これを読む頃には解決されていることを願います。
WiFi101リファレンス
スケッチに必要な2つのライブラリ:
ソフトウェア(2)
- 最終ステップ: 同梱のArduinoスケッチをコピー&ペーストし、あなたのデバイス用にカスタマイズして、MKR1000にアップロードします。スケッチは9600ボーでシリアル出力も行うため、WiFi経由で送信されるデータを監視できます。Arduinoスケッチでカスタマイズ必須の3項目:
- A) あなたのWiFi名(SSID)
- B) あなたのWiFiパスワード
- C) あなたのPushingBox Device ID(devid)
以上です!すべて正しく完了していれば、出力は以下のようになります:
このプロジェクトの基盤となったソフトウェアコンポーネントの大部分を構築したすべての人々に感謝します。コードコメントに名前を記載して適切な帰属を行っています。このプロジェクトのどの部分でも自由に使用して、あなた独自の魔法を創造してください。
- SDB
コード
MKR1000からPushingBox経由でGoogleスプレッドシートへ(DHT使用)
//-----------------------------------------------
// Adafruit DHTセンサーとtdicolaのdht.hライブラリから結合
// https://learn.adafruit.com/dht/overview
// https://gist.github.com/teos0009/acad7d1e54b97f4b2a88
// 他の作者(Arduinoと関連Googleスクリプト):
// Aditya Riska Putra
// Ahmed Reza Rafsanzani
// Ryan Eko Saputro
// 参照:
// https://jarkomdityaz.appspot.com/
// ELINS UGM
// Hackster.ioプロジェクト用にMKR1000向けに改変
// by Stephen Borsay (Portland, OR, USA)
// ArduinoはHTTPS非対応なので、PushingBox API(HTTP使用)を経由して
// Googleスクリプト(HTTPS使用)を実行。代替案としてIvanのSecureWifi暗号化も可
#include
#include "DHT.h"
#define DHTPIN 5 // 接続ピン(端から5番目のピン)
#define DHTTYPE DHT11 // DHT 11
//#define DHTTYPE DHT21 // DHT 21
//#define DHTTYPE DHT22 // DHT 22
DHT dht(DHTPIN, DHTTYPE);
const char WEBSITE[] = "api.pushingbox.com"; // PushingBox APIサーバー
const String devid = "YOUR_DEVICEID"; // PushingBoxのシナリオ用Device ID
const char* MY_SSID = "YOUR SSID";
const char* MY_PWD = "YOUR WiFi PASSWORD";
int status = WL_IDLE_STATUS;
void setup() {
Serial.begin(9600);
while (!Serial) { ; } // ネイティブUSBポートの場合のみ必要
// WiFiシールドの存在確認
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
while (true);
}
// WiFiネットワークへの接続試行
while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(MY_SSID);
status = WiFi.begin(MY_SSID, MY_PWD);
delay(10000);
}
Serial.println("Connected to wifi");
printWifiStatus();
}
void loop() {
delay(10000); // 測定間隔
int humidityData = dht.readHumidity();
int celData = dht.readTemperature();
int fehrData = dht.readTemperature(true);
// 読み取り失敗チェック
if (isnan(humidityData) || isnan(celData) || isnan(fehrData)) {
Serial.println("Failed to read from DHT sensor!");
return;
}
// 熱中症指数の計算
int hifData = dht.computeHeatIndex(fehrData, humidityData);
int hicData = dht.computeHeatIndex(celData, humidityData, false);
// シリアル出力
Serial.print("Humidity: "); Serial.print(humidityData); Serial.print(" %\t");
Serial.print("Temperature: "); Serial.print(celData); Serial.print(" *C ");
Serial.print(fehrData); Serial.print(" *F\t");
Serial.print("Heat index: "); Serial.print(hicData); Serial.print(" *C ");
Serial.print(hifData); Serial.println(" *F\n");
Serial.println("\nSending Data to Server...");
WiFiClient client;
if (client.connect(WEBSITE, 80)) {
client.print("GET /pushingbox?devid=" + devid +
"&humidityData=" + (String)humidityData +
"&celData=" + (String)celData +
"&fehrData=" + (String)fehrData +
"&hicData=" + (String)hicData +
"&hifData=" + (String)hifData);
client.println(" HTTP/1.1");
client.print("Host: "); client.println(WEBSITE);
client.println("User-Agent: MKR1000/1.0");
client.println();
Serial.println("\nData Sent");
}
}
void printWifiStatus() {
Serial.print("SSID: "); Serial.println(WiFi.SSID());
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: "); Serial.println(ip);
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):"); Serial.print(rssi); Serial.println(" dBm");
}
Google Apps Script(HTTPS形式でワイヤレスデータを受信)
//-----------------------------------------------
// Mogsdad@Stackoverflowによって最初に公開
// jarkomdityaz.appspot.com向けに改変
// Hackster.io向けにStephen Borsayが改変
//-----------------------------------------------
/* GETリクエストクエリ:
https://script.google.com/macros/s//exec?celData=data_here
----------------------------------------------------------------------
GScript、PushingBox、Arduino/ESP8266の変数順序:
humidityData, celData, fehrData, hicData, hifData
---------------------------------------------------- */
function doGet(e) {
Logger.log(JSON.stringify(e));
var result = 'Ok';
if (e.parameter == undefined) {
result = 'No Parameters';
} else {
var id = '';
var sheet = SpreadsheetApp.openById(id).getActiveSheet();
var newRow = sheet.getLastRow() + 1;
var rowData = [];
rowData[0] = new Date(); // タイムスタンプをA列に
for (var param in e.parameter) {
Logger.log('In for loop, param=' + param);
var value = stripQuotes(e.parameter[param]);
switch (param) {
case 'humidityData': rowData[1] = value; break;
case 'celData': rowData[2] = value; break;
case 'fehrData': rowData[3] = value; break;
case 'hicData': rowData[4] = value; break;
case 'hifData': rowData[5] = value; break;
default: result = "unsupported parameter";
}
}
Logger.log(JSON.stringify(rowData));
var newRange = sheet.getRange(newRow, 1, 1, rowData.length);
newRange.setValues([rowData]);
}
return ContentService.createTextOutput(result);
}
function stripQuotes(value) {
return value.replace(/^["']|["']$/g, "");
}
PushingBox URL文字列(HTTPSの接着剤として)
?humidityData=$humidityData$&celData=$celData$&fehrData=$fehrData$&hicData=$hicData$&hifData=$hifData$
カスタムパーツとエンクロージャ
その他のワイヤレスデータ:
https://github.com/sborsay/Arduino_Wireless
回路図
製造プロセス
- MATRIX Voice搭載Raspberry PiへのGoogle Assistantインストール:ステップバイステップガイド
- Firebase経由で2台のArduino間を温湿度データで連携するIoTチュートリアル
- Arduinoで作るモニター用Ambilightシステム:没入感アップの自作ガイド
- ArduinoとInfineon 3D磁気センサーで作る無線磁気データ転送
- Arduino UNOとOLEDディスプレイでクラシックPongゲームを自作:ステップバイステップチュートリアル
- Arduino Megaで写真撮影・Google Drive自動アップロード:PHPoC WiFiシールド活用
- Arduinoオーディオ周波数検出器 – 高感度サウンドモジュールで最大音量ピークの周波数を測定
- Arduinoで作る自作デジタルペット「Tamaguino」─ 3Dプリンター製ケース付き完全ガイド
- スマートワイヤレス照明スイッチコントローラー:Arduinoで物理スイッチを遠隔操作
- Arduino三目並べ:MAX7219 LEDマトリクスと段ボールケースで自作
- Arduino Nanoで作るスマートな動体検知水鉄砲