Converting ms to Hours:Mins:Secs?

I've re-written my project to use millis() instead of delays. I've been looking for easy to use code snippets to convert from ms to seconds, minutes and hours. The one I found in the thread

works OK and I've shown a section of my code using it. But can anyone recommend an alternative that's more intuitive please?

unsigned long currentMillis = millis();
  // If time for a keep-alive photo has been reached
  if (currentMillis - previousMillis >= interval)
  {
    // Take a photo, i.e press and release once
    myservo.write(inPos);
    delay(waitBeforeRelease);
    myservo.write(outPos);
    delay(200);
    previousMillis = currentMillis; // Save the last time a photo was taken
    countPhotos++; // Increment the photo count
    Serial.print("Keep alive photo ");
    Serial.print(countPhotos);

    char buf[21];
    sprintf(buf, " at runtime %02d:%02d:%02d", runHours, runMinutes, runSeconds);
    Serial.println(buf);

  }

P.S: Is it not possible to apply formating to code displayed here? I tried in vain to highlight
char buf[21];
** sprintf(buf, " at runtime %02d:%02d:%02d", runHours, runMinutes, runSeconds);**
** Serial.println(buf);**

Your thread title asks about converting millis() to Hours:Mins:Secs but the code snippet does not illustrate the conversion

Is the problem the conversion or the display of the converted values ?

That looks pretty intuitive to a C programmer

The common alternative to the sprintf() would be multiple print() statements with some if statements to handle the leading zeros, more code for you to write, but takes less code than the sprintf implementation.

The code you posted has nothing to do with converting millis to hours/minutes/seconds.

P.S: Is it not possible to apply formatting to code displayed here? I tried in vain to highlight
char buf[21];
sprintf(buf, " at runtime %02d:%02d:%02d", runHours, runMinutes, runSeconds);
Serial.println(buf);

No, it's not. Code tags turn off formatting because having it on means code gets interrupted as HTML and you end up with smiling faces and other nonsense instead of code.

For printing out hours, minutes and seconds your code is pretty much exactly how I would do it.

Bear in mind using Millis will not give you an accurate long term clock , for that use a module such as a DS3231.

How about this one?

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  unsigned long prMillis = millis();
  while (millis() - prMillis < 1000)
  {
    ;
  }
  prMillis = millis() / 1000;
  //------------------------
  byte sec = prMillis % 60;
  prMillis = prMillis / 60;
  //------------------------
  byte min = prMillis % 60;
  prMillis = prMillis / 60;
  //------------------------
  byte hrs = prMillis % 24;
  //------------------------
  Serial.print(hrs);
  Serial.print(':');
  //-----
  Serial.print(min);
  Serial.print(':');
  //-----
  Serial.println(sec);
  //-------------------------
}

smhrs.png

smhrs.png

GolamMostafa:
How about this one?

Big “oops” on the leading zeroes.

TheMemberFormerlyKnownAsAWOL:
Big "oops" on the leading zeroes.

Let the OP or others add it.

UKHeliBob:
Your thread title asks about converting millis() to Hours:Mins:Secs but the code snippet does not illustrate the conversion

The conversion itself was straightforward, it's the syntax of displaying of the result with sprintf that I find more difficult to understand. That was why I tried to bold it in the code box.

Is the problem the conversion or the display of the converted values ?

Obviously the former. A 'P.S' is an afterthought, an extra note; in this case an additional minor question. Which PerryBebbington has answered.

hammy:
Bear in mind using Millis will not give you an accurate long term clock , for that use a module such as a DS3231.

Thanks for the warning. But for the current purpose I'd be happy with a minute or two error daily.

Terry - your reply contradicts itself

You say

The conversion itself was straightforward

yet in reply to me asking

Is the problem the conversion or the display of the converted values ?

You reply

Obviously the former.

If you find using sprintf() confusing then simply print each element of the time separately and put the code in a function to be called whenever it is needed

PerryBebbington:
No, it's not. Code tags turn off formatting because having it on means code gets interrupted as HTML and you end up with smiling faces and other nonsense instead of code.

Thanks, understood.

For printing out hours, minutes and seconds your code is pretty much exactly how I would do it.

I'll study that sprintf thread again. It's nicely compact, just hard to grasp the syntax.

Terrypin:
I'll study that sprintf thread again. It's nicely compact, just hard to grasp the syntax.

It took me absolutely AGES to understand what you can do with sprintf, it is well worth learning how to use it, it is very powerful but you have to understand it. You will keep discovering new ways to use it.

@ UKHeliBob

OK, perhaps I should have pasted the code from the thread I linked (post #4 by @jurs, four years ago) rather than that fragment of my own. Here it is now:

void setup() {
  Serial.begin(9600);

}

void loop() {
unsigned long runMillis= millis();
unsigned long allSeconds=millis()/1000;
int runHours= allSeconds/3600;
int secsRemaining=allSeconds%3600;
int runMinutes=secsRemaining/60;
int runSeconds=secsRemaining%60;

char buf[21];
sprintf(buf,"Runtime%02d:%02d:%02d",runHours,runMinutes,runSeconds);
Serial.println(buf);
delay(1000);

GolamMostafa:
How about this one?

Thanks, appreciate the help. As a learning exercise later I'll try that (and have a crack at adding the zero padding, and a couple of decimal places of seconds). But as mentioned up-thread I'll also persist with that sprintf method.

If you want to study the syntax of sprintf(), google the c++ printf() command, that uses the same formatting and has a lot of documentation. Just remember that on most arduino's sprintf() does not support floats.

Terrypin:
Thanks, appreciate the help. As a learning exercise later I'll try that (and have a crack at adding the zero padding, and a couple of decimal places of seconds). But as mentioned up-thread I'll also persist with that sprintf method.

I appreciate your agnostic attitude that you have been showing from the very beginning as to grasp the knowledge of how to displaying the HRS:MIN:SEC from the millis counts using the first principles that I have presented in my Post#6.

The Library Functions hide the mechanics and serve those who are running after finishing the project rather than exploring what is being done and how.

david_2018:
If you want to study the syntax of sprintf(), google the c++ printf() command, that uses the same formatting and has a lot of documentation. Just remember that on most arduino's sprintf() does not support floats.

Thanks David. Although at first sight that looks pretty daunting to a non programmer like me!

Although ‘copy/paste mode’ lets me make some progress, I’m more comfortable when I understand what I’m doing! So on balance I think I’ll invest some time first on the approach you and others suggested earlier: derive H, M and S by the straightforward method (successive division etc). And try to make those accessible via functions, which is a new topic for me. One particular difficulty is how to get a decimal point or two in the S display?

I’m all for learning by doing but frankly I’d rather be doing so on something less ‘routine’. I’m surprised that this HMS stuff isn’t downloadable somewhere or in one of the Arduino libraries?

Terrypin:
I’m all for learning by doing but frankly I’d rather be doing so on something less ‘routine’. I’m surprised that this HMS stuff isn’t downloadable somewhere or in one of the Arduino libraries?

It is. The Time library, aka the DateTime library.