Stopwatch help

I'm trying to write a program for a stopwatch. I've looked at the stopwatch tutorial and browsed the forum posts that might help, but haven't come across anything extremely useful.

Basically, I have an LCD display that I want to use to display the time before a liquid reservoir is empty. The flow out of the reservoir can be turned off and on. How can I "pause" a timer?

Use a variable that remembers whether the program is allowed to decrement the timer or not.

Change:
Time--;

...To
if(CountingEnabled == True) Time--;

Or, even simpler:
time -= decrement;
where "decrement" is either one or zero.

Would I still use the millis() function? I’m trying to have a timer start when a certain button is pressed and then pause if certain conditions are met, and then continue when something changes. Doing the decrement doesn’t map to a certain measure of time, does it?

What if I were to have something like:

unsigned long time, prevTime;
int timer;                   //use timer as whether or not the timer is active

time = millis();
if (time - prevTime <= 0) {
  if (timer == 1) {  
    stopwatch++;
    prevTime = time;
  } 
}

Assumptions:

You have a timer running

The timer is counting from a starting time back to 0


What we were trying to say is that you can check to see if the "on condition" is there before decrementing the timer.

(Grove has a more subtle, but awesome way of doing it)

If you are having trouble understanding what we are saying, you can post your code, and we will tell you how to do it with your code.

:slight_smile:

thanks for your help!
here’s the code I have right now. it’s a couple of functions in my program that do the time calculations:

//prints elapsed time
void LCD_printETime() {
  totalSeconds = (millis() - pumpStartTime)/1000;
  long Eminutes = floor(totalSeconds/60);
  long Eseconds = floor(totalSeconds - (Eminutes*60));
  //print values to lcd
  lcd.setCursor(0,0);
  lcd.print("Time Elapsed: ");
  lcd.print(Eminutes);
  lcd.print(":");
  if (Eseconds < 10) {
    lcd.print(0);
  }
  lcd.print(Eseconds);
}

void LCD_printDTime(int Dmins, int Dsecs) {
  //Time until death
  totalSeconds_D = (Dmins*60) + Dsecs + (endTime-curTime) + int(secsTourn);
  lcd.setCursor(0,1);
  lcd.print("Dead In: ");
  int Dminutes = floor(totalSeconds_D/60);
  int Dseconds = floor(totalSeconds_D - (Dminutes*60));
  if ((Dminutes < 1) && (Dseconds < 0)) {
    lcd.print("-");
    totalSeconds_D = (-1)*totalSeconds_D;
    Dminutes = floor(totalSeconds_D/60);
    Dseconds = floor(totalSeconds_D - (Dminutes*60));
  }
  //Print values to lcd
  lcd.print(Dminutes);
  lcd.print(":");
  if (Dseconds < 10) {
    lcd.print(0);
  }
  lcd.print(Dseconds);
  lcd.print("     ");
}

void calcBloodVol() {
  //check which tourns are successful
  int Rsuccess;
  int Lsuccess;
  if (tournL >= tournThreshold) {
    Lsuccess = 1;
  }
  else if (tournL < tournThreshold) {
    Lsuccess =0;
  }
  if (tournR >= tournThreshold) {
    Rsuccess = 1;
  }
  else if (tournR < tournThreshold) {
    Rsuccess =0;
  }
  //find elapsed time
  int ElapsedSeconds = (millis() - pumpStartTime)/1000;
  if (ElapsedSeconds-prevTime >= 1) {
    //if no tourniquets...
    if ((Lsuccess == 0) && (Rsuccess == 0)) {
      bloodVol = bloodVol + flowRate;
      minutesD = 2;
      secondsD = 13;
      curTime = (millis() - pumpStartTime)/1000;
    }
    //if L tourniquet...
    else if ((Lsuccess == 1) && (Rsuccess == 0)) {
      bloodVol = bloodVol + RflowRate;
      minutesD = 2;
      secondsD = 52;
      secsTourn = secsTourn + (37/133);
      curTime = (millis() - pumpStartTime)/1000;
    }
    //if right tourniquet...
    else if ((Lsuccess == 0) && (Rsuccess == 1)) {
      bloodVol = bloodVol + LflowRate;
      minutesD = 2;
      secondsD = 50;
      secsTourn = secsTourn + (40/133);
      curTime = millis() - pumpStartTime;
    }
    //if this is true, timer pauses
    else if ((Lsuccess == 1) && (Rsuccess == 1)) {
      //print blanks or "infinite", etc.
      minutesD = 30101;
      secondsD = 30101;
    }
  }
  prevTime = ElapsedSeconds;
}

Sorry about the late reply.

I see where you confusion came from, being that you have made the program in a different way.

A quick way of "Stopping" the time for the pump is:

