Timers using the time input widget

Wow…that is going to be feat…the code is 2210 lines long divided into tabs!

I will see how I can compress as there are a lot of reps

Well, we at least need to see the bit where you’re doing the Blynk.syncVirtual, the Blynk connection and understand what BLYNK_WRITEs you have and what’s happening in each of them.

Pete.

Ok…here it is. I have removed all the reps and all the WiFi Manager stuff ect to make it shorter. Just to be clear I am not saying it does NOT CONNECT it does but takes up to 5 minutes before it does

//MASTER TAB//
/*BLYNK APP
 * V0-TIME
 * V1-DATE
 * V2-TANK TEMP
 * V3-HEATING ON
 * V4-CHILLER ON
 * V5-UV LED % BAR
 * V6-RBLUE/BLUE LED % BAR
 * V7-BLUE LED % BAR
 * V8-OCW LED % BAR
 * V9-LIME/AMBER LED % BAR
 * V10-MODE SWITCH (Manual/Auto)
 * V11-CH1 UV TIME SET
 * V12-CH1 UV FADEIN TIME
 * V13-CH1 UV FADEOUT TIME
 * V14-CH1 UV INTENSITY SETTING
 * V15-CH2 RBLUE/BLUE TIME SET
 * V16-CH2 RBLUE/BLUE FADEIN TIME
 * V17-CH2 RBLUE/BLUE FADEOUT TIME
 * V18-CH2 RBLUE/BLUE INTENSITY SETTING
 * V19-CH3 BLUE TIME SET
 * V20-CH3 BLUE FADEIN TIME
 * V21-CH3 BLUE FADEOUT TIME
 * V22-CH3 BLUE INTENSITY SETTING
 * V23-CH4 OCW TIME SET
 * V24-CH4 OCW FADEIN TIME
 * V25-CH4 OCW FADEOUT TIME
 * V26-CH4 OCW INTENSITY SETTING
 * V27-CH5 AMBER TIME SET
 * V28-CH5 AMBER FADEIN TIME
 * V29-CH5 AMBER FADEOUT TIME
 * V30-CH5 AMBER INTENSITY SETTING
 * V31-PH DATA FOR GRAPH
 * V32-CH1 UV LED WIDGET
 * V33-CH2 RBLUE/BLUE LED WIDGET
 * V34-CH3 BLUE LED WIDGET
 * V35-CH4 OCW LED WIDGET
 * V36-CH5 AMBER LED WIDGET
 * V37-TANK TEMP SET
 * V38-TANK TEMP DATA FOR GRAPH
 * V39-TERMINAL WIDGET
 * V40-SAFELED LED WIDGET
 * V41-CH5 LIME TIME SET
 * V42-CH5 LIME FADEIN TIME
 * V43-CH5 LIME FADEOUT TIME
 * V44-CH5 LIME INTENSITY SETTING
 * V45-LIME LED % BAR
 * V46-CH5 AMBER LED WIDGET
 * V47-STIMER1
 * V48-STIMER2
 * V49-STIMER3
 * V50-STIMER4
 * V51-MTIMER1 TIME INPUT WIDGET
 * V52-MTIMER1 DOSES/DAY WIDGET
 * V53-MTIMER1 DOSE DURATION WIDGET
 * V54-MTIMER1 SWITCH
 * V55-MTIMER2 TIME INPUT WIDGET
 * V56-MTIMER2 DOSES/DAY WIDGET
 * V56-MTIMER2 DOSE DURATION WIDGET
 * V58-MTIMER2 SWITCH
 * V60-DATA EXCHANGE S1
 * V61-DATA EXCHANGE S2
 * V62-BRIDGE WIDGET 1
 * V63-BRIDGE WIDGET 2   
 * V64-BRIDGE WIDGET 3
 * V65-BRIDGE WIDGET 4
 * V66-BRIDGE WIDGET 5
 * V71-MTIMER3 TIME INPUT WIDGET
 * V72-MTIMER3 DOSES/DAY WIDGET
 * V73-MTIMER3 DOSE DURATION WIDGET
 * V74-MTIMER3 SWITCH
 * V75-MTIMER4 TIME INPUT WIDGET
 * V76-MTIMER4 DOSES/DAY WIDGET
 * V77-MTIMER4 DOSE DURATION WIDGET
 * V78-MTIMER4 SWITCH
 * V79-STIMER1 LED
 * V80-STIMER2 LED
 * V81-STIMER3 LED
 * V82-STIMER4 LED
 * V83-MTIMER1 LED
 * V84-MTIMER2 LED
 * V85-MTIMER3 LED
 * V86-MTIMER4 LED
 */

