NOBのArduino日記!

NOBのArduino日記!

趣味は車・バイク・自転車・ラジコン・電子工作です。

グリーンカーテン(2021)!

f:id:nobita_RX7:20210613164847j:plain

グリーンカーテン(2021)!
 
 2017年から今年で5年目、我が家恒例のグリーンカーテンを今年も設置しました!
 

1.「植えたもの」

 「アサガオ」1種類を種から、「トマト」1種類を2株、「バジル」1種類を2株、「ゴーヤ」1種類を7株、「キュウリ」7種類を各1株と、例年より盛沢山です。

 

1.1 「アサガオ
 息子が小学校で貰って来たアサガオの種を撒いたら一週間でご覧の通りです!

f:id:nobita_RX7:20210613164851j:plain

アサガオ(6/14 )

 

アサガオ(7/24 追記 after!)
1.2 「トマト」
 葉っぱが既にトマトの臭いで良いですね!

f:id:nobita_RX7:20210613164854j:plain

トマト

トマト(7/24 追記 after!)
1.3 「バジル」
 既に虫に食われてます、ネットを掛けた方が良いのかな?

f:id:nobita_RX7:20210613164858j:plain

バジル

バジル(7/24 追記 after!)
1.4 「ゴーヤ」
 昨年はゴーヤの収穫が少なかったので、今年は大収穫と書かれた所に引かれてこちらの苗一択7株購入。

f:id:nobita_RX7:20210613164834j:plain

f:id:nobita_RX7:20210613164838j:plain

ゴーヤ「島豊、5383」

ゴーヤ(7/24 追記 after!)

 
1.5 「キュウリ」
 毎年キュウリについては、成功した試しが無いです。
 今年はプランター7つそれぞれ違う種類の苗を植えて、家の庭環境に合ったキュウリを探す実験年にしました。

f:id:nobita_RX7:20210613164908j:plain

f:id:nobita_RX7:20210613164912j:plain

1/7_キュウリ「はやみどり、J0008」

f:id:nobita_RX7:20210613164919j:plain

f:id:nobita_RX7:20210613164925j:plain

2/7_キュウリ「バリQ、J0007」

f:id:nobita_RX7:20210613164930j:plain

f:id:nobita_RX7:20210613164934j:plain

3/7_キュウリ「うどんこつよしDX」

f:id:nobita_RX7:20210613164938j:plain

f:id:nobita_RX7:20210613164942j:plain

4/7_キュウリ「耐病性強力キュウリ、5345」

f:id:nobita_RX7:20210613164950j:plain

f:id:nobita_RX7:20210613164954j:plain

5/7_キュウリ「夏すずみ、E0102」

f:id:nobita_RX7:20210613164959j:plain

f:id:nobita_RX7:20210613165003j:plain

6/7_キュウリ「なるなるZUTTO、J0006」

f:id:nobita_RX7:20210613164826j:plain

f:id:nobita_RX7:20210613164831j:plain

7/7_キュウリ「夏すずみ,23-395-032」

(7/24 追記 after!:結論 大差なし!)

