Irrigation timer 'Cycle and Soak'

Hi

I have created a 2-zone timer irrigation Controller based on the amazing work and posts of everyone in thIs Blynk Community post.

Ive managed to get the 2 zones working based on 2 time input widgets with a on/off button for both.

The next bit of functionality im keen to add is a ‘cycle/soak’ where the Selected time input (I.e. watering time) is split up to allow time for the water to soak in before more water is added. I.E. Water for 5 minutes, turn off for 5 minutes, run again for 5 minutes and so on.

I’d be very keen to get some good ideas on how best to achieve this.

My very crude attempt is to divide the total time input duration by 5 (3 running intervals and 2 soak intervals) and run a new function turning the relay on/off and then calling the next function (cycle_soak_1/2/3/4/5).

You’ll see the first timer called in the “BLYNK_WRITE(V10)//Zone 1 time input handling” section and then the subsequent cycle_soak functions at the end of the V10 Write.

Some of the problems i’m having with this

  1. The 10 second check doesnt seem to happen once the Zone 1 Cycle/Soak has kicked off (no updated on the terminal.

  2. reinstating to normal checking of the next input time doesnt appear to be working

A couple of notes

  • i’ve only implemented the CYcle/soak on Zone1 at this stage for testing
  • i’ve commented out some of the original code From link above while I’m testing incase i need to retrieve later on

Any help, or better ideas on how to achieve would be greatly appreciated.


// changes to allow cycle and soak in auto mode

/**************************************************************
 * timeinput.ino Demonstrate interaction of Time library with
 * Blynk's TimeInput widget.
 * App project setup:
 * RTC widget (no pin required!!!)
 * V1 : Manual/auto1 button
 * V2: On-off button
 * Terminal on V3 // Label will be the clock + wifi signal!!!!

 * 
 * Time Input widget on V10 (Auto)
 * Button selection for Time Input (Auto) on V11
 * 
 **************************************************************/

#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
//#include <SimpleTimer.h>
#include <TimeLib.h>
#include <WidgetRTC.h>

SimpleTimer timer;

WidgetRTC rtc;
WidgetTerminal terminal(V3);

//#define server "blynk.cloud-com"   // or "blynk.cloud-com" for Blynk's cloud server
#define TestLED 2                 // on board LED pin assignment
char Date[16];
char Time[16];
char auth[] = "xxxx";
char ssid[] = "xxxx";
char pass[] = "xxxx";
long startsecondswd;            // weekday start time in seconds
long stopsecondswd;             // weekday stop  time in seconds
long nowseconds;                // time now in seconds
bool isFirstConnect = true;


String displaycurrenttimepluswifi;
int wifisignal;
int manual=0;
int oldstatus;
int zone1 = 4;  // digital pin for relay 1
int zone2 = 5;  // digital pin for relay 2

int auto1;

int zone1_state;
int zone2_state;

int timerID;

long cycle_soak_int;

void setup()
{
  pinMode(TestLED, OUTPUT);
  digitalWrite(TestLED, LOW); // set LED OFF
  
  digitalWrite(zone1, LOW);
  digitalWrite(zone2,LOW);
  pinMode(zone1,OUTPUT);
  pinMode(zone2,OUTPUT);

 
  Serial.begin(115200);
  Serial.println("\Starting");
  Blynk.begin(auth, ssid, pass);
  int mytimeout = millis() / 1000;
  while (Blynk.connect() == false) { // try to connect to server for 10 seconds
    if((millis() / 1000) > mytimeout + 8){ // try local server if not connected within 9 seconds
       break;
    }
  }
  rtc.begin();
  
  Blynk.syncVirtual(V2);
  Blynk.syncVirtual(V6);
  Blynk.syncVirtual(V1);


  timer.setInterval(10000L, activetoday);  // check every 10 SECONDS if schedule should run today 
  timer.setInterval(30000L, reconnectBlynk);  // check every 30s if still connected to server 
  timer.setInterval(5000L, clockvalue);  // check value for time
  timer.setInterval(5000L, sendWifi);    // Wi-Fi singal

}


BLYNK_CONNECTED() {
if (isFirstConnect) {
  Blynk.syncAll();
  Blynk.notify("TIMER STARTING!!!!");
isFirstConnect = false;
}
}

void sendWifi() {
  wifisignal = map(WiFi.RSSI(), -105, -40, 0, 100);
}

void clockvalue() // Digital clock display of the time
{
 int gmthour = hour();
  if (gmthour == 24){
     gmthour = 0;
  }
  String displayhour =   String(gmthour, DEC);
  int hourdigits = displayhour.length();
  if(hourdigits == 1){
    displayhour = "0" + displayhour;
  }
  String displayminute = String(minute(), DEC);
  int minutedigits = displayminute.length();  
  if(minutedigits == 1){
    displayminute = "0" + displayminute;
  }  

  displaycurrenttimepluswifi = "                                          Clock:  " + displayhour + ":" + displayminute + "               Signal:  " + wifisignal +" %";
  Blynk.setProperty(V3, "label", displaycurrenttimepluswifi);
  
}

void activetoday(){        // check if schedule should run today
  if(year() != 1970){

   if (auto1==1) {  
    Blynk.syncVirtual(V10); // sync timeinput widget  
    Blynk.syncVirtual(V20);
   }
  }
}

void checklastbuttonpressed (){

    if((auto1==1)){ oldstatus=1;}
}

void restorelastbuttonpressed (){
    if(oldstatus==1){auto1=1;}
}

//void resetTerminal()
//{
//    timer.setTimeout(50, checklastbuttonpressed);
//    terminal.println();
//    terminal.println();
//    terminal.println("New MODE has been selected");
//    terminal.println("Wait for update (Max 10 Seconds)");
//    terminal.println();
//    terminal.println();
//    terminal.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
//    terminal.flush();
//}

void resetManual()
{
Blynk.virtualWrite(V1, 0);   //Turn OFF Manual Mode Widget
Blynk.virtualWrite(V2, 0);   //Turn OFF Button Widget Device
Blynk.virtualWrite(V6, 0);   //Turn OFF Button Widget Device

digitalWrite(TestLED, LOW); // set LED OFF
digitalWrite(zone1, LOW);
digitalWrite(zone2, LOW);
}

BLYNK_WRITE(V1)  // Manual/auto selection
{
  if (param.asInt()==1) {
    manual=1;
    terminal.println();
    terminal.println("Manual MODE is ON");
    terminal.println("Press Zone ON/OFF buttons as required");
    terminal.println();

    terminal.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
    terminal.flush();

    checklastbuttonpressed ();
  
    auto1=0;

    
  } else {

    restorelastbuttonpressed ();
    
    manual=0;
    //timer.setTimeout(50, resetTerminal);
    timer.setTimeout(50, resetManual);
    timer.setTimeout(50, checklastbuttonpressed);
    auto1=1;

    terminal.println();
    terminal.println("Manual MODE is OFF");
    terminal.println("Auto MODE restored from last status");
    terminal.println("Wait for update (Max 10 Seconds)");
    terminal.println();
    terminal.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
    terminal.flush();
}
}

BLYNK_WRITE(V2)  // Zone 1 ON-OFF Manual 
{
    if (param.asInt()==1) {  // boton encendido  
    terminal.println();
    terminal.println("Manual MODE is ON");
    terminal.println("Zone 1 is ON");

    terminal.println();
    terminal.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
    terminal.flush();
    
        if (manual==0){  //está en modo auto1mático     
         checklastbuttonpressed ();
         manual=1;

         auto1=0;


         digitalWrite(TestLED, HIGH); // set LED ON 
         digitalWrite(zone1, HIGH);


         Blynk.virtualWrite(V2, 1);   //Turn ON Button Widget
         Blynk.virtualWrite(V1, 1);   //Turn OFF Auto Mode
         
         } else {             //está en modo manual 

         auto1=0;


         Blynk.virtualWrite(V2, 1);   //Turn ON Button Widget
         Blynk.virtualWrite(V1, 1);   //Turn OFF Auto Mode
         digitalWrite(TestLED, HIGH); // set LED ON 
         digitalWrite(zone1, HIGH);

         
         }                           
    }else {

    terminal.println();
    terminal.println("Manual MODE is ON");
    terminal.println("Press ON/OFF button if required");
    terminal.println("Zone 1 is OFF");
    terminal.println();
    terminal.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
    terminal.flush();

        if (manual==0){      //modo auto1mático
         checklastbuttonpressed ();
         manual=1;

         auto1=0;
       
         Blynk.virtualWrite(V1, 1);   //Turn OFF Auto Mode
         digitalWrite(TestLED, LOW); // set LED OFF
         digitalWrite(zone1, LOW);
         Blynk.virtualWrite(V2, 0);   //Turn OFF Button Widget
         } else {  

         auto1=0;   

         Blynk.virtualWrite(V1, 1);   //Turn OFF Auto Mode
         digitalWrite(TestLED, LOW); // set LED OFF
         digitalWrite(zone1, LOW);
         Blynk.virtualWrite(V2, 0);   //Turn OFF Button Widget
         }  
         }
}

BLYNK_WRITE(V6)  // Zone 2 ON-OFF Manual 
{
    if (param.asInt()==1) {  // boton encendido  

    terminal.println();
    terminal.println("Manual MODE is ON");

    terminal.println("Zone 2 is ON");

    terminal.println();
    terminal.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
    terminal.flush();
    
        if (manual==0){  //está en modo auto1mático     
         checklastbuttonpressed ();
         manual=1;

         auto1=0;

         digitalWrite(TestLED, HIGH); // set LED ON 
         digitalWrite(zone2, HIGH);

         Blynk.virtualWrite(V6, 1);   //Turn ON Button Widget
         Blynk.virtualWrite(V1, 1);   //Turn OFF Auto Mode
         
         } else {             //está en modo manual 

         auto1=0;


         Blynk.virtualWrite(V6, 1);   //Turn ON Button Widget
         Blynk.virtualWrite(V1, 1);   //Turn OFF Auto Mode
         digitalWrite(TestLED, HIGH); // set LED ON 
         digitalWrite(zone2, HIGH);

         
         }                           
    }else {
      

    terminal.println();
    terminal.println("Manual MODE is ON");
    terminal.println("Press ON/OFF button if required");
    terminal.println("Zone 2 is OFF");
    terminal.println();
    terminal.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
    terminal.flush();

        if (manual==0){      //modo auto1mático
         checklastbuttonpressed ();
         manual=1;

         auto1=0;

         
         Blynk.virtualWrite(V1, 1);   //Turn OFF Auto Mode
         digitalWrite(TestLED, LOW); // set LED OFF
         digitalWrite(zone2, LOW);
         Blynk.virtualWrite(V6, 0);   //Turn OFF Button Widget
         } else {  

         auto1=0;
   

         Blynk.virtualWrite(V1, 1);   //Turn OFF Auto Mode
         digitalWrite(TestLED, LOW); // set LED OFF
         digitalWrite(zone2, LOW);
         Blynk.virtualWrite(V6, 0);   //Turn OFF Button Widget
         }  
         }
}

BLYNK_WRITE(V10)//Zone 1 time input handling
{  
  if (auto1==1) {         
    sprintf(Date, "%02d/%02d/%04d",  day(), month(), year());
    sprintf(Time, "%02d:%02d:%02d", hour(), minute(), second());
  
    TimeInputParam t(param);
    terminal.println("GENERAL:");
    terminal.println(String("      Time zone: ") + t.getTZ()); // Timezone is already added to start/stop time 
    terminal.println("      Ensure at least ONE day is selected for each zone");
    terminal.println();
    
    terminal.println("ZONE 1:");
    terminal.print("      Schedule checked at: ");
    terminal.println(Time);
    terminal.flush();
    int dayadjustment = -1;  
    if(weekday() == 1){
      dayadjustment =  6; // needed for Sunday, Time library is day 1 and Blynk is day 7
    }
    if(t.isWeekdaySelected(weekday() + dayadjustment)){ //Time library starts week on Sunday, Blynk on Monday
    terminal.println("      Auto ACTIVE today");
    terminal.println("      Cycle/Soak Active.  3 equal intervals of watering split up by 2 equal intervals of soak");
    terminal.flush();
    if (t.hasStartTime()) // Process start time
    {
      if(t.getStartMinute()<10){
        terminal.println(String("      Scheduled Start: ") + t.getStartHour() + ":0" + t.getStartMinute());
      }else{
        terminal.println(String("      Scheduled Start: ") + t.getStartHour() + ":" + t.getStartMinute());
      }
      terminal.flush();
    }
    if (t.hasStopTime()) // Process stop time
    {
      if(t.getStopMinute()<10){
        terminal.println(String("      Scheduled Stop : ") + t.getStopHour() + ":0" + t.getStopMinute());
      }else{
        terminal.println(String("      Scheduled Stop : ") + t.getStopHour() + ":" + t.getStopMinute());
        
      }
      int durationwd = ((t.getStopHour()*3600 + t.getStopMinute()*60 + t.getStopSecond()) - (t.getStartHour()*3600 + t.getStartMinute()*60 + t.getStartSecond()))/60;
      cycle_soak_int = (durationwd*60*1000)/5;
      
      terminal.print("      Total Duration (mins):");
      terminal.println(durationwd);
      terminal.print("      Total Watering Time over 3 intervals (mins):");
      terminal.println((cycle_soak_int/1000/60)*3);
      terminal.print("      Total Soak Time over 2 intervals (mins):");
      terminal.println((cycle_soak_int/1000/60)*2);
      terminal.flush();
    }
    // Display timezone details, for information purposes only 
    
    terminal.flush();
  
//     for (int i = 1; i <= 7; i++) {  // Process weekdays (1. Mon, 2. Tue, 3. Wed, ...)
//        if (t.isWeekdaySelected(i)) {
//        terminal.println(String("Zone 1 Days ") + i + " is selected");
//        terminal.flush();
//        }
//      } 
    nowseconds = ((hour() * 3600) + (minute() * 60) + second());
    startsecondswd = (t.getStartHour() * 3600) + (t.getStartMinute() * 60);
    //Serial.println(startsecondswd);  // used for debugging
    if(nowseconds >= startsecondswd){    
      terminal.print("      Auto STARTED at");
      if(t.getStartMinute()<10){
        terminal.println(String(" ") + t.getStartHour() + ":0" + t.getStartMinute());
      }else{
      terminal.println(String(" ") + t.getStartHour() + ":" + t.getStartMinute());
      }
      terminal.flush();
      if(nowseconds <= startsecondswd + 90){    // 90s on 60s timer ensures 1 trigger command is sent
        digitalWrite(TestLED, HIGH); // set LED ON
        digitalWrite(zone1, HIGH);
        Serial.println("Zone 1 active");
    
        timer.deleteTimer(timerID);
        timerID = timer.setTimeout(cycle_soak_int, cycle_soak_1);
        
        Serial.print("Cycle for: ");   
        Serial.print(cycle_soak_int/1000/60);
        Serial.println(" minutes");
        
        Blynk.virtualWrite(V2, 1);
        // code here to switch the relay ON
      }      
    }
    else{
      Blynk.virtualWrite(V2,0);
      terminal.println();
      terminal.println("      Auto NOT STARTED today");
      terminal.flush();
         
    }
    stopsecondswd = (t.getStopHour() * 3600) + (t.getStopMinute() * 60);
    //Serial.println(stopsecondswd);  // used for debugging
    if(nowseconds >= stopsecondswd){
      digitalWrite(TestLED, LOW); // set LED OFF
      digitalWrite(zone1, LOW);
      Blynk.virtualWrite(V2, 0);
      terminal.print("      Auto STOPPED at");
      if(t.getStopMinute()<10){
        terminal.println(String(" ") + t.getStopHour() + ":0" + t.getStopMinute());
      }else{
        terminal.println(String(" ") + t.getStopHour() + ":" + t.getStopMinute());
        
      }
      terminal.flush();
      if(nowseconds <= stopsecondswd + 90){   // 90s on 60s timer ensures 1 trigger command is sent
        digitalWrite(TestLED, LOW); // set LED OFF
        digitalWrite(zone1, LOW);
        Blynk.virtualWrite(V2, 0);
        // code here to switch the relay OFF
      }              
    }
    else{
      if(nowseconds >= startsecondswd){  
        digitalWrite(TestLED, HIGH); // set LED ON 
        digitalWrite(zone1, HIGH);

        Blynk.virtualWrite(V2, 1);
        terminal.println("      Auto is ON");
        terminal.flush();

      }
             
    }
  }
  else{
    terminal.println();
    terminal.println("      Auto INACTIVE today");
    terminal.flush();
    // nothing to do today, check again in 30 SECONDS time    
  }
  
  terminal.println();
}
}

void cycle_soak_1(){
  Serial.print("Soak for : ");   
  Serial.print(cycle_soak_int/1000/60);
  Serial.println(" minutes");

  digitalWrite(zone1, LOW);
  Blynk.virtualWrite(V2, 0);
  timer.deleteTimer(timerID);
  timerID = timer.setTimeout(cycle_soak_int, cycle_soak_2);
  
}

void cycle_soak_2(){
  Serial.print("Cycle (2nd) for: ");   
  Serial.print(cycle_soak_int/1000/60);
  Serial.println(" minutes");
  digitalWrite(zone1, HIGH);
  Blynk.virtualWrite(V2, 1);
  timer.deleteTimer(timerID);
  timerID = timer.setTimeout(cycle_soak_int, cycle_soak_3);
  
}

void cycle_soak_3(){
  Serial.print("Soak (2nd) for: ");   
  Serial.print(cycle_soak_int/1000/60);
  Serial.println(" minutes");
  digitalWrite(zone1, LOW);
  Blynk.virtualWrite(V2, 0);
  timer.deleteTimer(timerID);
  timerID = timer.setTimeout(cycle_soak_int, cycle_soak_4);

}


void cycle_soak_4(){
  Serial.print("Cycle (3rd) for: ");   
  Serial.print(cycle_soak_int/1000/60);
  Serial.println(" minutes");
  digitalWrite(zone1, HIGH);
  Blynk.virtualWrite(V2, 1);
  timer.deleteTimer(timerID);
  timerID = timer.setTimeout(cycle_soak_int, cycle_soak_5);
}


void cycle_soak_5(){
  Serial.print("End of cycle/soak");   
  digitalWrite(zone1, LOW);
  Blynk.virtualWrite(V2, 0);
  timer.deleteTimer(timerID);
  
}
BLYNK_WRITE(V20)//Zone 2 time input handling
{  
       
  if (auto1==1) {         
    sprintf(Date, "%02d/%02d/%04d",  day(), month(), year());
    sprintf(Time, "%02d:%02d:%02d", hour(), minute(), second());
  
    TimeInputParam t(param);

    terminal.println("ZONE 2:");
    terminal.print("      Schedule checked at: ");
    terminal.println(Time);
    terminal.flush();
    int dayadjustment = -1;  
    if(weekday() == 1){
      dayadjustment =  6; // needed for Sunday, Time library is day 1 and Blynk is day 7
    }
    if(t.isWeekdaySelected(weekday() + dayadjustment)){ //Time library starts week on Sunday, Blynk on Monday
    terminal.println("      Auto ACTIVE today");
    terminal.flush();
    if (t.hasStartTime()) // Process start time
    {
      if(t.getStartMinute()<10){
        terminal.println(String("      Scheduled Start: ") + t.getStartHour() + ":0" + t.getStartMinute());
      }else{
        terminal.println(String("      Scheduled Start: ") + t.getStartHour() + ":" + t.getStartMinute());
      }
      terminal.flush();
    }
    if (t.hasStopTime()) // Process stop time
    {
      if(t.getStopMinute()<10){
        terminal.println(String("      Scheduled Stop : ") + t.getStopHour() + ":0" + t.getStopMinute());
      }else{
        terminal.println(String("      Scheduled Stop : ") + t.getStopHour() + ":" + t.getStopMinute());
        
      }
      int durationwd = ((t.getStopHour()*3600 + t.getStopMinute()*60 + t.getStopSecond()) - (t.getStartHour()*3600 + t.getStartMinute()*60 + t.getStartSecond()))/60;
      terminal.print("      Duration (mins):");
      terminal.println(durationwd);
      terminal.flush();
    }
    // Display timezone details, for information purposes only 


   // terminal.println(String("Time zone offset: ") + t.getTZ_Offset()); // Get timezone offset (in seconds)
    terminal.flush();
  
//     for (int i = 1; i <= 7; i++) {  // Process weekdays (1. Mon, 2. Tue, 3. Wed, ...)
//        if (t.isWeekdaySelected(i)) {
//        terminal.println(String("Zone 2 Days ") + i + " is selected");
//        terminal.flush();
//        }
//      } 
    nowseconds = ((hour() * 3600) + (minute() * 60) + second());
    startsecondswd = (t.getStartHour() * 3600) + (t.getStartMinute() * 60);
    //Serial.println(startsecondswd);  // used for debugging
    if(nowseconds >= startsecondswd){    
      terminal.print("      Auto STARTED at");
      if(t.getStartMinute()<10){
        terminal.println(String(" ") + t.getStartHour() + ":0" + t.getStartMinute());
      }else{
      terminal.println(String(" ") + t.getStartHour() + ":" + t.getStartMinute());
      }
      terminal.flush();
      if(nowseconds <= startsecondswd + 90){    // 90s on 60s timer ensures 1 trigger command is sent
        digitalWrite(TestLED, HIGH); // set LED ON
        digitalWrite(zone2, HIGH);
        
        Blynk.virtualWrite(V6, 1);
        // code here to switch the relay ON
      }      
    }
    else{
      Blynk.virtualWrite(V6,0);
      terminal.println();
      terminal.println("      Auto NOT STARTED today");
      terminal.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
      terminal.flush();
         
    }
    stopsecondswd = (t.getStopHour() * 3600) + (t.getStopMinute() * 60);
    //Serial.println(stopsecondswd);  // used for debugging
    if(nowseconds >= stopsecondswd){
      digitalWrite(TestLED, LOW); // set LED OFF
      digitalWrite(zone2, LOW);
      Blynk.virtualWrite(V6, 0);
      terminal.print("      Auto STOPPED at");
      if(t.getStopMinute()<10){
        terminal.println(String(" ") + t.getStopHour() + ":0" + t.getStopMinute());
      }else{
        terminal.println(String(" ") + t.getStopHour() + ":" + t.getStopMinute());
        
      }
      terminal.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
      terminal.flush();
      if(nowseconds <= stopsecondswd + 90){   // 90s on 60s timer ensures 1 trigger command is sent
        digitalWrite(TestLED, LOW); // set LED OFF
        digitalWrite(zone2, LOW);
        Blynk.virtualWrite(V6, 0);
        // code here to switch the relay OFF
      }              
    }
    else{
      if(nowseconds >= startsecondswd){  
        digitalWrite(TestLED, HIGH); // set LED ON 
    digitalWrite(zone2, HIGH);

        Blynk.virtualWrite(V6, 1);
        terminal.println("      Auto is ON");
        terminal.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
        terminal.flush();

      }
             
    }
  }
  else{
    terminal.println();
    terminal.println("      Auto INACTIVE today");
    terminal.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
    terminal.flush();
    // nothing to do today, check again in 30 SECONDS time    
  }
  
  terminal.println();
}
}


void reconnectBlynk() {
  if (!Blynk.connected()) {
    if(Blynk.connect()) {
     BLYNK_LOG("Reconnected");
    } else {
      BLYNK_LOG("Not reconnected");
    }
  }
}

void loop()
{

  if (Blynk.connected()) {
    Blynk.run();
  }
  timer.run();
}

Hello there,

Your so-called very crude attempt is very good, more than enough to make it running, although it’s not very efficient.
I suggest you make these changes, if possible, then test to see if it’s OK (as I don’t have the system to test, just test in memory !!!)



void setup()
{
  ...
  //rtc.begin();

  //Blynk.syncVirtual(V2);
  //Blynk.syncVirtual(V6);
  //Blynk.syncVirtual(V1);

  timer.setInterval(10000L, activetoday);  // check every 10 SECONDS if schedule should run today
  timer.setInterval(30000L, reconnectBlynk);  // check every 30s if still connected to server
  timer.setInterval(5000L, clockvalue);  // check value for time
  timer.setInterval(5000L, sendWifi);    // Wi-Fi signal
  
  // Create a timer with arbitrary timeout, then disable, to use later
  timerID = timer.setInterval(100000, cycle_soak_1);
  timer.disable(timerID);
}

BLYNK_CONNECTED()
{
  // To remove same rtc.begin() in setup()
  rtc.begin();

  Blynk.syncAll();
  Blynk.notify("Blynk Connected");
}

BLYNK_WRITE(V10)//Zone 1 time input handling
{
  ...
        if (nowseconds <= startsecondswd + 90) 
        {  
          // 90s on 60s timer ensures 1 trigger command is sent
          digitalWrite(TestLED, HIGH); // set LED ON
          digitalWrite(zone1, HIGH);
          Serial.println("Zone 1 active");

          // Use this to run timer repetitively until being deleted
          timer.changeInterval(timerID, cycle_soak_int);
          timer.enable(timerID);
          
          Serial.print("Cycle for: ");
          Serial.print(cycle_soak_int / 1000 / 60);
          Serial.println(" minutes");

          Blynk.virtualWrite(V2, 1);
          // code here to switch the relay ON
        }
  ....

}


void cycle_soak_1() 
{
  static int cycle_no = 1;
  static bool relay_state = LOW;
  
  Serial.print("Cycle No ");
  Serial.print(cycle_no);
  
  if (relay_state)
    Serial.print("Water for : ");
  else
    Serial.print("Soak for : ");
    
  Serial.print(cycle_soak_int / 1000 / 60);
  Serial.println(" minutes");

  digitalWrite(zone1, relay_state);
  Blynk.virtualWrite(V2, relay_state);
  
  cycle_no++;
  relay_state = !relay_state;
  
  if (cycle_no == 5)
  {
    // Prepare for next round
    cycle_no = 1;
    relay_state = LOW;
    timer.disable(timerID);
  }
}

The reason to avoid those repeated timer calls, such as

timer.deleteTimer(timerID);
timerID = timer.setTimeout(cycle_soak_int, cycle_soak_1);

is for better efficiency (faster, lower code size and memory usage, etc.) and especially to avoid unnecessary copy, delete, memset operations that can potentially create problems.

There are too many duplications, hardcoding in the code, and you can take time to eliminate them later by grouping similar operations into functions, etc.

There are too many duplications, hardcoding in the code, and you can take time to eliminate them later by grouping similar operations into functions, etc.

1 Like

Hi khoih

Thanks for your help and suggestions. Definately had improved results but still got a few issues that i’d appreciate your help on

I have put a 5 minute Time input into the widget for Zone 1 (i.e. on at 10pm and off and 10:05pm. THis should mean the watering/soak intervals are 1 minute each). The relay triggers correctly at the start time (10pm in example above). I would expect that the relay is active for 1minute, and then goes into a 1 minute soak.

I’ve got the following issues

  1. The first cycle_soak_1 doesnt seem to happen after the first minute. It seems to happens about 2 minutes and 20 seconds after the relay first activates.
  2. When the first soak period occurs (i.e. relay goes inactive), the code is causing the relay to re-activate on the next 10 second cycle.

I havent incoproated some of the other changes as i had unfavourable results (e.g. moving the Blynk.Sync and rtc.begin).

// changes to allow cycle and soak in auto mode

/**************************************************************
 * timeinput.ino Demonstrate interaction of Time library with
 * Blynk's TimeInput widget.
 * App project setup:
 * RTC widget (no pin required!!!)
 * V1 : Manual/auto1 button
 * V2: On-off button
 * Terminal on V3 // Label will be the clock + wifi signal!!!!

 * 
 * Time Input widget on V10 (Auto)
 * Button selection for Time Input (Auto) on V11
 * 
 **************************************************************/

#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
//#include <SimpleTimer.h>
#include <TimeLib.h>
#include <WidgetRTC.h>

SimpleTimer timer;

WidgetRTC rtc;
WidgetTerminal terminal(V3);

//#define server "blynk.cloud-com"   // or "blynk.cloud-com" for Blynk's cloud server
#define TestLED 2                 // on board LED pin assignment
char Date[16];
char Time[16];
char auth[] = "ozdoYOoEt59L0L3XhBwA3bvEf1xEI3DP";
char ssid[] = "Atthow Ave TC";
char pass[] = "512maidstone";
long startsecondswd;            // weekday start time in seconds
long stopsecondswd;             // weekday stop  time in seconds
long nowseconds;                // time now in seconds
bool isFirstConnect = true;


String displaycurrenttimepluswifi;
int wifisignal;
int manual=0;
int oldstatus;
int zone1 = 4;  // digital pin for relay 1
int zone2 = 5;  // digital pin for relay 2

int auto1;

int zone1_state;
int zone2_state;

int timerID;

long cycle_soak_int;

void setup()
{
  pinMode(TestLED, OUTPUT);
  digitalWrite(TestLED, HIGH); // set LED OFF
  
  digitalWrite(zone1, LOW);
  digitalWrite(zone2,LOW);
  pinMode(zone1,OUTPUT);
  pinMode(zone2,OUTPUT);

 
  Serial.begin(115200);
  Serial.println("\Starting");
  Blynk.begin(auth, ssid, pass);
  int mytimeout = millis() / 1000;
  while (Blynk.connect() == false) { // try to connect to server for 10 seconds
    if((millis() / 1000) > mytimeout + 8){ // try local server if not connected within 9 seconds
       break;
    }
  }
  rtc.begin();
  //Blynk.syncAll();
//  
  Blynk.syncVirtual(V2);
  Blynk.syncVirtual(V6);
  Blynk.syncVirtual(V1);


  timer.setInterval(10000L, activetoday);  // check every 10 SECONDS if schedule should run today 
  timer.setInterval(30000L, reconnectBlynk);  // check every 30s if still connected to server 
  timer.setInterval(5000L, clockvalue);  // check value for time
  timer.setInterval(5000L, sendWifi);    // Wi-Fi singal

  timerID = timer.setInterval(100000L, cycle_soak_1);
  timer.disable(timerID);
}


BLYNK_CONNECTED() {
if (isFirstConnect) {
  //rtc.begin();
  //Blynk.syncAll();
  
  Blynk.notify("TIMER STARTING!!!!");
  isFirstConnect = false;
}
}

void sendWifi() {
  wifisignal = map(WiFi.RSSI(), -105, -40, 0, 100);
}

void clockvalue() // Digital clock display of the time
{
 int gmthour = hour();
  if (gmthour == 24){
     gmthour = 0;
  }
  String displayhour =   String(gmthour, DEC);
  int hourdigits = displayhour.length();
  if(hourdigits == 1){
    displayhour = "0" + displayhour;
  }
  String displayminute = String(minute(), DEC);
  int minutedigits = displayminute.length();  
  if(minutedigits == 1){
    displayminute = "0" + displayminute;
  }  

  displaycurrenttimepluswifi = "                                          Clock:  " + displayhour + ":" + displayminute + "               Signal:  " + wifisignal +" %";
  Blynk.setProperty(V3, "label", displaycurrenttimepluswifi);
  
}

void activetoday(){        // check if schedule should run today

  if(year() != 1970){

   if (auto1==1) {  
    Blynk.syncVirtual(V10); // sync timeinput widget  
    Blynk.syncVirtual(V20);
   }
  }
}

void checklastbuttonpressed (){

    if((auto1==1)){ oldstatus=1;}
}

void restorelastbuttonpressed (){
    if(oldstatus==1){auto1=1;}
}

//void resetTerminal()
//{
//    timer.setTimeout(50, checklastbuttonpressed);
//    terminal.println();
//    terminal.println();
//    terminal.println("New MODE has been selected");
//    terminal.println("Wait for update (Max 10 Seconds)");
//    terminal.println();
//    terminal.println();
//    terminal.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
//    terminal.flush();
//}

void resetManual()
{
Blynk.virtualWrite(V1, 0);   //Turn OFF Manual Mode Widget
Blynk.virtualWrite(V2, 0);   //Turn OFF Button Widget Device
Blynk.virtualWrite(V6, 0);   //Turn OFF Button Widget Device

digitalWrite(TestLED, HIGH); // set LED OFF
digitalWrite(zone1, LOW);
digitalWrite(zone2, LOW);
}

void reconnectBlynk() {
  if (!Blynk.connected()) {
    if(Blynk.connect()) {
     BLYNK_LOG("Reconnected");
    } else {
      BLYNK_LOG("Not reconnected");
    }
  }
}

void loop()
{

  if (Blynk.connected()) {
    Blynk.run();
  }
  timer.run();
}

BLYNK_WRITE(V1)  // Manual/auto selection
{
  if (param.asInt()==1) {
    manual=1;
    terminal.println();
    terminal.println("Manual MODE is ON");
    terminal.println("Press Zone ON/OFF buttons as required");
    terminal.println();

    terminal.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
    terminal.flush();

    checklastbuttonpressed ();
  
    auto1=0;

    
  } else {

    restorelastbuttonpressed ();
    
    manual=0;
    //timer.setTimeout(50, resetTerminal);
    timer.setTimeout(50, resetManual);
    timer.setTimeout(50, checklastbuttonpressed);
    auto1=1;

    terminal.println();
    terminal.println("Manual MODE is OFF");
    terminal.println("Auto MODE restored from last status");
    terminal.println("Wait for update (Max 10 Seconds)");
    terminal.println();
    terminal.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
    terminal.flush();
}
}

BLYNK_WRITE(V2)  // Zone 1 ON-OFF Manual 
{
    if (param.asInt()==1) {  // boton encendido  
    terminal.println();
    terminal.println("Manual MODE is ON");
    terminal.println("Zone 1 is ON");

    terminal.println();
    terminal.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
    terminal.flush();
    
        if (manual==0){  //está en modo auto1mático     
         checklastbuttonpressed ();
         manual=1;

         auto1=0;


         digitalWrite(TestLED, LOW); // set LED ON 
         digitalWrite(zone1, HIGH);


         Blynk.virtualWrite(V2, 1);   //Turn ON Button Widget
         Blynk.virtualWrite(V1, 1);   //Turn OFF Auto Mode
         
         } else {             //está en modo manual 

         auto1=0;


         Blynk.virtualWrite(V2, 1);   //Turn ON Button Widget
         Blynk.virtualWrite(V1, 1);   //Turn OFF Auto Mode
         digitalWrite(TestLED, LOW); // set LED ON 
         digitalWrite(zone1, HIGH);

         
         }                           
    }else {

    terminal.println();
    terminal.println("Manual MODE is ON");
    terminal.println("Press ON/OFF button if required");
    terminal.println("Zone 1 is OFF");
    terminal.println();
    terminal.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
    terminal.flush();

        if (manual==0){      //modo auto1mático
         checklastbuttonpressed ();
         manual=1;

         auto1=0;
       
         Blynk.virtualWrite(V1, 1);   //Turn OFF Auto Mode
         digitalWrite(TestLED, HIGH); // set LED OFF
         digitalWrite(zone1, LOW);
         Blynk.virtualWrite(V2, 0);   //Turn OFF Button Widget
         } else {  

         auto1=0;   

         Blynk.virtualWrite(V1, 1);   //Turn OFF Auto Mode
         digitalWrite(TestLED, HIGH); // set LED OFF
         digitalWrite(zone1, LOW);
         Blynk.virtualWrite(V2, 0);   //Turn OFF Button Widget
         }  
         }
}

BLYNK_WRITE(V6)  // Zone 2 ON-OFF Manual 
{
    if (param.asInt()==1) {  // boton encendido  

    terminal.println();
    terminal.println("Manual MODE is ON");

    terminal.println("Zone 2 is ON");

    terminal.println();
    terminal.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
    terminal.flush();
    
        if (manual==0){  //está en modo auto1mático     
         checklastbuttonpressed ();
         manual=1;

         auto1=0;

         digitalWrite(TestLED, LOW); // set LED ON 
         digitalWrite(zone2, HIGH);

         Blynk.virtualWrite(V6, 1);   //Turn ON Button Widget
         Blynk.virtualWrite(V1, 1);   //Turn OFF Auto Mode
         
         } else {             //está en modo manual 

         auto1=0;


         Blynk.virtualWrite(V6, 1);   //Turn ON Button Widget
         Blynk.virtualWrite(V1, 1);   //Turn OFF Auto Mode
         digitalWrite(TestLED, LOW); // set LED ON 
         digitalWrite(zone2, HIGH);

         
         }                           
    }else {
      

    terminal.println();
    terminal.println("Manual MODE is ON");
    terminal.println("Press ON/OFF button if required");
    terminal.println("Zone 2 is OFF");
    terminal.println();
    terminal.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
    terminal.flush();

        if (manual==0){      //modo auto1mático
         checklastbuttonpressed ();
         manual=1;

         auto1=0;

         
         Blynk.virtualWrite(V1, 1);   //Turn OFF Auto Mode
         digitalWrite(TestLED, HIGH); // set LED OFF
         digitalWrite(zone2, LOW);
         Blynk.virtualWrite(V6, 0);   //Turn OFF Button Widget
         } else {  

         auto1=0;
   

         Blynk.virtualWrite(V1, 1);   //Turn OFF Auto Mode
         digitalWrite(TestLED, HIGH); // set LED OFF
         digitalWrite(zone2, LOW);
         Blynk.virtualWrite(V6, 0);   //Turn OFF Button Widget
         }  
         }
}

BLYNK_WRITE(V10)//Zone 1 time input handling
{  
  if (auto1==1) {         
    sprintf(Date, "%02d/%02d/%04d",  day(), month(), year());
    sprintf(Time, "%02d:%02d:%02d", hour(), minute(), second());
  
    TimeInputParam t(param);
    terminal.println("GENERAL:");
    terminal.println(String("      Time zone: ") + t.getTZ()); // Timezone is already added to start/stop time 
    terminal.println("      Ensure at least ONE day is selected for each zone");
    terminal.println();
    
    terminal.println("ZONE 1:");
    terminal.print("      Schedule checked at: ");
    terminal.println(Time);
    terminal.flush();
    int dayadjustment = -1;  
    if(weekday() == 1){
      dayadjustment =  6; // needed for Sunday, Time library is day 1 and Blynk is day 7
    }
    if(t.isWeekdaySelected(weekday() + dayadjustment)){ //Time library starts week on Sunday, Blynk on Monday
    terminal.println("      Auto ACTIVE today");
    terminal.println("      Cycle/Soak Active.  3 equal intervals of watering split up by 2 equal intervals of soak");
    terminal.flush();
    if (t.hasStartTime()) // Process start time
    {
      if(t.getStartMinute()<10){
        terminal.println(String("      Scheduled Start: ") + t.getStartHour() + ":0" + t.getStartMinute());
      }else{
        terminal.println(String("      Scheduled Start: ") + t.getStartHour() + ":" + t.getStartMinute());
      }
      terminal.flush();
    }
    if (t.hasStopTime()) // Process stop time
    {
      if(t.getStopMinute()<10){
        terminal.println(String("      Scheduled Stop : ") + t.getStopHour() + ":0" + t.getStopMinute());
      }else{
        terminal.println(String("      Scheduled Stop : ") + t.getStopHour() + ":" + t.getStopMinute());
        
      }
      int durationwd = ((t.getStopHour()*3600 + t.getStopMinute()*60 + t.getStopSecond()) - (t.getStartHour()*3600 + t.getStartMinute()*60 + t.getStartSecond()))/60;
      cycle_soak_int = (durationwd*60*1000)/5;
      
      terminal.print("      Total Duration (mins):");
      terminal.println(durationwd);
      terminal.print("      Total Watering Time over 3 intervals (mins):");
      terminal.println((cycle_soak_int/1000/60)*3);
      terminal.print("      Total Soak Time over 2 intervals (mins):");
      terminal.println((cycle_soak_int/1000/60)*2);
      terminal.flush();
    }
    // Display timezone details, for information purposes only 
    
    terminal.flush();
  
//     for (int i = 1; i <= 7; i++) {  // Process weekdays (1. Mon, 2. Tue, 3. Wed, ...)
//        if (t.isWeekdaySelected(i)) {
//        terminal.println(String("Zone 1 Days ") + i + " is selected");
//        terminal.flush();
//        }
//      } 
    nowseconds = ((hour() * 3600) + (minute() * 60) + second());
    startsecondswd = (t.getStartHour() * 3600) + (t.getStartMinute() * 60);
    //Serial.println(startsecondswd);  // used for debugging
    if(nowseconds >= startsecondswd){    
      terminal.print("      Auto STARTED at");
      if(t.getStartMinute()<10){
        terminal.println(String(" ") + t.getStartHour() + ":0" + t.getStartMinute());
      }else{
      terminal.println(String(" ") + t.getStartHour() + ":" + t.getStartMinute());
      }
      terminal.flush();
      if(nowseconds <= startsecondswd + 90){    // 90s on 60s timer ensures 1 trigger command is sent
        digitalWrite(TestLED, LOW); // set LED ON
        digitalWrite(zone1, HIGH);
        Serial.println("Zone 1 active");
        
        timer.changeInterval(timerID, cycle_soak_int);
        timer.enable(timerID);
        
        //timer.deleteTimer(timerID);
        //timerID = timer.setTimeout(cycle_soak_int, cycle_soak_1);
        
//        Serial.print("Cycle for: ");   
//        Serial.print(cycle_soak_int/1000/60);
//        Serial.println(" minutes");
        
        Blynk.virtualWrite(V2, 1);
        // code here to switch the relay ON
      }      
    }
    else{
      Blynk.virtualWrite(V2,0);
      terminal.println();
      terminal.println("      Auto NOT STARTED today");
      terminal.flush();
         
    }
    stopsecondswd = (t.getStopHour() * 3600) + (t.getStopMinute() * 60);
    //Serial.println(stopsecondswd);  // used for debugging
    if(nowseconds >= stopsecondswd){
      digitalWrite(TestLED, HIGH); // set LED OFF
      digitalWrite(zone1, LOW);
      Blynk.virtualWrite(V2, 0);
      terminal.print("      Auto STOPPED at");
      if(t.getStopMinute()<10){
        terminal.println(String(" ") + t.getStopHour() + ":0" + t.getStopMinute());
      }else{
        terminal.println(String(" ") + t.getStopHour() + ":" + t.getStopMinute());
        
      }
      terminal.flush();
      if(nowseconds <= stopsecondswd + 90){   // 90s on 60s timer ensures 1 trigger command is sent
        digitalWrite(TestLED, HIGH); // set LED OFF
        digitalWrite(zone1, LOW);
        Blynk.virtualWrite(V2, 0);
        // code here to switch the relay OFF
      }              
    }
    else{
      if(nowseconds >= startsecondswd){  
        digitalWrite(TestLED, LOW); // set LED ON 
        digitalWrite(zone1, HIGH);

        Blynk.virtualWrite(V2, 1);
        terminal.println("      Auto is ON");
        terminal.flush();

      }
             
    }
  }
  else{
    terminal.println();
    terminal.println("      Auto INACTIVE today");
    terminal.flush();
    // nothing to do today, check again in 30 SECONDS time    
  }
  
  terminal.println();
}
}

void cycle_soak_1(){
  
  static int cycle_no = 1;
  static bool relay_state = LOW;
  Serial.println("~~~~~~~~~~~~~~~~~~~~~~Cycle Soak routine running~~~~~~~~~~~~~~~~~~~~~");
  Serial.print("Time: ");
  Serial.println(Time);
  
  Serial.print("Cycle No: ");
  Serial.println(cycle_no);

  Serial.print("Relay State: ");
  Serial.println(relay_state);

  if (relay_state == HIGH){
    Serial.print("Water for : ");
    Blynk.virtualWrite(V2, 1);
  }else{
    Serial.print("Soak for : "); 
    Blynk.virtualWrite(V2, 0);
  }  
  
  Serial.print(cycle_soak_int/1000/60);
  Serial.println(" minutes");

  digitalWrite(zone1, relay_state);
  //Blynk.virtualWrite(V2, relay_state);
  cycle_no++;
  relay_state = !relay_state;

  if (cycle_no == 5){
    cycle_no = 1;
    relay_state = LOW;
    timer.disable(timerID);
  }
}

BLYNK_WRITE(V20)//Zone 2 time input handling
{  
       
  if (auto1==1) {         
    sprintf(Date, "%02d/%02d/%04d",  day(), month(), year());
    sprintf(Time, "%02d:%02d:%02d", hour(), minute(), second());
  
    TimeInputParam t(param);

    terminal.println("ZONE 2:");
    terminal.print("      Schedule checked at: ");
    terminal.println(Time);
    terminal.flush();
    int dayadjustment = -1;  
    if(weekday() == 1){
      dayadjustment =  6; // needed for Sunday, Time library is day 1 and Blynk is day 7
    }
    if(t.isWeekdaySelected(weekday() + dayadjustment)){ //Time library starts week on Sunday, Blynk on Monday
    terminal.println("      Auto ACTIVE today");
    terminal.flush();
    if (t.hasStartTime()) // Process start time
    {
      if(t.getStartMinute()<10){
        terminal.println(String("      Scheduled Start: ") + t.getStartHour() + ":0" + t.getStartMinute());
      }else{
        terminal.println(String("      Scheduled Start: ") + t.getStartHour() + ":" + t.getStartMinute());
      }
      terminal.flush();
    }
    if (t.hasStopTime()) // Process stop time
    {
      if(t.getStopMinute()<10){
        terminal.println(String("      Scheduled Stop : ") + t.getStopHour() + ":0" + t.getStopMinute());
      }else{
        terminal.println(String("      Scheduled Stop : ") + t.getStopHour() + ":" + t.getStopMinute());
        
      }
      int durationwd = ((t.getStopHour()*3600 + t.getStopMinute()*60 + t.getStopSecond()) - (t.getStartHour()*3600 + t.getStartMinute()*60 + t.getStartSecond()))/60;
      terminal.print("      Duration (mins):");
      terminal.println(durationwd);
      terminal.flush();
    }

    terminal.flush();
  
    nowseconds = ((hour() * 3600) + (minute() * 60) + second());
    startsecondswd = (t.getStartHour() * 3600) + (t.getStartMinute() * 60);
    //Serial.println(startsecondswd);  // used for debugging
    if(nowseconds >= startsecondswd){    
      terminal.print("      Auto STARTED at");
      if(t.getStartMinute()<10){
        terminal.println(String(" ") + t.getStartHour() + ":0" + t.getStartMinute());
      }else{
      terminal.println(String(" ") + t.getStartHour() + ":" + t.getStartMinute());
      }
      terminal.flush();
      if(nowseconds <= startsecondswd + 90){    // 90s on 60s timer ensures 1 trigger command is sent
        digitalWrite(TestLED, LOW); // set LED ON
        digitalWrite(zone2, HIGH);
        
        Blynk.virtualWrite(V6, 1);
        // code here to switch the relay ON
      }      
    }
    else{
      Blynk.virtualWrite(V6,0);
      terminal.println();
      terminal.println("      Auto NOT STARTED today");
      terminal.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
      terminal.flush();
         
    }
    stopsecondswd = (t.getStopHour() * 3600) + (t.getStopMinute() * 60);
    //Serial.println(stopsecondswd);  // used for debugging
    if(nowseconds >= stopsecondswd){
      digitalWrite(TestLED, HIGH); // set LED OFF
      digitalWrite(zone2, LOW);
      Blynk.virtualWrite(V6, 0);
      terminal.print("      Auto STOPPED at");
      if(t.getStopMinute()<10){
        terminal.println(String(" ") + t.getStopHour() + ":0" + t.getStopMinute());
      }else{
        terminal.println(String(" ") + t.getStopHour() + ":" + t.getStopMinute());
        
      }
      terminal.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
      terminal.flush();
      if(nowseconds <= stopsecondswd + 90){   // 90s on 60s timer ensures 1 trigger command is sent
        digitalWrite(TestLED, HIGH); // set LED OFF
        digitalWrite(zone2, LOW);
        Blynk.virtualWrite(V6, 0);
        // code here to switch the relay OFF
      }              
    }
    else{
      if(nowseconds >= startsecondswd){  
        digitalWrite(TestLED, LOW); // set LED ON 
    digitalWrite(zone2, HIGH);

        Blynk.virtualWrite(V6, 1);
        terminal.println("      Auto is ON");
        terminal.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
        terminal.flush();

      }
             
    }
  }
  else{
    terminal.println();
    terminal.println("      Auto INACTIVE today");
    terminal.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
    terminal.flush();
    // nothing to do today, check again in 30 SECONDS time    
  }
  
  terminal.println();
}
}
~~~

Hi @Bobbyh88
It’s nice to see you’ve made some improvement. Somehow, there are still several bugs that creating your posted issues 1. and 2.

You can have a look at and test the new full code, based on yours, to see if all the issues have been fixed

/**************************************************************
   Irrigation_Timer.ino Demonstrate interaction of Time library with
   Blynk's TimeInput widget.
   App project setup:
   RTC widget (no pin required!!!)
   BLYNK_VPIN_AUTO_MANUAL   => V1 : Manual/auto1 button
   BLYNK_VPIN_ZONE1_BUTTON  => V2 : On-off button
   BLYNK_VPIN_TERMINAL      => V3 // Label will be the clock + wifi signal!!!!


   BLYNK_VPIN_ZONE1_TIME_INPUT  => Time Input widget Zone 1 on V10 (Auto)
   BLYNK_VPIN_ZONE2_TIME_INPUT  => Time Input widget Zone 1 on V20 (Auto)

   Button selection for Time Input (Auto) on V11

 **************************************************************/

#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>

#define USE_BLYNK_WM      false

#if USE_BLYNK_WM
  #include <BlynkSimpleEsp8266_WM.h>           //https://github.com/khoih-prog/Blynk_WM
#else
  #include <BlynkSimpleEsp8266.h>
  #if 1
    #define server "account.duckdns.org"   // or "blynk.cloud-com" for Blynk's cloud server
    // Irrigation
    char auth[] = "****";
    char ssid[] = "***";
    char pass[] = ****";
  #else
    #define server "blynk.cloud-com"   // or "blynk.cloud-com" for Blynk's cloud server
    char auth[] = "****";
    char ssid[] = "****";
    char pass[] = "****";
  #endif
  #define BLYNK_HARDWARE_PORT     8080
#endif

#include <TimeLib.h>
#include <WidgetRTC.h>

#define BLYNK_VPIN_AUTO_MANUAL          V1
#define BLYNK_VPIN_ZONE1_BUTTON         V2
#define BLYNK_VPIN_TERMINAL             V3
#define BLYNK_VPIN_ZONE2_BUTTON         V6
#define BLYNK_VPIN_ZONE1_TIME_INPUT     V10
#define BLYNK_VPIN_ZONE2_TIME_INPUT     V20



#define WATER_SOAK_CYCLE_TIME     5

BlynkTimer timer;

WidgetRTC rtc;
WidgetTerminal terminal(BLYNK_VPIN_TERMINAL);

#define TestLED 2                 // on board LED pin assignment


int wifisignal;

int manual = 0;
int oldstatus;
int zone1 = 4;  // digital pin for relay 1
int zone2 = 5;  // digital pin for relay 2

int auto1;

int zone1_state;
int zone2_state;

int timerID;
int timerID2;

long cycle_soak_int;
long cycle_soak_int2;

BLYNK_CONNECTED()
{
  //if (isFirstConnect)
  {
    rtc.begin();
    Blynk.syncAll();
    terminal.clear();
    //terminal.flush();
    //Blynk.notify("TIMER STARTING!!!!");
    //isFirstConnect = false;
  }
}

void sendWifi() {
  wifisignal = map(WiFi.RSSI(), -105, -40, 0, 100);
}

void clockvalue() // Digital clock display of the time
{
  static String displaycurrenttimepluswifi;
  static String displayhour;
  static int hourdigits;
  static String displayminute;
  static int minutedigits;
  
  int gmthour = hour();
  if (gmthour == 24) 
  {
    gmthour = 0;
  }
  
  displayhour =   String(gmthour, DEC);
  hourdigits = displayhour.length();
  
  if (hourdigits == 1) 
  {
    displayhour = "0" + displayhour;
  }
  
  displayminute = String(minute(), DEC); 
  minutedigits = displayminute.length();
  
  if (minutedigits == 1) 
  {
    displayminute = "0" + displayminute;
  }

  displaycurrenttimepluswifi = "                                          Clock:  " + displayhour + ":" + displayminute + "               Signal:  " + wifisignal + " %";
  Blynk.setProperty(BLYNK_VPIN_TERMINAL, "label", displaycurrenttimepluswifi);

}

void activetoday() 
{       
  // check if schedule should run today

  if (year() != 1970) 
  {
    if (auto1 == 1) 
    {
      Blynk.syncVirtual(BLYNK_VPIN_ZONE1_TIME_INPUT); // sync timeinput widget
      Blynk.syncVirtual(BLYNK_VPIN_ZONE2_TIME_INPUT);
    }
  }
}

void checklastbuttonpressed () 
{
  if ((auto1 == 1)) 
  {
    oldstatus = 1;
  }
}

void restorelastbuttonpressed () 
{
  if (oldstatus == 1) 
  {
    auto1 = 1;
  }
}

void resetManual()
{
  Blynk.virtualWrite(BLYNK_VPIN_AUTO_MANUAL, 0);   //Turn OFF Manual Mode Widget
  Blynk.virtualWrite(BLYNK_VPIN_ZONE1_BUTTON, 0);   //Turn OFF Button Widget Device
  Blynk.virtualWrite(BLYNK_VPIN_ZONE2_BUTTON, 0);   //Turn OFF Button Widget Device

  digitalWrite(TestLED, HIGH); // set LED OFF
  digitalWrite(zone1, LOW);
  digitalWrite(zone2, LOW);
}

void reconnectBlynk() 
{
  if (!Blynk.connected()) 
  {
    if (Blynk.connect()) 
    {
      BLYNK_LOG("Reconnected");
    } 
    else 
    {
      BLYNK_LOG("Not reconnected");
    }
  }
}

BLYNK_WRITE(BLYNK_VPIN_AUTO_MANUAL)  // Manual/auto selection
{
  if (param.asInt() == 1) 
  {
    manual = 1;
    terminal.println();
    terminal.println("Manual MODE is ON");
    terminal.println("Press Zone ON/OFF buttons as required");
    terminal.println();

    terminal.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
    terminal.flush();

    checklastbuttonpressed ();

    auto1 = 0;


  } 
  else 
  {
    restorelastbuttonpressed ();

    manual = 0;
    //timer.setTimeout(50, resetTerminal);
    timer.setTimeout(50, resetManual);
    timer.setTimeout(50, checklastbuttonpressed);
    auto1 = 1;

    terminal.println();
    terminal.println("Manual MODE is OFF");
    terminal.println("Auto MODE restored from last status");
    terminal.println("Wait for update (Max 10 Seconds)");
    terminal.println();
    terminal.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
    terminal.flush();
  }
}

BLYNK_WRITE(BLYNK_VPIN_ZONE1_BUTTON)  // Zone 1 ON-OFF Manual
{
  if (param.asInt() == 1) 
  { // boton encendido
    terminal.println();
    terminal.println("Manual MODE is ON");
    terminal.println("Zone 1 is ON");

    terminal.println();
    terminal.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
    terminal.flush();

    if (manual == 0) 
    { //está en modo auto1mático
      checklastbuttonpressed ();
      manual = 1;
      auto1 = 0;

      digitalWrite(TestLED, LOW); // set LED ON
      digitalWrite(zone1, HIGH);


      Blynk.virtualWrite(BLYNK_VPIN_ZONE1_BUTTON, 1);   //Turn ON Button Widget
      Blynk.virtualWrite(BLYNK_VPIN_AUTO_MANUAL, 1);   //Turn OFF Auto Mode

    } 
    else 
    {             //está en modo manual
      auto1 = 0;

      Blynk.virtualWrite(BLYNK_VPIN_ZONE1_BUTTON, 1);   //Turn ON Button Widget
      Blynk.virtualWrite(BLYNK_VPIN_AUTO_MANUAL, 1);   //Turn OFF Auto Mode
      digitalWrite(TestLED, LOW); // set LED ON
      digitalWrite(zone1, HIGH);
    }
  } 
  else 
  {
    terminal.println();
    terminal.println("Manual MODE is ON");
    terminal.println("Press ON/OFF button if required");
    terminal.println("Zone 1 is OFF");
    terminal.println();
    terminal.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
    terminal.flush();

    if (manual == 0) 
    {   //modo auto1mático
      checklastbuttonpressed ();
      manual = 1;
      auto1 = 0;

      Blynk.virtualWrite(BLYNK_VPIN_AUTO_MANUAL, 1);   //Turn OFF Auto Mode
      digitalWrite(TestLED, HIGH); // set LED OFF
      digitalWrite(zone1, LOW);
      Blynk.virtualWrite(BLYNK_VPIN_ZONE1_BUTTON, 0);   //Turn OFF Button Widget
    } 
    else 
    {
      auto1 = 0;

      Blynk.virtualWrite(BLYNK_VPIN_AUTO_MANUAL, 1);   //Turn OFF Auto Mode
      digitalWrite(TestLED, HIGH); // set LED OFF
      digitalWrite(zone1, LOW);
      Blynk.virtualWrite(BLYNK_VPIN_ZONE1_BUTTON, 0);   //Turn OFF Button Widget
    }
  }
}

BLYNK_WRITE(BLYNK_VPIN_ZONE2_BUTTON)  // Zone 2 ON-OFF Manual
{
  if (param.asInt() == 1) 
  { // boton encendido

    terminal.println();
    terminal.println("Manual MODE is ON");
    terminal.println("Zone 2 is ON");
    terminal.println();
    terminal.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
    terminal.flush();

    if (manual == 0) 
    { //está en modo auto1mático
      checklastbuttonpressed ();
      manual = 1;
      auto1 = 0;

      digitalWrite(TestLED, LOW); // set LED ON
      digitalWrite(zone2, HIGH);
      Blynk.virtualWrite(BLYNK_VPIN_ZONE2_BUTTON, 1);   //Turn ON Button Widget
      Blynk.virtualWrite(BLYNK_VPIN_AUTO_MANUAL, 1);   //Turn OFF Auto Mode

    } 
    else 
    {             
      //está en modo manual
      auto1 = 0;

      Blynk.virtualWrite(BLYNK_VPIN_ZONE2_BUTTON, 1);   //Turn ON Button Widget
      Blynk.virtualWrite(BLYNK_VPIN_AUTO_MANUAL, 1);   //Turn OFF Auto Mode
      digitalWrite(TestLED, LOW); // set LED ON
      digitalWrite(zone2, HIGH);
    }
  } 
  else 
  {
    terminal.println();
    terminal.println("Manual MODE is ON");
    terminal.println("Press ON/OFF button if required");
    terminal.println("Zone 2 is OFF");
    terminal.println();
    terminal.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
    terminal.flush();

    if (manual == 0) 
    {   //modo auto1mático
      checklastbuttonpressed ();
      manual = 1;
      auto1 = 0;

      Blynk.virtualWrite(BLYNK_VPIN_AUTO_MANUAL, 1);   //Turn OFF Auto Mode
      digitalWrite(TestLED, HIGH); // set LED OFF
      digitalWrite(zone2, LOW);
      Blynk.virtualWrite(BLYNK_VPIN_ZONE2_BUTTON, 0);   //Turn OFF Button Widget
    } 
    else 
    {
      auto1 = 0;
      
      Blynk.virtualWrite(BLYNK_VPIN_AUTO_MANUAL, 1);   //Turn OFF Auto Mode
      digitalWrite(TestLED, HIGH); // set LED OFF
      digitalWrite(zone2, LOW);
      Blynk.virtualWrite(BLYNK_VPIN_ZONE2_BUTTON, 0);   //Turn OFF Button Widget
    }
  }
}

BLYNK_WRITE(BLYNK_VPIN_ZONE1_TIME_INPUT)//Zone 1 time input handling
{
  static long startsecondswd;            // weekday start time in seconds
  static long stopsecondswd;             // weekday stop  time in seconds
  static long nowseconds;                // time now in seconds
  static int durationwd;
  static char Date[16];
  static char Time[16];

  static bool timeInputTriggered = false;
  
  if (auto1 == 1) 
  {
    sprintf(Date, "%02d/%02d/%04d",  day(), month(), year());
    sprintf(Time, "%02d:%02d:%02d", hour(), minute(), second());

    TimeInputParam t(param);
    terminal.println("GENERAL:");
    terminal.println(String("      Time zone: ") + t.getTZ()); // Timezone is already added to start/stop time
    terminal.println("      Ensure at least ONE day is selected for each zone");
    terminal.println();

    terminal.println("ZONE 1:");
    terminal.print("      Schedule checked at: ");
    terminal.println(Time);
    terminal.flush();
    int dayadjustment = -1;
    
    if (weekday() == 1) 
    {
      dayadjustment =  6; // needed for Sunday, Time library is day 1 and Blynk is day 7
    }
    
    if (t.isWeekdaySelected(weekday() + dayadjustment)) 
    { 
      //Time library starts week on Sunday, Blynk on Monday
      terminal.println("      Auto ACTIVE today");
      terminal.println("      Cycle/Soak Active.  3 equal intervals of watering split up by 2 equal intervals of soak");
      terminal.flush();
      
      if (t.hasStartTime()) // Process start time
      {      
        startsecondswd = (t.getStartHour() * 3600) + (t.getStartMinute() * 60) + t.getStartSecond();
        
        if (t.getStartMinute() < 10) 
        {
          terminal.println(String("      Scheduled Start: ") + t.getStartHour() + ":0" + t.getStartMinute());
        } 
        else 
        {
          terminal.println(String("      Scheduled Start: ") + t.getStartHour() + ":" + t.getStartMinute());
        }
        terminal.flush();
      }
      
      if (t.hasStopTime()) // Process stop time
      {
        stopsecondswd = (t.getStopHour() * 3600) + (t.getStopMinute() * 60) + t.getStopSecond();
        
        if (t.getStopMinute() < 10) 
        {
          terminal.println(String("      Scheduled Stop : ") + t.getStopHour() + ":0" + t.getStopMinute());
        }
        else 
        {
          terminal.println(String("      Scheduled Stop : ") + t.getStopHour() + ":" + t.getStopMinute());
        }
        
        durationwd = ( stopsecondswd - startsecondswd) / 60;
        cycle_soak_int = (durationwd * 60 * 1000) / WATER_SOAK_CYCLE_TIME;

        terminal.print("      Total Duration (mins):");
        terminal.println(durationwd);

        terminal.print("      Total Watering Time over ");
        terminal.print((WATER_SOAK_CYCLE_TIME / 2) + 1);
        terminal.print(" intervals (mins):");
        terminal.println((cycle_soak_int / 1000 / 60) * ( (WATER_SOAK_CYCLE_TIME / 2) + 1) );
        terminal.print("      Total Soak Time over ");
        terminal.print((WATER_SOAK_CYCLE_TIME / 2));
        terminal.print(" intervals (mins):");       
        terminal.println((cycle_soak_int / 1000 / 60) * (WATER_SOAK_CYCLE_TIME / 2) );
        
        terminal.flush();
      }
      // Display timezone details, for information purposes only

      terminal.flush();

      //     for (int i = 1; i <= 7; i++) {  // Process weekdays (1. Mon, 2. Tue, 3. Wed, ...)
      //        if (t.isWeekdaySelected(i)) {
      //        terminal.println(String("Zone 1 Days ") + i + " is selected");
      //        terminal.flush();
      //        }
      //      }
      
      nowseconds = ((hour() * 3600) + (minute() * 60) + second());

      //Serial.println(startsecondswd);  // used for debugging
      if (nowseconds >= startsecondswd) 
      {
        terminal.print("      Auto STARTED at");
        if (t.getStartMinute() < 10) 
        {
          terminal.println(String(" ") + t.getStartHour() + ":0" + t.getStartMinute());
        } 
        else 
        {
          terminal.println(String(" ") + t.getStartHour() + ":" + t.getStartMinute());
        }
        terminal.flush();
        
        if ( !timeInputTriggered && (nowseconds <= startsecondswd + 90) ) 
        {  
          // 90s on 60s timer ensures 1 trigger command is sent
          timeInputTriggered = true;
          
          digitalWrite(TestLED, LOW); // set LED ON
          digitalWrite(zone1, HIGH);
          Serial.println("Zone 1 active");

          timer.changeInterval(timerID, cycle_soak_int);
          timer.enable(timerID);

          printCycleData(0, HIGH, 1);

          Blynk.virtualWrite(BLYNK_VPIN_ZONE1_BUTTON, 1);
          // code here to switch the relay ON
        }
      }
      else 
      {
        Blynk.virtualWrite(BLYNK_VPIN_ZONE1_BUTTON, 0);
        terminal.println();
        terminal.println("      Auto NOT STARTED today");
        terminal.flush();
      }
      
      //Serial.println(stopsecondswd);  // used for debugging
      if (nowseconds >= stopsecondswd) 
      {
        digitalWrite(TestLED, HIGH); // set LED OFF
        digitalWrite(zone1, LOW);
        Blynk.virtualWrite(BLYNK_VPIN_ZONE1_BUTTON, 0);
        terminal.print("      Auto STOPPED at");
        
        if (t.getStopMinute() < 10) 
        {
          terminal.println(String(" ") + t.getStopHour() + ":0" + t.getStopMinute());
        } 
        else 
        {
          terminal.println(String(" ") + t.getStopHour() + ":" + t.getStopMinute());
        }
        terminal.flush();
        
        if ( timeInputTriggered && (nowseconds <= stopsecondswd + 90) )
        { 
          // 90s on 60s timer ensures 1 trigger command is sent
          timeInputTriggered = false;
          
          digitalWrite(TestLED, HIGH); // set LED OFF
          digitalWrite(zone1, LOW);
          Blynk.virtualWrite(BLYNK_VPIN_ZONE1_BUTTON, 0);
          // code here to switch the relay OFF
        }
      }
      else 
      {
        if ( !timeInputTriggered && (nowseconds >= startsecondswd) )
        {
          timeInputTriggered = true;
          
          digitalWrite(TestLED, LOW); // set LED ON
          digitalWrite(zone1, HIGH);

          Serial.println("Zone 1 active");

          timer.changeInterval(timerID, cycle_soak_int);
          timer.enable(timerID);

          printCycleData(0, HIGH, 1);
          
          Blynk.virtualWrite(BLYNK_VPIN_ZONE1_BUTTON, 1);
          terminal.println("      Auto is ON");
          terminal.flush();
        }
      }
    }
    else 
    {
      terminal.println();
      terminal.println("      Auto INACTIVE today");
      terminal.flush();
      // nothing to do today, check again in 30 SECONDS time
    }

    terminal.println();
  }
}

void printCycleData(int cycle_no, bool relay_state, int zone)
{
  static char cycleTime[16];
  
  Serial.println("~~~~~~~~~~~~~~~~~~~~~~Cycle Soak routine running~~~~~~~~~~~~~~~~~~~~~");
  sprintf(cycleTime, "%02d:%02d:%02d", hour(), minute(), second());
  Serial.print("Cycle Start Time: ");
  Serial.println(cycleTime);

  Serial.print("Cycle No: ");
  Serial.println(cycle_no);

  Serial.print("Relay State: ");
  Serial.println(relay_state);

  if (relay_state == HIGH) 
    Serial.print("Water for : ");
  else 
    Serial.print("Soak for : ");

  if (zone == 1)
  {
    Blynk.virtualWrite(BLYNK_VPIN_ZONE1_BUTTON, relay_state);
    Serial.print(cycle_soak_int / 1000 / 60);
  }
  else if (zone == 2)
  {
    Blynk.virtualWrite(BLYNK_VPIN_ZONE1_BUTTON, relay_state);
    Serial.print(cycle_soak_int2 / 1000 / 60);
  }
    
  Serial.println(" minutes");  
}

void cycle_soak_1() 
{
  static int cycle_no = 1;
  static bool relay_state = LOW;

  printCycleData(cycle_no, relay_state, 1);
  
  digitalWrite(zone1, relay_state);

  cycle_no++;
  relay_state = !relay_state;

  if (cycle_no == WATER_SOAK_CYCLE_TIME) 
  {
    cycle_no = 1;
    relay_state = LOW;
    timer.disable(timerID);
  }
}

void cycle_soak_2() 
{
  static int cycle_no = 1;
  static bool relay_state = LOW;

  printCycleData(cycle_no, relay_state, 2);
  
  digitalWrite(zone2, relay_state);

  cycle_no++;
  relay_state = !relay_state;

  if (cycle_no == WATER_SOAK_CYCLE_TIME) 
  {
    cycle_no = 1;
    relay_state = LOW;
    timer.disable(timerID2);
  }
}

BLYNK_WRITE(BLYNK_VPIN_ZONE2_TIME_INPUT)//Zone 2 time input handling
{
  static long startsecondswd2;            // weekday start time in seconds
  static long stopsecondswd2;             // weekday stop  time in seconds
  static long nowseconds2;                // time now in seconds
  static int durationwd2;
  static char Date2[16];
  static char Time2[16];
  
  static bool timeInputTriggered = false;
  
  if (auto1 == 1) 
  {
    sprintf(Date2, "%02d/%02d/%04d",  day(), month(), year());
    sprintf(Time2, "%02d:%02d:%02d", hour(), minute(), second());

    TimeInputParam t(param);
    terminal.println("GENERAL:");
    terminal.println(String("      Time zone: ") + t.getTZ()); // Timezone is already added to start/stop time
    terminal.println("      Ensure at least ONE day is selected for each zone");
    terminal.println();

    terminal.println("ZONE 2:");
    terminal.print("      Schedule checked at: ");
    terminal.println(Time2);
    terminal.flush();
    int dayadjustment = -1;
    
    if (weekday() == 1) 
    {
      dayadjustment =  6; // needed for Sunday, Time library is day 1 and Blynk is day 7
    }
    
    if (t.isWeekdaySelected(weekday() + dayadjustment)) 
    { 
      //Time library starts week on Sunday, Blynk on Monday
      terminal.println("      Auto ACTIVE today");
      terminal.println("      Cycle/Soak Active.  3 equal intervals of watering split up by 2 equal intervals of soak");
      terminal.flush();
      
      if (t.hasStartTime()) // Process start time
      {      
        startsecondswd2 = (t.getStartHour() * 3600) + (t.getStartMinute() * 60) + t.getStartSecond();
        
        if (t.getStartMinute() < 10) 
        {
          terminal.println(String("      Scheduled Start: ") + t.getStartHour() + ":0" + t.getStartMinute());
        } 
        else 
        {
          terminal.println(String("      Scheduled Start: ") + t.getStartHour() + ":" + t.getStartMinute());
        }
        terminal.flush();
      }
      
      if (t.hasStopTime()) // Process stop time
      {
        stopsecondswd2 = (t.getStopHour() * 3600) + (t.getStopMinute() * 60) + t.getStopSecond();
        
        if (t.getStopMinute() < 10) 
        {
          terminal.println(String("      Scheduled Stop : ") + t.getStopHour() + ":0" + t.getStopMinute());
        }
        else 
        {
          terminal.println(String("      Scheduled Stop : ") + t.getStopHour() + ":" + t.getStopMinute());
        }
        
        durationwd2 = ( stopsecondswd2 - startsecondswd2) / 60;
        cycle_soak_int2 = (durationwd2 * 60 * 1000) / WATER_SOAK_CYCLE_TIME;

        terminal.print("      Total Duration (mins):");
        terminal.println(durationwd2);

        terminal.print("      Total Watering Time over ");
        terminal.print((WATER_SOAK_CYCLE_TIME / 2) + 1);
        terminal.print(" intervals (mins):");
        terminal.println((cycle_soak_int2 / 1000 / 60) * ( (WATER_SOAK_CYCLE_TIME / 2) + 1) );
        terminal.print("      Total Soak Time over ");
        terminal.print((WATER_SOAK_CYCLE_TIME / 2));
        terminal.print(" intervals (mins):");       
        terminal.println((cycle_soak_int2 / 1000 / 60) * (WATER_SOAK_CYCLE_TIME / 2) );
        
        terminal.flush();
      }
      // Display timezone details, for information purposes only

      terminal.flush();

      //     for (int i = 1; i <= 7; i++) {  // Process weekdays (1. Mon, 2. Tue, 3. Wed, ...)
      //        if (t.isWeekdaySelected(i)) {
      //        terminal.println(String("Zone 1 Days ") + i + " is selected");
      //        terminal.flush();
      //        }
      //      }
      
      nowseconds2 = ((hour() * 3600) + (minute() * 60) + second());

      //Serial.println(startsecondswd);  // used for debugging
      if (nowseconds2 >= startsecondswd2) 
      {
        terminal.print("      Auto STARTED at");
        if (t.getStartMinute() < 10) 
        {
          terminal.println(String(" ") + t.getStartHour() + ":0" + t.getStartMinute());
        } 
        else 
        {
          terminal.println(String(" ") + t.getStartHour() + ":" + t.getStartMinute());
        }
        terminal.flush();
        
        if ( !timeInputTriggered && (nowseconds2 <= startsecondswd2 + 90) ) 
        {  
          // 90s on 60s timer ensures 1 trigger command is sent
          timeInputTriggered = true;
          
          digitalWrite(TestLED, LOW); // set LED ON
          digitalWrite(zone2, HIGH);
          Serial.println("Zone 2 active");

          timer.changeInterval(timerID2, cycle_soak_int);
          timer.enable(timerID2);

          printCycleData(0, HIGH, 2);

          Blynk.virtualWrite(BLYNK_VPIN_ZONE2_BUTTON, 1);
          // code here to switch the relay ON
        }
      }
      else 
      {
        Blynk.virtualWrite(BLYNK_VPIN_ZONE2_BUTTON, 0);
        terminal.println();
        terminal.println("      Auto NOT STARTED today");
        terminal.flush();
      }
      
      //Serial.println(stopsecondswd);  // used for debugging
      if (nowseconds2 >= stopsecondswd2) 
      {
        digitalWrite(TestLED, HIGH); // set LED OFF
        digitalWrite(zone2, LOW);
        Blynk.virtualWrite(BLYNK_VPIN_ZONE2_BUTTON, 0);
        terminal.print("      Auto STOPPED at");
        
        if (t.getStopMinute() < 10) 
        {
          terminal.println(String(" ") + t.getStopHour() + ":0" + t.getStopMinute());
        } 
        else 
        {
          terminal.println(String(" ") + t.getStopHour() + ":" + t.getStopMinute());
        }
        terminal.flush();
        
        if ( timeInputTriggered && (nowseconds2 <= stopsecondswd2 + 90) )
        { 
          // 90s on 60s timer ensures 1 trigger command is sent
          timeInputTriggered = false;
          
          digitalWrite(TestLED, HIGH); // set LED OFF
          digitalWrite(zone2, LOW);
          Blynk.virtualWrite(BLYNK_VPIN_ZONE2_BUTTON, 0);
          // code here to switch the relay OFF
        }
      }
      else 
      {
        if ( !timeInputTriggered && (nowseconds2 >= startsecondswd2) )
        {
          timeInputTriggered = true;
          
          digitalWrite(TestLED, LOW); // set LED ON
          digitalWrite(zone2, HIGH);

          Serial.println("Zone 2 active");

          timer.changeInterval(timerID2, cycle_soak_int);
          timer.enable(timerID2);

          printCycleData(0, HIGH, 2);
          
          Blynk.virtualWrite(BLYNK_VPIN_ZONE2_BUTTON, 1);
          terminal.println("      Auto is ON");
          terminal.flush();
        }
      }
    }
    else 
    {
      terminal.println();
      terminal.println("      Auto INACTIVE today");
      terminal.flush();
      // nothing to do today, check again in 30 SECONDS time
    }

    terminal.println();
  }
}

void setup()
{
  pinMode(TestLED, OUTPUT);
  digitalWrite(TestLED, HIGH); // set LED OFF

  digitalWrite(zone1, LOW);
  digitalWrite(zone2, LOW);
  pinMode(zone1, OUTPUT);
  pinMode(zone2, OUTPUT);


  Serial.begin(115200);
  Serial.println("\nStarting Irrigation");

#if USE_BLYNK_WM
    // Use DHCP Hostname "Irrigation-Timer
    Blynk.begin("Irrigation-Timer");
#else
  //Blynk.begin(auth, ssid, pass);
  Blynk.begin(auth, ssid, pass, server, BLYNK_HARDWARE_PORT);
#endif

  timer.setInterval(10000L, activetoday);     // check every 10 SECONDS if schedule should run today
  timer.setInterval(30000L, reconnectBlynk);  // check every 30s if still connected to server
  timer.setInterval(5000L, clockvalue);       // check value for time
  timer.setInterval(5000L, sendWifi);         // Wi-Fi singal

  timerID = timer.setInterval(100000L, cycle_soak_1);
  timer.disable(timerID);

  timerID2 = timer.setInterval(100000L, cycle_soak_2);
  timer.disable(timerID2);  
}

void loop()
{
  Blynk.run();
  timer.run();
}

And this is the test output showing the timer is working correctly now

Starting Irrigation
[62] Connecting to ****
[6449] Connected to WiFi
[6449] IP: 192.168.2.114
[6449] 
    ___  __          __
   / _ )/ /_ _____  / /__
  / _  / / // / _ \/  '_/
 /____/_/\_, /_//_/_/\_\
        /___/ v0.6.1 on NodeMCU

