LoginSignup
2
10

More than 3 years have passed since last update.

M5Stackでセンサ値をメール通知するアプリ作ってみた

Last updated at Posted at 2019-10-22

TL;DR

センサ値(今回は温湿度情報)をとある事情でメール通知したかったため作成しました。
(温度感覚が鈍って自分では熱中症になりそうなことを感じないご高齢の方が身内にいたら使えたりするかも)
手元にあったM5Stack Gray(普通のArduinoの方がネット上にサンプルが溢れているのでより簡単だった模様)と、GROVE - デジタル温度・湿度センサを使って作成。
Gmail送信するため、WiFi環境下でのみ動作しますのでご注意を。

ソースコードはC++に慣れていないのでヨチヨチですが公開してます。(ツッコミなど大歓迎でございます m(_ _)m )
https://github.com/LittleWat/m5stack-notify-sensors

セットアップ

開発環境構築

Arduino IDEより、VS Codeの方が慣れているのでそちらで環境構築しました。

丁寧な記事があったのでそちらを参考にしました。執筆者に感謝!

  1. 【心折れずに】MacでM5stackをはじめる
  2. M5Stackの開発環境を整える - PlatformIO IDE編

PlatformIO IDEのLibraryは platformio.iniで指定しているので追加不要かもですが、下記のライブラリを追加しました。

  • M5Stack@^0.2.9
  • SimpleDHT@^1.0.12
  • ezTime@^0.8.1

ちなみに、Serial Monitorの設定や、ログレベルの設定もplatformio.iniで行なっています。
(ログレベルはソースコードからではコントロールできなかったです。)

platformio.ini
[env:m5stack-core-esp32]
platform = espressif32
board = m5stack-core-esp32
framework = arduino
monitor_speed = 115200
build_flags = -DCORE_DEBUG_LEVEL=4

lib_deps =
    M5Stack@^0.2.9
    SimpleDHT@^1.0.12
    ezTime@^0.8.1

デバイス

  • M5Stack Gray
    • 9軸センサがついてるらしいですが、今回は使用してないです汗
  • GROVE - デジタル温度・湿度センサ(DHT11)
    • M5Stackを使うのであれば、DHT11よりも DHT12を使えばサンプルがそのまま動きそうでよかったのですが、たまたま手元にあったのがDHT11だったのでそちらを使用。

VCCとGNDは普通につないで、GROVE - デジタル温度・湿度センサSIGM5Stack Grayの5番のポートにつなぎました。

2番ポートにつなぐと、デバイスにソースコード書き込みができない下記エラーが発生します汗

`A fatal error occurred: MD5 of file does not match data in flash!
*** [upload] Error 2`

調べたところ、どうもESPの問題らしいです。
書き込み時にはケーブルを2番ポートから抜いて、書き込み後に刺せば動作します。が、面倒なので5番ポートを使用しました。

参考

Gmailの設定

あまり好ましくはないのですが、簡単にメールを送るためセキュリティを緩くしました。(メール送信に使うgmailアカウントは最悪乗っ取られてもよいものを作っておくのが良さそうですが)

Googleアカウントで、安全性の低いアプリを許可する

スクリーンショット 2019-10-22 23.28.44.png

Gmailの設定でIMAPを有効にする

スクリーンショット 2019-10-22 23.28.25.png

以上でセットアップ終了です!

実行

下記コマンドを実行し、できたMyConfig.hを各自の環境に合わせて編集します。

git clone https://github.com/LittleWat/m5stack-notify-sensors
cd m5stack-notify-sensors/include
cp MyConfig.h.template MyConfig.h
MyConfig.h
const char* wifi_ssid = "xxx";
const char* wifi_pass = "xxx";
const char* smtp_username = "xxx";
const char* smtp_password = "xxx";
const char* smtp_from_address = "xxx@gmail.com";
const int smtp_port = 465;
const char* smtp_hostname = "smtp.gmail.com";

const char* to_address = "xxx@gmail.com";
const char* subject = "温湿度情報";

const int temperature_upper_limit = 28;
const int temperature_lower_limit = 15;
const int minimum_email_interval_seconds = 60 * 10;  // 10 minutes
const int sensing_interval_milliseconds = 5000;      // should be more than 1500

下4行で、下記を設定してます。

  • 通知すべき温度の上限値、下限値
  • メールを送りまくらないように最低開ける時間(上記では10分に設定)
  • センサ値を取得する感覚(上記では5秒に設定)

