OGIMOノート

6歳の娘と、4歳の息子(脳性麻痺)を持った父親エンジニアの備忘録。自作の電子工作おもちゃ/リハビリ器具の製作記録、勉強記録を残していきます

M5stack(ESP32)で朝顔水やりロボットを作ってみた

はじめに(動機)

前記事では、M5stackを使ってキッチンの手前に置く「お風呂沸かしボタン」押しロボットを作った。

ogimotokin.hatenablog.com

これに味を占めて、M5Stackを使って遊んでみようと企んでいた。
先日に訪問したMaker Faire TokyoでM5stack開発者のJimmyさんとお話して、M5stackに思い入れが少し入った事もある(笑)

そんな矢先、8月初旬(一週間前)、妻&娘から
「夏休みの旅行期間中、
 朝顔に自動で水をやる機械ができないか?」
といった相談が入ってきた。
今年で小一になる娘が学校で育てて持ち帰った朝顔の鉢、忘れがちながらも水やりを毎日頑張って、ここまで枯らさずに育ててきた。しかし、明日からの旅行で長期間不在にしてしまうので、不在中に水分量が足りなくなったら、下手したら朝顔の鉢が枯れてしまう。。。

娘も「枯らしたらどうしよう…」と不安な顔をしていたので、これはもう「やるしかない!」という事で、
朝顔に水をやるロボット』
の開発に乗り出した

依頼要件

朝顔の鉢に定期的に水を与える事
(2回以上/日)
・水をちゃんとあげられたかどうかを
フィードバックして欲しい
(万が一、うまくいってなかった場合、ばぁば召喚の可能性も想定するため)
・開発期間: 旅行出発まで
(実働期間は深夜3日間のみ)

要件はいいが、厳しいのが開発期間! モノは作れても検証期間が取れない。。。

だが、父の名誉と妻娘からの信頼感、そして今後の自分の趣味時間の確保&拡大のためにも、ここはなんとかやり遂げる!

完成品

という訳で、短期間での開発を実現するため、手元にあったM5stackを活用して、朝顔水やりロボットを完成させた。

完成ハードウェア写真は以下。
f:id:motokiinfinity8:20180815000733j:plainf:id:motokiinfinity8:20180815000736j:plain

完成動画は以下。

ロボット仕様

・一定時間(4時間置き)にロボット起動。
 バケツの水からポンプでくみ上げて、朝顔鉢上に放水!
 放水箇所を分散させるためホースは可動式にする
・放水動作完了したら、Lineに完了通知をお知らせ
 その際、温度&湿度&土壌乾燥度の情報も通知。
 特に土壌乾燥度は放水前後の値を取得する事で、確実に放水されている事を検知する

正直なところ、M5stackである必要はあまりない。だって、屋外に置いて放置してる(しかも留守居にしている)ので、液晶&スピーカは本来は無用なのだ。
しかし、真の目的は、娘&妻へのプレゼン&信頼感を得る事であるため、
「映像&音でデモ映えする方が、より『おおーっ!』って言ってもらえるし、
 個人的にもモチベーション上がる!」
という事だ。個人モノづくりにとってモチベーションは何よりも最優先だと思う!




ハードウェア検討

全体システム図

f:id:motokiinfinity8:20180815231717j:plain

水やりのためのポンプ&ホース選定は以下のサイトを参考にした。
2m3g1.com

「水中用ポンプ」「ホース」は時間がなかったので全く同じものをAmazonで購入。
水中用ポンプが12V駆動なので、屋外コンセントレス環境での使用を想定して
「乾電池BOX 単三×8本」も購入した。
https://www.amazon.co.jp/gp/product/B0714BK7M5/ref=oh_aui_detailpage_o02_s00?ie=UTF8&psc=1

水中用ポンプの電源ON/OFFを切り替えるのは、トランジスタを使うのがラク
なので一般的であろうNPN型2SC1815-GRを購入。

また、M5stackへは5V入力が必要なので、12V→5V変換DC/DCモジュールも使用した。
https://www.amazon.co.jp/gp/product/B010RYGGJC/ref=oh_aui_detailpage_o01_s00?ie=UTF8&psc=1
サイズ感の割に対応電圧幅が広いため、まとめ購入して重宝しているDC/DCモジュールだ。