[6544] Ready (ping: 8ms).
[6698] Time sync: OK
Zone 1 active
~~~~~~~~~~~~~~~~~~~~~~Cycle Soak routine running~~~~~~~~~~~~~~~~~~~~~
Cycle Start Time: 17:09:16
Cycle No: 0
Relay State: 1
Water for : 1 minutes
~~~~~~~~~~~~~~~~~~~~~~Cycle Soak routine running~~~~~~~~~~~~~~~~~~~~~
Cycle Start Time: 17:10:16
Cycle No: 1
Relay State: 0
Soak for : 1 minutes
~~~~~~~~~~~~~~~~~~~~~~Cycle Soak routine running~~~~~~~~~~~~~~~~~~~~~
Cycle Start Time: 17:11:16
Cycle No: 2
Relay State: 1
Water for : 1 minutes
~~~~~~~~~~~~~~~~~~~~~~Cycle Soak routine running~~~~~~~~~~~~~~~~~~~~~
Cycle Start Time: 17:12:16
Cycle No: 3
Relay State: 0
Soak for : 1 minutes
~~~~~~~~~~~~~~~~~~~~~~Cycle Soak routine running~~~~~~~~~~~~~~~~~~~~~
Cycle Start Time: 17:13:16
Cycle No: 4
Relay State: 1
Water for : 1 minutes

