0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

岩手の人とか、岩手県立大学の人とか Advent Calendar 2024Advent Calendar 2024

Day 7

~ビオトープの冬超し~ IoT的モニタリングしてみた

Last updated at Posted at 2024-12-06

岩手アドベントカレンダーに参加します

今年はあまり記事を書けなかったけど、これは参加したい。

はじめに

image.png

ビオトープでミナミヌマエビを飼育しています。私の住む岩手では豪雪&-20℃近くまで冷え込んでしまうので何らか冬対策する必要がある。

そこでエビだけ救出して、半屋外へ移動した。
その場所もまぁまぁ寒いので、せっかくなのでIoT的にモニタリングしてみた。(外よりは大丈夫だろうけど、、)

あとはLookerStudioも使ってみたかったという動機。

引っ越し先&設置イメージ

外よりはいいけど、それなりに寒い。
今回はモバイルバッテリーで電源確保。どのくらい持つか??
image.png

やったこと

  1. ESP32で温度・湿度計を実装
  2. スプレッドシートへ送信(GAS)
  3. 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;
  }

こんな感じで受信

image.png

LookerStudio

とりあえずグラフだけ。LookerStudio便利ですね~
リビング温度や外気温との比較もあったらよかったかも。(APIでとるか、別に設置するか...)

image.png

表示Tips: データの並び替えと範囲指定

Google Apps Script (GAS)でデータを挿入する際、データはスプレッドシートの一番下に追加されます。そのまま日付順にすると表示が乱れる可能性があるため、以下の手順で調整するのがおすすめです。

並び順を降順に設定

最新データが上に表示されるように日付を降順にソートします。
さらにX軸を逆方向にするといい感じに降順で表示できるっぽい。
image.png

表示範囲を制限

表示ポイントを「最新の20~30件」に絞り込むことで、適切なデータを表示します。

スマホでも見られるように

リンク共有で手軽に見れる!全然これでいい。

image.png

今度は水温を年中モニタリングできたらいいかも。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?