見出し画像

【SALZ製作】SALZ2のシェイクダウン

長い長いGWが終わりました。
GW突入直前にMaker Fair Kyoto 2020 onlineの情報を知り、急きょ出展することにしました。
自らも出展者となることで、他の出展者の展示をひとつずつ丁寧に見て回ることができました。
午後からのオンライン討論会も聴講しました。
結局、全ての展示を見て回る事はできませんでしたが展示会を満喫し、メイカー文化の楽しさと奥深さを垣間見ることができました。

このGWで自学の時間が多く取れ、SALZの製作も次のステップへ進むことができました。
ここまでの振り返りをいたします。

SALZ2が組み上がり、テストを開始しました。

先のポストでも触れましたが、obnizによらない装置作りを進めてきました。
新しい水やり装置キットをベースに、USBで駆動する水中ポンプをリレーに接続しました。

その各ステップは小さな失敗の連続で、

課題に当たる

解決方法を模索する

答えが出ない

休む

アイデアを思いつく

試してみる

の繰り返しでした。
納期のない試行錯誤はとても楽しいものです。
これが仕事と異なるところですね。

装置の説明

名称:SALZ2(ザルツ2)
機能:盆栽用の自動潅水機能を備える。データロガー付き
マイコン:DOIT ESP32 DEVKIT V1
水分センサ:Capacitive Soil Moisture Sensor v1.2
給水ポンプ:USB給電 AD180-0510 DC5V
リレーモジュール:キット品(JQC3F-05VDC-C)
サーボモータ:SG92R(SALZ1のまま)
コンテナ:アステージ製システムコンテナ 250
その他部品:USB延長ケーブル、ビニールホース、ジャンパー線、ブレッドボード、USBアダプタ2個口、屋外用延長コード、漏電保護タップ、ビニルテープ、エアコン用粘着テープ、塩ビ管、塩ビ管エルボ、ペットボトルの口、ビー玉、肥料カバー、タコ糸、バスコーク透明、プラ容器 ほか

SALZ1のハードを流用しています。

これまでの製作過程はこちらをご覧ください。

【SALZ製作】ハードウェア編

【SALZ製作】給水口編

【SALZ製作】排水口編2

このハードウェアに、ESP32のマイコン、水分センサ、リレーを組み合わせます。

画像1

[ESP32、水分計、リレー]

画像2

[上部トレー]

画像3

[マイコン部]

画像4

[バルコニーの際に設置しました]

テスト中はESP32をブレッドボード2つにまたいで使っていましたが、片側はそのままピンに挿せばよいので、1つにしました。最終的には、VCCとGNDを2つに分岐させれば良いだけなので、ブレッドボードなしでも良さそうです。

今回は、これから夏に向かい、たくさんの日光を浴びて、大きく成長して欲しいため、バルコニーの際に設置しました。

そして、まずは「TEST_MODE」で動作確認。全てのサイクルタイムを短く設定しており、各装置が正しく動作するか確認しました。懸念していたサーボはキッチリと動作し、サーボホーンのキャリブレーションも不要でした。

そしていよいよ、「TEST_MODE」を切って、本動作にしようと思ったとき、

大きな問題に気付きました。

obnizのようにコントロールするスマホがないので、プログラムを更新するときは、装置からマイコンを取り出し、PCと接続しなければなりません。
これは今後の課題です。

プログラムに関しては、水やりキットのチュートリアルから出発し、SALZ1で作った処理フローの実装、Wifiの接続、IFTTT経由のGoogle Spreadsheetへのログ出力を取り込みました。ArduinoIDEでC言語を用いてのコーディングは安心してできます。

// SALZ2 r2020.05.10 bbd
// 参考資料:
// @masciiさん「ESP32からIFTTTを使ってLINE Notifyで通知を送ってみた」
//  https://qiita.com/mascii/items/4c366ad4709469d5fda9
// TomoSoftさん「IFTTTを用いてESP-WROOM-02からGoogleドライブ・スプレッドシートに書き込み」
//  https://tomosoft.jp/design/?p=7598
// ほか
 #include  <WiFi.h>
 #include  <WiFiClient.h>
 #include  <Servo.h>

//テストモード(ON:1, OFF:0)
//#define TEST_MODE 1
 #define  TEST_MODE 0

const int DRY_LEVEL = 3000;
const int WD_TIME = (TEST_MODE) ? (5 * 1000) : (10 * 60 * 1000);
const int DOBU_TIME = (TEST_MODE) ? (5 * 1000) : (10 * 60 * 1000);
const int WAIT_TIME = (TEST_MODE) ? (10 * 1000) : (60 * 60 * 1000);

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

// 接続先のSSIDとパスワード
const char* ssid     = "XXXXXXXX";
const char* password = "XXXXXXXX";

// IFTTT
String makerEvent = "salz2_check"; // Maker Webhooks
String makerKey   = "XXXXXXXX"; // Maker Webhooks

int wsPin = 18; // 給水モータ用リレースイッチ
int wdPin = 19; // 排水弁用サーボモータ
int wlPin = 34; // 水分計センサ
float moistureLevel = 0.0;
int idLog = 0;

WiFiClient client;
Servo myServo;

void errorBlink() {
/*
 for (int i = 0; i < 10; i++) {
   digitalWrite(outputLed, HIGH);
   delay(300);
   digitalWrite(outputLed, LOW);
   delay(300);
 }
*/
 Serial.println("errorBlink();");
}

void wifiBegin() {
 Serial.print("Attempting to connect to SSID: ");
 Serial.println(ssid);
 WiFi.begin(ssid, password);
}