I already made the Zone 2 ready for timer operations similar to Zone 1.

There are still many things I really don’t like, and if you have time and energy, you can spend time to fix later

  1. I haven’t checked the logic of the whole sketch, just the Zone 1 timer operation
  2. You’re writing too much and unnecessarily to the terminal. You might have flooding / overflowing issues with the Blynk Cloud Server, and especially if and whenever the Internet speed is slow.
    How to fix this:
  • Don’t use terminal
  • Just only rewrite data that are dynamic to display widgets
  • Write static data once to other display widgets

If you experience more issue, just let us know.
Cheers,

Update
Testing Zone1 and Zone2 Timer working consecutively and OK.
Test results

Starting Irrigation
[62] Connecting to ****
[5065] Connected to WiFi
[5066] IP: 192.168.2.114
[5066] 
    ___  __          __
   / _ )/ /_ _____  / /__
  / _  / / // / _ \/  '_/
 /____/_/\_, /_//_/_/\_\
        /___/ v0.6.1 on NodeMCU

[5110] Ready (ping: 11ms).
[5250] Time sync: OK
Zone 1 active                                <==== Zone1 starts ontime
~~~~~~~~~~~~~~~~~~~~~~Cycle Soak routine running~~~~~~~~~~~~~~~~~~~~~
Cycle Start Time: 21:40:01
Cycle No: 0
Relay State: 1
Water for : 1 minutes
~~~~~~~~~~~~~~~~~~~~~~Cycle Soak routine running~~~~~~~~~~~~~~~~~~~~~
Cycle Start Time: 21:41:02
Cycle No: 1
Relay State: 0
Soak for : 1 minutes
~~~~~~~~~~~~~~~~~~~~~~Cycle Soak routine running~~~~~~~~~~~~~~~~~~~~~
Cycle Start Time: 21:42:02
Cycle No: 2
Relay State: 1
Water for : 1 minutes
~~~~~~~~~~~~~~~~~~~~~~Cycle Soak routine running~~~~~~~~~~~~~~~~~~~~~
Cycle Start Time: 21:43:02
Cycle No: 3
Relay State: 0
Soak for : 1 minutes
~~~~~~~~~~~~~~~~~~~~~~Cycle Soak routine running~~~~~~~~~~~~~~~~~~~~~
Cycle Start Time: 21:44:02
Cycle No: 4
Relay State: 1
Water for : 1 minutes
Zone 2 active                                <==== Zone2 starts ontime
~~~~~~~~~~~~~~~~~~~~~~Cycle Soak routine running~~~~~~~~~~~~~~~~~~~~~
Cycle Start Time: 21:45:02
Cycle No: 0
Relay State: 1
Water for : 1 minutes
~~~~~~~~~~~~~~~~~~~~~~Cycle Soak routine running~~~~~~~~~~~~~~~~~~~~~
Cycle Start Time: 21:46:02
Cycle No: 1
Relay State: 0
Soak for : 1 minutes
~~~~~~~~~~~~~~~~~~~~~~Cycle Soak routine running~~~~~~~~~~~~~~~~~~~~~
Cycle Start Time: 21:47:02
Cycle No: 2
Relay State: 1
Water for : 1 minutes
~~~~~~~~~~~~~~~~~~~~~~Cycle Soak routine running~~~~~~~~~~~~~~~~~~~~~
Cycle Start Time: 21:48:02
Cycle No: 3
Relay State: 0
Soak for : 1 minutes
~~~~~~~~~~~~~~~~~~~~~~Cycle Soak routine running~~~~~~~~~~~~~~~~~~~~~
Cycle Start Time: 21:49:01
Cycle No: 4
Relay State: 1
Water for : 1 minutes

