Using the new Arduino IDE for ESP8266 and found bugs, report them here

Moderator: igrr

User avatar
By trackerj
#20503 Working last days on the driver for MAX7219 8 digit display module I found that dtostrf() STDLIB function is not working properly for very small values as below 0.0xxx.

Can anybody else test please to see if is only a local problem with my 1.6.4 IDE install, a ESP8266 implementation of STDLIB or a general BUG?

For example, try and check the result for :
0.256
0.0256
0.00256

Thank you.
User avatar
By trackerj
#20504 For reference:

Code: Select all
void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
}

// the loop routine runs over and over again forever:
void loop() {

 char charVal[10];          //temporarily holds data from vals
 String stringVal = "";     //data on buff is copied to this string
 
 float fVal = 0.0256;
 Serial.print("Value :");
 Serial.println((float)fVal);
 
 dtostrf(fVal, 8, 4, charVal);  //4 is mininum width, 3 is precision; float value is copied onto buff

 stringVal = charVal;
 int strl = stringVal.length()-1;

 Serial.print("Conv val :"); Serial.println(charVal);
 Serial.print("Length: ");Serial.println(strl); //display string
 Serial.print("Conv val :"); Serial.println(stringVal);
 Serial.println("\n");
  delay(3000);        // delay in between reads for stability
}


It looks like it's "eating" the ZERO's after comma...
User avatar
By trackerj
#20518 NEWS: tested on some Arduino boards with the guys from Arduino.cc Forum and is working OK for native Arduino platform.

Looks like a ESP8266 dtostrf() function implementation BUG.

For ESP8266 extension the "dtostrf()" is hidding in
"core_esp8266_noniso.c" and is called by "#include<stdlib_noniso.h>"

If anybody want to have fun, a copy below:
Code: Select allchar * dtostrf(double number, signed char width, unsigned char prec, char *s) {

    if(isnan(number)) {
        strcpy(s, "nan");
        return s;
    }
    if(isinf(number)) {
        strcpy(s, "inf");
        return s;
    }

    if(number > 4294967040.0 || number < -4294967040.0) {
        strcpy(s, "ovf");
        return s;
    }
    char* out = s;
    // Handle negative numbers
    if(number < 0.0) {
        *out = '-';
        ++out;
        number = -number;
    }

    // Round correctly so that print(1.999, 2) prints as "2.00"
    double rounding = 0.5;
    for(uint8_t i = 0; i < prec; ++i)
        rounding /= 10.0;

    number += rounding;

    // Extract the integer part of the number and print it
    unsigned long int_part = (unsigned long) number;
    double remainder = number - (double) int_part;
    out += sprintf(out, "%d", int_part);

    // Print the decimal point, but only if there are digits beyond
    if(prec > 0) {
        *out = '.';
        ++out;
    }

    while(prec-- > 0) {
        remainder *= 10.0;
    }
    sprintf(out, "%d", (int) remainder);

    return s;
}
User avatar
By trackerj
#20525 MISTERY SOLVED: it is a bug in the ESP8266 dtostrf() function implementation -> "core_esp8266_noniso.c".

Confirmed and fixed with the guys from ardino forum. It was affecting ESP8266 code only.

Corrected code below, if somebody is kind enough to add it also in the main code will be great.

Code: Select allchar * dtostrf(double number, signed char width, unsigned char prec, char *s) {

    if(isnan(number)) {
        strcpy(s, "nan");
        return s;
    }
    if(isinf(number)) {
        strcpy(s, "inf");
        return s;
    }

    if(number > 4294967040.0 || number < -4294967040.0) {
        strcpy(s, "ovf");
        return s;
    }
    char* out = s;
    // Handle negative numbers
    if(number < 0.0) {
        *out = '-';
        ++out;
        number = -number;
    }

    // Round correctly so that print(1.999, 2) prints as "2.00"
    double rounding = 0.5;
    for(uint8_t i = 0; i < prec; ++i)
        rounding /= 10.0;

    number += rounding;

    // Extract the integer part of the number and print it
    unsigned long int_part = (unsigned long) number;
    double remainder = number - (double) int_part;
    out += sprintf(out, "%d", int_part);

    // Print the decimal point, but only if there are digits beyond
    if(prec > 0) {
        *out = '.';
        ++out;
    }

    while(prec-- > 0) {
        remainder *= 10.0;
        if((int)remainder == 0){
                *out = '0';
                 ++out;
        }
    }
    sprintf(out, "%d", (int) remainder);

    return s;
}