Colorado
Offline
Edison Member
Karma: 39
Posts: 1225
Reviving dead brain cells with Arduinos.
|
 |
« on: January 14, 2013, 01:33:13 am » |
I have the following code: #include <DS3231.h> #include <Wire.h> #include <stdio.h>
DS3231 Clock; bool Century = false; bool h12; bool PM;
char currDate[24]; char currTime[22];
long lastRun = 0; int pause = 1000;
void setup() { Wire.begin(); Serial.begin(57600); }
void loop() { if (millis() - lastRun > pause) { sprintf(currDate, "Current Date: 20%02d/%02d/%02d", Clock.getYear(), Clock.getMonth(Century), Clock.getDate()); sprintf(currTime, "Current Time: %02d:%02d:%02d", Clock.getHour(h12, PM), Clock.getMinute(), Clock.getSecond());
Serial.println(currDate); Serial.println(currTime);
Serial.print('\n');
lastRun = millis(); } } And the output I'm getting is: Current Date: 2013/01/13Current Time: 23:31:49 Current Time: 23:31:49
Current Date: 2013/01/13Current Time: 23:31:50 Current Time: 23:31:50
Current Date: 2013/01/13Current Time: 23:31:51 Current Time: 23:31:51 Can anyone explain to me why it appears that the 'currTime' variable gets tacked onto the end of the 'currDate' one? If I just output 'currDate', I get: Current Date: 2013/01/13Current Time: 23:32:27 Why's that?
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Sr. Member
Karma: 12
Posts: 327
The last thing you did is where you should start looking.
|
 |
« Reply #1 on: January 14, 2013, 01:36:41 am » |
I would guess you have to add a Line feed in there.
|
|
|
|
|
Logged
|
|
|
|
|
Colorado
Offline
Edison Member
Karma: 39
Posts: 1225
Reviving dead brain cells with Arduinos.
|
 |
« Reply #2 on: January 14, 2013, 01:40:23 am » |
LarryD, read (or reread) the entire post and code before you answer. 'currDate' does *not* contain the time variables in it.
|
|
|
|
|
Logged
|
|
|
|
|
Radelaide!
Offline
Newbie
Karma: 0
Posts: 39
|
 |
« Reply #3 on: January 14, 2013, 01:41:12 am » |
You haven't allocated space for a null terminator in the currDate array, and as luck would have it the next block of memory is the currTime array. You want to allocate 1 more than the longest string to allow for a null terminator (\0) otherwise when you print it will keep reading memory as a string until it hits a null. You really want to allocate your arrays as char currDate[25]; char currTime[23];
|
|
|
|
|
Logged
|
|
|
|
|
Colorado
Offline
Edison Member
Karma: 39
Posts: 1225
Reviving dead brain cells with Arduinos.
|
 |
« Reply #4 on: January 14, 2013, 01:48:06 am » |
Lovely. That explains a lot. Though it doesn't explain why I never encountered that before in other languages that also use printf() and sprintf() ... Oh well. Thanks SPD.
|
|
|
|
|
Logged
|
|
|
|
|
France
Offline
God Member
Karma: 19
Posts: 615
Scientia potentia est.
|
 |
« Reply #5 on: January 14, 2013, 03:46:22 am » |
Which other languages? You will have the same problem in any languages that uses char arrays that are too small to store a null terminated string  That code reproduce it so you can see it's not specific to Arduino: http://codepad.org/xUm6gagq
|
|
|
|
|
Logged
|
|
|
|
|
Offline
God Member
Karma: 9
Posts: 836
|
 |
« Reply #6 on: January 14, 2013, 07:18:45 am » |
C and C++ will give you the same error.
|
|
|
|
|
Logged
|
|
|
|
|
UK
Offline
Edison Member
Karma: 42
Posts: 2200
What a host of balls she had seen: gaity, the brass buttons...
|
 |
« Reply #7 on: January 14, 2013, 08:00:09 am » |
The "error" is compounded by the order you are doing your sprintfs. If you were to swap them around you would get very different results. The first sprintf is placing the data in the first array fine, but the terminating null character is ending up as the first character of the second array. The second sprintf is then overwriting that null character. Swapping them around would give you the first array looking perfectly fine, but the second array would appear empty, which would be just as confusing 
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Sr. Member
Karma: 15
Posts: 463
|
 |