What is your specific question?

If you are waiting for someone to write you the code with the features you listed, then I think you will be waiting for a long time. As I suspect no one is going to do it for you.

Hello i don’t need that someone write the code for me, but like i said, i need help to change some parts of the code, that i don’t understand, i made some changes, but the features i need to make is difficult for me.

What is missing, create another two times, and put only one cicle of watering, of 20 minuts.

I think that in reality, you’re unlikely to get much help with this, especially as you’ve already made some changes of your own.

My advice would be to work-out what each section of the code does, and add lots of documentation into the code. The process of doing this should make it easier for you to identify what needs to be added to provide the additional functionality.
Follow the variable naming conventions that are already used, and add notes to explain the logic behind the changes that you’ve made.

Pete.

Hello Peteknight, i made change, to show that im working and verified if don’t have errors, and than publish, but like i was think someone in the group gonna write" don’t wait that someone right the code four you".

Changes i made in the code
In original code only have 2 relays, i put another four and describe what they do, i follow the logical of the original and I added that changes, i used one pcf8574, and the code was correct.
My biggest problem is when i duplicate the part of the code that give me the time for which zone, give me errors on “printCycleData” and if i touch in this the code don’t work.
I only want some guidance nothing more.

Well, unless you share details of what you did here:

and what the errors are that you experienced, then that guidance isn’t likely to be forthcoming.

