I have created the uptime() function to show human readable Arduino uptime based on millis() counter.
That is the code:
char *uptime() // Function made to millis() be an optional parameter
{
return (char *)uptime(millis()); // call original uptime function with unsigned long millis() value
}
char *uptime(unsigned long milli)
{
static char _return[32];
unsigned long secs=milli/1000, mins=secs/60;
unsigned int hours=mins/60, days=hours/24;
milli-=secs*1000;
secs-=mins*60;
mins-=hours*60;
hours-=days*24;
sprintf(_return,"Uptime %d days %2.2d:%2.2d:%2.2d.%3.3d", (byte)days, (byte)hours, (byte)mins, (byte)secs, (int)milli);
return _return;
}
This is the complete code with test, tips and comments:
/*
function_uptime.pde
Description: Show uptime system based on millis();
Author: Evandro Stein (2011-09-02)
*/
void setup() {
Serial.begin(115200);
Serial.println("function_uptime.pde");
Serial.println("");
Serial.print("Zero = ");
Serial.println(uptime(0));
Serial.print("End of first day = ");
Serial.println(uptime(86400000-1));
Serial.print("Second day 86400000 = ");
Serial.println(uptime((unsigned long)24*60*60*1000)); // 24hours * 60min * 60sec * 1000mili = 86400000
Serial.print("Last millis() complete day = ");
Serial.println(uptime((unsigned long) -1 + ((byte)(4294967295/86400000)) * 86400000 )); // -1 + 49 * 86400000 = 4233599999
Serial.print("Absolutely MAX millis() unsigned long is 4294967295 = ");
Serial.println(uptime(4294967295));
Serial.println("If millis() > 4294967295 then Arduino reset millis() counter to zero!!!");
Serial.println("");
}
unsigned long time; // var created to show uptime more close to zero milliseconds as possible
void loop() {
if ((millis()/1000) != time) {
time = millis()/1000;
Serial.println(uptime(millis()));
}
delay(1);
}
char *uptime() // Function made to millis() be an optional parameter
{
return (char *)uptime(millis()); // call original uptime function with unsigned long millis() value
}
char *uptime(unsigned long milli)
{
static char _return[32];
unsigned long secs=milli/1000, mins=secs/60;
unsigned int hours=mins/60, days=hours/24;
milli-=secs*1000;
secs-=mins*60;
mins-=hours*60;
hours-=days*24;
sprintf(_return,"Uptime %d days %2.2d:%2.2d:%2.2d.%3.3d", (byte)days, (byte)hours, (byte)mins, (byte)secs, (int)milli);
return _return;
}
Suggestion are welcome! If you like or use it, please reply.
Zero = Uptime 0 days 00:00:00.000
End of first day = Uptime 0 days 23:59:59.999
Second day 86400000 = Uptime 1 days 00:00:00.000
Last millis() complete day = Uptime 48 days 23:59:59.999
Absolutely MAX millis() unsigned long is 4294967295 = Uptime 49 days 17:02:47.295
If millis() > 4294967295 then Arduino reset millis() counter to zero!!!
Uptime 0 days 00:00:01.001
Uptime 0 days 00:00:02.000
Uptime 0 days 00:00:03.000
Uptime 0 days 00:00:04.000
Uptime 0 days 00:00:05.000
Uptime 0 days 00:00:06.000
Uptime 0 days 00:00:07.001
Uptime 0 days 00:00:08.000
Uptime 0 days 00:00:09.001
Uptime 0 days 00:00:10.000
You need to make _return static or it will be corrupted by future function calls.
If you call uptime() and call another function (e.g. serial.Print()) before using the returned string it may be corrupted by that function.
In fact an interrupt occurring between the call to uptime() and the use of the returned string could also corrupt the result.
AWOL:
Of course, even if it is static, something like this:
char* timeZero = uptime (millis ());
... time passes
char* timeOne = uptime (millis());
... time passes
Serial.print (timeZero);
isn't going to work either!
This kind of function I usually don't store the result in string, I only store the number is and call function to show same result again.
But when I want anyway store it in a array, I do it like that:
My quetion is: Return a pointer is not a good way to return the text in this case?
It's a fine way to return the character data. The issue is that the pointer points to a block of memory that is not going to move. When the data in that memory location changes, every pointer that you have that points to that block of memory will, when dereferenced, see the latest data at that location, not the data that was there when the pointer was stored.
If you want to save the data that is in the pointed-to location when the function ends, you need to make a copy of it, in another location.