2.自動水やり機!

 2017年から4年稼働している鉛バッテリー「WP5-12」が遂にお亡くなりになりました(´;ω;`)、秋月電子で再度購入し接続したところプランター自動水やり機復活です!
 ついでにセンサーを旧型(土壌湿度センサー(SEN0114))から、新型の(Capacitive Soil Moisture Sensor V1.0)にしたのと、それに伴いプログラムもバージョンアップしておきました!

f:id:nobita_RX7:20210613164843j:plain

プランター自動水やり機
 
2.1 プログラム
 2017年のプログラムから、メンテナンスしやすい様に以下の3つのファイルに分割しました。
/* NOBのArduino日記! プランター自動水やり機制御プログラム(20210614作成)
 * Ver   :2.0
 * 変更内容:調整しやすいように変数化・関数化・プログラム分割実施
*/
#include <Arduino.h>
#include "Data.h"
#include <Wire.h>
#include "DS1307.h"
DS1307 clock;//DS1307クラスのオブジェクトを定義する

void setup() {
  clock.begin();
  Serial.begin(9600);
  pinMode(SensorPower, OUTPUT);
  pinMode(SolenoidPower, OUTPUT);
  pinMode(SwitchIn, INPUT);


/*
 * 時刻調整関数
 * 20190624:インターネット時間-3秒に調整済み
 * 通常の書き込み時は確実にDEBUG値を「0」にする!!
 */
#if DEBUG
//            年, 月, 日, 時, 分, 秒, 曜日
//RTC_Write(2019,  7, 21, 12,  5,  0,  0);//前回
//RTC_Write(2020,  6, 14,  6, 49, 55,  0);//書き込み後直ぐ出す_Test用
//RTC_Write(2021,  6, 13, 15, 39,  0,  0);//20210614 いつでも値が確認できるようにDEBUGModeでシリアル出すが日付リセットは止めておく
#endif



/*
 * 時間・センサー値確認用
 */
#if 0//DEBUG
  while(1){
    Sencer_Print();
    RTC_Print();
  }
#endif
  
}

void loop() {

/*
 * 時間・センサー値確認用
 */
#if DEBUG
  Sencer_Print();
  RTC_Print();
#endif
  
  /*
   * 手動スイッチが押されていれば強制的に水を出す
   */
  if(Skip == false && Switch_Read()){
    digitalWrite(SolenoidPower, HIGH);  //水を出す
    Skip = true;
  }

  /*
   * 規定時刻に土が乾いていれば水を出す
   */
  if(Skip == false && Time_Read()){
    if(Sensor_Read()){
      digitalWrite(SolenoidPower, HIGH);  //水を出す
      //delay(OnTime * 1000);  //secをmsに変換 ※32767以上の値になる時は末尾に「UL」を付ける
      for(int i=0;i>=OnTime;i++){
        delay(1000);  //secをmsに変換 ※32767以上の値になる時は末尾に「UL」を付ける
        Time_Read();
        Sensor_Read();
      }
      Skip = true;
    }
  }

  /*
   * 最後までSkipされていなければ水を止める
   */
  if(Skip == false){
    digitalWrite(SolenoidPower, LOW);  //水を止める
  }else{
    Skip = false;                      //Skipトグルが「true」だったら「false」に戻す
  }
}
イメージ 1
Mailn_PlantWatering.ino

 

#include <Arduino.h>
#define DEBUG 1

/*
 * 機能:土壌湿度センサーの値を判定
 * Dry: (520 430]
 * Wet: (430 350]
 * Water: (350 260]
 * 
 * 土に直挿し実測値
 * 390:少し湿っている
 * 272:水没!
 * 337:水が滴っている
 * 
 * センサーの周りにスポンジセットし水散布
 * 一回目
 * 350:水あげ5min後
 * 425:水あげ10min後
 * 453:水あげ60min後
 * 
 * 二回目
 * 280:水あげ 0min後 13:09
 * 283:水あげ 1min後 13:10
 * 303:水あげ 2min後 13:11
 * 339:水あげ 3min後 13:12
 * 386:水あげ 4min後 13:13
 * 398:水あげ 5min後 13:14
 * 404:水あげ 6min後 13:15
 * 406:水あげ 7min後 13:16
 * 407:水あげ 8min後 13:17
 * 408:水あげ 9min後 13:18
 * 408:水あげ10min後 13:19
 * 409:水あげ11min後 13:20
 * 411:水あげ15min後 13:24
 * 415:水あげ20min後 13:29 水が滴っている
 * 415:水あげ25min後 13:34 水が滴っている
 * 417:水あげ30min後 13:39 水が滴っている
 * 423:水あげ50min後 13:59 水が滴っていない
 * 
 * 三回目(8/3 晴れ 11:08)
 * 443:水あげ4h後 乾燥している
*/
const int SensorThreshold_Morning = 410;                 //SensorReadの値が朝410を超えたら土に水をあげる
const int SensorThreshold_Night   = 462;                 //SensorReadの値が夜475を超えたら土に水をあげる
const unsigned long OnTime = 60;                         //←30秒間水を出す(単位:Sec)
const int Hor_Morning = 7;                               //朝一の時刻(閾値)

/*
 * ピン番号
*/
const int SensorPower = 2;//土壌湿度センサー電力供給制御ピン番号
const int SolenoidPower = 8;//水電磁弁開閉制御ピン番号
const int SwitchIn = A1;//水電磁弁の手動ONスイッチ接続ピン番号
const int SensorIn = A3;//土壌湿度センサー値取得ピン番号

/* 
 *  宣言
*/
int Mon;
int Hor;
int Min;
int Sec;

/*
 * 条件判定
 */
bool Skip = false;



/*
 * 「月」列挙
 */
enum MONTH{
  January = 1,
  February,
  March,
  April,
  May,
  June,
  July,
  August,
  September,
  October,
  November,
  December
};

イメージ 1

Data.h
 

#include <Arduino.h>


bool Sensor_Read(){
  int SensorValue = 0;                                  //SensorValueをint型の変数として宣言(毎回0にリセット)
  for(byte i=0;i<=10;i++){                              //A3ポートの電圧を10回読み平均値を出す
    digitalWrite(SensorPower, HIGH);                    //センサー電力供給開始
    delay(10);                                          //一定時間電流を流して測定値を安定させる
    SensorValue = SensorValue + analogRead(SensorIn);   //センサー電圧を読み合計する
    digitalWrite(SensorPower, LOW);                     //センサー電力供給停止
  }
  SensorValue = SensorValue / 10;                       //センサー電圧平均値を返す
  int SensorThreshold_Data;                             //朝晩によって閾値を変える
  if(Hor < Hor_Morning){ 
    SensorThreshold_Data = SensorThreshold_Morning;
  }else{
    SensorThreshold_Data = SensorThreshold_Night;
  }
  if(SensorValue > SensorThreshold_Data){               //測定値が閾値より高い場合は1を返す
    return true;
#if DEBUG
  Serial.println("Senser_ON ");
#endif
  }else{
    return false;
  }
#if DEBUG
  Serial.println("Senser_OFF");
#endif
}



/*
 * 手動スイッチ入力状態の測定
 */
bool Switch_Read(){
  if(digitalRead(SwitchIn) == HIGH){
    return true;
  }else{
    return false;
  }
}



/*
 *機能:リアルタイムクロックの値を判定
*/
bool Time_Read(){
  /*閾値・変数*/
  const unsigned long TimeThreshold_Data = 1000;   //1000msに一回の判定(単位:ms)
  unsigned long Time_Now = millis();               //現在の経過時間を取得(単位:ms)
  static unsigned long Time_Old = 0;               //前回の測定時間を取得(単位:ms)
  static bool Toggle;                              //ソレノイドバルブのON・OFF状態を格納
  /*周期処理(1sec/回)*/
  if(Time_Now - Time_Old > TimeThreshold_Data){
    Time_Old = Time_Now;
    Toggle = false;
    /*現在の時刻を取得*/
    clock.getTime();
    Mon = clock.month;
    Hor = clock.hour;
    Min = clock.minute;
    Sec = clock.second;
    /*規定時刻でtrueを返す処理*/
    switch (Mon) {
      case June:       //6月
        if(Hor == 6 || Hor == 8){                                              //←時間の
          if(Min == 50){     //←分に
            if(Sec < OnTime){Toggle = true;}                         //OnTime秒間「1」を返す
          }
        }
        break;
      case July:       //7月
        if(Hor == 6 || Hor == 8 || Hor == 16 ||Hor == 18){                                 //←時間の
          if(Min == 50){     //←分に
            if(Sec < OnTime){Toggle = true;}                         //OnTime秒間「1」を返す
          }
        }
        break;
      case August:     //8月
        if(Hor == 6 || Hor == 8 ||Hor == 10 ||Hor == 12 ||Hor == 14 ||Hor == 16 ||Hor == 18){                                //←時間の
          if(Min == 50){    //←分に
            if(Sec < OnTime){Toggle = true;}                        //OnTime秒間「1」を返す
          }
        }
        break;
      case September:  //9月
        if(Hor == 6 || Hor == 8 ||Hor == 10 ||Hor == 12 ||Hor == 14 ||Hor == 16 ||Hor == 18){                                             //←時間の
          if(Min == 50){    //←分に
            if(Sec < OnTime){Toggle = true;}                        //OnTime秒間「1」を返す
          }
        }      
        break;
      default:   //1~5月「Jan,Feb,Mar,Apr,May」、10~12月「Oct,Nov,Dec」)
        if(Hor == 6 || Hor == 8){                                             //←時間の
          if(Min == 50){                              //←分に
            if(Sec < OnTime){Toggle = true;}                        //OnTime秒間「1」を返す
          }
        }
        break;
    }
  }

    return Toggle;
}


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////以下Debug用//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
 * センサーの値を1秒おきに出力する関数
 */
void Sencer_Print(){
  int SensorValue = 0;                                  //SensorValueをint型の変数として宣言(毎回0にリセット)
  /*閾値・変数*/
  const unsigned long TimeThreshold_Data = 1000;   //1000msに一回の判定(単位:ms)
  unsigned long Time_Now = millis();               //現在の経過時間を取得(単位:ms)
  static unsigned long Time_Old = 0;
  /*周期処理(1sec/回)*/
  if(Time_Now - Time_Old > TimeThreshold_Data){
    Time_Old = Time_Now;
    for(byte i=0;i<=10;i++){                              //A3ポートの電圧を10回読み平均値を出す
      digitalWrite(SensorPower, HIGH);                    //センサー電力供給開始
      delay(10);                                          //一定時間電流を流して測定値を安定させる
      SensorValue = SensorValue + analogRead(SensorIn);   //センサー電圧を読み合計する
      digitalWrite(SensorPower, LOW);                     //センサー電力供給停止
    }
    SensorValue = SensorValue / 10;                       //センサー電圧平均値を返す
    Serial.print("SensorValue:");Serial.print(SensorValue);Serial.print("  ");
  }
}



/* 
 * RTCの時刻を修正する関数
 * 使い方      年, 月, 日, 時, 分, 秒, 曜日
 * RTC_Write(2019,  6, 24, 13, 51, 00, MON);
 */
void RTC_Write(int Y,int M,int D,int h,int m,int s,int W){
  clock.fillByYMD(Y,M,D);  //年,月,日
  clock.fillByHMS(h,m,s);  //時:分,秒"
  clock.fillDayOfWeek(W);   //曜日
  clock.setTime();           //RTCチップへの書き込み
}



/*
 * RTCの時刻を表示する関数
 */
void RTC_Print(){
  /*閾値・変数*/
  const unsigned long TimeThreshold_Data = 1000;   //1000msに一回の判定(単位:ms)
  unsigned long Time_Now = millis();               //現在の経過時間を取得(単位:ms)
  static unsigned long Time_Old = 0;
  /*周期処理(1sec/回)*/
  if(Time_Now - Time_Old > TimeThreshold_Data){
    Time_Old = Time_Now;
    clock.getTime();
    Serial.print(clock.year+2000, DEC);Serial.print("/");
    Serial.print(clock.month, DEC);Serial.print("/");
    Serial.print(clock.dayOfMonth, DEC);
    Serial.print("(");
    switch (clock.dayOfWeek){// Friendly printout the weekday
      case MON:Serial.print("MON");break;
      case TUE:Serial.print("TUE");break;
      case WED:Serial.print("WED");break;
      case THU:Serial.print("THU");break;
      case FRI:Serial.print("FRI");break;
      case SAT:Serial.print("SAT");break;
      case SUN:Serial.print("SUN");break;
    }
    Serial.print(")");Serial.print("");
    char A[2];
    dtostrf(clock.hour,2,0,A);Serial.print(A);Serial.print(":");
    dtostrf(clock.minute,2,0,A);Serial.print(A);Serial.print(":");
    dtostrf(clock.second,2,0,A);Serial.print(A);
    /*出力状態も出力*/
    Serial.print("  SolenoidPower:");
    if(digitalRead(SolenoidPower)){Serial.println("ON");}else{Serial.println("OFF");} 
  }
}

イメージ 1

Function.ino
 
 

3.まとめ!

 今年は豊作間違いなし!?

f:id:nobita_RX7:20210613164904j:plain

グリーンカーテン

イメージ 1 イメージ 3
励みになりますのでよければクリック下さい(^o^)/

↩【プランター自動水やり機!(他ガーデニング)】目次に戻る