Pete.

You’ll need to post the ACTUAL CODE that created these error messages for it to make any sense, otherwise we are just guessing at what steps you actually took, and what mistakes you made along the way, when you did this:

Pete.

i can`t post the code Body is limited to 32000 characters; you entered 36245.

Pete.

Okay, when I copy your code from pastebin and compile it on my PC, I get the same error message:

and, If I search your code for “void printCycleData” I find two occurences of the same function, one at line 607 and one at line 894

You can only have, and you only need, this function once. You call it from as many locations as needed within your code.

Also, taking a quick look at this function, it contains this:

  if (zone == 1)
  {
    Blynk.virtualWrite(BLYNK_VPIN_ZONE1_BUTTON, relay_state);
    Serial.print(cycle_soak_int / 1000 / 60);
  }
  else if (zone == 2)
  {
    Blynk.virtualWrite(BLYNK_VPIN_ZONE1_BUTTON, relay_state);
    Serial.print(cycle_soak_int2 / 1000 / 60);
  }
    
  Serial.println(" minutes");  
}

It seems that you need to add an if test for your new zone 3 if you want the expected functionality.

Pete.

You are correct this is to much for me, i need do this for other point of view, first i need eliminate the soak part only have the watering time.

I’m not sure that is the best approach.

As I said before, I think you need to go through the code one section at a time and understand fully what it does, and add-in documentation that you can follow which allows you to understand the functionality.

Searching for every occurance of “zone” will then help you to see where additional zones need to be added-in.

Pete.

That isn’t what I suggested, and I think it was a bad move.

My advice was to document the code, and although you have some comments that say what an individual line of code does, you don’t have higher level comments that explain the overall function of a section of code, when it’s called, where it fits into the process etc.

If you’re not prepared to do this, either in the code or ion a separate flowchart, then I don’t think you’ll get on top of a sketch with 1200+ lines of code and you certainly wont be able to come back to it in future and make minor changes.

I’m certainly not going to go through the code and work-out what each of your bloclks of code doesn, what each variable does, and what the overall logic flow is - that’s your job.

Pete.