->When the program is stopped, record the millis() value,
->Don't updated time on LCD when paused,
->When program starts, record the millis() value,
->You can then calculate the time which the program had stopped (start time - stop time),
->If you add the stop time to the variable "pumpStartTime", it's like the program started later.

Tell me how it goes :slight_smile:

Thanks for the ideas! Now, this looks like it'll work if the timer is only paused once. In order to pause it multiple times, couldn't you just use that method and add a variable that gets the "paused time" data added to it?

Well if you add the stopped time to the variable "pumpStartTime" and start the program again, there is no reason why you can't do it time and time again!

This is a simple example on how it works (please ignore the unrealistic numbers)

pumpStartTime = 0;

->time is measured and calculated from millis - pumpStartTime

->program stopped at let's say 4 (time = 4)
->program started at 6
->therefore stopped time = 2
pumpStartTime += stopped time
->pumpStartTime is then set to 2
(time = 6 - 2 = 4)

time is then millis - 2 (so the added time gets cancelled out.)

if you do it again at time = 10

->program stopped at 10 (millis = 12)
->program started at 14
->therefore stopped time = 4
pumpStartTime += stopped time
->pumpStartTime is then set to 6
(time = millis(which is now 16) - 6 = 10)

:slight_smile:

Thank you so much! That makes so much sense! ;D

Okay, I’m having some trouble. My stopped time variable doesn’t do what I want it to. Sometimes it will decrease instead of increase. Any help would be helpful. Here’s what I have:

void calcBloodVol() {
  //check which tourniquets are successful
  int Rsuccess;
  int Lsuccess;
  if (tournL >= tournThreshold) {
    Lsuccess = 1;
  }
  else if (tournL < tournThreshold) {
    Lsuccess =0;
  }
  if (tournR >= tournThreshold) {
    Rsuccess = 1;
  }
  else if (tournR < tournThreshold) {
    Rsuccess =0;
  }
  //find elapsed time
  int ElapsedSeconds = (millis() - pumpStartTime)/1000;
  if ((ElapsedSeconds-curTime >= 1) && (bloodPump == 1)) {
    //if no tourniquets...
    if ((Lsuccess == 0) && (Rsuccess == 0)) {
      bloodVol = bloodVol + flowRate;
      minutesD = 2;
      secondsD = 13;
      curTime = (millis() - pumpStartTime)/1000;
      if (bloodCount == 2) {
        pumpStartTime = pumpStartTime + (curTime-endTime);
      }
      bloodCount = 1;
    }
    //if L tourniquet...
    else if ((Lsuccess == 1) && (Rsuccess == 0)) {
      bloodVol = bloodVol + RflowRate;
      minutesD = 2;
      secondsD = 52;
      curTime = (millis() - pumpStartTime)/1000;
      if (bloodCount == 2) {
        stoppedTime = stoppedTime + (curTime - endTime);
      }
      bloodCount = 1;
    }
    //if right tourniquet...
    else if ((Lsuccess == 0) && (Rsuccess == 1)) {
      bloodVol = bloodVol + LflowRate;
      minutesD = 2;
      secondsD = 50;
      curTime = (millis() - pumpStartTime)/1000;
      if (bloodCount == 2) {
        stoppedTime = stoppedTime + (curTime - endTime);
      }
      bloodCount = 1;
    }
    //if both tourniquets (bloodVol = bloodVol)
    else if (((Lsuccess == 1) && (Rsuccess == 1)) && (bloodCount == 1)) {
      //print blanks or "infinite", etc.
      bloodCount = 2;
      endTime = (millis() - pumpStartTime)/1000 + stoppedTime;    //secs
    }
  }
}
totalSeconds_Death = (Dmins*60) + Dsecs - totalSeconds + stoppedTime;

totalSeconds_Death is the value I’m printing to the LCD screen

Hey there, sorry for the late reply!

I'm having trouble going through your code, and was wondering if you could:

  1. Go through your code and write pseudo for each stage (making sure that you don't miss anything). Basically saying what you think the values should be; what the block is trying to achieve, and try to use what a variable means instead of the name.

  2. Go though and tell me what each variable is.

This will help you sort out the logic behind it.

Some quick note though:
ElapsedSeconds should be "unsigned long" not int (as any value with accepting data from millis() )

"endTime = (millis() - pumpStartTime)/1000 + stoppedTime; "

The idea was each time you stopped, you added it to "pumpStartTime", so that you no longer had to worry about it. I'm assuming that you did divide stoppedTime by 1000?....

"totalSeconds_Death = (Dmins*60) + Dsecs - totalSeconds + stoppedTime; "
... Look, I have no idea what you are doing here. You seem to have lots of variables and I can't see what is going into them.

Once again; I'm really sorry that I missed your reply.

:slight_smile: