Timers using the time input widget

I am nearing the end of my project and am trying to sort out the timers. I have 2 types of timer functions:

  1. Standard Timer which you select the days to be active and times. 1 shot/day timer.

  2. MutiTimer which you select the days, the doses/day, dose duration and controlled by a switch widget which when on the Mtimer is active and when off the Mtimer is inactive.
    I have been trying to put these functions into a BLYNK_WRITE function as opposed to a void() function, and the reasoning has been i was trying to avoid having BlynkTimer actions as the timers will be used as needed and could go weeks without being required. I saw no point in calling a timer acttion every x seconds when not needed.
    Unfortunately it does not work.
    can somebody please have a look at my 2 timer codes and tell me where i am going wrong or how can i achieve the desired result.

STIMER
BLYNK_WRITE(V47)  //STIMER1
{
  unsigned long TotalSec = ((hour()*3600) + (minute()*60) + second());
  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 dayNum = weekday();
  int onDays = 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))
    {
      onDays++;
      if(i==dayNum)
      {
        Blynk.syncVirtual(V79);
        ST1LED.setColor(DBlue);
        ST1LED.on();
        if(t.hasStartTime())
        {
          ST1 = (Shour*3600) + (Smin*60) + Ssec;   //Start time seconds
          if (TotalSec >= ST1)
          {
            Blynk.syncVirtual(V79);
            master_slave4.digitalWrite(D1, HIGH);
            ST1LED.setColor(Blue);
            ST1LED.on();
          }
        }
        if(t.hasStopTime())
        {
          ET1 = (Ehour*3600) + (Emin*60) + Esec;    //End time seconds
          if (TotalSec >= ET1)
          {
            Blynk.syncVirtual(V79);
            master_slave4.digitalWrite(D1, LOW);
            ST1LED.off();
            ST1LED.setColor(DBlue);
            ST1LED.on();
          }
        }
      }
      if (onDays == 0)
      {
        Blynk.syncVirtual(V79);
        master_slave4.digitalWrite(D1, LOW);
        ST1LED.off();
      }
    }
  }
}
MTIMER
BLYNK_WRITE(V51)            //Time input    
{
  TimeInputParam t(param);
  int MThr = t.getStartHour();
  int MTmin = t.getStartMinute();
  int MTsec = t.getStartSecond();
  int MTday = weekday();
  int MTOnDays = 0;
  for (int i = 1; i <= 7; i++)  
  {
    if (t.isWeekdaySelected(i))
    {
      MTOnDays++;
      if(i==MTday && t.hasStartTime())
      {
        MT1S = (MThr*3600) + (MTmin*60) + MTsec;   //Time in secs
        MT1active = true;
      }
    if (MTOnDays == 0)
    {
    }
  }
}
}

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

BLYNK_WRITE(V53)        //Dose duration
{
  DoseTime1 = param.asInt();
}

BLYNK_WRITE(V54)        //Activate MTimer
{
  switch1 = param.asInt();
  unsigned long TimeSeconds = (hour()*3600) + (minute()*60) + second();
  if (switch1 == 1 && MT1active == true)
  {
    SetMTimer(MT1, TimeSeconds, MT1S, Doses1, DoseTime1);
  }
  else if (switch1 == 0)
  {
    master_slave5.digitalWrite(D1, LOW);
    Blynk.virtualWrite(V83, 0);
    MT1active = false;
  }
}

It would help if you changed the terminology you are using, to knelt others understand what you’re doung.

The Blynk app has two types of time related widget - Timer (best referred to as Timer Widget to avoid confusion with the use of Blynktimer in code) and the Time Input Widget.

I can’t tell which widgets you’re using in your app, or which virtual pins have what attached to them. You also talk about a Switch Widget, but I have no idea which virtual pin this is connected to, and where it fits in to the code.

I’d suggest that you edit your post to change the terminology you are using, plus add a bit of background information about how the various inputs are meant to work together.

The simple solution is to add/delete or enable/disable Blynktimers as and when required.

Pete.

Ok I have noted up the sketch for ease of understanding.
The STimer is quite basic …a time input widget gets the input time and day compares it to the current time and acts accordingly.
The Mtimer works thus …you set the days and time to start via a time input widget…you set the number of doses per day…you set the time each dose must be. the switch widget is used thus… if the switch is off(0) the timer is off regardless of the settings above, if the switch is on(1) it turns the timer on according to void SetMtimer()…(sorry forgot to include that code in the beginning).
just for info my abbreviations are S stands for standard M multiple T timer

