BLYNK
HOME       📲 GETTING STARTED       📗 DOCS       ❓HELP CENTER       👉 SKETCH BUILDER

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