温度/湿度センサーは、以前にM5stackのプロトキットを購入した際に付いてきたDHP-12モジュールを使用。GROOVE対応のため、接続イメージは簡単。

土壌乾燥度センサーは、園芸系電子工作ではよくつかわれているYL-69を使用。
https://www.amazon.co.jp/gp/product/B01H6WK51I/ref=oh_aui_detailpage_o04_s00?ie=UTF8&psc=1
水分量(電圧)に応じたアナログ値を出力してくるため、M5stack側はAD端子で受ける必要がある




ソフトウェア検討

詳細に記載すると大変なので、メモとポインタだけ。

Deep Sleep遷移設定

電池駆動である事を考えると、常にマイコン駆動させておくのは非効率のため、この機会にESP32の売り機能であるDeep Sleep機能を使ってみる事にした。Deep Sleepモードとは、要はRTC/割込み系等最低限のハードウェアだけ生かして他コアはSleepさせるモードの事。Deep Sleep時の待機電流は数十uAなので、電池駆動機器に使うには必須となる機能である。

d.hatena.ne.jp

上記サイト等を参考にさせてもらった。Deep Sleepからのwake条件は、RTC Timer時間指定や、特定のGPIO値の割り込みなどが選択できる様だ。今回は RTC Timer時間指定をして、一定時間毎にモジュールを起動させる様にした。

#include "esp_deep_sleep.h"

void setup() {
   (中略)
  esp_deep_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_OFF);
  esp_deep_sleep_pd_config(ESP_PD_DOMAIN_RTC_SLOW_MEM, ESP_PD_OPTION_OFF);
  esp_deep_sleep_pd_config(ESP_PD_DOMAIN_RTC_FAST_MEM, ESP_PD_OPTION_OFF);
  esp_deep_sleep_pd_config(ESP_PD_DOMAIN_MAX, ESP_PD_OPTION_OFF); 
}

void loop() {
   (中略)
    // DEEP SLEEPモードに移行
    const uint32_t DEEP_SLEEP_uS = 1000*1000*60*60; //1時間置きに起動
    esp_deep_sleep_enable_timer_wakeup(DEEP_SLEEP_uS);  // wakeup(restart) after 6hours
    esp_deep_sleep_start();
}
温度/湿度センサDHT12動作

github.com
を参照。cloneデータを解凍してライブラリに入れておけばOK

Line通知

調べたところ、簡単なやり方としては、
 IFTTT連携 → Line Notify通知
になる様だ。

ESP32 Wifi経由でIFTTTへ接続しLINEへ通知 – thousandiy

上記サイトを参考にすればOK
 ・Lineへの投稿文章は、IFTTT側のアクションフィールド内で定義
  その際に、変数(String型)は3つまで設定でき、ESP32側で変数を作って投稿する

Arduino側の設定環境は以下

const char* ifttt = "maker.ifttt.com";  // Server URL
WiFiClient client;

void setup() {
   (中略)
}

void loop() {
   (中略)
      // LINEに完了通知を送信
      // Make a HTTP request:
      String  value1 = String(temper, DEC);    //value1: 外気温度表示
      String  value2 = String(humidity, DEC);  //value2: 外気湿度表示    
      String  value3 = String(dojyo_val, DEC);    //value3: 土壌乾燥値の表示(水やり前)
    
      while(!client.connect(ifttt, 80)){
         Serial.print(".");
         delay(500);
      } 
      Serial.print("client,Connect");
      String url = "/trigger/" + makerEvent + "/with/key/" + makerKey;
      url += "?value1=" + value1 + "&value2=" + value2 + "&value3=" + value3;
      client.println("GET " + url + " HTTP/1.1");
      client.print("Host: ");
      client.println(ifttt);
      client.println("Connection: close");
      client.println();

      int count = 0;
      while (!client.available()) {
        delay(50); //
        Serial.print(".");

        count++;
        if (count > 20 * 20) { // about 20s
          Serial.println("(send) failed!");
          return;
        }
      }
}

開発ハプニング事例

①定期Wake時間のSleep時間