« Reply #8 on: January 14, 2013, 11:38:32 am » |
Can anyone explain to me why it appears that the 'currTime' variable gets tacked onto the end of the 'currDate' one? If I just output 'currDate', I get: Current Date: 2013/01/13Current Time: 23:32:27 Why's that? You need to have cr/lf sequences in your sprintf format strings. Example: sprintf(buffer, "Hello, my name is %s", "Roger"); Serial.print(buffer); sprintf(buffer, "I am %d years old", 56); Serial.print(buffer); ...produces: Hello, my name is RogerI am 56 years oldHowever, this: sprintf(buffer, "Hello, my name is %s\r\n", "Roger"); Serial.print(buffer); sprintf(buffer, "I am %d years old\r\n", 56); Serial.print(buffer); ...produces: Hello, my name is Roger I am 56 years oldThe "\r" is a "return" (carriage return - 0x0D or 13 decimal) and "\n" is a "newline" (moves to the next line - 0x0A or 10 decimal). NOTE that using %f (floating point) in sprintf will fail (it will print a question mark "?" instead of the number) because the floating point code for sprintf and sscanf has been removed from the "libc.a" library in order to make compiled sketches smaller. If you would like to add the ability to use floating point in sprintf and sscanf, replace your "pde.jar" file with the one attached. This version adds an option to turn on or off floating point support and save the setting in your "preferences.txt" file. Simply rename your "pde.jar" file to "pde.bak", then unzip the new on in place. You will see a new checkbox option in the "Preferences" menu called "Enable floating point support". Turn this on or off as needed. If it's on, it will make your compiled sketches about 1.5K larger (but then floating point will actually work!) (edit): This pde.jar file is for IDE version 1.0.0 to 1.0.3, NOT for the new 1.5.1 version.Hope this helps.
|
|
|
|
« Last Edit: January 14, 2013, 11:51:59 am by Krupski »
|
Logged
|
|
|
|
|
Pittsburgh, PA, USA
Offline
Faraday Member
Karma: 30
Posts: 2916
I only know some basic electricity....
|
 |
« Reply #9 on: January 14, 2013, 12:38:14 pm » |
He used Serial.println() to print both. That adds cr/lf.
|
|
|
|
|
Logged
|
Examples can be found at Learning in the Main Site and at the Playground
|
|
|
|
Colorado
Offline
Edison Member
Karma: 39
Posts: 1225
Reviving dead brain cells with Arduinos.
|
 |
« Reply #10 on: January 14, 2013, 02:13:54 pm » |
Yeah, I used println(). And rather than adding the additional 1.5K to my sketches to allow for floating points, I did it like this: float cTemp = Clock.getTemperature(); int cTemp1 = (cTemp - (int)cTemp) * 100; sprintf(currTemp, "Current Temp: %0d.%d C", (int)cTemp, cTemp1);
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 312
Posts: 35483
Seattle, WA USA
|
 |
« Reply #11 on: January 14, 2013, 02:29:10 pm » |
Suppose cTemp is 12.07. What gets put in currTemp?
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Sr. Member
Karma: 15
Posts: 463
|
 |
« Reply #12 on: January 14, 2013, 02:31:17 pm » |
Yeah, I used println(). And rather than adding the additional 1.5K to my sketches to allow for floating points, I did it like this: float cTemp = Clock.getTemperature(); int cTemp1 = (cTemp - (int)cTemp) * 100; sprintf(currTemp, "Current Temp: %0d.%d C", (int)cTemp, cTemp1); Is your sketch right at the edge of not having enough memory to run in, or do you just feel better having unused flash?  Note that the new PDE.JAR file allows you to enable or disable the floating point support. If you want to use floating point support (and use an extra 1.5K) turn on FP support, If you are against the wall for memory, turn FP off. In any case, it's better to HAVE the option than not... agreed?
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Sr. Member
Karma: 15
Posts: 463
|
 |
« Reply #13 on: January 14, 2013, 02:34:00 pm » |
Suppose cTemp is 12.07. What gets put in currTemp?
LOL! Good point... never thought about that. I suppose a few more lines of code to check for "cTemp1 < 10" and then adding an ascii 0 kludge is SO much better than using "printf (%5.2f)" 
|
|
|
|
|
Logged
|
|
|
|
|
Colorado
Offline
Edison Member
Karma: 39
Posts: 1225
Reviving dead brain cells with Arduinos.
|
 |
« Reply #14 on: January 14, 2013, 02:34:23 pm » |
Suppose cTemp is 12.07. What gets put in currTemp?
It won't be. The temperature reading is always in .25 increments, thus 12.00, 12.25, 12.50, or 12.75. And I never claimed that method to be perfect. I just choose it because I know the incoming temperature readings. Is your sketch right at the edge of not having enough memory to run in, or do you just feel better having unused flash?  Ultimately, quite possible. Right now I'm hovering around 29-30K ... however, I also have not done any optimization to the code yet. I'm in the R&D stage and just writing code to get the result I want. Once I have things working, I will go through and clean it up, at which point I may very well have plenty of room.
|
|
|
|
|
Logged
|
|
|
|
|
|