//Blynk Master device Authorisation code : " 9b67012003144e4b874fa61a5e57e935 " //

//LIBRARIES//
       
//#include <FS.h>                   

#include <ESP8266WiFi.h>  
//#include <DNSServer.h>
#include <TimeLib.h>
#include <WidgetRTC.h>
#include <OneWire.h>
#include <DallasTemperature.h>
//#include "DFRobot_PH.h"   //version2
//#include <EEPROM.h>       //version2
WidgetRTC rtc;
BlynkTimer timer;

WidgetLED ch1(V32); //LED WIDGET TO SHOW LED LIGHTING CHANNEL 1 IS SET

WidgetLED ST1LED(V79);  //LED WIDGET TO SHOW STANDARD TIMER IS ON/OFF

WidgetLED MT1LED(V83);  //LED WIDGET TO SHOW MULTIPLE TIMER IS ON/OFF

#define Green "#23C48E"  //LED WIDGET COLOUR GREEN SET NOT ON
#define Blue  "#04C0F8"   //LED WIDGET COLOUR BLUE ON

//PIN ASSIGNMENTS//
#define ONE_WIRE_BUS D1
#define PH_PIN A0           

//WIFI Variables
char auth[] =
char ssid[] = 
char pass[] =

//BRIDGE WIDGET//
WidgetBridge master_slave1(V62);   //Master/slave1 bridge - LED unit 1
WidgetBridge master_slave2(V63);   //Master/slave2 bridge - LED unit 2
WidgetBridge master_slave3(V64);   //Master/slave3 bridge - Chiller & Heater plugbar
WidgetBridge master_slave4(V65);   //Master/slave4 - Supplimentary plugbar1 4xSTimers
WidgetBridge master_slave5(V66);   //Master/slave5 - Supplimentary plugbar2 4xMTimers

//GLOBAL ATTRIBUTES & VARIABLES//
int BTNval;  //BUTTON WIDGET AUTO AND MANUAL MODES USED TO SET LEDS INITIALLY.

//PH CONTROL GLOBALS//
#define Offset -4.00            
#define samplingInterval 20
#define printInterval 800
#define ArrayLenth  40 
int pHArray[ArrayLenth];
int pHArrayIndex=0;
static float pHValue,voltage;

//RTC & TIME IMPUT ATTRIBUTES & VARIABLES
char currentTime[9];    //RTC time
char currentDate[11];   //RTC date

//LED CHANNEL 1 TIME GLOBALS//
int SThour1;            //Time input widget
int STmin1;             //Time input widget
int STsec1;             //Time input widget
int SPhour1;            //Time input widget
int SPmin1;             //Time input widget
int SPsec1;             //Time input widget
int dayNumber1;         //Time input widget

//LED FADE ATTRIBUTES & VARIABLES//
//CHANNEL 1//
unsigned long CH1S;  //START TIME
unsigned long CH1E;  //END TIME
unsigned long FadeINmin1;
unsigned long FadeOUTmin1;
int maxPWM1;
int PWMinput1;

//NB!!!! THERE ARE 6 CHANNELS FOR LEDS//

//TEMPERATURE ATTRIBUTES & VARIABLES//
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
float TankTempSet = 0;
float TankTemp = 0;

//MULTIPLE TIMER GLOBALS// THESE WORK: YOU SET TIME & DAY. THEY ACTIVATE ON AND OFF MULTIPLE TIMES DURING THE DAY IN ACCORDANCE WITH YOUR INPUT SETTINGS
enum MTimer1 {RESET1, ON, RESET2, OFF};  //STATE MACHINE STATES
MTimer1 state = RESET1;
int Doses1;  //NUMBER OF DOSES/DAY SET BY A NUMERIC INPUT WIDGET
unsigned long DoseTime1; //DOSE TIME SET BY A NUMERIC INPUT WIDGET
int MT1Button;  //BUTTON WIDGET TO ACTIVATE THE MULTIPLE TIMER FUNCTION. NEEDS TO BE 1 TO ACTIVATE

unsigned long MT1S;  //START TIME FOR MULTIPLE TIME SET BY TIME INPUT WIDGET
bool MT1active = false;
int M1;  //BLYNK TIMER VARIABLE FOR MULTIPLE TIMER1

long M1CountRemain; // COUNTDOWN TIMER FOR MULTIPLE TIMER

