M5Stackでの電子工作の学習中。
こちらの続きで、一定間隔でセンサ値をデータベース(Spreadsheet)に送るような仕組みを作っていく。
以前のこちらの記事に載せたスケッチと組み合わせて、まずは毎分データをSpreadsheetへ送信するようにしてみた。
実装
Spreadsheetに送られたデータを確認
スケッチを書いて、1分ごとにセンサー値をSpreadsheetに送信してみた。
(最終的なスケッチは最後に記載している。)
Spreadsheetには、日時とセンサーデータが入るようにしている。
今回のスケッチは、まずloop()
関数の中でdelay(1000)
で1秒間待機させて毎分実行されるようにしてみた。
するとこんな感じでデータの取得には成功してるのだけど、毎回7秒ずつずれてデータが入ってきている。
11:53台は飛んでしまっている。
案の定、送信処理のたびに少しずつラグがあるようだ。
1秒間の待機の他の処理に時間がかかるので、1回のループで1分以上かかってくるのだろう。
時間のズレを調整
なので毎回のループをdelay(883)
に修正してみる。
(60秒間で7秒のずれを解消したいので、7000ミリ秒/60 ≒ 116.66を1000ミリ秒から減算している。)
スケッチ書き込み後、改めてSpreadsheetを確認してみると、大きなラグはないけどやっぱり少しずつズレは生じているようだ。
このようにdelay()
を調整するだけだと、ズレが出てきてしまうんだな。
ひとまず今回はここまで。
ここまでのスケッチ
▼毎分センサーデータをSpreadsheetに送信する(delay修正後)
#include <M5Stack.h> #include <DHT.h> #include <HTTPClient.h> #include <WiFi.h> #include <ArduinoJson.h> #define WIFI_SSID "483FE9EB00D9-2G" #define WIFI_PASSWORD "00000001" // 関数のプロトタイプ宣言 static uint8_t conv2d(const char* p); void sendValues(); // スプレッドシートへデータを飛ばすWebhook URL const char *host = "https://script.google.com/macros/s/AKfycbyAcTUmJI_pDovJgI1Ol3-7MKFBGD7G2qqHofZrCVe0xk64U1pQIpTJvKMqTIldHKDQtA/exec"; // JSON設定 StaticJsonDocument<255> json_request; char buffer[255]; // dht設定 const int PIN_DHT = 5; DHT dht(PIN_DHT, DHT11); // センサー値 float humidity; // 湿度 float temperature; // 温度 uint16_t moisture = 0; // 土壌水分 // 時刻合わせ用変数 uint8_t hh = conv2d(__TIME__), mm = conv2d(__TIME__ + 3), ss = conv2d(__TIME__ + 6); // Get H, M, S from compile time uint8_t omm = mm; /* setup関数 */ void setup() { // M5の初期化 M5.begin(); dht.begin(); // Wi-Fi接続 WiFi.begin(WIFI_SSID, WIFI_PASSWORD); WiFi.setSleep(false); // btnA連打バグへの対応 Serial.print("connectiong"); while(WiFi.status() != WL_CONNECTED) { Serial.print("."); delay(500); } Serial.println(); // 接続に成功 Serial.println("¥nWiFi Connected."); Serial.println(WiFi.localIP()); M5.Lcd.fillScreen(TFT_BLACK); M5.Lcd.setTextSize(3); M5.Lcd.println("WiFi Connected:"); M5.Lcd.println(WiFi.localIP()); M5.Lcd.println(""); } /* loop関数 */ void loop(){ // 1秒進めて時間合わせ ss++; // if(ss == 60){ ss = 0; mm++; if(mm > 59){ mm = 0; hh++; if(hh > 23){ hh = 0; } } } // if(mm == 0 || mm == 30) { // (※)毎時00分、30分の時に実行する場合はこのコメントアウトを外す if(mm != omm){ // 分の切り替わりを検知して一回だけこの中身が実行される omm = mm; // 現在の分を保管 // センサーの値を送る sendValues(); } // } // (※)毎時00分、30分の時に実行する場合はこのコメントアウトを外す humidity = dht.readHumidity(); temperature = dht.readTemperature(); moisture = analogRead(36); M5.Lcd.clear(BLACK); M5.Lcd.setTextColor(WHITE); M5.Lcd.setTextSize(1); M5.Lcd.drawString("M5STACK SENSORS:", 0, 0, 4); M5.Lcd.setTextColor(YELLOW); M5.Lcd.drawString("Humidity:", 0, 30, 4); M5.Lcd.drawFloat(humidity, 0, 0, 60, 4); M5.Lcd.drawString("%", 50, 60, 4); M5.Lcd.setTextColor(GREEN); M5.Lcd.drawString("Temperature:", 0, 90, 4); M5.Lcd.drawFloat(temperature, 0, 0, 120, 4); M5.Lcd.drawString("C", 50, 120, 4); M5.Lcd.setTextColor(BLUE); M5.Lcd.drawString("Moisture:", 0, 150, 4); M5.Lcd.drawFloat(moisture, 0, 0, 180, 4); // 1秒間待機 delay(883); } /* センサーの値送信 */ void sendValues(){ json_request["humidity"] = humidity; json_request["temperature"] = temperature; json_request["moisture"] = moisture; serializeJson(json_request, buffer, sizeof(buffer)); HTTPClient http; http.begin(host); http.addHeader("Content-Type", "application/json"); int status_code = http.POST((uint8_t*)buffer, strlen(buffer)); Serial.println(status_code); if(status_code > 0){ if(status_code == HTTP_CODE_FOUND){ String payload = http.getString(); Serial.println(payload); M5.Lcd.setCursor(10, 100); M5.Lcd.fillScreen(BLACK); M5.Lcd.setTextColor(WHITE); M5.Lcd.setTextSize(3); M5.Lcd.println("Send Done!"); } } else { Serial.printf("[HTTP] GET... failed, error: %s¥n", http.errorToString(status_code).c_str()); } http.end(); } /* 時刻をミリ秒から時・分・秒へ変換 */ static uint8_t conv2d(const char* p) { uint8_t v = 0; if ('0' <= *p && *p <= '9') v = *p - '0'; return 10 * v + *++p - '0'; }
今回のまとめ
定期的にSpreadsheetへの送信する処理はできたけど、delay()
で時間管理するとどうしてもラグは発生する。
そもそも正確にやるならNTPサーバで時刻合わせしたりすべきだし、大した用途じゃなければこれでも良さそうだな、と考えている。
今後の改善点としては、
連続起動時間の検証 電源を繋いでいないと4時間くらいでデータが飛んで来なくなっている。
画面が消えているので、スリープモードに入るのかバッテリーがもたないのか。この辺りは検証したい。省電力な仕様に
loop()
関数をもうちょっと工夫したい。deepsleepというのも活用できるのかな? モバイルバッテリーの利用も検討しなければいけないかもしれない。