Pages: [1]   Go Down
Author Topic: adding decimal points and zero padding for display.  (Read 3830 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 1
Posts: 19
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I am creating a motion control project. It needs to display a number that can be upto 99.999 - this number, however, does not need to be a real float - it will not be used for any floating point anything, it just represents inches in thousandths.

So the number would typically be values such as "00.012" or 00.150" or "01.625" or even "32.699". I can see that I can hold this number in a Long type.

I need help parsing this beast and adding the decimal place. I currently have some messy messy code..

I have seen the various posts about similar topics concerning creating a string from a float, but I am not sure the requirements are the same.

Does anyone have any advice? An idea for a function that takes the raw integer and simply puts it, properly formatted, into a string?
Code:
decimate(string containing integer, number of decimal places)

void decimate(char test[],int dec) {
 int i=0; 
 int length=strlen(test);
 char msg[10]="";

 strcpy(msg,test);

 if (length <= dec) {
   for(i=dec;i>(dec-length);i--)  msg[i] = msg[i-(dec-length+1)];
   for(i=0;i<(dec+1-length);i++)  msg[i]='0';
   length = strlen(msg);
 }
 for (i=length;i>(length-dec);i--)  msg[i]=msg[i-1];
 msg[length-dec]='.';

 strcpy(test,msg);
}
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 653
Posts: 50881
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The sprintf function will convert the long to a string, with leading 0 padding:

Code:
int val = 1238;
char buff[6];
sprintf(buff, "%.5ld", val); // buff will be "01238"

Then, copy the data into another array:
Code:
char withDot[7];
withDot[0] = buff[0];
withDot[1] = buff[1];
withDot[2] = '.'; // Add the "decimal point"
withDot[3] = buff[2];
withDot[4] = buff[3];
withDot[5] = buff[4];
withDot[6] = buff[5]; // The terminating NULL
withDot will now contain "01.238"
Logged

0
Offline Offline
Newbie
*
Karma: 1
Posts: 19
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Pauly,

Hey - thanks! That does seem close to operational. Unfortunately it is displaying really weird numbers, such as: "87.608Â
" or 84.597Â" - always with a "Â" at the end.

I have this in a loop, and the numbers change each time..
Logged

~/earth/north_america/usa/mi
Offline Offline
Newbie
*
Karma: 3
Posts: 20
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Looks like the terminating null isn't there.  You could work around that with
Code:
withDot[6] = '\0';
« Last Edit: January 31, 2011, 01:11:37 pm by tdc218 » Logged

0
Offline Offline
Newbie
*
Karma: 1
Posts: 19
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

tdc,

I tried that.. It had the exact same effect as the original code. I have been looking at sprintf syntax. It looks like the problem is possibly that the print command is trying to display the ascii values for the 1238 number, not just the 'ascii'.. if that makes any sense... This is starting to get frustrating!



 here is my current test code:
Code:
int testNumber = 1238;
char buff[6];
sprintf(buff, "%.5li", testNumber); // buff will be "01238"
char withDot[7];
withDot[0] = buff[0];
withDot[1] = buff[1];
withDot[2] = '.'; // Add the "decimal point"
withDot[3] = buff[2];
withDot[4] = buff[3];
withDot[5] = buff[4];
withDot[6] = '\0'; // The terminating NULL
Serial.println(withDot);
Logged

0
Offline Offline
Newbie
*
Karma: 1
Posts: 19
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Here is an example of the output. Notice the first value is unique, then it oscillates around at some other odd numbers..

Code:
89.247
95.997
89.292
95.997
89.292
95.997
89.292
95.997
89.292
95.997
89.292
95.997
89.292
95.997
89.292
95.997
Logged

~/earth/north_america/usa/mi
Offline Offline
Newbie
*
Karma: 3
Posts: 20
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hmm.  That's odd.  I have a meeting to run to in a couple of minutes or I'd code it up and see what was going on.

The sprintf conversion syntax is odd, the source number is an int and you've got "%.5li".  Try "%.5d" or just "%5d".
Logged

Northern California (by San Francisco)
Offline Offline
Sr. Member
****
Karma: 3
Posts: 258
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Here is an example of the output. Notice the first value is unique, then it oscillates around at some other odd numbers..

Where is that output from? The problem seems to be with your Serial.println(withDot); statement. I ran the other code and it generates exactly what you want it to. That is, you get a character array withDot that has the following in it:
Code:
- withDot 0x001ff7d0 "01.238" char [7]
[0] 48 '0' char
[1] 49 '1' char
[2] 46 '.' char
[3] 50 '2' char
[4] 51 '3' char
[5] 56 '8' char
[6] 0 char
Logged

0
Offline Offline
Newbie
*
Karma: 1
Posts: 19
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Oh. I just got it working with advice from above, but it wont work with numbers greater than around 50,000... I am using a long type..

Code:
testNumber = 98000;
void setup()
{
  Serial.begin(57600);
}

void loop()
{

char buff[6];
sprintf(buff, "%.5u", testNumber); // buff will be "01238"
char withDot[7];
withDot[0] = buff[0];
withDot[1] = buff[1];
withDot[2] = '.'; // Add the "decimal point"
withDot[3] = buff[2];
withDot[4] = buff[3];
withDot[5] = buff[4];
withDot[6] = '\0'; // The terminating NULL
Serial.println(testNumber);
Serial.println(withDot);
}


Logged

Northern California (by San Francisco)
Offline Offline
Sr. Member
****
Karma: 3
Posts: 258
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Sounds like you may be bumping into the upper limit for an unsigned integer, which is 65,535.

Quote
Unsigned ints (unsigned integers) are the same as ints in that they store a 2 byte value. Instead of storing negative numbers however they only store positive values, yielding a useful range of 0 to 65,535 (2^16) - 1).
Logged

