Is it possible to pause time?

Hi,

I am using the code below to display the current time on one line and a stopwatch on another line of an LCD screen.

When I press a button attacjed to D2 I want to pause the time (which it does) and when I press D2 again I want the time to carry on from where it left off (which it doesn't). Currently when I press D2 to carry on with the timer it resets the time to zero and starts counting.
What I would like to do is store the time in a variable when D2 is pressed and when D2 is pressed again it would take the stored variable time and add it to the zero count.
Is this possible and if so please could somebody help me with the code required to do this.

// include the library code:
#include <LiquidCrystal.h>
#include <Bounce2.h>
#include <Wire.h>
#include "RTClib.h"
RTC_DS1307 rtc;

// initialize the library by associating any needed LCD interface pin with the arduino pin number it is connected to
const int rs = 6, rw = 5, en = 4, d4 = 8, d5 = 9, d6 = 10, d7 = 11;

//LiquidCrystal(rs, rw, enable, d4, d5, d6, d7) 
LiquidCrystal lcd(rs, rw, en, d4, d5, d6, d7);

const byte ledPin = 13;
const byte startButton = 2;
// Initiate a Bounce object
Bounce startDebouncer1 = Bounce(); 

const byte resetButton = 3;
// Initiate another Bounce object
Bounce resetDebouncer2 = Bounce();  

void setup() { 
 lcd.begin(16, 2);
 
 Serial.begin(9600);
 if (! rtc.begin()) {
  Serial.println("Couldn't find RTC");
  while (1);
}
 //rtc.adjust(DateTime(__DATE__, __TIME__)); //this syncs the time to the computer
/*
 * 
 if (! rtc.isrunning()) {
  Serial.println("RTC is NOT running!");
  // following line sets the RTC to the date & time this sketch was compiled
  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  // This line sets the RTC with an explicit date & time, for example to set
  // January 21, 2014 at 3am you would call:
  // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
}
*/
// pinMode(LED_BUILTIN, OUTPUT); 
pinMode(ledPin, OUTPUT);
 pinMode(startButton, INPUT_PULLUP);
 // After setting up the button, setup the Bounce instance :
 startDebouncer1.attach(startButton);
 startDebouncer1.interval(5); // interval in ms
   
 pinMode(resetButton, INPUT_PULLUP);
 // After setting up the button, setup the Bounce instance :
 resetDebouncer2.attach(resetButton);
 resetDebouncer2.interval(5); // interval in ms

 // clear screen for the next loop:
 lcd.clear();
 
 lcd.setCursor(0, 0);
 lcd.print("Press Red Button");
 
}


bool startState = LOW;
bool resetState = LOW;

unsigned long startMillis;
unsigned long currentMillis;
unsigned long elapsedMillis;

void loop() {
  DateTime now = rtc.now();
  char dateBuffer[12];

  sprintf(dateBuffer,"%02u:%02u:%02u ",now.hour(),now.minute(),now.second());
  //Serial.println(dateBuffer);

 // Update the Bounce instances :
 startDebouncer1.update();

  if ( startDebouncer1.fell() ) {     // Call code if button transitions from HIGH to LOW
    startState = !startState;         // Toggle start button state
    startMillis = millis();
  }

 if (startState)
 {   lcd.clear();
   digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
   currentMillis = millis();
   elapsedMillis = (currentMillis - startMillis);
   lcd.setCursor(0, 0);
   lcd.print("Time ");
   lcd.print(dateBuffer);
   lcd.setCursor(0, 1);
   lcd.print("SW (hh:mm:ss:ms)");

   unsigned long durMS = (elapsedMillis%1000);       //Milliseconds
   unsigned long durSS = (elapsedMillis/1000)%60;    //Seconds
   unsigned long durMM = (elapsedMillis/(60000))%60; //Minutes
   unsigned long durHH = (elapsedMillis/(3600000));  //Hours
   durHH = durHH % 24; 

   String durMilliSec = timeMillis(durHH, durMM, durSS,durMS);

   lcd.setCursor(0, 1);
   lcd.print(durMilliSec); 
   delay(150);
 }
 
 resetDebouncer2.update();

 if (resetDebouncer2.fell())
 {
   resetState = HIGH;
 }

 if (resetState)
 {
    digitalWrite(LED_BUILTIN, LOW);   // turn the LED off (LOW is the voltage level)
   // clear screen for the next loop:
   lcd.clear();

   
   lcd.setCursor(0, 0);
   lcd.print("Press Red Button");
   
   lcd.setCursor(0, 1);
   lcd.print("Press A-Reset");

   delay(100);
   
   resetState = LOW;
 }
    
}

String timeMillis(unsigned long Hourtime,unsigned long Mintime,unsigned long Sectime,unsigned long MStime)
{
 String dataTemp = "";

 if (Hourtime < 10)
 {
   dataTemp = dataTemp + "0" + String(Hourtime)+ "h:";
 }
 else{
   dataTemp = dataTemp + String(Hourtime)+ "h:";
 }
 
 if (Mintime < 10)
 {
   dataTemp = dataTemp + "0" + String(Mintime)+ "m:";
 }
 else{
   dataTemp = dataTemp + String(Mintime)+ "m:";
 }
 
 if (Sectime < 10)
 {
   dataTemp = dataTemp + "0" + String(Sectime)+ "s:";
 }
 else{
   dataTemp = dataTemp + String(Sectime)+ "s:";
 }
 
 dataTemp = dataTemp + String(MStime);

 return dataTemp;
}

Thanks

To make it easy for people to help you please modify your post and use the code button </>
codeButton.png

so your code 
looks like this

and is easy to copy to a text editor. See How to use the Forum

Also please use the AutoFormat tool to indent your code consistently for easier reading.

Your code is too long for me to study quickly without copying to my text editor.

When your clock restarts you need to calculate the amount of time that elapsed while it was paused, Then to update the time you need to subtract that amount from the actual time whenever you want to update the display.

This will be much easier if you use a single number for the time representing (for example) the number seconds since some time in the past. Just convert that number to hours, minutes and seconds when it is needed for the display.

...R

//when you zero/start the stopwatch...
pausedMillis = 0;
....
//when you pause...
pauseStart = currentMillis;
....
//when you stop pausing...
pausedMillis += currentMillis - pauseStart;
....
//when you calculate elapsed time...
elapsedMillis = currentMillis - startMillis - pausedMillis;
....

Robin2:
To make it easy for people to help you please modify your post and use the code button </>
codeButton.png

so your code 

looks like this


and is easy to copy to a text editor. See [How to use the Forum](https://forum.arduino.cc/index.php?topic=148850.0) 

Also please use the AutoFormat tool to indent your code consistently for easier reading.

Your code is too long for me to study quickly without copying to my text editor.




When your clock restarts you need to calculate the amount of time that elapsed while it was paused, Then to update the time you need to subtract that amount from the actual time whenever you want to update the display.

This will be much easier if you use a single number for the time representing (for example) the number seconds since some time in the past. Just convert that number to hours, minutes and seconds when it is needed for the display.

...R

Hi, thanks for the advice and sorry for incorrectly posting. I have now updated.

Robin2:
When your clock restarts you need to calculate the amount of time that elapsed while it was paused, Then to update the time you need to subtract that amount from the actual time whenever you want to update the display.

This will be much easier if you use a single number for the time representing (for example) the number seconds since some time in the past. Just convert that number to hours, minutes and seconds when it is needed for the display.

...R

I don't want the clock to add the time that it missed while paused. I want it to take the time from when paused, i.e. paused at 10 seconds.
Then when D2 is pressed I want it to carry on
i.e. take the 10 seconds and next start at 11 seconds.
Thanks

mrmagoo2:
I don't want the clock to add the time that it missed while paused. I want it to take the time from when paused, i.e. paused at 10 seconds.

I know. What I suggested is a way to allow the time to continue as if there had been no pause.

Take a simple example. Suppose you stop the clock at 123 seconds and restart it when the real time has reached 231 seconds. The difference between those is 108 seconds. When the real time gets to 236 seconds (i.e. 5 seconds later) you want the re-started clock to show 128 seconds and 236 - 108 = 128.

...R

Juraj:
KitchenTimerClock/KitchenTimerClock/KitchenTimerClock.ino at master · JAndrassy/KitchenTimerClock · GitHub

Juraj:
KitchenTimerClock/KitchenTimerClock/KitchenTimerClock.ino at master · JAndrassy/KitchenTimerClock · GitHub

I will check that one out. Thank you

Robin2:
I know. What I suggested is a way to allow the time to continue as if there had been no pause.

Take a simple example. Suppose you stop the clock at 123 seconds and restart it when the real time has reached 231 seconds. The difference between those is 108 seconds. When the real time gets to 236 seconds (i.e. 5 seconds later) you want the re-started clock to show 128 seconds and 236 - 108 = 128.

...R

Oh, I see now.

Please could you help me by showing an example how this would work with my timer.
I am very new and still trying to learn

mrmagoo2:
Please could you help me by showing an example how this would work with my timer.

I'm not familiar with the RTC library. Perhaps you can post a link to the library documentation?

Does it have the ability to produce a time value that represents the number of seconds since some moment in the past?

...R

Is this the library documentation that you mean?
http://adafruit.github.io/RTClib/html/class_r_t_c___d_s1307.html

pcbbc:

//when you zero/start the stopwatch...

pausedMillis = 0;
....
//when you pause...
pauseStart = currentMillis;
....
//when you stop pausing...
pausedMillis += currentMillis - pauseStart;
....
//when you calculate elapsed time...
elapsedMillis = currentMillis - startMillis - pausedMillis;
....

How would this work in the current code?
I have tried your suggestion and I can't get it to work.
Thanks

Please post the entire sketch in which it doesn't work.

mrmagoo2:
Is this the library documentation that you mean?
RTClib: RTC_DS1307 Class Reference

It seems to be. However it's not clear to me what sort of result you get using the now() function. For example what do you see if your print the value that you get from the now() function? I don't have an RTC so I can't try it out.

...R

mrmagoo2:
How would this work in the current code?
I have tried your suggestion and I can't get it to work.
Thanks

Post the code that you tried. At least make a stab first.
It serves no purpose just us writing the code for you. You learn nothing that way.
If you don’t understand your current code, then I would respectfully suggest starting with some simpler examples and working up to more complex projects.

Robin2:
For example what do you see if your print the value that you get from the now() function? I don't have an RTC so I can't try it out.

...R

When I try Serial.println(now());
I receive error 'now' was not declared in this scope'

mrmagoo2:
When I try Serial.println(now());
I receive error 'now' was not declared in this scope'

Where is your definition for function now()?
Where did this function suddenly come from?
It’s not mentioned in any of the posts so far here, as far as I can see...

Print the result you got at the start of loop...

Serial.println(now);

Or get a new copy...

Serial.println(rtc.now());

Here goes, this seems to give some strange results and it's starting at 17 hours and sometimes pausing

// include the library code:
#include <LiquidCrystal.h>
#include <Bounce2.h>
#include <Wire.h>
#include "RTClib.h"
RTC_DS1307 rtc;
unsigned long pausedMillis;
unsigned long pauseStart;

// initialize the library by associating any needed LCD interface pin
// with the arduino pin number it is connected to
const int rs = 6, rw = 5, en = 4, d4 = 8, d5 = 9, d6 = 10, d7 = 11;

//LiquidCrystal(rs, rw, enable, d4, d5, d6, d7) 
LiquidCrystal lcd(rs, rw, en, d4, d5, d6, d7);

const byte ledPin = 13;
//int ledPin = 13;
const byte startButton = 2;
// Instantiate a Bounce object
Bounce startDebouncer1 = Bounce(); 

const byte resetButton = 3;
// Instantiate another Bounce object
Bounce resetDebouncer2 = Bounce();  

void setup() { 
  lcd.begin(16, 2);
  
  Serial.begin(9600);
  if (! rtc.begin()) {
   Serial.println("Couldn't find RTC");
   while (1);
   
 }

 // rtc.adjust(DateTime(__DATE__, __TIME__)); //this syncs the time to the computer
 /*
  * 
  if (! rtc.isrunning()) {
   Serial.println("RTC is NOT running!");
   // following line sets the RTC to the date & time this sketch was compiled
   rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
   // This line sets the RTC with an explicit date & time, for example to set
   // January 21, 2014 at 3am you would call:
   // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
 }
 */
 // pinMode(LED_BUILTIN, OUTPUT); 
  pinMode(ledPin, OUTPUT);
  pinMode(startButton, INPUT_PULLUP);
  // After setting up the button, setup the Bounce instance :
  startDebouncer1.attach(startButton);
  startDebouncer1.interval(5); // interval in ms
    
  pinMode(resetButton, INPUT_PULLUP);
  // After setting up the button, setup the Bounce instance :
  resetDebouncer2.attach(resetButton);
  resetDebouncer2.interval(5); // interval in ms

  // clear screen for the next loop:
  lcd.clear();
  
  lcd.setCursor(0, 0);
  lcd.print("Press Red Button");
  
}


bool startState = LOW;
bool resetState = LOW;

unsigned long startMillis;
unsigned long currentMillis;
unsigned long elapsedMillis;

void loop() {
   DateTime now = rtc.now();
   char dateBuffer[12];

   sprintf(dateBuffer,"%02u:%02u:%02u ",now.hour(),now.minute(),now.second());
   //Serial.println(dateBuffer);

  // Update the Bounce instances :
  startDebouncer1.update();

   if ( startDebouncer1.fell() ) {     // Call code if button transitions from HIGH to LOW
     startState = !startState;         // Toggle start button state
     startMillis = millis();
   }

  if (startState)
  {   lcd.clear();

    digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
    currentMillis = millis();
    //elapsedMillis = (currentMillis - startMillis);
     elapsedMillis = currentMillis - startMillis - pausedMillis;
    lcd.setCursor(0, 0);
    lcd.print("Time ");
    lcd.print(dateBuffer);
    lcd.setCursor(0, 1);
    lcd.print("hh:mm:ss:ms");
 
    unsigned long durMS = (elapsedMillis%1000);       //Milliseconds
    unsigned long durSS = (elapsedMillis/1000)%60;    //Seconds
    unsigned long durMM = (elapsedMillis/(60000))%60; //Minutes
    unsigned long durHH = (elapsedMillis/(3600000));  //Hours
    durHH = durHH % 24; 

    String durMilliSec = timeMillis(durHH, durMM, durSS,durMS);

    lcd.setCursor(0, 1);
    lcd.print(durMilliSec); 
    delay(150);
 pausedMillis += currentMillis - pauseStart;
  Serial.print(" pausedMillis");
Serial.println(pausedMillis);
 Serial.print(" elapsed Millis");
Serial.println(elapsedMillis);
  //when you zero/start the stopwatch...
//pausedMillis = 0;
//when you pause...
pauseStart = currentMillis;
  }
  
  resetDebouncer2.update();

  if (resetDebouncer2.fell())
  {
    resetState = HIGH;
  }

  if (resetState)
  {
     digitalWrite(LED_BUILTIN, LOW);   // turn the LED off (LOW is the voltage level)
    // clear screen for the next loop:
    lcd.clear();

    
    lcd.setCursor(0, 0);
    lcd.print("Press Red Button");
    
    lcd.setCursor(0, 1);
    lcd.print("Press A-Reset");

    delay(100);
    
    resetState = LOW;
  }
     
}

String timeMillis(unsigned long Hourtime,unsigned long Mintime,unsigned long Sectime,unsigned long MStime)
{
  String dataTemp = "";

  if (Hourtime < 10)
  {
    dataTemp = dataTemp + "0" + String(Hourtime)+ "h:";
  }
  else{
    dataTemp = dataTemp + String(Hourtime)+ "h:";
  }
  
  if (Mintime < 10)
  {
    dataTemp = dataTemp + "0" + String(Mintime)+ "m:";
  }
  else{
    dataTemp = dataTemp + String(Mintime)+ "m:";
  }
  
  if (Sectime < 10)
  {
    dataTemp = dataTemp + "0" + String(Sectime)+ "s:";
  }
  else{
    dataTemp = dataTemp + String(Sectime)+ "s:";
  }
  
  dataTemp = dataTemp + String(MStime);

  return dataTemp;
}

pcbbc:
Where is your definition for function now()?
Where did this function suddenly come from?
It’s not mentioned in any of the posts so far here, as far as I can see...

Print the result you got at the start of loop...

Serial.println(now);

Or get a new copy...

Serial.println(rtc.now());

Robin2:
It seems to be. However it's not clear to me what sort of result you get using the now() function. For example what do you see if your print the value that you get from the now() function? I don't have an RTC so I can't try it out.

...R

It was requested by Robin2.

mrmagoo2:
It was requested by Robin2.

I assumed you would know to do it like this (as with the other calls to the library such as rtc.adjust() )

Serial.println(rtc.now());

and when you do it like that what answer do you get?

...R