Function to run only once

This is what i have got this far

void relayON() {  
 if (flag1 == 0) { 
 flag1 = 1;  
        digitalWrite(TestLED2, LOW);
        delay(2000);
        digitalWrite(TestLED2, HIGH);
 }
}


void relayOFF() {  
 if (flag2 == 0) {
 flag2 = 1;  
         digitalWrite(TestLED3, LOW);
        delay(2000);
        digitalWrite(TestLED3, HIGH);
 }
}

And this is bit of the code of the scheduler that i have modified calling the function.

BLYNK_WRITE(V4)//Monday-Friday
{  
  if (mondayfriday==1) {         
    sprintf(Date, "%02d/%02d/%04d",  day(), month(), year());
    sprintf(Time, "%02d:%02d:%02d", hour(), minute(), second());
  
    TimeInputParam t(param);
  
    terminal.print("M-F Checked schedule 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("Monday-Friday ACTIVE today");
    terminal.flush();
    if (t.hasStartTime()) // Process start time
    {
      terminal.println(String("Start: ") + t.getStartHour() + ":" + t.getStartMinute());
      terminal.flush();
    }
    if (t.hasStopTime()) // Process stop time
    {
      terminal.println(String("Stop : ") + t.getStopHour() + ":" + t.getStopMinute());
      terminal.flush();
    }
    // Display timezone details, for information purposes only 
    terminal.println(String("Time zone: ") + t.getTZ()); // Timezone is already added to start/stop time 
  //  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("Day ") + 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("Monday-Friday STARTED at");
      terminal.println(String(" ") + t.getStartHour() + ":" + t.getStartMinute());
      terminal.flush();
      if(nowseconds <= startsecondswd + 90){    // 90s on 60s timer ensures 1 trigger command is sent
        digitalWrite(TestLED1, HIGH); // set LED ON
        Blynk.virtualWrite(V2, 1);
        relayON();
       
        // code here to switch the relay ON
      }      
    }
    else{
      terminal.println("Monday-Friday Device NOT STARTED today");
      terminal.flush();
   
    }
    stopsecondswd = (t.getStopHour() * 3600) + (t.getStopMinute() * 60);
    //Serial.println(stopsecondswd);  // used for debugging
    if(nowseconds >= stopsecondswd){
      digitalWrite(TestLED1, LOW); // set LED OFF
      Blynk.virtualWrite(V2, 0);
      terminal.print("Monday-Friday STOPPED at");
      terminal.println(String(" ") + t.getStopHour() + ":" + t.getStopMinute());
      terminal.flush();
      
        if(nowseconds <= stopsecondswd + 90){   // 90s on 60s timer ensures 1 trigger command is sent
        digitalWrite(TestLED1, LOW); // set LED OFF
        Blynk.virtualWrite(V2, 0);
        relayOFF();
        
        // code here to switch the relay OFF
      }              
    }
    else{
      if(nowseconds >= startsecondswd){  
        digitalWrite(TestLED1, HIGH); // set LED ON    test
        Blynk.virtualWrite(V2, 1);
        terminal.println("Monday-Friday is ON");
        terminal.flush();
        flag2 = 0;
        flag1 = 0;
       }          
    }
  }
  else{
    terminal.println("Monday-Friday INACTIVE today");
    terminal.flush();
    
    // nothing to do today, check again in 30 SECONDS time    
  }
  terminal.println();
  
}
}

i have called for the function

when i need the relay to be triggered. And again set the flag to 0 for future trigger. This idea is working fine for the OFF relay not for the ON relay. Because the code i have mention above loops every 10 sec when running and loops every 30 sec when idle, then the relays will keep clicking, which i dont want.

It will not turn on again until after the time has expired. if you use the functions I supplied.

It is turning on. Because it keeps checking every 30 sec whether to turn on the device or not. then it turns the relay on. If am not resetting the flag to 0, then first time it will work as it should. And the second time it wont. Because the flag will be set to 1.

I have placed the flag2 in place and is working fine. But the flag1 (the turn on relay flag) is the problem.

can you please help me achieve this ? Can you give me some example ?

the relayoff code resets the flag so that it can be turned on again. In the relay on code I have a timer set to call the relay off after 5 seconds If you do not want this action then delete the timer code.