//STANDARD TIMER GLOBALS// THESE WORK: SET START/STOP/DAY REQUIRED. THEY WILL TURN OF 1/DAY AT SETTINGS INPUTTED.
bool STimer1Active = true;
unsigned long ST1;  //STANDARD TIME START TIME
unsigned long ET1;  //STANDARD STOP TIME
int S1; //VARIABLE FOR BLYNK TIMER
int ST1Button; //BUTTON WIDGET TO SET/ACTIVATE STANDARD TIMER

//CONNECT TO BLYNK SERVER//
BLYNK_CONNECTED()
{
  Blynk.syncVirtual(V10, V11, V12, V13, V14, V15, V16, V17, V18, 
  V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30, V41, 
  V42, V43, V44, V47, V48, V49, V50, V51, V52, V53, V54, V55, V56, 
  V57, V58, V71, V72, V73, V74, V75, V76, V77, V78, V87, V88, V89, V90);
  rtc.begin();
  master_slave1.setAuthToken("0d10d17a44c94f3795fd5d7c36206bf1");   //SLAVE 1 LED UNIT 1
  master_slave2.setAuthToken("b62b199dc066429e833baa753ea70dad");   //SLAVE 2 LED UNIT 2
  //master_slave3.setAuthToken("XXXXXXXXXXXXXX");   //SLAVE 3         //SLAVE 3 HEATER/CHILLER PLUGBAR
  //master_slave4.setAuthToken("XXXXXXXXXXXXXX");   //SLAVE 4         //SLAVE 4 STIMER PLUGBAR
  //master_slave5.setAuthToken("XXXXXXXXXXXXXX");   //SLAVE 5         //SLAVE 5 MTIMER PLUGBAR
}


void setup()
{
  Serial.begin(115200);
  Blynk.begin(auth, ssid, pass);
  pinMode(ONE_WIRE_BUS, INPUT);
  pinMode(PH_PIN, INPUT);
  sensors.begin();
  setSyncInterval(30);
  timer.setInterval(1000L, ClockDisplay);
  timer.setInterval(2000L, TankTempControl);
  timer.setInterval(3000L, PHFunction);
  S1 = timer.setInterval(950L, STimer1);
  M1 = timer.setInterval(1000L, MTimer1);
  timer.disable(S1);  //DISABLE TIMER ON START UP
  timer.disable(M1);
}

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

}
//LED LIGHTING TAB//
BLYNK_WRITE(V10)   //BUTTON WIDGET USED TO SET THE LEDS. OFF POSITION IS MANUAL ON POSITION IS AUTO
{
  BTNval = param.asInt();
  master_slave1.virtualWrite(V25, BTNval); //SEND DATA TO BRIDGE
}

//CHANEL 1 UV///////////////////////////////////////////////////////////////////////////
BLYNK_WRITE(V11)  //CH1 TIME IMPUT WIDGET
{
  TimeInputParam t(param);
  SThour1 = t.getStartHour();
  STmin1 = t.getStartMinute();
  STsec1 = t.getStartSecond();
  SPhour1 = t.getStopHour();
  SPmin1 = t.getStopMinute();
  SPsec1 = t.getStopSecond();
  dayNumber1 = weekday();
  unsigned int OnDays1 = 0;
  for (int i = 1; i <= 7; i++)    //Process weekdays (1-Mon, 2-Tues, 3-Wed, 4-Thurs, 5-Fri, 6-Sat, 7-Sun)
  {
    if (t.isWeekdaySelected(i))
    {
      OnDays1++;
      if(i==dayNumber1)
      {
        master_slave1.virtualWrite(V1, 1);
      }
      if(t.hasStartTime())
      {
        CH1S = (SThour1*60) + STmin1;   //Start time min
        master_slave1.virtualWrite(V2, CH1S);  //SEND DATA TO BRIDGE
      }
      if(t.hasStopTime())
      {
        CH1E = (SPhour1*60) + SPmin1;    //End time min
        master_slave1.virtualWrite(V3, CH1E);  //SEND DATA TO BRIDGE
      }
    }
    if (OnDays1 == 0)
    {
      master_slave1.virtualWrite(V1, 0);  //SEND DATA TO BRIDGE
    }
  }
}

BLYNK_WRITE(V12)   //CH1 FADEIN TIME NUMERIC INPUT WIDGET
{
  FadeINmin1 = param.asInt();
  master_slave1.virtualWrite(V4, FadeINmin1); 
}

BLYNK_WRITE(V13)   //CH1 FADEOUT TIME NUMERIC INPUT WIDGET
{
  FadeOUTmin1 = param.asInt();
  master_slave1.virtualWrite(V5, FadeOUTmin1);
}

