When I was using the web interface to lower the nozzle,
the reported nozzle height suddenly jumped up and down.
The problem:
A float with a zero on the right of the comma is converted incorrectly,
when the Z height is 0,09 it is presented as 0,9 in the web interface.
The problem location:
The "convert float to string" function in RepRapFirmware.cpp at line 293:
The float value is split in two parts, left of the comma and right of the comma.
When both parts are combined with the desired precision, the %d kills zero's.
I have tried to fix this and my version of the code looks like this:
I have attached a source file to test it on a PC.
the %d should probably be replaced by %ld for long int values.
the reported nozzle height suddenly jumped up and down.
The problem:
A float with a zero on the right of the comma is converted incorrectly,
when the Z height is 0,09 it is presented as 0,9 in the web interface.
The problem location:
The "convert float to string" function in RepRapFirmware.cpp at line 293:
// Float to a string.
static long precision[] = {0,10,100,1000,10000,100000,1000000,10000000,100000000};
char scratchString[STRING_LENGTH];
char* ftoa(char *a, float f, int prec)
{
if(a == NULL)
a = scratchString;
char *ret = a;
long whole = (long)f;
if(!whole && f < 0.0)
{
a[0] = '-';
a++;
}
snprintf(a, STRING_LENGTH, "%d", whole);
while (*a != '\0') a++;
*a++ = '.';
long decimal = abs((long)((f - (float)whole) * precision[prec]));
snprintf(a, STRING_LENGTH, "%d", decimal);
return ret;
}
My translation:The float value is split in two parts, left of the comma and right of the comma.
When both parts are combined with the desired precision, the %d kills zero's.
I have tried to fix this and my version of the code looks like this:
// Float to a string. static const char *formatting[] = {"%d", "%d", "%02d","%03d","%04d","%05d","%06d","%07d","%08d"}; static long precision[] = {0,10,100,1000,10000,100000,1000000,10000000,100000000}; char scratchString[STRING_LENGTH]; char* ftoa(char *a, float f, int prec) { if(a == NULL) a = scratchString; char *ret = a; long whole = (long)f; if(!whole && f < 0.0) { a[0] = '-'; a++; } snprintf(a, STRING_LENGTH, "%d", whole); while (*a != '\0') a++; *a++ = '.'; long decimal = abs((long)((f - (float)whole) * precision[prec])); snprintf(a, STRING_LENGTH, formatting[prec], decimal); return ret; }The bug is a bit hard to trigger on the printer,
I have attached a source file to test it on a PC.
$ ./ftoa Old ftoa with input 0.000 and precision 2: 0.0 Old ftoa with input 0.090 and precision 2: 0.9 Old ftoa with input 0.123 and precision 2: 0.12 New ftoa with input 0.000 and precision 2: 0.00 New ftoa with input 0.090 and precision 2: 0.09 New ftoa with input 0.123 and precision 2: 0.12There are warnings about the %d in combination with 'long int',
the %d should probably be replaced by %ld for long int values.
$ gcc ftoa.c -o ftoa ftoa.c:23:3: warning: format ‘%d’ expects argument of type ‘int’, but argument 4 has type ‘long int’ [-Wformat] ftoa.c:27:3: warning: format ‘%d’ expects argument of type ‘int’, but argument 4 has type ‘long int’ [-Wformat] ftoa.c:44:3: warning: format ‘%d’ expects argument of type ‘int’, but argument 4 has type ‘long int’ [-Wformat]