岩手アドベントカレンダーに参加します
今年はあまり記事を書けなかったけど、これは参加したい。
はじめに
ビオトープでミナミヌマエビを飼育しています。私の住む岩手では豪雪&-20℃近くまで冷え込んでしまうので何らか冬対策する必要がある。
そこでエビだけ救出して、半屋外へ移動した。
その場所もまぁまぁ寒いので、せっかくなのでIoT的にモニタリングしてみた。(外よりは大丈夫だろうけど、、)
あとはLookerStudioも使ってみたかったという動機。
引っ越し先&設置イメージ
外よりはいいけど、それなりに寒い。
今回はモバイルバッテリーで電源確保。どのくらい持つか??
やったこと
- ESP32で温度・湿度計を実装
- スプレッドシートへ送信(GAS)
- LookerStudioでグラフ化
ESP32 温度・湿度計
自分の記事を参考にサクッと。
ポイント
今回モバイルバッテリーを使用する。
稼働時間を増やすためDeepSleepも入れてみた(効果はいかほど?)
(追記)
1週間程度稼働させましたが、無事稼働していました!(3200mAh)
全体のコード
#include <Arduino.h>
#include <DHT.h>
#include <WiFi.h>
#include <HTTPClient.h>
// DHT11のピン
const int PIN_DHT = 4;
DHT dht(PIN_DHT, DHT11);
// Wi-Fi接続情報
const char *ssid = "hogehoge"; // wifiのssid
const char *password = "fugafuga"; // wifiのパスワード
const char *scriptURL = "https://script.google.com_hogehoge";
// Deep Sleep間隔(3時間)
const uint64_t SLEEP_INTERVAL = 3 * 60 * 60 * 1000000ULL;
//---------------------------
// Wi-Fi接続関数
//---------------------------
void connectWiFi()
{
Serial.println("Connecting to Wi-Fi...");
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println("\nWi-Fi connected");
}
//---------------------------
// データ送信関数
//---------------------------
void sendData(float temperature, float humidity)
{
if (WiFi.status() != WL_CONNECTED)
{
Serial.println("Wi-Fi not connected. Reconnecting...");
connectWiFi();
}
HTTPClient http;
http.begin(scriptURL);
http.addHeader("Content-Type", "application/json");
String jsonData = "{\"val1\":" + String(temperature) + ", \"val2\":" + String(humidity) + "}";
int httpResponseCode = http.POST(jsonData);
if (httpResponseCode > 0)
{
String response = http.getString();
Serial.println("Response: " + response);
}
else
{
Serial.println("Error on sending POST: " + String(httpResponseCode));
}
http.end();
}
//---------------------------
// セットアップ&ループ
//---------------------------
void setup()
{
Serial.begin(9600);
dht.begin();
connectWiFi();
}
void loop()
{
float temperature = dht.readTemperature();
float humidity = dht.readHumidity();
Serial.printf("Temperature: %.2f°C Humidity: %.2f%%\n", temperature, humidity);
sendData(temperature, humidity);
// Deep Sleepに入る
Serial.println("Entering deep sleep...");
esp_deep_sleep(SLEEP_INTERVAL);
}
GAS(スプレッドシート)
こっちはPOSTを受けられるように
function doPost(e) {
try {
// POSTデータの取得と解析
const string = e.postData.getDataAsString();
const JsonData = JSON.parse(string);
const val1 = JsonData.val1;
const val2 = JsonData.val2;
// スプレッドシートを開く
const sheet = SpreadsheetApp.openById("sheetID");
if (!sheet) {
throw new Error("Spreadsheet not found. Check the spreadsheet ID.");
}
// シートを取得
const sheetName = "Sheet1";
const sheetObj = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); // アクティブなシートを取得
if (!sheetObj) {
throw new Error(`Sheet "${sheetName}" not found. Check the sheet name.`);
}
// データを追加
const row = [new Date(), val1, val2];
sheetObj.appendRow(row);
// レスポンスを返す
const data = { message: "Data added successfully", val1: val1, val2: val2 };
const response = ContentService.createTextOutput();
response.setMimeType(ContentService.MimeType.JSON);
response.setContent(JSON.stringify(data));
return response;
} catch (error) {
Logger.log("Error: " + error.message);
const errorMessage = { error: error.message };
const response = ContentService.createTextOutput();
response.setMimeType(ContentService.MimeType.JSON);
response.setContent(JSON.stringify(errorMessage));
return response;
}
こんな感じで受信
LookerStudio
とりあえずグラフだけ。LookerStudio便利ですね~
リビング温度や外気温との比較もあったらよかったかも。(APIでとるか、別に設置するか...)
表示Tips: データの並び替えと範囲指定
Google Apps Script (GAS)でデータを挿入する際、データはスプレッドシートの一番下に追加されます。そのまま日付順にすると表示が乱れる可能性があるため、以下の手順で調整するのがおすすめです。
並び順を降順に設定
最新データが上に表示されるように日付を降順にソートします。
さらにX軸を逆方向にするといい感じに降順で表示できるっぽい。
表示範囲を制限
表示ポイントを「最新の20~30件」に絞り込むことで、適切なデータを表示します。
スマホでも見られるように
リンク共有で手軽に見れる!全然これでいい。
今度は水温を年中モニタリングできたらいいかも。