esp_deep_sleep_enable_timer_wakeup関数の引数値を試しに6時間程度に指定してみたが、なぜか10分程度の間隔になってしまった。そこで、- Read the Docs for Businessなどのサイトを調べたところ、最大でInt32最大us=71.5分しかできない事が判明した。つまり、6時間Sleepはそのままでは不可である。
そこで、作戦を以下に変更した。
 ・モジュールは60分毎に起動
 ・起動したらRTCを取得して現在時刻を把握
 ・起動した時間情報が想定の時間であれば放水開始

RTCを取得するコードは以下。納品当日に変更したが、一発勝負で上手くいった!!

void setup() {
  //NTP設定
  configTime(9 * 3600L, 0, "ntp.nict.jp", "time.google.com", "ntp.jst.mfeed.ad.jp");
}

void loop(){
  struct tm timeInfo;
  getLocalTime(&timeInfo);
  Serial.print(timeInfo.tm_year);
  Serial.print(" ");
  Serial.print(timeInfo.tm_mon);
  Serial.print(" ");
  Serial.print(timeInfo.tm_mday);
  Serial.print(" ");
  Serial.print(timeInfo.tm_hour);
  Serial.print(" ");
  Serial.print(timeInfo.tm_min);
  Serial.print(" ");
  Serial.print(timeInfo.tm_sec);

 // 一定時刻(8時/12時/16時/20時/23時)のみ水やり動作実施
  if (timeInfo.tm_hour == 8 || timeInfo.tm_hour == 12  || timeInfo.tm_hour == 16 || timeInfo.tm_hour == 20 || timeInfo.tm_hour == 23 ){
 (中略)
 }
}
②M5stack ADC端子からanalogReadが出来ない

土壌センサの値がうまく読めず0値状態。信号の電圧値は3.3V近いのに何故!?
M5stack側の設定を疑いにかかった結果、ピン依存がある事は見えてきたが、原因解明まで至らず。。。

Pin25→〇(Speaker共用)
Pin26→〇
Pin35→×(0値)
Pin36→×(0値)

一旦時間がないのでPin26を使って回避しておくが、謎すぎる。。。
公式としてはPin35&36がADC推奨端子の様に見えるのだが、回路図を見ても、GPIO35/36共にESP32に直結してるだけだし…謎だ。

M5stack側の単品不良の可能性も踏まえて、後日追い込んでみよう。

③水回り周辺の電子機器開発トラブル

実は、初めての体験だった。やはり水と電気は相性が悪い。
事件は、納品前日の深夜3時。水を入れない状態で、一通りのモジュール結合動作を確認完了。
「さて、最後にポンプで水を吸い上げる事を確認したら寝よう」
と考えて、ベランダで最終確認をしようとしたのだが、その際に誤って、、、バケツの水をはねさせてしまい、モジュールに水がばさっとかかってもた!
突然M5stackが真っ白くざざっとノイズが乗って、その後沈黙。
これにより、M5stack本体と、DHT12モジュール/YL-69モジュールがやられたっぽい。

正直、納品前日(旅行出発前々日)の深夜3時にやらかしたので、、、もう絶望しかなかった。
幸い、M5stackは手元に予備があったので助かったが、、、DHT12モジュールは現品のみだったので、
温度/湿度/土壌乾燥度を通知する仕様はあきらざるを得なかった。

自分の不注意ではあるのだが、、、、今後は気をつける




最後に

今は、旅行先からの投稿になるのだが、無事に
朝顔の水やりが完了しました」
通知を受信しており、安定動作している様で、とても安心している。

f:id:motokiinfinity8:20180816080605j:plain

娘も「朝顔さん、枯れてなさそうでよかった」と嬉しそうにしていて、まさに『家族のためのモノづくり』が出来てる実感を持てて、嬉しい限り!


せっかく作った水やりロボットだが、この旅行を最後に使う事がなくなるのは大変もったいないので、
いっその事、『ロボットを使うために植物を育てる』事をやってやろうか!?


(これを、目的と手段の逆転、という)


本ロボットをバージョンアップさせるならば、
 ・土壌乾燥度を見ながら、
乾いてきたら自動で水を実施する
 ・M5stack→ESP32モジュール変更&
省電力機能をまじめに実装する

辺りを頑張ってみたいので、もし新たな植物を育てるネタができたら、かな。