Dtostrf not working on the ESP32

I am trying to convert a float variable to a 3 digit decimal value using the dtostrf , but I am unable compile.

I get the following error.

exit status 1
expression list treated as compound expression in initializer [-fpermissive]

Post a small but complete sketch illustrating the problem

1 Like

Here it is.. I missed it on the main post..


char VOLTS [7];



float V = pzem.voltage();
    dtostrf(V, 7, 3, VOLTS);

Is that

?

1 Like

In the code below I am sending data to the firebase,


char VOLTS [7];



void Task2code( void * pvParameters ){
  for(;;){
    V=pzem.voltage();
    dtostrf(V, 7, 3, VOLTS);
    
      json.set("/volts",VOLTS);
  
      
      Firebase.updateNode(firebaseData,"/users/user1",json);
  
    
    disableCore0WDT();
    
  }
}// END of Loop 1


void loop() {
}
 json.set("/volts",VOLTS);

Just by removing the VOLTS from the above line and putting some other value lets the code to get compiled successfully.
What could be the problem..?

Cf #2 and #4

1 Like

Post a small but complete sketch illustrating the problem

1 Like

You could use sprintf with the correct format string.

try this:

float V = 123.456;

void setup() {
  char voltString [20]; // has to be large enough...
  Serial.begin(115200);
  while (!Serial);
  dtostrf(V, 7, 3, voltString); // AVR convenience
  Serial.print("\nVolts = "); Serial.println(voltString);
  Serial.print("String length :"); Serial.println(strlen(voltString));
}

void loop() {}

Note the length of the string, there is a hint there...

Use snprintf it is safer. It won't crash your sketch if your char[ ] is too small for the result.
sprintf and dtostrf will crash your sketch if you don't allow enough space.

char c[7];
  double d= 17.22;
  if (snprintf(c, sizeof(c), "%f", d) >= sizeof(c)) {
    Serial.println(F("Warning result string truncated."));
  }
  Serial.println(c);

Edit -- corrected if test, thanks @J-M-L
Output

Warning result string truncated.
17.220

https://rules.sonarsource.com/c/RSPEC-6069

1 Like

that's probably not the whole test to decide if the string got truncated...

Interestingly the firebase library cannot send string or char.
It worked just by converting the dtostrf value to String.

V = pzem.voltage();
dtostrf(V, 7, 3, VOLTS);

String volts =VOLTS;

json.set("/volts",  volts );

This is beyond my understanding..
This is the same case with sprintf too.

json.set("/volts", String(pzem.voltage(), 3));

your issue was that you were overflowing the 7 char buffer...

sprintf is absolutely safe if you don't screw up, admittedly it's easy for beginners to do so,
basic arithmetic, counting and taking the zero delimiter into account is not for everyone.

Thanks @J-M-L, caught my stuff up, again.
if (snprintf(c, sizeof(c), "%f", d) >= sizeof(c)) {
@Whandall not all programmers are at perfect as you, mere mortals like me, often get things wrong, including the required size of the char[ ]
BTW the required size for the above format was to me an unexpected 10 due to the default 6 decimal points.

Another few other points about sprintf (and snprintf). Float conversions are not supported by UNO (AVR), but ESP32 does support them.

I find my SafeString library the easiest thing to use for a few reasons,
i) the code is simple and safe against crashes.

  char c[7];
  double d = 17.22;
  cSFA(sfC,c); // wrap the char[] in a SafeString for processin
  sfC = d; // default 2 dec.
  Serial.print(F("d="));Serial.println(c);

ii) it works on UNO as well as ESP32
iii) it protects against buffer overflows so you don't need to allow an excessive sizes char[20] when char[7] will do.
iv) the optional error messages are detailed
v) you don't have to check every call for failure. It is recorded in a global error flag you can check later.
vi) if you specify a width the result is padded to that max width, (dtostrf, snprintf, sprintf widths are all min widths which the conversion can exceed)

Output from the sample sketch below

d=17.22
d=17.2
Error: sfC.print() needs capacity of 7 too add number formatted to fixed width:7
        sfC cap:6 len:0 ''
d=
d=17.22
Error in a SafeString operation

Sample sketch

// download SafeString V4.1.5+ library from the Arduino Library manager or from
// https://www.forward.com.au/pfod/ArduinoProgramming/SafeString/index.html
#include "SafeString.h"
void setup() {
  Serial.begin(115200); //for debug
  for (int i = 10; i > 0; i--) {
    delay(500);
    Serial.print(i); Serial.print(' ');
  }
  Serial.println("ESP32 started");
  SafeString::setOutput(Serial); // enable error msgs

  char c[7];
  double d = 17.22;
  
  cSFA(sfC,c); // wrap the char[] in a SafeString for processin
  sfC = d; // default 2 dec.
  Serial.print(F("d="));Serial.println(c);

  // OR for more control use SafeString.print( )
  sfC = ""; //clear it
  sfC.print(d,1); // one dec
  Serial.print(F("d="));Serial.println(c);
  
  sfC = "";
  sfC.print(d,5,7); // 5decs padded to width 7, width too large for char[ ]
  Serial.print(F("d="));Serial.println(c);

  sfC = "";
  sfC.print(d,5,5); // 5decs padded to width 5,  dec reduced to fit in requested width
  Serial.print(F("d="));Serial.println(c);
}

void loop() {
  if (SafeString::errorDetected()) {
    Serial.print(F("Error in a SafeString operation"));
  }
}