It will then only be able to run the code again if you first call the relay off function.

Bro however as we are in the same loop and calling the relayoff function it will set the relayon flag to 0 and again when the loop happens the relay triggers. IF AM NOT WRONGā€¦because i tried this well before, and failed :tired_face:

why are you calling relay off and on in the same loop.

Because i want the same procedure to be carried out next time the schedule happensā€¦

I am not finding any other wayā€¦

You must figure out your logic before you can be helped.

yeah i have understood the logic. I think am not able to explain better here in words.

If there is no flags at all, the ON relay clicks every 10 sec till the scheduled period is ON. and once the Schedule is done the OFF relay clicks every 10 sec till the next schedule comes.

To eliminate this i used @Gunner flag idea, this works partially.

if i reset the device every time the flag idea works flawlessly !! But not when looping because i am not setting and reset to the flag.

Now when i am resetting the flag i need to do it a the loop itself !! Because next time the schedule happens it will reset the flag and work like the 1st time(just like the device was reset).

But as the loop happens every 10 sec the flag will get reset and trigger the relay.

Is there a way to accomplish this out side the loop ? (to reset the flag and keep it ready for the next schedule !!??)

use the time to set a schedule for the reset. Like reset every 24 hours or whatever you like.

what if it varies daily in between 24 hrs ???

In the code I supplied you can just change the timer event to reset the flag instead of turning the relay off

then use the flags as you have coded

Have it happen at a set time or at sun rise orā€¦

it is your logic not mine so you will need to figure out what the event is.

Yes!!! Need to figure that outā€¦ Right now i have tried many different ways. But not getting what i need.

Hi, so I understand, with the code you have, you have a desire to only run the ā€˜pumpā€™ during certain days of the week when you push a virtual button on your Blynk app?

You have a virtual LED on Blynk V2 pin?

So you push the button on your app (probably a button switch), it fires a 0 or 1 to Blynk V4 pin.
Depending on the day of the week it either ignores the input or it turns the pump on?