STIMER
BLYNK_WRITE(V47)  //STIMER1 TIME INPUT WIDGET
{
  unsigned long TotalSec = ((hour()*3600) + (minute()*60) + second()); //ACTUAL TOTAL TIME SINCE MIDNIGHT
  TimeInputParam t(param);      //TIME/DAY IMPUT FROM WIDGET
  int Shour = t.getStartHour();   //START HOUR VARIABLE
  int Smin = t.getStartMinute();  //START MINUTE VARIABLE
  int Ssec = t.getStartSecond();  //START SECOND VARIABLE
  int Ehour = t.getStopHour();    //END HOUR VARIABLE
  int Emin = t.getStopMinute();   //END MINUTE VARIABLE
  int Esec = t.getStopSecond();   //END SECOND VARIABLE
  int dayNum = weekday();         //DAYNUMBER VARIABLE
  int onDays = 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))
    {
      onDays++;
      if(i==dayNum)
      {
        Blynk.syncVirtual(V79);     //V79 IS THE ST1LED LED WIDGET..I WAS TRYING THIS TO SEE IF THIS WORKS..NOT SURE
        ST1LED.setColor(DBlue);     //ST1LED WIDGET TURNED ON TO DARK BLUE TO INDICATE THE TIMER IS ACTIVE
        ST1LED.on();
        if(t.hasStartTime())
        {
          ST1 = (Shour*3600) + (Smin*60) + Ssec;   //START TIME IN SECONDS
          if (TotalSec >= ST1)                     //COMPARE CURRENT TIME TO START TIME FROM TIME INPUT WIDGET
          {
            Blynk.syncVirtual(V79); //V79 IS THE ST1LED LED WIDGET..I WAS TRYING THIS TO SEE IF THIS WORKS..NOT SURE
            master_slave4.digitalWrite(D1, HIGH);   //TURN ON PIN ON MASTER_SLAVE4 BRIDGE
            ST1LED.setColor(Blue);                  //ST1LED WIDGET TURNED ON TO BLUE TO INDICATE D1 ON BRIDGE WIDGET IS ON
            ST1LED.on();
          }
        }
        if(t.hasStopTime())
        {
          ET1 = (Ehour*3600) + (Emin*60) + Esec;    //END TIME IN SECONDS
          if (TotalSec >= ET1)                      //COMPARE CURRENT TIME TO END TIME FROM TIME INPUT WIDGET
          {
            Blynk.syncVirtual(V79);                 //V79 IS THE ST1LED LED WIDGET..I WAS TRYING THIS TO SEE IF THIS WORKS..NOT SURE
            master_slave4.digitalWrite(D1, LOW);    //TURN OFF PIN ON MASTER_SLAVE4 BRIDGE
            ST1LED.off();
            ST1LED.setColor(DBlue);     //ST1LED WIDGET TURNED ON TO DARK BLUE TO INDICATE THE TIMER IS ACTIVE UNTIL NEXT DOSE WHICH WILL BE NEXT DAY
            ST1LED.on();
          }
        }
      }
      if (onDays == 0)      //IF NO DAYS ARE SELECTED
      {
        Blynk.syncVirtual(V79);
        master_slave4.digitalWrite(D1, LOW);  //ST1LED WIDGET TURNED OFF TO INDICATE THE TIMER IS INACTIVE
        ST1LED.off();
      }
    }
  }
}
MTIMER
BLYNK_WRITE(V51)            //TIME INPUT WIDGET    
{
  TimeInputParam t(param);
  int MThr = t.getStartHour();      //VARIABLE TO GET START TIME
  int MTmin = t.getStartMinute();
  int MTsec = t.getStartSecond();
  int MTday = weekday();
  int MTOnDays = 0;
  for (int i = 1; i <= 7; i++)  
  {
    if (t.isWeekdaySelected(i))
    {
      MTOnDays++;
      if(i==MTday && t.hasStartTime())
      {
        MT1S = (MThr*3600) + (MTmin*60) + MTsec;   //START TIME CONVERTED TO SECONDS
        MT1active = true;                          // MT1 IS ACTIVE TODAY
      }
    if (MTOnDays == 0)                            //NO DAYS SELECTED
    {
      //DO NOTHING
    }
  }
}
}

BLYNK_WRITE(V52)          //Doses/Day NUMERIC INPUT WIDGET 1-48 DOSES
{
  Doses1 = param.asInt();
}

BLYNK_WRITE(V53)        //Dose duration   NUMERIC INPUT WIDGET 3-120 SECONDS
{
  DoseTime1 = param.asInt();
}

BLYNK_WRITE(V54)        //Activate MTimer BUTTON WIDGET WICH CONTROLS THE ENTIRE FUNCTION
{
  switch1 = param.asInt();
  unsigned long TimeSeconds = (hour()*3600) + (minute()*60) + second(); //GET CURRENT TIME IN SECONDS
  if (switch1 == 1 && MT1active == true)    //IF SWITCH IS ON (1) AND MUTLITIMER1 IS ACTIVE - FROM TIME INPUT WIDGET
  {
    SetMTimer(MT1, TimeSeconds, MT1S, Doses1, DoseTime1);   //DOSE FUNCTION
  }
  else if (switch1 == 0)        //IF SWITCH IS OFF (0)
  {
    master_slave5.digitalWrite(D1, LOW);    //TURN BRIDGE PIN OFF
    Blynk.virtualWrite(V83, 0);
    MT1active = false;                  //NOT ACTIVE ANYMORE
  }
}
void SetMTimer(int pin,                     //Pin number
              unsigned long time,           //Current time in seconds
              unsigned long start,          //Start time in seconds
              int dose,                     //Doses/Day
              unsigned long doseTime)       //Dose duration
{
  if (time >= start)
  {
    unsigned long doseInt = ((time - start) + 86400 - (dose*doseTime) / dose);
    int MtimerState = LOW;
    if (Mtimer.check() == 1)        //THIS IS FROM THE METRO LIBRAY WHICH IS A TIMER LIBRARY
    {
      if (MtimerState == HIGH)
      {
        Mtimer.interval(doseTime);
        MtimerState = LOW;
      }
      else
      {
        Mtimer.interval(doseInt);
        MtimerState = HIGH;
      }
      master_slave4.digitalWrite(pin, !MtimerState);
      Blynk.virtualWrite(V83, MtimerState);
      Blynk.virtualWrite(V84, MtimerState);
      Blynk.virtualWrite(V85, MtimerState);
      Blynk.virtualWrite(V86, MtimerState);
    }
  }
}

Why not look at just using the timer widget?

The time input widget is literally that, a way of sending a start and stop time to your hardware. BLYNK_WRITE for that timer will only get called ONCE, that is when you press OK after inputting the times.

Also you would an RTC to keep track of current time and compare this against what you input using the Time Input Widget.

However,

With the timer widget, that will trigger BLYNK_WRITE (as you are wanting) when your specified time/day is active.

@JustBertC I did have the Timer widget before and that works just fine the only thing is you don’t have the option of choosing what days you want the timer to be active.

1 Like

@PeteKnight going back to your point about enabling and disabling Blynktimers… do you mean I put say for example a blynktimer BLYNK_WRITE(V54) which is the button widget , so as long as the button is ON(1) the blynktimer will be counting and as soon as the button is off stop the blynktimer?

You can do that if you wish. Read the documentation for Simpletimer to see what’s possible.

Pete.

Sorry mate, my mistake I thought I saw the days input on the timer widget just the other day - I was obviously wrong.

Edit: Are you using this on battery or deep sleep?

Edit 2: Or just implement the RTC widget and compare against your given times?

@JustBertC no battery. I am comparing against RTC values.

Unless you implemented both? Time input for days selection and timer for time? Or, I haven’t checked, but maybe time input could update the timer widget for you?

I will try

1 Like

Ok i have my 2 types of timers working. There is only 1 issue. When power is disconnected the timers sit in the Set state which is displayed via a LED widget with green colour. When in On state it should turn blue. When i go to the Time Input Widget and hit OK it reverts back into the correct mode ie if it should be on LED is blue and if it should be off LED is green. This is telling me I need force a syncvirtual of the Time Input Widget to somewhere. Any ideas anybody?

STANDARD TIMER on 1/day
/STIMER1////////////////////////////////////////////////////
BLYNK_WRITE(V87) //SWITCH 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());
  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.digitalWrite(D1, HIGH);
          ST1LED.setColor(Blue);
          ST1LED.on();
          Serial.println("ON");
        }
        else
        {
          if (STime1Update == false)
          STime1Update = true;
          master_slave4.digitalWrite(D1, LOW);
          ST1LED.setColor(Green);
          ST1LED.on();
          Serial.println("OFF");
        }
      }
    }
  }
}

Add it after you’ve connected to Blynk, or add a BLYNK_CONNECTED() callback function and put your syncVirtual in there.

Pete.

Thanks

A thought just occured I think I will add Blynk Not Connected situation in case of a disconnection…if 1 of the timers is dosing a chemical during the disconnection it should stop until reconnected…avoid overdosing something and doing damage to the aquarium

1 Like

@PeteKnight just to clarify, I read through the blynk documents you linked to…so
Blynk.syncAll syncs all the settings stored on the Blynk server and Blynk.syncVirtual syncs from my app back to the server. With that said should we not be Blynk.syncVirtual on all the widgets which handle data? Otherwise when does Blynk.syncAll gets its data?

Blynk.syncAll is a bit of a sledgehammer approach, and can cause issues, so it’s best avoided if you can.

What Blynk.syncVirtual(VPin) does is to force the server to push its current saved value back to the device.
So, if you used the app to set V10 to 27 then this is the value stored on the server. It doesn’t matter if the app isn’t connected, the value of “27” is still stored on the server.
Blynk.syncVirtual(V10) will force the server to push that value to the device, triggering the BLYNK_WRITE(V10) callback.

You only need to do this for values that are stored on the server and that need to be pulled-back to the device after a reboot.

Pete.

1 Like

Thanks for that. It is now clear.

1 Like

@PeteKnight sorry to bother you again… is there a maximum limit as how many virtual pins you can syncVirtual? I have removed the Blynk.syncAll and adopted the Blynk.syncVirtual and i have noticed that it takes very much longer to connect to the Blynk server, sometimes up to 5mins!

Post your code and details of what widgets are attached to each of the virtual pins, and why each of them is being synched.

Pete.