I’m trying to count the time that passes from turning a relay on

Hi guys,
I’m trying to use the same example to count the time that passes from turning a relay on.
The RTC is working but I don’t understand how to connect it to the “on” and “off”.
I want it to start from 0 when turning on the relay and stop when turning the relay off.

Can you please assist?

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

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "Token";

// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "ssid";
char pass[] = "pass";

BlynkTimer timer;
WidgetRTC rtc;

// Digital clock display of the time
void clockDisplay()
{
  // You can call hour(), minute(), ... at any time
  // Please see Time library examples for details

  String currentTime = String(hour()) + ":" + minute() + ":" + second();
  Serial.print("Current time: ");
  Serial.print(currentTime);
  Serial.print(" ");
  // Send time to the App
  Blynk.virtualWrite(V1, currentTime);
}
void setup()
{
Serial.begin(115200);
pinMode(0, OUTPUT);
pinMode(2, OUTPUT);
Blynk.begin(auth, ssid, pass);
rtc.begin();
// Display digital clock every 1 seconds
timer.setInterval(1000L, clockDisplay);
}
BLYNK_WRITE(V1)
{
int i=param.asInt();
if (i==1)
{
delay(300);
digitalWrite(0, HIGH);
digitalWrite(2, HIGH);
delay(1750); // delay 1000 = 1 sec
digitalWrite(0, LOW);
digitalWrite(2, LOW);
}
else
{
digitalWrite(0, LOW);
digitalWrite(2, LOW);
}
}

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

There are lots of ways to track time, a incremented counter every x amount of time, etc…

And using BlynkTimer and a timeout Timer, you can have a relay turn on with a button press and automatically turn off x amount of time later.

Please supply more details and show your (properly formatted - as per the Welcome Topic) code for further guidance.

simply keep the millis() in a variable when you start and subtract that from the millis() when it is turned off.

long starttime=millis();
.
.
.
Serial.println(millis() - starttime);

Thanks a lot for the prompt and detailed answers.
I’m using ESP8266 - 01 that I’m connecting directly to the relay.
I have combined the RTC sample with the one I have but don’t know how to make the condition and the time reset (I have a very poor coding skills)

.

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

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "Token";

// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "ssid";
char pass[] = "pass";

BlynkTimer timer;
WidgetRTC rtc;

// Digital clock display of the time
void clockDisplay()
{
  // You can call hour(), minute(), ... at any time
  // Please see Time library examples for details

  String currentTime = String(hour()) + ":" + minute() + ":" + second();
  Serial.print("Current time: ");
  Serial.print(currentTime);
  Serial.print(" ");
  // Send time to the App
  Blynk.virtualWrite(V1, currentTime);
}
void setup()
{
Serial.begin(115200);
pinMode(0, OUTPUT);
pinMode(2, OUTPUT);
Blynk.begin(auth, ssid, pass);
rtc.begin();
// Display digital clock every 1 seconds
timer.setInterval(1000L, clockDisplay);
}
BLYNK_WRITE(V1)
{
int i=param.asInt();
if (i==1)
{
delay(300);
digitalWrite(0, HIGH);
digitalWrite(2, HIGH);
delay(1750); // delay 1000 = 1 sec
digitalWrite(0, LOW);
digitalWrite(2, LOW);
}
else
{
digitalWrite(0, LOW);
digitalWrite(2, LOW);
}
}

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

Hi, OK!
@Gunner - I used the first code you added and it works!
The stopwatch start, stop and reset as I wanted.The only problem is that I want to see the time in live and not after I’m stopping it. I tried few things that I saw in the forums but I couldn’t find a way to do it.
I tried to use this:

Blynk.virtualWrite(V2, buf, 1000);

but it basically do nothing :slight_smile:

This is the new code:
Can you please help me figure it out?

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>


// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "token";

// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "ssid";
char pass[] = "pass";