0
Offline Offline
Newbie
*
Karma: 1
Posts: 19
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

oh.. yeah. i am trying to use longs though..

"long testNumber = 98000;"

this is outputting "32.464"

with 68000, for instance, it is outputting "02.464"

with 38120 it outputs "38.120" - correctly! (yay) Maybe I will just limit that motion to +/- the value allowed in an int.. It should be fine.. I did want to let users select units though = so this xx.xxx could be millimeters, for instance.. A larger range than +/1 65,000 would be nice.

Code:
long testNumber = 68000;
void setup()
{
  Serial.begin(57600);
}

void loop()
{
char buff[6];
sprintf(buff, "%.5u", testNumber); // buff will be "01238"
char withDot[7];
withDot[0] = buff[0];
withDot[1] = buff[1];
withDot[2] = '.'; // Add the "decimal point"
withDot[3] = buff[2];
withDot[4] = buff[3];
withDot[5] = buff[4];
withDot[6] = '\0'; // The terminating NULL
Serial.println(testNumber);
Serial.println(withDot);
}
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 653
Posts: 50881
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
sprintf(buff, "%.5u", testNumber); // buff will be "01238"
Where did the l (long) go? You are trying to output testNumber as though it is unsigned int, not unsigned long. Try "%.5ld" like I first suggested.
Logged

0
Offline Offline
Newbie
*
Karma: 1
Posts: 19
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Paul,

Thank you very much!- I eventually got it working. I do not know what I was doing wrong the first time, but here is what has ended up working:

Code:
long testNumber = 99999;
void setup()
{
  Serial.begin(57600); 
char buff[6];
sprintf(buff, "%.5ld", testNumber); // buff will be "01238"
char withDot[7];
withDot[0] = buff[0];
withDot[1] = buff[1];
withDot[2] = '.'; // Add the "decimal point"
withDot[3] = buff[2];
withDot[4] = buff[3];
withDot[5] = buff[4];
withDot[6] = '\0'; // The terminating NULL
Serial.println(testNumber);
Serial.println(withDot);
}

void loop(){
}




Logged

Offline Offline
Newbie
*
Karma: 1
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Guys,

Could you do something like (may need converting to arduino c   smiley-red)

void decimate(char *result, int value, int dec)
{
     sprintf(result, "%.*f", dec, (float) value);
}

int main(void)
{
     char result[10];

     decimate(result, 1.2, 3);

     printf("[%s]\n", result);              // output [1.200]
}
Logged

Offline Offline
Newbie
*
Karma: 1
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

sorry you also mentioned zero padding:

void decimate(char *result, int value, int length, int dec)
{
     sprintf(result, "%0*.*f", length, dec, (float) value);
}

int main(void)
{
     char result[10];

     decimate(result, 1.2, 6, 3);

     printf("[%s]\n", result);              // output [01.200]
}
Logged

Pages: [1]   Go Up
Jump to: