Go Down

Topic: Leading zeros for seconds coding (Read 9416 times) previous topic - next topic

LRAT

Hi,

I want the time to display a constant number of digits. Therefore I require a leading zero in front of the seconds.

The code I've written is as follows:

Code: [Select]
if (now.second() < 10)
{String thisSecond("0" + now.second());}
String thisSecond = String(now.second(), DEC);


However, this always returns a value without the leading zero when the seconds are less then 10.
Any ideas how to sort out this problem?

I want to do the same for month, day, hour and minute as well but this should be easy once I've got it sorted out for the seconds.
Cheers,

Luc

Delta_G

#1
Jan 11, 2016, 02:21 am Last Edit: Jan 11, 2016, 02:21 am by Delta_G
You're naming two variables the same name.  The one inside the braces is local to there and goes out of scope immediately.  The second one is the only one avaialable anywhere else. 

Why mess with String at all?  Print is perfectly capable of printing numbers. 

Code: [Select]


if(now.second() < 10){
    Serial.print("0");
}
Serial.print(now.second());



Replace Serial.print with whatever you are using for display. 
|| | ||| | || | ||  ~Woodstock

Please do not PM with technical questions or comments.  Keep Arduino stuff out on the boards where it belongs.

LRAT

Thank you very much Delta_G for the fast response and excellent explanation.

I should have given a bit more information. (My mistake).

I want to create a global date and time string which can then be called from other functions. Therefore I want to add the leading zero before I create the string.

Here is an extended version of the code:

Code: [Select]
Serial.print(now.second());
{String thisSecond("0" + now.second());}
String thisSecond = String(now.second(), DEC);
//Put all the time and date strings into one String
DateAndTimeString = String(thisYear + "-" + thisMonth + "-" + thisDay + " " + thisHour + ":" + thisMinute + ":" + thisSecond);
Serial.println(DateAndTimeString);


For this reason there I've to manipulate the thisSecond string so that a leading zero will appear when needed.
Cheers,

Luc

MorganS

Don't use big-S strings. They're awfully bad for the Arduino. Here's an example using a small-s string.

Code: (Not Tested) [Select]
#include <strings.h>
//Put this declaration at the top of your program outside every function so it's global
char DateAndTimeString[20]; //19 digits plus the null char
...

  sprintf(DateAndTimeString, "%4d-%02d-%02d %d:%02d:%02d", thisYear, thisMonth, thisDay, thisHour, thisMinute, thisSecond);


%d is a placeholder for a (decimal) integer of variable length. It can be modified to print a specific length by adding the number of characters in front of the "d". Then the padding for short numbers will be spaces unless you then add a zero in front of that to show you want it padded with zeros. %02d will print who digits, padded with a zero as required.

"The problem is in the code you didn't post."

OldSteve

#4
Jan 11, 2016, 06:06 am Last Edit: Jan 11, 2016, 06:13 am by OldSteve
Or even better:-
Code: [Select]
sprintf_P(DateAndTimeString, PSTR("%4d-%02d-%02d %d:%02d:%02d"), thisYear, thisMonth, thisDay, thisHour, thisMinute, thisSecond);
Edit: I should have added, this stores the format string in program memory instead of RAM.
Please do not PM me for help. I am not a personal consultant.
And others will benefit as well if you post your question publicly on the forums.

LRAT

Thanks for the tips MorganS and OldSteve! Much appreciated!

I'm actually more confused now for following reasons:

"Don't use big-S strings. They're awfully bad for the Arduino."; Why are they so bad for the Arduino?
Can they physically destroy the chip?

"#include <strings.h>" ; My compiler tells me: "fatal error: strings.h: No such file or directory"
A search on the internet tells me that such a library doesn't exists as it is already part of the IDE (I use 1.6.6) but that doesn't seems to be the case.
Where can I find this library?

sprintf_P(DateAndTimeString, PSTR("%4d-%02d-%02d %d:%02d:%02d"), thisYear, thisMonth, thisDay, thisHour, thisMinute, thisSecond);" This line of code has made me completely confused. My knowledge of programming is not up to this level and I have to copy as is. However it wasn't accepted by the compiler and have no idea how to correct this.
I can understand the mask but struggle with sprintf_P and the PSTR in front of the mask.
Could you point me in a direction where I can read more about these commands?


It that would be extremely helpful if you could elaborate on it .
Cheers!

Luc

UKHeliBob

Code: [Select]
sprintf_P(DateAndTimeString, PSTR("%4d-%02d-%02d %d:%02d:%02d"), thisYear, thisMonth, thisDay, thisHour, thisMinute, thisSecond);"

What error do you get when you compile the code ?
Have you actually got quotation marks on the end of the statement or is that a copy/paste error ?
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

LRAT

Hi UKHeliBob,

I'm not in front of Arduino work station but the compiler throws a fault about the strings.h library. Something in the order that Strings is not recognized.
The quotation marks are not part of the code. I just used them to differentiate between code and explanatory text.
Cheers,

Luc

OldSteve

#8
Jan 11, 2016, 11:14 am Last Edit: Jan 11, 2016, 11:26 am by OldSteve
Hi UKHeliBob,

I'm not in front of Arduino work station but the compiler throws a fault about the strings.h library. Something in the order that Strings is not recognized.
The quotation marks are not part of the code. I just used them to differentiate between code and explanatory text.
Cheers,

Luc
1. The "String" class can cause memory issues, fragmentation in particular, and is not recommended.
It's much better to use C strings, (char arrays), with the standard C library functions for manipulation.

2. You don't need to include any libraries. It should compile fine without. As Bob asked, what error did you get?
I compiled that example using your variables before I posted it - it definitely works. And just did it again - see below.

3. 'sprintf_P()' does exactly the same as 'sprintf()', but the format string is stored in program memory rather than in RAM, conserving precious RAM. Much like using the 'F' macro for string literals. The PSTR() just casts the char array to a Pointer to STRing, as required when using the _P version of the library functions.
Nick Gammon has kindly provided some explanations and examples of F() and ..._P(), along with 'PROGMEM' here:-PROGMEM

Load, compile and run this. (Tested on UNO with IDE V1.6.5):-
Edit: You might want to change the baud rate, but it works fine for me at 115200.
Code: [Select]
char DateAndTimeString[20]; //19 digits plus the null char
int thisYear = 2016;
int thisMonth = 1;
int thisDay = 11;
int thisHour = 9;
int thisMinute = 9;
int thisSecond = 30;

void setup()
{
    Serial.begin(115200);
    sprintf_P(DateAndTimeString, PSTR("%4d-%02d-%02d %d:%02d:%02d"), thisYear, thisMonth, thisDay, thisHour, thisMinute, thisSecond);
    Serial.println(DateAndTimeString);
}

void loop() {}

Edit2: There's a bit more info on format strings here:- http://forum.arduino.cc/index.php?topic=156850.msg1175574#msg1175574
Please do not PM me for help. I am not a personal consultant.
And others will benefit as well if you post your question publicly on the forums.

arduinodlb

#9
Jan 11, 2016, 01:44 pm Last Edit: Jan 11, 2016, 01:46 pm by arduinodlb
When people say "little s string" they mean "character array", not a "string" class. So, there is no "string.h".

String objects simply take up more memory, and are slow to append, so for low memory systems it is generally better to avoid them.
Do not IM me. I will not respond. Ask questions in the forum.

krupski

#10
Jan 11, 2016, 01:47 pm Last Edit: Jan 11, 2016, 01:52 pm by Krupski
Hi,

I want the time to display a constant number of digits. Therefore I require a leading zero in front of the seconds.

The code I've written is as follows:

Code: [Select]
if (now.second() < 10)
{String thisSecond("0" + now.second());}
String thisSecond = String(now.second(), DEC);

Don't use String at all. Do it the right way (example assumes you are printing the full time):

Code: [Select]
char buffer [16];
uint8_t sec, min, hour;
sec = now.second();
min = now.minute();
hour = now.hour();
sprintf (buffer, "Time: %02u:%02u:%02u\n", hour, min, sec);
Serial.print (buffer);


The "%02u" means "print an unsigned integer with 2 places, fill with leading zero if necessary". So, the code above would print something like this:

"Time: 07:41:03"
--or--
"Time: 15:24:07"

If you leave off the zero in the hours place format string (i.e. use "%2u"), then means "print with two places" and the result would then be this:

"Time:  7:41:03"
--or--
"Time: 15:24:07"

Now, "buffer" has to be declared large enough to hold your string, and it doesn't hurt to add a few more just in case. For example, the strings above take up 6 (for "Time: ") plus 8 (for XX:XX:XX) plus 1 for the newline character plus 1 for the ending null (0) character which is 6 + 8 + 1 + 1 = 16 which is why I chose "buffer[16]" and maybe "buffer[24]" would have been even safer (unless you are short on RAM).

Hope this helps.

(edit): Sorry OldSteve basically gave you the same info. Sorry for the duplicate.

I will add though that using PROGMEM strings is more complicated and only really needed if you are dealing with a LOT of string data and running out of SRAM. For small strings and/or just a few strings to print, just use standard "sprintf". For a large number of strings, use OldSteve's example of PROGMEM strings.
Gentlemen may prefer Blondes, but Real Men prefer Redheads!

PaulS

Quote
So, there is no "string.h".
Well, there is, but it is included automatically, as part of Arduino.h. It contains all the function prototypes for the string handling functions like strcmp, strtok, etc.
The art of getting good answers lies in asking good questions.

krupski

When people say "little s string" they mean "character array", not a "string" class. So, there is no "string.h".

String objects simply take up more memory, and are slow to append, so for low memory systems it is generally better to avoid them.
May I also suggest trying out my "Stdinout" Arduino library which adds the ability to easily use standard input, standard output and standard error directly in Arduino.

For example, to print the time, ALL that would be needed is this:

Code: [Select]
Serial.begin (115200); // same as always
STDIO.open (Serial); // connect serial port to stdin/stdout/stderr
printf ("Time: %02u:%02u:%02u\n", hour, min, sec);


Get it here: https://github.com/krupski/Stdinout

Simply unzip the master file into "libraries", then at the top of a sketch use "include <Stdinout.h>" or better yet, add it directly to the Arduino.h master header so it will always be available. It takes NO memory unless actually used, so there's no reason not to include it directly in Arduino.h.
Gentlemen may prefer Blondes, but Real Men prefer Redheads!

krupski

Well, there is, but it is included automatically, as part of Arduino.h. It contains all the function prototypes for the string handling functions like strcmp, strtok, etc.
Actually, that stuff is provided by stdio.h.
Gentlemen may prefer Blondes, but Real Men prefer Redheads!

arduinodlb

#14
Jan 11, 2016, 02:02 pm Last Edit: Jan 11, 2016, 03:05 pm by arduinodlb
Well, there is, but it is included automatically, as part of Arduino.h. It contains all the function prototypes for the string handling functions like strcmp, strtok, etc.
Well, <cstring> :)
Do not IM me. I will not respond. Ask questions in the forum.

Go Up