その後vscodeで開き、下のバーにある ボタン(コンパイルしてm5stackに書き込みするボタン)を押せば動く(ハズです)。

ソースコード作成にあたって下記資料参考にさせていただきました。
- ELEGOO:Lesson 12
- ESP32からメールを送る

メインのコード

main.cpp
#include <M5Stack.h>
#include <Mailer.h>
#include <SimpleDHT.h>
#include <ezTime.h>

#include "MyConfig.h"

// ref: http://shikarunochi.matrix.jp/?p=2586
// 抵抗は https://www.switch-science.com/catalog/818/ を使っていたら、いらない
// for DHT11,
//      VCC: 5V or 3V
//      GND: GND
//      DATA: 2
// int pinDHT11 = SCL;
int pinDHT11 = G5;
SimpleDHT11 dht11(pinDHT11);

Mailer mail(smtp_username, smtp_password, smtp_from_address, smtp_port,
            smtp_hostname);
Timezone Tokyo;
time_t last_emailed_at;
void send_email(const String content);

void setup() {
  M5.begin();
  M5.Power.begin();

  M5.Lcd.setTextSize(3);

  log_i("Connecting to %s", wifi_ssid);
  WiFi.begin(wifi_ssid, wifi_pass);
  waitForSync();
  log_i("WiFi connected");
  log_i("IP Address: %s", WiFi.localIP().toString().c_str());

  Tokyo.setLocation("Asia/Tokyo");
  Serial.println("Asia/Tokyo time: " + Tokyo.dateTime());
  last_emailed_at = Tokyo.now();
}

void loop() {
  // start working...
  Serial.println("=================================");
  Serial.println("Sample DHT11...");

  M5.Lcd.setCursor(0, 0);

  // read without samples.
  byte temperature = 0;
  byte humidity = 0;
  int err = SimpleDHTErrSuccess;
  if ((err = dht11.read(&temperature, &humidity, NULL)) !=
      SimpleDHTErrSuccess) {
    Serial.print("Read DHT11 failed, err=");
    Serial.println(err);
    M5.Lcd.print("Read DHT11 failed, err=");
    M5.Lcd.println(err);
    delay(1000);
    return;
  }

  // LCD display
  M5.Lcd.print((int)temperature);
  M5.Lcd.print(" *C, ");
  M5.Lcd.print((int)humidity);
  M5.Lcd.println(" H");

  Serial.print("Sample OK: ");
  Serial.print((int)temperature);
  Serial.print(" *C, ");
  Serial.print((int)humidity);
  Serial.println(" H");

  // 経過時間を計算しそれが一定以上、かつ温度が閾値を超えていたらメール送信
  auto elapsed_seconds = difftime(Tokyo.now(), last_emailed_at);

  String email_content = "温度: ";
  email_content += (int)temperature;
  email_content += "℃、湿度: ";
  email_content += (int)humidity;
  email_content += "%です。\n";
  Serial.println(email_content);

  log_d("経過時間:%.1f秒", elapsed_seconds);
  if (elapsed_seconds > minimum_email_interval_seconds) {
    if (temperature > temperature_upper_limit) {
      send_email(email_content + "暑いので冷房を強くしてください。");
    } else if (temperature < temperature_lower_limit) {
      send_email(email_content + "寒いので暖房を強くしてください。");
    }
  }
  // DHT11 sampling rate is 1HZ.
  delay(sensing_interval_milliseconds);
}

void send_email(const String content) {
  mail.send(to_address, subject, content);

  M5.Lcd.println("");
  M5.Lcd.println("Emailed at ");
  M5.Lcd.println(Tokyo.dateTime());

  last_emailed_at = Tokyo.now();
}

所感

ネット上の記事を漁れば手軽に色々と作れそうな印象を受けました。先人に感謝。今後も色々と作っていきたいですね。

今回、時間が一番かかった気がするのは、地味に下記の文字列結合。
長くてダサいですが一応動いたのでよしとしました。

String email_content = "温度: ";
email_content += (int)temperature;
email_content += "℃、湿度: ";
email_content += (int)humidity;
email_content += "%です。\n";

%dとか使ってやったりして色々と詰まりました汗。。
Arduinoはstdio:stringではなく、Stringを使わねばならないみたいですね。(慣れている人からしたら当然のことなのでしょうが...)
もっといい書き方などありましたら教えてくださいませ。。m(_ _)m

PythonやSwiftの手軽さは魅力的ですが、c++(普通の意味で)チョットデキルくらいにはなりたいものです。

2
10
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
2
10