BLYNK_WRITE(V14)   //CH1 UV INTENSITY NUMERIC INPUT WIDGET
{
  PWMinput1 = param.asInt();
  maxPWM1 = map(PWMinput1, 0, 100, 0, 1023);
  master_slave1.virtualWrite(V6, FadeOUTmin1);   
}
//NB!!!6 OF THESE AS WELL//
//TIMERS TAB//
//STIMER1////////////////////////////////////////////////////
BLYNK_WRITE(V87) //BUTTON WIDGET
{
  ST1Button = param.asInt();
  if (ST1Button == 1)
  {
    STimer1Active = true;
    timer.enable(S1);
    STimer1();
    ST1LED.setColor(Green);
    ST1LED.on();
  }
  else
  {
    STimer1Active = false;
    timer.disable(S1);
    ST1LED.off();
  }
}
   
BLYNK_WRITE(V47)  //TIME INPUT WIDGET
{
  TimeInputParam t(param);
  int Shour = t.getStartHour();
  int Smin = t.getStartMinute();
  int Ssec = t.getStartSecond();
  int Ehour = t.getStopHour();
  int Emin = t.getStopMinute();
  int Esec = t.getStopSecond();
  int dayadjust = -1;
  if (weekday() == 1)
  {
    dayadjust = 6;
  }
  if (t.isWeekdaySelected((weekday() + dayadjust)))
  {
    if (t.hasStartTime())
    {
      ST1 = (Shour*3600) + (Smin*60) + Ssec;   //Start time seconds
    }
    if (t.hasStopTime())
    {
      ET1 = (Ehour*3600) + (Emin*60) + Esec;    //End time seconds
    }
    for (int i = 1; i <=7; i++)
    {
      if (t.isWeekdaySelected(i))
      {
        //terminal.println(String("Day ") + i + " is selected");
      }
    }
  }
}

void STimer1()
{
  unsigned long TotalSec = ((hour()*3600) + (minute()*60) + second());  //NOW TIME
  if (STimer1Active)
  {
    if(STime1Update)
    {
      if (ST1 > ET1)          //Check for midnight correction if needed
      {
        ET1 = ET1 + 86400;    //Midnight correction
      }
      if (TotalSec >= ST1 && TotalSec <= ET1)
      {
        if (STime1Update)
        {
          STime1Update = false;
          master_slave4.virtualWrite(D1, 1);
          ST1LED.setColor(Blue);
          ST1LED.on();
          Serial.println("ON");
        }
        else
        {
          if (STime1Update == false)
          STime1Update = true;
          master_slave4.virtualWrite(D1, 0);
          ST1LED.setColor(Green);
          ST1LED.on();
          Serial.println("OFF");
        }
      }
    }
  }
}
//MTIMER1////////////////////////////////////////////////////
BLYNK_WRITE(V51)            //Time input    
{
  TimeInputParam t(param);
  int Shour = t.getStartHour();
  int Smin = t.getStartMinute();
  int Ssec = t.getStartSecond();
  int Ehour = t.getStopHour();
  int Emin = t.getStopMinute();
  int Esec = t.getStopSecond();
  int dayadjust = -1;
  if (weekday() == 1)
  {
    dayadjust = 6;
  }
  if (t.isWeekdaySelected((weekday() + dayadjust)))
  {
    if (t.hasStartTime())
    {
      MT1S = (Shour*3600) + (Smin*60) + Ssec;   //Start time seconds
    }
    for (int i = 1; i <=7; i++)
    {
      if (t.isWeekdaySelected(i))
      {
        //terminal.println(String("Day ") + i + " is selected");
      }
    }
  }
}

BLYNK_WRITE(V52)          //Doses/Day
{
  Doses1 = param.asInt();
}

BLYNK_WRITE(V53)        //Dose duration in seconds 3-240
{
  DoseTime1 = param.asInt();
}

BLYNK_WRITE(V54)        //Activate MTimer
{
  MT1Button = param.asInt();
  {
    if (MT1Button == 1)
    {
      MTimer1();
      timer.enable(M1);
      MT1LED.setColor(Green);
      MT1LED.on();
    }
    else
    {
      timer.disable(M1);
      MT1LED.off();
    }
  }
}

