Using modulus operator to extract minutes/seconds from millis value SOLVED!

I am trying to break millis down into its components parts regarding
conversion to seconds/minutes.
The code below works...sort of. But I thought the modulus operator
would take the remainder and and throw it back to the millis value.
I am probably misapplying the operator, right?
The issue is once the conversion passes the 1 minute mark the seconds continue to count up instead of resetting to 0.
Min Sec
0 .... 0
0..... 2
0 .... 4
0 .... 58
1 .... 60 < here it should go to 0
1 .... 62
and so on....

#include <math.h>


static uint32_t start_Millis = 0;
static uint32_t current_Millis = 0;
static uint32_t elapsed_Millis = 0;

void setup() {
  Serial.begin(115200);
 start_Millis = millis();
   }

void loop() {
 
 current_Millis = millis(); 
  elapsed_Millis = current_Millis - start_Millis;
  int seconds = elapsed_Millis / 1000;
  seconds %= 1000;
  int minutes = seconds / 60;
  minutes %= 60;

   Serial.println(minutes);
   Serial.println();
   Serial.println(seconds);
   Serial.println();

   delay(2000);
}
1 Like
if (!(seconds % 60) && (seconds != 0)) { // zero remainder
  minutes ++;
  seconds = 0;
}

No, it will only go back to zero after 999 because of this line:

I added that bit of code and:

0 ..... 58
2 ...... 0
1 ...... 62
1 ....... 64

is what happened. It reset for that one cycle and went back to the larger total.... ????

I see the minutes went up then down. Looks like my conditional was visited many times in one second. Need a flag to say "we did the 60s = 1m and s = 0, do not enter" until seconds change to 1.

I tried adding a delay (1000) inside that if statement but it still
went back to the big value.....

Perhaps something like:

unsigned long seconds {elapsed_Millis / 1000};
unsigned long minutes {seconds / 60};

Serial.println(minutes);
Serial.println();
Serial.println(seconds % 60);
Serial.println();
2 Likes

you are mixing signed and unsigned int of different size guarantees hours of interesting problems :slight_smile:

uint32_t now=millis();
uint32_t s=millis/1000;
uint32_t m=s/60;
uint32_t h=m/60;
s-=m*60;
m-=h*60;

You seem to have hit upon a winning formula!!! I am curious about the use of the curly brackets on those second / minute code lines.
What is the reason for that instead of just enclosing them parethentically?

thanks fo r your input ..... :+1: :+1: :+1:

ed

It’s another way to initialize a variable in C++, usually more for more complex types but Brace-initialization is a uniform method for initializing data in C++ (11 and beyond). For this reason, it is also called uniform initialization

It is called uniform initialisation. You can see it as a safer version of the the classical initialisation:

unsigned long seconds = elapsed_Millis / 1000;
unsigned long minutes = seconds / 60;
// ...
uint32_t s=millis/1000;

I am trying your code but think millis needs the closed parenthesis ().
I appreciate your warning about mixing integer definitions. It is a weak area of my C understanding admittedly. I am really just an old neopyhte barely holding on to grasping everything.... lol.
Without a reliance on the dreaded "c & p" I would be sunk....drowned. :grinning:

ed

thanks for explaining... :+1:

thank you for the explanation... :+1: :+1:

zwieblum,

Your code works fine. I now have two different solutions
provided by forum members!!

appreciater the assist... :+1:

ed

Please keep in mind that the processor you are using may or my not have built in division (atmega328p does not), so / or % will be slow compared to integer - or *.

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