int latchButton;
int latchFlag;
int runDays;
int runHours;
int secsRemaining;
int runMinutes;
int runSeconds;
char buf[21];
unsigned long startMillis;
unsigned long endMillis;
unsigned long allSeconds;


//===== Timeed latching button =====
BLYNK_WRITE(V1) {  // Button Widget set as switch
  latchButton = param.asInt();
  if (latchButton == 1 && latchFlag == 0) {
    latchFlag = 1;  // Keeps from allowing button press more then once while relay activated
    startMillis = millis();  // The key command for starting the count
    Blynk.virtualWrite(V2, buf, 1000); // Display Widget
    digitalWrite(0, HIGH); // Activate digital pin
    Serial.println(latchButton);
  }
    else{
      digitalWrite(0, LOW); // Deactivate digital pin
      Serial.println("off");
      Blynk.virtualWrite(V1, 0);  // Reset Latching Button to OFF
      latchFlag = 0;  // resets to allow next interaction
     endMillis = millis();  // The key command for ending the count
    // The key process for displaying the converted duration
    allSeconds = (endMillis - startMillis) / 1000;
    runDays = allSeconds / 86400;
    secsRemaining = allSeconds % 86400;
    runHours = secsRemaining / 3600;
    secsRemaining = allSeconds % 3600;
    runMinutes = secsRemaining / 60;
    runSeconds = secsRemaining % 60;
    sprintf(buf, "Duration: %02d H : %02d M : %02d S", runHours, runMinutes, runSeconds);
    Blynk.virtualWrite(V2, buf);  // Display Widget showing duration the Switch was 
    Serial.println(buf);
    }  // END Timer Function
  }
void setup()
{
Serial.begin(115200);
pinMode(0, OUTPUT);
pinMode(2, OUTPUT);
Blynk.begin(auth, ssid, pass);
}

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

You need to put the code that calculates the duration into a separate function, then set-up a timer to call that function - lets say once every second.

You wont get a perfect result, because there is lag in the process of sending the data to the server then to the app, so the seconds may jump forward several seconds at a time, but you should get a reasonable indication of how long the relay has been activated for.

Pete.

Thanks!
I’m totally fine with OK result :slight_smile:
Do you mean something like that?
I should add something in the setup() / loop()?

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <SimpleTimer.h>

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "token";

// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "ssid";
char pass[] = "pass";

BlynkTimer timer; 

int latchButton;
int latchFlag;
int runDays;
int runHours;
int secsRemaining;
int runMinutes;
int runSeconds;
char buf[21];
unsigned long startMillis;
unsigned long endMillis;
unsigned long allSeconds;

void TimeCalculator()
{
// The key process for displaying the converted duration
    allSeconds = (endMillis - startMillis) / 1000;
    runDays = allSeconds / 86400;
    secsRemaining = allSeconds % 86400;
    runHours = secsRemaining / 3600;
    secsRemaining = allSeconds % 3600;
    runMinutes = secsRemaining / 60;
    runSeconds = secsRemaining % 60;
    sprintf(buf, "Duration: %02d H : %02d M : %02d S", runHours, runMinutes, runSeconds);
}

//===== Timeed latching button =====
BLYNK_WRITE(V1) {  // Button Widget set as switch
  latchButton = param.asInt();
  if (latchButton == 1 && latchFlag == 0) {
    latchFlag = 1;  // Keeps from allowing button press more then once while relay activated
    startMillis = millis();  // The key command for starting the count
    TimeCalculator();
    digitalWrite(0, HIGH); // Activate digital pin
    Serial.println(latchButton);
  }
    else{
     digitalWrite(0, LOW); // Deactivate digital pin
     Serial.println("off");
     Blynk.virtualWrite(V1, 0);  // Reset Latching Button to OFF
     latchFlag = 0;  // resets to allow next interaction
     endMillis = millis();  // The key command for ending the count
    TimeCalculator(); 
    Serial.println(buf);
    }  // END Timer Function
  }
void setup()
{
Serial.begin(115200);
pinMode(0, OUTPUT);
pinMode(2, OUTPUT);
Blynk.begin(auth, ssid, pass);
}

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