void MTimer1()
{
  unsigned long TotalSec = ((hour()*3600) + (minute()*60) + second());
  unsigned long doseInt = ((86400 - (Doses1 * DoseTime1)) / Doses1);
  Serial.println(doseInt);
  if ((TotalSec >= MT1S) && (TotalSec <= (MT1S - MT1S) + 86400))   //Time to start timer & add a day if start up is before Start time
  switch (state)
  {
    case RESET1:
    {
      if (M1CountRemain != DoseTime1)
        {
          M1CountRemain = DoseTime1;
          M1FormattedON(M1CountRemain);
          timer.enable(M1);
          state = ON;
          Serial.println("RESET1");
        }
        break;
       }
            
    case ON:
    {
      if (M1CountRemain)
      {
        M1CountRemain--;
        M1FormattedON(M1CountRemain);
        master_slave5.virtualWrite(D1, 1);
        MT1LED.setColor(Blue);
        MT1LED.on();    //On period
        Serial.println("ON");
      }
      if (M1CountRemain == 0)
      {
        state = RESET2;
      }
      break;
    }
      
    case RESET2:
    {
      if (M1CountRemain != doseInt)
      {
        M1CountRemain = doseInt;
        Serial.println(doseInt);
        M1FormattedOFF(M1CountRemain);
        timer.enable(M1);
        state = OFF;
         Serial.println("RESET2");
      }
      break;
    }

    case OFF:
    {
      if (M1CountRemain)
      {
        M1CountRemain--;
        M1FormattedOFF(M1CountRemain);
        master_slave5.virtualWrite(D1, 0);
        MT1LED.setColor(Green);
        MT1LED.on();    //Off period
        Serial.println("OFF");
      }
      if (M1CountRemain == 0)
      {
        state = RESET1;
      }
    break;
    }
  }
}
//RTC TAB//
void ClockDisplay()
{
  sprintf(currentTime, "%02d:%02d:%02d", hour(), minute(), second());
  sprintf(currentDate, "%02d/%02d/%04d", day(), month(), year());

  Blynk.virtualWrite(V0, currentTime);    //Send time to TIME widget
  Blynk.virtualWrite(V1, currentDate);    //Send date to DATE widget
  Blynk.virtualWrite(V47, day());
}

void M1FormattedON(long seconds) //On period
{
  long days = 0;
  long hours = 0;
  long mins = 0;
  long secs = 0;
  String secs_o = ":";
  String mins_o = ":";
  String hours_o = "";
  secs = seconds;
  mins = secs / 60;
  hours = mins / 60;
  days = hours / 24;
  secs = secs - (mins * 60);
  mins = mins - (hours * 60); 

  if (secs < 10)
  {
    secs_o = ":0";
  }
  if (mins < 10) {
    mins_o = ":0";
  }
  if (hours < 10) {
    hours_o = "0";
  }
  Blynk.virtualWrite(V91, "DOSING " + hours_o + hours + mins_o + mins + secs_o + secs);
}

void M1FormattedOFF(long seconds)   //Off period
{
  long days = 0;
  long hours = 0;
  long mins = 0;
  long secs = 0;
  String secs_o = ":";
  String mins_o = ":";
  String hours_o = "";
  secs = seconds;
  mins = secs / 60;
  hours = mins / 60;
  days = hours / 24;
  secs = secs - (mins * 60);
  mins = mins - (hours * 60); 

  if (secs < 10)
  {
    secs_o = ":0";
  }
  if (mins < 10) {
    mins_o = ":0";
  }
  if (hours < 10) {
    hours_o = "0";
  }
  Blynk.virtualWrite(V91, "NEXT DOSE " + hours_o + hours + mins_o + mins + secs_o + secs);
}

Sorry forgot to mention the reason behind syncing the pins is to avoid the issue of a power failure or reboot and the programme not starting of from where it should be. I noticed this with the Time Input Widget which needs to be re-OKed.

And does this actually work, are all of the variables synched correctly when the device does connect?

You’re trying to get 50 items to sync at the same time, which could mean that you run into some issues.

Personally, I think you’ve added far to many controls to your app for it to be really useable. Once you’ve established the basic operating parameters then all you should really need to do is tweak a couple of controls and your timers.

Looking at the complexity of the project, with multi devices and the wide arange of parameters to be controlled, I would have used Node-Red and MQTT as the basis for the project, as it simplifies all of the bridging and allows you to tweak parameter values without the need to re-load code. It also overcomes the issues of needing to sync so much data with Blynk if you use retained MQTT messages.

Pete.

Yes it does work when it gets connected. I do not know Node-Red I will have to look into that

Take a look here:

Pete.

I don’t know if this made the difference or not but I split the Blynk.sync like this
Blynk.sincvirtual(1, 2, 3, 4, 5, 6,);
Blynk.sincvirtual(7, 8, 9, 10, 11);
ect…
ect…
And connection is much faster now

I hope you are using the correct syntax and spelling in your code :stuck_out_tongue:

Yes, just the fact that you are splitting up into multiple group commands will allow the syncing to happen in stages… still fast, yes, but at least not all simultaneously.