bool checkWifiConnected() {
 // attempt to connect to Wifi network:
 int count = 0;
 while (WiFi.status() != WL_CONNECTED) {
   Serial.print(".");
   // wait 1 second for re-trying
   delay(1000);

   count++;
   if (count > 15) { // about 15s
     Serial.println("(wifiConnect) failed!");
     errorBlink();
     return false;
   }
 }

 Serial.print("Connected to ");
 Serial.println(ssid);

 return true;
}

void sendIFTTT(String s1, String s2, String s3) {
 while (!checkWifiConnected()) {
   wifiBegin();
 }

 Serial.println("\nStarting connection to server...");
 if (!client.connect(server, 80)) {
   Serial.println("Connection failed!");
 } else {
   Serial.println("Connected to server!");
   // Make a HTTP request:
   String url = "/trigger/" + makerEvent + "/with/key/" + makerKey;
   url += "?value1=";
   url += s1;
   url += "&value2=";
   url += s2;
   url += "&value3=";
   url += s3;
   
   client.println("GET " + url + " HTTP/1.1");
   client.print("Host: ");
   client.println(server);
   client.println("Connection: close");
   client.println();
   Serial.println("url:" + url);
   Serial.print("Waiting for response "); //WiFiClientSecure uses a non blocking implementation

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

     count++;
     if (count > 20 * 20) { // about 20s
       Serial.println("(send) failed!");
       errorBlink();
       return;
     }
   }
   // if there are incoming bytes available
   // from the server, read them and print them:
   while (client.available()) {
     char c = client.read();
     Serial.write(c);
   }

   // if the server's disconnected, stop the client:
   if (!client.connected()) {
     Serial.println();
     Serial.println("disconnecting from server.");
     client.stop();
   }
 }
}

void sendData() {
 sendIFTTT(String(idLog++), String(moistureLevel), "");
}

void wdOpen() {
 //排水弁を開く
 Serial.println("排水弁を開く");
 myServo.attach(wdPin);
 myServo.write(170);
 delay(3000);
 myServo.detach();
}

void wdClose() {
 //排水弁を閉じる
 Serial.println("排水弁を閉じる");
 myServo.attach(wdPin);
 myServo.write(10);
 delay(3000);
 myServo.detach();
}

void wsOn() {
 //給水On
 Serial.println("給水On");
 digitalWrite(wsPin, LOW);
}

void wsOff() {
 //給水Off
 Serial.println("給水Off");
 digitalWrite(wsPin, HIGH);
}

void setup() {
 Serial.begin(115200);
 delay(100);

 pinMode(wsPin, OUTPUT);
 pinMode(wdPin, OUTPUT);
 digitalWrite(wsPin, HIGH);

 wifiBegin();
 while (!checkWifiConnected()) {
   wifiBegin();
 }
 delay(500);

 sendIFTTT(String(idLog++), String(moistureLevel), "SALZ2 Start");

 for (int i = 0; i < 2; i++) {
   wdClose();
   wdOpen();
   wsOn();
   delay(1000);
   wsOff();
   delay(1000);
 }
}

void loop() {
 float val = 0.0;
 for (int i = 0; i < 5; i++) {
   val += analogRead(wlPin);
 }
 moistureLevel = val / 5;

 Serial.print("MOISTURE LEVEL:");
 Serial.println(moistureLevel);
 sendData();

 if(moistureLevel > DRY_LEVEL) {
   Serial.println("ドライ");
   wdClose();
   wsOn();
   delay(WD_TIME);

   wsOff();
   delay(DOBU_TIME);

   wdOpen();
 }
 delay(WAIT_TIME);
}

今回の成果:
・obnizからESP32への転換ができた。
   ・制御用の端末が不要になった。
   ・装置が扱いやすくなった。
   ・ArduinoIDEで開発できた。
   ・馴染みのC言語でプログラミングできた。
   ・他の人にも勧めやすくなった。

・SALZ2をベランダの手すり側に設置できたこと。
   ・日当たりの良い場所に設置することで成長が早くなるかも。
   ・電源の取り回しに気を使った。

・Amazonの水やりキットを活用できた。
   ・リレーの使い方を勉強できた。
   ・静電方式の水分計を使ってみた。
   ・Arduino用のサンプルコードを入手できた。
   ・他の人にも勧めやすくなった。

今回の課題:
・ESP32を用いたプログラムの更新は、装置から取り外しUSB接続して行う必要がある。
   ・装置に付けたままで更新を行いたいときは、ノートPCを装置の近くへもっていく必要あり。

・土の上に置いた肥料が溶け出さない。
   ・どぶ浸けの水位の問題か?
   ・水位を上げることは問題ないが、上部トレーの縁を高くすると、日当たりが悪くなるのではないか。

・ポンプの勢いが増した、もう少し水深を深くしたい。オーバーフローの高さを上げたい。
   ・塩ビ管を切って取り付ければよいか。

・日なたに設置したにもかかわらず、乾くまでに時間が掛かった。
   ・閾値の調整。
   ・Wifiでパラメータを変えられる必要あり。(キャリブレーションが必要)
   ・土を変える。
      ・現在は、赤玉土100%
      ・植え替えにはリスクが伴う。
      ・約2週間は装置にセットできない。

参考資料:

WayinTop 自動水やり装置 DIYキット 静電容量式土壌水分センサー + 小型ポンプ DC3V 5V + 1M ホース + リレーモジュール 1チャンネル ガーデニング 家庭園芸 盆栽 庭園 花植 木鉢 植木鉢 のチュートリアル、サンプルコード

@masciiさん「ESP32からIFTTTを使ってLINE Notifyで通知を送ってみた」

TomoSoftさん「IFTTTを用いてESP-WROOM-02からGoogleドライブ・スプレッドシートに書き込み」

この記事が気に入ったらサポートをしてみませんか?