Yes, but you’ve left-out the code that prints the elapsed time to the V2.
I’d put that at the end of your TimeCalculator() function.

You then need a timer to call this once every second.
You’ll need to define the timer, initialise it in your void setup, then include timer.run in your void loop.

Once you have that running then you should refine it a little.
You only want the elapsed time to be calculated and outputted to V2 if the timer is running, so your TimeCalculator() should have an ‘if’ statement which checks if the relay is actuated before doing the calculation of elapsed time and outputting the result.

Pete.

Thanks a lot Pete. I really appreciate your help :slight_smile:
I removed the prints from there and put it in the TimeCalculater(). I added

timer.setInterval(1000L, buf);

In the setup… I hope I did it right…?
I also added the timer.run() in the loop. I still don’t understand something. In the Blynk_Write function I added if and else with startMillis = millis(); and endMillis = millis(); to start the timer and stop it, I should create something similar in the TimeCalculater() as well?

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <SimpleTimer.h>

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "token";

// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "ssid";
char pass[] = "pass";

BlynkTimer timer; 

int latchButton;
int latchFlag;
int runDays;
int runHours;
int secsRemaining;
int runMinutes;
int runSeconds;
char buf[21];
unsigned long startMillis;
unsigned long endMillis;
unsigned long allSeconds;

void TimeCalculator()
{
// The key process for displaying the converted duration
    allSeconds = (endMillis - startMillis) / 1000;
    runDays = allSeconds / 86400;
    secsRemaining = allSeconds % 86400;
    runHours = secsRemaining / 3600;
    secsRemaining = allSeconds % 3600;
    runMinutes = secsRemaining / 60;
    runSeconds = secsRemaining % 60;
    sprintf(buf, "Duration: %02d H : %02d M : %02d S", runHours, runMinutes, runSeconds);
    Blynk.virtualWrite(V2, buf);  // Display Widget showing duration the Switch was 
}

//===== Timeed latching button =====
BLYNK_WRITE(V1) {  // Button Widget set as switch
  latchButton = param.asInt();
  if (latchButton == 1 && latchFlag == 0) {
    latchFlag = 1;  // Keeps from allowing button press more then once while relay activated
    startMillis = millis();  // The key command for starting the count
    TimeCalculator();
    digitalWrite(0, HIGH); // Activate digital pin
    Serial.println(latchButton);
  }
    else{
     digitalWrite(0, LOW); // Deactivate digital pin
     Serial.println("off");
     Blynk.virtualWrite(V1, 0);  // Reset Latching Button to OFF
     latchFlag = 0;  // resets to allow next interaction
     endMillis = millis();  // The key command for ending the count
    TimeCalculator(); 
    }  
  }
void setup()
{
Serial.begin(115200);
pinMode(0, OUTPUT);
pinMode(2, OUTPUT);
Blynk.begin(auth, ssid, pass);
// Display digital clock every 1 seconds
timer.setInterval(1000L, buf);
}

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

That makes no sense. The timer.setinterval command needs the frequency that a function is going to be called (1000ms in this case) and the name of the function that will be called.
Your function is TimeCalculator not buf

I’m slightly unsure about what TimeCalculator is supposed to be calculating. Without picking through the code in detail, it seems that you’re showing remaining time, not elapsed time. Is that correct?

Pete.

No, I want to present the elapsed time and it worked well but I wanted to see the elapsed time live and not only the calculation after I’m switching the button to off.

In that case, you need a function that will calculate the elapsed time and write it out to V2, and that function need to run every second.

The function will take the current millis and compare it to when the relay was activated (startMillis)

This will really make your current TimeCalculator function redundant, as when the relay is deactivated, the function will stop updating V2 (provided you used an ‘if’ statement as I suggested earlier).

My concern with your current code is that you’re using variable names like secsRemaining when in actual fact you aren’t using the code to calculate remaining time, just elapsed time.
You’d find it easier to follow when you re-write your code if you use meaningful variable names, and when you declare them add a comment like this:

int runDays;    // will hold the calculated number of elapsed whole days (the DD element of DD/HH/MM/SS display of time) since the relay was activated
int runHours;   //  will hold the calculated number of elapsed whole hours (the HH element of DD/HH/MM/SS display of time) since the relay was activated
int runMinutes; //  will hold the calculated number of elapsed whole minutes (the MM element of DD/HH/MM/SS display of time) since the relay was activated
int runSeconds; // will hold the calculated number of elapsed seconds (the SS element of DD/HH/MM/SS display of time) since the relay was activated

Pete.

Solved!
@PeteKnight I created the Time Calculator function like you suggested, changed few things and it worked! Thanks a lot for your help Pete!
Here is the code, in case someone is looking for something similar:

BlynkTimer timer; 

int latchButton;
int latchFlag;
int runHours;
int runMinutes;
int runSeconds;
int secsRemaining;
char buf[21];
unsigned long startMillis;
unsigned long endMillis;
unsigned long allSeconds;

//===== Timeed latching button =====
BLYNK_WRITE(V1) {  // Button Widget set as switch
  latchButton = param.asInt();
  if (latchButton == 1 && latchFlag == 0) {
    latchFlag = 1;  // Keeps from allowing button press more then once while relay activated
    digitalWrite(0, HIGH); // Activate digital pin
    Serial.println(latchButton); //Debug
  }
    else{
      digitalWrite(0, LOW); // Deactivate digital pin
      Serial.println("off"); //Debug
      Blynk.virtualWrite(V1, 0);  // Reset Latching Button to OFF
      latchFlag = 0;  // resets to allow next interaction
    }
  }

void ElapsedTime(){
  if (latchFlag == 1){ //When the button is active
    endMillis = millis(); //Start the counting from 0
    //The key process for displaying the converted duration
    allSeconds = (endMillis - startMillis) / 1000;
    secsRemaining = allSeconds % 86400;
    runHours = secsRemaining / 3600;
    secsRemaining = allSeconds % 3600;
    runMinutes = secsRemaining / 60;
    runSeconds = secsRemaining % 60;
    sprintf(buf, "Duration: %02d:%02d:%02d", runHours, runMinutes, runSeconds);
    Blynk.virtualWrite(V2, buf); // Display Widget
  }
   else{
    startMillis = millis();  // Stop the counting
   }
}

void setup()
{
Serial.begin(115200);
pinMode(0, OUTPUT);
pinMode(2, OUTPUT);
Blynk.begin(auth, ssid, pass);
// Display digital clock every 1 seconds
timer.setInterval(1000L, ElapsedTime);
}

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

Exactly was I was looking for @Natial and @PeteKnight .
Need a slight alteration.
I want the time to be cumulative. Count time while relay is HIGH, pause when relay is LOW, then start count again from paused time after relay is High and so forth.
What happens in the case of a disconnection from cloud?

Isn’t that what the code currently does?

The relay will stay in its current state and the counter will continue to run if the button widget was set to On at the point when the disconnection occurred.

I’m guessing from your comments/questions that you haven’t actually tried this code for yourself yet? The easiest way to learn is to experiment.

Pete.

Thank you @PeteKnight for the quick response.
I have tried the code on a Particle Photon and displaying the time the button is pressed in Blynk.
When button is pressed, time is displayed and counting.
After button is pressed again, time stops counting.
When pressing again, it goes back to zero and starts counting. Its not cumulative.

Try commenting-out this line then.

Pete.

Hi PeteKnight Sir,
I am a beginner and want to make home automation with four relays.
The above code works well for one-Relay count time. But I want to know how to write code for three-Relay. I try but fail to write code for more than one relay.

I am waiting for your kind support.

You will need two more versions of each of these variables, and you’ll need to use the new versions in the appropriate places.

Pete.

Hello Sir,
Thanks for your reply.

. . . . Can you write example code for two relay time duration count.