How to pause time count in MillisCounterUp?

Hello All,

Well, this is my first post, and English is not my mother language so please forgive me if i made lot of mistakes.

I was trying to make a Running Hour monitoring for my house water pump, but still lack of programming skill, and i thought the best approach is to start from example, figuring how it work, and try to modify it to meet my purpose, one function at a time.
So i start from Library Example made by XbergCode and modifying the Start/Stop Counting Time using switch.
but here's my problem start: when i turn off the switch the time wasn't paused, instead it continue to count in the background and when i turn the switch back ON, the value printed in Serial Monitor was kinda "jumped"
heres the code (my modification is only in void runTheCountUp1() under // Simulate Something Turning On / Off)

//    FILE: MillisCounter_Up.ino
//  AUTHOR: XbergCode
// VERSION: 1.0.0
// PURPOSE: Arduino library to count up and down time using the millis() function.
//     URL: https://github.com/XbergCode/MillisCounter


// Millis Counter Library
#include <MillisCounter.h>  // Millis Counter Library
MillisCounter countUp;      // Set The Call Name
// Global Time String
//char countUp_Str[38] = "No Time"; // 100.Y, 10.M, 10.D, 10.h, 10.m, 10.sec = 37.Characters


void setup() {
  pinMode(2, INPUT_PULLUP);
  Serial.begin(115200UL);                                  // Start The Serial
  delay(500);                                              // Give Serial Time To Wake Up
  Serial.println(F("\nSketch Purpose: Millis Counter."));  // Serial Print Sketch Purpose
  Serial.print(F("Version: "));
  Serial.println(MILLISCOUNTER_VERSION);

  // Run Count Up Timer
  bool runTheCounter = true;                    // Bool For The Counter Status
  countUp.getCountUp();                         // Run The Counter
  delay(412UL);                                 // Delay For Some Time
  Serial.println(countUp.getCountUp());         // Print The Count Up Time
  countUp.reset();                              // Reset The Counter
  runTheCounter = countUp.isRunning();          // Get And Set The Counter Running Status
  Serial.print(F("Counter Bool State: "));      // Serial Print Counter State
  if (runTheCounter) Serial.println(F("On."));  // Counter Is On
  else Serial.println(F("Off."));               // Counter Is Off
}

void loop() {
  // Count Up
  runTheCountUp1();  // Run The Count Up Function
  // runTheCountUp2();              // Run The Count Up Function
  // runTheCountUp_Custom();        // Get The Count Up Time - Make Custom Output String

  delay(10);  // Slow Down A Bit
}


// Count Up Function 1 - Max: 4294967295.sec = 136.years, 70.days, 6.hours, 28.min, 15.sec (49710.days)
void runTheCountUp1() {  // Run The Count Up Function
  // Local Variables
  MillisCounter countUp1;            // Set The Call Name
  const uint32_t MILLIS = millis();  // Get The Millis Once Per Run
  char countUp_Str[38] = "Empty";    // Local Buffer For The Time String

  // Simulate Something Turning On / Off
  static bool runTheCounter = false;  // Start/Stop The Counter

  // Turning Counter On / Off
  if (digitalRead(2) == HIGH) {  // Switch OFF Position
    runTheCounter = false;       // Stop the Counter
  }
  if (digitalRead(2) == LOW) {  // Switch ON Position
    runTheCounter = true;       // Counter Is Off - Start The Counter
    // Get And Print The Time
    const uint32_t Function_Time = 1000UL;           // Run The Function Every X Seconds
    static uint32_t Function_Wait = 0UL;             // Keep Track Of The Time
    if (MILLIS - Function_Wait >= Function_Time) {   // Wait For Timeout
      Function_Wait = MILLIS;                        // Keep Track Of The Time
      if (runTheCounter) {                           // If The Counter Is On
        strcpy(countUp_Str, countUp1.getCountUp());  // Make The Time String
        // Serial Print The Time
        Serial.print(F("Run Time 1: "));
        Serial.println(countUp_Str);
      }
    }
  }
}

// Count Up Function 2
void runTheCountUp2() {  // Run The Count Up Function
  // Local Variables
  MillisCounter countUp2;            // Set The Call Name
  const uint32_t MILLIS = millis();  // Get The Millis Once Per Run
  char countUp_Str[38] = "Empty";    // Local Buffer For The Time String

  // Simulate Something Turning On / Off
  const uint32_t RunTheTimerForX = 1000UL * 12UL;  // Run The Function Every X Seconds
  static uint32_t RunTheTimer_Wait = MILLIS;       // Keep Track Of The Time
  static bool runTheCounter = true;                // Start/Stop The Counter

  // Simulate Something Turning On / Off
  if (MILLIS - RunTheTimer_Wait >= RunTheTimerForX) {  // Wait For Timeout
    RunTheTimer_Wait = MILLIS;                         // Keep Track Of The Time

    // Stop The Counter < "Like if some light turns off"
    if (runTheCounter) {  // Counter Is On - Stop The Counter

      runTheCounter = false;  // Stop The Counter
      //runTheCounter = countUp2.isRunning();                    // Get And Set The Counter Running Status
      Serial.println(F("Counter Was Turned Off."));  // Serial Print
    }

    // Start The Counter < "Like if some light turns on"
    else
      runTheCounter = true;  // Counter Is Off - Start The Counter
  }

  // Get And Print The Time
  const uint32_t Function_Time = 1000UL;                      // Run The Function Every X Seconds
  static uint32_t Function_Wait = 0UL;                        // Keep Track Of The Time
  if (MILLIS - Function_Wait >= Function_Time) {              // Wait For Timeout
    Function_Wait = MILLIS;                                   // Keep Track Of The Time
    if (runTheCounter) {                                      // If The Counter Is On
      strcpy(countUp_Str, countUp2.getCountUp());             // Make The Time String
      const uint32_t _tSeconds = countUp2.getTotalSeconds();  // Get The Total Seconds (0-4294967295)
      // Serial Print The Time
      Serial.print(F("Run Time 2: "));
      Serial.println(countUp_Str);
      Serial.print(F("Run Time 2 Total Seconds: "));
      Serial.println(_tSeconds);
    }
  }
}

// Count Up Function Custom Output String
void runTheCountUp_Custom() {  // Run The Count Up Function
  // Local Variables
  MillisCounter countUpCustom;       // Set The Call Name
  const uint32_t MILLIS = millis();  // Get The Millis Once Per Run
  char countUp_Str[38] = "Empty";    // Local Buffer For The Time String

  // Simulate Something Turning On / Off
  const uint32_t RunTheTimerForX = 1000UL * 13UL;  // Run The Function Every X Seconds
  static uint32_t RunTheTimer_Wait = MILLIS;       // Keep Track Of The Time
  static bool runTheCounter = true;                // Start/Stop The Counter

  // Simulate Something Turning On / Off
  if (MILLIS - RunTheTimer_Wait >= RunTheTimerForX) {  // Wait For Timeout
    RunTheTimer_Wait = MILLIS;                         // Keep Track Of The Time

    // Stop The Counter < "Like if some light turns off"
    if (runTheCounter) {      // Counter Is On - Stop The Counter
      countUpCustom.reset();  // Reset The Counter
      runTheCounter = false;  // Stop The Counter
      //runTheCounter = countUpCustom.isRunning();               // Get And Set The Counter Running Status
      Serial.println(F("Counter Was Turned Off."));  // Serial Print
    }

    // Start The Counter < "Like if some light turns on"
    else
      runTheCounter = true;  // Counter Is Off - Start The Counter
  }

  // Get And Print The Time
  const uint32_t Function_Time = 1000UL;          // Run The Function Every X Seconds
  static uint32_t Function_Wait = 0UL;            // Keep Track Of The Time
  if (MILLIS - Function_Wait >= Function_Time) {  // Wait For Timeout
    Function_Wait = MILLIS;                       // Keep Track Of The Time
    if (runTheCounter) {                          // If The Counter Is On
      // Call The Count Up Function
      countUpCustom.getCountUp();  // Call The Count Up Function
      // Variables For The Custom String
      const uint8_t _seconds = countUpCustom.getSeconds();         // Get Seconds (0-59)
      const uint8_t _minutes = countUpCustom.getMinutes();         // Get Minutes (0-59)
      const uint8_t _hours = countUpCustom.getHours();             // Get Hours   (0-23)
      const uint8_t _days = countUpCustom.getDays();               // Get Days    (0-31)
      const uint8_t _months = countUpCustom.getMonths();           // Get Months  (0-11)
      const uint8_t _years = countUpCustom.getYears();             // Get Years   (0-136)
      const uint16_t _tDays = countUpCustom.getTotalDays();        // Get Total Days (0-49710)
      const uint32_t _tSeconds = countUpCustom.getTotalSeconds();  // Get The Total Seconds (0-4294967295)

      // Make The Time String
      if (_years == 0U) {  // Run Time Is Less Than One Year
        if (_seconds == 0U && _minutes == 0U && _hours == 0U && _days == 0U && _months == 0U)
          sprintf_P(countUp_Str, PSTR("%u.sec"), _seconds);
        else if (_minutes == 0U && _hours == 0U && _days == 0U && _months == 0U)
          sprintf_P(countUp_Str, PSTR("%u.sec's"), _seconds);
        else if (_minutes == 1U && _hours == 0U && _days == 0U && _months == 0U)
          sprintf_P(countUp_Str, PSTR("%u.min, %u.sec"), _minutes, _seconds);
        else if (_minutes >= 2U && _hours == 0U && _days == 0U && _months == 0U)
          sprintf_P(countUp_Str, PSTR("%u.min's, %u.sec"), _minutes, _seconds);
        else if (_hours >= 1U && _days == 0U && _months == 0U)
          sprintf_P(countUp_Str, PSTR("%u.h, %u.min, %u.sec"), _hours, _minutes, _seconds);
        else if (_days == 1U && _months == 0U)
          sprintf_P(countUp_Str, PSTR("%u.D, %u.h, %u.min, %u.sec"), _days, _hours, _minutes, _seconds);
        else if (_days >= 2U && _months == 0U)
          sprintf_P(countUp_Str, PSTR("%u.D's, %u.h, %u.min, %u.sec"), _days, _hours, _minutes, _seconds);
        else if (_months >= 1U)
          sprintf_P(countUp_Str, PSTR("%u.M, %u.D, %u.h, %u.min, %u.sec"), _months, _days, _hours, _minutes, _seconds);
      } else  // Run Time Is More Than One Year
        sprintf_P(countUp_Str, PSTR("%u.Y, %u.M, %u.D, %u.h, %u.m, %u.sec"), _years, _months, _days, _hours, _minutes, _seconds);

      // Serial Print The Time
      Serial.print(F("Run Time Custom: "));
      Serial.println(countUp_Str);
      Serial.print(F("Run Time. Total Days: "));
      Serial.println(_tDays);
      Serial.print(F("Run Time. Total Seconds: "));
      Serial.println(_tSeconds);
    }
  }
}


// End Of File.

and here's what printed in my Serial Monitor:

Sketch Purpose: Millis Counter.
Version: 1.0.0

413.milliseconds
Counter Bool State: Off.

Run Time 1: 0.milliseconds
Run Time 1: 1.seconds
Run Time 1: 2.seconds
Run Time 1: 3.seconds
Run Time 1: 6.seconds
Run Time 1: 7.seconds
Run Time 1: 10.seconds
Run Time 1: 36.minutes, 14.seconds

First, turn on timestamping in Serial Monitor. That will give your output information much more context.
Why so complex? The basic function you're trying to get working, and show us problems with, could be made much simpler and clearer by simply testing a button input and putting messages to Serial Monitor. Code modularly, something like:

loop()
read input (in this case, simply reading a button and timestamp to start with)
process information (did the button change? if so, do something, depending)
send output (report the change to serial monitor, or LCD, or both)
(end loop)

Three simple function calls. By doing this, you can

  • modify read input, without messing up anything else
  • modify processing, again...
    • modify send output to write to Serial monitor, LCD, or both, again...

Learning to code modularly is useful even with simple projects, because the knowledge, rigor and habits it teaches you will be even more useful with bigger projects.

1 Like
void setup() {
  pinMode(2, INPUT_PULLUP);
  Serial.begin(115200UL);
}

void loop() {
  static unsigned long HOUR = 60UL * 60;
  if ((millis() % 1000) == 0) {
    if (digitalRead(2) == 0)HOUR--;
    delay(1);
  }
  if ((millis() % 100) == 3) {
    Serial.println(String(HOUR / 60) + ':' + String(HOUR % 60));
    delay(1);
  }
}

1 Like

When you turn off your switch, you must remember the time counter value, and when you turn the switch on again, calculate the time it was off and subtract this time from the total.

1 Like

Thank you so much.
I'm currently mobile now, but I will give your code a try tomorrow.

yes, honestly I felt ashamed. I just realized after posting, that I must do as your suggestion first before asking question. Thank you anyway. I'll update it tomorrow.

Thank you so much @camsysca
I'll try and update it tomorrow

Sounds like you need a stopwatch e.g.

You can start and stop the time counting and reset to zero.

1 Like

that IS actually a really great idea! thank you I knew right after I saw notification about your reply, you will point me to right direction. I definitely will give it a try tomorrow.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.