Creating a Timer and saving into the EEPROM

Hello, I need some advice on how to program timers. My goal is to create a timer that will time how long my mcu has been on. Currently the code I have written so far saves the number of minutes my board has turned on for into the EEPROM. Instead of counting hours I count minutes for the time being to help speed my process up and it works great. I am just concerned that being dependent on a millis call will show some inaccurate counting as my program gets larger in functionality.

My code is below. It counts the seconds and every time it hits 60 seconds I save a +1 into the EEPROM which is minutes. If I turned this into saving hours, I would count the minutes and save a +1 into the EEPROM.

#include <Arduino.h>
#include <EEPROM.h>
#include <TimeLib.h>
#include <Streaming.h>

// Address in EEPROM to store the total uptime
#define UPTIME_ADDRESS 0

unsigned long startTime;;
unsigned long readTotalUptime;

struct {
  int operationalHours = 0;
  elapsedMillis checkTime = 0;
} OOH;

void setup() {
  Serial.begin(9600);
  while (!Serial) {
    ;
  }
  startTime = millis(); // Record the starting time
  //Serial << "StartUp OOH read: " << EEPROM.read(UPTIME_ADDRESS) << endl;
}

void loop() {
  if (OOH.checkTime >= 1000) {
    OOH.checkTime = 0;
    unsigned long currentTime = millis();
    unsigned long uptime = currentTime - startTime;

    if (EEPROM.read(UPTIME_ADDRESS) >= 5) {
      Serial << "You are OUT of time!" << endl;
      for ( unsigned int i = 0 ; i < EEPROM.length() ; i++ )
        EEPROM.write(i, 0);
    }

    else {
      // Calculate hours, minutes, and seconds from uptime
      unsigned long Hours = uptime / 3600000;
      unsigned long Minutes = (uptime / 60000) % 60;
      unsigned long Seconds = (uptime / 1000) % 60;

      Serial << Seconds << endl;

      // Save the updated total uptime to EEPROM
      if (Seconds == 59) {
        OOH.operationalHours++;
        EEPROM.write(UPTIME_ADDRESS, OOH.operationalHours);
      }
    }
    Serial << "OOH: " << EEPROM.read(UPTIME_ADDRESS) << endl;
  }
}

Wy do you think that millis() function is not accurate to count elapsed time since the CPU has become active?

Any interrupt will disable the interrupt logic of the MCU; so, there is a good chance that the millisCounter will not be updated as it works on interrupts. Therefore, all ISR() functions should be as shot as possible; otherwise, there will be inaccuracies in the millisCounter based time calculation. The OP may try by relocating codes from the ISR() (if any) functions into loop() function.

The millisCounter is not an independent entity. At best, it can be said that the millisCounter is running concurrently with the loop() function. The millisCounter is capable of storing 232 milliseconds time which is about 49 days. The current content of the millisCounter can be read at any time and on the fly by executing the millis() function.

TOV0 flag interrupts the MCU at 1 ms inerval, which advances the 32-bit millisCounter by 1. If some other ISR() function lasts for more than 1 ms, then there is a chance that the millisCounter will be off by 1 ms.

I agree that Timer 0 is is an independent entity but not the millisCounter as its operation depends on the intervantion of the MCU.

Thank you for the feedbacks. I searched back on the board that I have, and according to the details most of its software Timing features use Systick timer. Systick timer generates an interrupt every millisecond.

So far, I plan on using an interrupt to measure rotations per minute of a small motor. Other than that, I may not use any other interrupts.

Which Arduino Board you are using?

It's an Arduino compatible board TEENSY 4.1 that can be used with the arduino ide

Thanks! I usually play around with standard Arduino (UNO, NANO, MEGA). Somestimes with ESP32 and DUE.

Another approach could be using polled interrupt; where, only the TOV0 interrupt will remain active to advance the millisCounter and all other interrupts will be kept OFF, but the services will be rendered by polling their statuses.

Right now it's working nicely, but I am going to need to keep all the feedbacks in mind. I appreciate your inputs.