First off I would pull the bulk of the code out of the Blynk_Write routine and focus the Blynk_Write routine on collecting the change of state of the virtual pin V4. (though reading through things this is looking more like you want the program to run and then report back whatā€™s going on than have any real control over itā€¦ Which I think you may want to revise the approachā€¦

// Global variables (byte used as you are only carrying a single digit and could use bool as in true/false
    byte flag1 = 0;
    byte flag2 = 0;
byte PumpSwitch;

void relayOFF() {  
     if (flag2 == 0) {
       flag2 = 1;  
       flag1 = 0;       
       digitalWrite(TestLED3, LOW);
       delay(2000);
       digitalWrite(TestLED3, HIGH);
  }
}

  void relayON() {  
     if (flag1 == 0) { 
       flag1 = 1;  
       flag2 = 0;
            digitalWrite(TestLED2, LOW);
            delay(2000);
            digitalWrite(TestLED2, HIGH);
     }
    }

BLYNK_WRITE_DEFAULT() {  // Wider default routine that gives you scope to manage other pins.
byte BrequestPin = request.pin;   // Blynk update pin reported container
  for (auto i = param.begin(); i < param.end(); ++i) {   // Print all parameter values
    Serial.print(i.asString());  // so you can see the data come in
    if (BrequestPin == 4)  {    //  global variable  if (BrequestPin == BlynkPumpPin) 
        PumpSwitch = i;      // PumpSwitch global variable to carry the current switch value
        Serial.println();
        Serial.print("Data input from Blynk: V");
        Serial.print(request.pin);
        Serial.print(" Data received: ");
        Serial.print(PumpSwitch);
        Serial.println();
    }
  }
}

Routine returns you state of Blynk Switch

You could use two Blynk push buttons, one Green on V4 and a Red on V5 (set to push not switch)

Then you could carry PumpSwitchOn and PumpSwitchOff as global variables, and keep it simple to read and manage.

// Global variables (byte used as you are only carrying a single digit and could use bool as in true/false
byte flag1 = 0;
byte flag2 = 0;
byte PumpSwitchChange = 0;
byte LastPumpSwOn = 0;
byte LastPumpSwOff = 0; 

void relayOFF() {  
  if (flag2 == 0) {
    flag2 = 1;  // flag for pump turned off to stop it continuing to turn it off
    flag1 = 0;  // flag for pump turned on, if it's off, it can no longer be on
    digitalWrite(TestLED3, LOW);
    delay(2000);
    digitalWrite(TestLED3, HIGH);
  }
}

void relayON() {  
  if (flag1 == 0) { 
    flag1 = 1;  // flag for pump turned on to stop it continuing to turn it on
    flag2 = 0;  // flag for pump turned off, if it's on, it can no longer be off
    digitalWrite(TestLED2, LOW);
    delay(2000);
    digitalWrite(TestLED2, HIGH);
  }
}

BLYNK_WRITE_DEFAULT() {  // Wider default routine that gives you scope to manage other pins.
  byte BrequestPin = request.pin;   // Blynk update pin reported container
  for (auto i = param.begin(); i < param.end(); ++i) {   // Print all parameter values
    Serial.print(i.asString());  // so you can see the data come in
    if (BrequestPin == 4)  {    //  global variable  if (BrequestPin == BlynkPumpPin) 
      if (i !=0) { // filter out the 0 return of the push button and only capture the poistive push of the button
          if (LastPumpSwOn != i) { // if a change then setflag the change          
            PumpSwitchOn = i;      // PumpSwitch global variable to carry the current switch value
            Serial.println();
            Serial.print("Data input from Blynk: V");
            Serial.print(request.pin);
            Serial.print(" Data received: ");
            Serial.println(PumpSwitchOn);
            PumpSwitchChange = 1;
            LastPumpSwOn = PumpSwitchOn; // flag to stop the loop multiple triggers.
          }
       }
     }
    if (BrequestPin == 5)  {    //  global variable  if (BrequestPin == BlynkPumpPin) 
      if (i !=0) { // filter out the 0 return of the push button and only capture the poistive push of the button
        if (LastPumpSwOff != i) { // if a change then setflag the change          
          PumpSwitchOff = i;      // PumpSwitch global variable to carry the current switch value
          Serial.println();
          Serial.print("Data input from Blynk: V");
          Serial.print(request.pin);
          Serial.print(" Data received: ");
          Serial.println(PumpSwitchOff);
          PumpSwitchChange = 1;
          LastPumpSwOff = PumpSwitchOff; // flag to stop the loop multiple triggers.
        }
      }
    }
  }
}

Routine returns you state of Blynk buttons on V4 and V5 if pushed in variables PumpSwitchOn and PumpSwitchOff.

The following routing is used to determine is your pump turns on (pretty much your existing code)

(This will turn the pump on or off based on your time settings and not from Blynk input. (Being it inā€™s own routine may break the Blynk terminal reporting you are looking for)

void PumpRunTimerRoutine() //Monday-Friday {  
      if (mondayfriday==1) {   

// I think this if statement is in the wrong place, you need the day data before checking if it is Monday to Friday

    sprintf(Date, "%02d/%02d/%04d",  day(), month(), year());

  sprintf(Time, "%02d:%02d:%02d", hour(), minute(), second());
  
    TimeInputParam t(param);
  
    terminal.print("M-F Checked schedule 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 start week on Sun, Blynk on Mon
terminal.println("Monday-Friday ACTIVE today");
terminal.flush();
if (t.hasStartTime()) // Process start time
{
  terminal.println(String("Start: ") + t.getStartHour() + ":" + t.getStartMinute());
  terminal.flush();
}
if (t.hasStopTime()) // Process stop time
{
  terminal.println(String("Stop : ") + t.getStopHour() + ":" + t.getStopMinute());
  terminal.flush();
}
// Display timezone details, for information purposes only 
terminal.println(String("Time zone: ") + t.getTZ()); // Timezone is already added to start/stop time 
  //  terminal.println(String("Time z`Preformatted text`one 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("Day ") + 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("Monday-Friday STARTED at");
  terminal.println(String(" ") + t.getStartHour() + ":" + t.getStartMinute());
  terminal.flush();
  if(nowseconds <= startsecondswd + 90){    // 90s on 60s timer ensures 1 trigger command is sent
    digitalWrite(TestLED1, HIGH); // set LED ON
    Blynk.virtualWrite(V2, 1);
    relayON(); // Call the routine to turn the pump off
  }      
}
    else{
      terminal.println("Monday-Friday Device NOT STARTED today");
      terminal.flush();
    }
    stopsecondswd = (t.getStopHour() * 3600) + (t.getStopMinute() * 60);
    //Serial.println(stopsecondswd);  // used for debugging
    if(nowseconds >= stopsecondswd){
      digitalWrite(TestLED1, LOW); // set LED OFF
      Blynk.virtualWrite(V2, 0);
      terminal.print("Monday-Friday STOPPED at");
      terminal.println(String(" ") + t.getStopHour() + ":" + t.getStopMinute());
      terminal.flush();
        if(nowseconds <= stopsecondswd + 90){   // 90s on 60s timer ensures 1 trigger command is sent
        digitalWrite(TestLED1, LOW); // set LED OFF
        Blynk.virtualWrite(V2, 0);
        relayOFF();   // Call the routine to turn the pump off
      }              
    }
    else{
      if(nowseconds >= startsecondswd){  
        digitalWrite(TestLED1, HIGH); // set LED ON    test
        Blynk.virtualWrite(V2, 1);
        terminal.println("Monday-Friday is ON");
        terminal.flush();
       }          
    }
  }
  else{
    terminal.println("Monday-Friday INACTIVE today");
    terminal.flush();
  }
  terminal.println();
}

void loop() {
  timer.run();
  Blynk.run();
  if (!flag1 && !flag2) { // if both flags 0 pump off and neither is set, go set one of them.
    PumpRunTimerRoutine() ;
  }
  if (PumpSwitchChange) { // If there has been a change in button state from Blynk
    if (flag2 && PumpSwitchOn) { // if flag2 is 1 it means it is off, and pump switch on can run
      relayOn();
      LastPumpSwOff = 0; // Resetting the Blynk routine to allow an off to process
      PumpSwitchChange = 0; //Resetting the switch change to stop unnecessary looping.
    } 
    else if (flag1 && PumpSwitchOff) { // if flag1 is 1 it means it is on, and pump switch off can run
       relayOff();
       LastPumpSwOn = 0; // Resetting the Blynk routine to allow an on to process
       PumpSwitchChange = 0; //Resetting the switch change to stop unnecessary looping.
    } 
  }
}

Hope that helps, or gives you a bunch of ideasā€¦ :wink:

@jhale716
Thank you giving me such a good idea to go with.

After going through your ideas i got a crude idea !!! (may be dumb and may not work)

The Bit code i have given above will loop every 10 sec and the relay clicks every 10 sec > this was the problem !!

So now what am thinking is >>> As the TestLED1 is constantly On during the Device ON stage , can i read the state of the TestLED1 and accordingly set flag to hold the repeated trigger ??

Can this be done ? This is a crude method yet simple. But i am not sure i can get it right or not !!

Can you please tell me how to achieve the above stated idea !!

Thank you in advanceā€¦

int flag1 = 0;

void relayON() {  
 if (flag1 == 0) { 
 flag1 = 1;  
        digitalWrite(TestLED2, LOW);
         timer.setTimeout(2000L, []() {  // Run once after 2 seconds
       digitalWrite(TestLED2, HIGH);
         });  // END Timer Function
        
 }
}


void relayOFF() {  
 if (flag1 == 1) {
 flag1 = 0;  
         digitalWrite(TestLED3, LOW);
        timer.setTimeout(2000L, []() {  // Run once after 2 seconds
       digitalWrite(TestLED3, HIGH);
         });  // END Timer Function
 }
}

It may be helpful to post your current full code. With all the edits above it is impossible to tell what version/edit you are using.

Or maybe try increasing the timer interval for the schedule check from 10 seconds to 60 seconds. It may introduce some slight lag as to when the pump actually turns off/on. But it will make the if(nowseconds <= startsecondswd + 90){ // 90s on 60s timer ensures 1 trigger command is sent
statement work.

I suspect with the 10 second interval it fires the relay about 6 times, then stops.

timer.setInterval(60000L, activetoday);  // check every 60 SECONDS if schedule should run today 

YESSSSSS !!! Finally someone understood my problem !!!

How to eliminate that repeated trigger ? I tried many ways !! But failing badly !!!