Visualizzare valore float a numero di cifre fisse

Ciao a tutti
gradirei riuscire a visualizzare sul display lcd il valore della misura della sonda pH (valore float)
compreso di segno - fisso a 5 caratteri fissi.
Mi spiego meglio con un esempio di quello che desidererei ottenere :

Valore reale -0,01 gradirei visualizzare -0,01
Valore reale -1,45 gradirei visualizzare -1,45
Valore reale 0,05 gradirei visualizzare 00,05
Valore reale 11,33 gradirei visualizzare 11,33

con sprintf non posso ottenere valori negativi, corretto ?
con dtostrf ottengo valori negativi perfetti ma il positivo sotto il valore 10 non mi visualizza lo zero davanti

c'è un modo per ottenere come sprintf %02d o %02u sempre due cifre con zero davanti se minore di 10 ?

Spero di aver spiegato bene cosa desidererei ottenere

Grazie in anticipo

con questo codice ho fatto varie prove ma non ottengo ciò che gradirei

void setup()
{
Serial.begin(115200);
}

void loop()
{
int index = 0;
float f = 0.01;
Serial.print("Original value: ");
Serial.println(f);

char str[50];
dtostrf(f, 5, 2, str);
// sprintf(str, "String value: %02d.%02d", (int)f, (int)(f*100)%100);
Serial.println(str);
delay(2000);
}

Cancellato post :slight_smile:

Mi sempra che sprintf() si comporti come printf(), quindi non hai problemi con numeri float negativi!

Il numero viene stampato correttamente tranne il caso dove vuoi due zeri davanti, prova a vedere se risolvi
cosi...

if(f>=0 && f<10){ // Aggiungo uno zero davanti
    sprintf(str,"0%2f",f);
}else
    sprintf(str,"%2f",f);

Ho modificato il codice postato perché "ho capito" che vuoi che mosti uno zero se il numero è minore di 10. Prima era f>0 && f<1 "solo se era zero aggiungeva un altro zero" ora invece aggiunge uno zero se la parte intera è minore di 10. :slight_smile:

sprintf come printf accetta %02d che mette lo zero in automatico se serve, ovvero 8=>08, mentre 18=>18

P.S. suggerisco usare snprint() che vuole un parametro in più, la dimensione del buffer in cui scaricare il valore.

dtostrf() non mi pare possa mettere gli 0 davanti, @datalife vuoi usare dtostr() perchè più leggero di sprintf() ?

Innanzitutto grazie

torn24:

if(f>=0 && f<10){ // Aggiungo uno zero davanti

sprintf(str,"0%2f",f);
}else
    sprintf(str,"%2f",f);

cosi ottengo Original value: 10.00 ?

Infatti ho letto che "Arduino has a small limitation in sprintf function that does not print correctly float numbers ... that the float is always formatted a question mark '?'. There is a little trick to correctly print the float value using sprintf.

sprintf(str, "String value: %02d.%02d", (int)f, (int)(f*100)%100);

A better solution is to use the dtostrf function. It it is more flexible and works well also with negative numbers.

So che sprintf è identico a printf quindi per questo mi ero orientato su dtostrf dato che gradirei visualizzare su LCD un valore sempre a 5 caratteri sia in negativo che positivo compreso tra -9.99 e 14.00

-9.99 sono 5 caratteri
-1.99 sono 5 caratteri
02.46 sono 5 caratteri
14.00 sono 5 caratteri

Spero di aver spiegato il mio obbiettivo

Forse grazie a voi ho risolto.
La soluzione era li, troppo semplice...

void setup()
{
  Serial.begin(115200);
}

void loop()
{
  float f = -0.01;
  Serial.print("Original value: ");
  Serial.println(f);

  char str[50];
  if (f >= 0 && f < 10) { // Aggiungo uno zero davanti
    sprintf(str, "String value: %02d.%02d", (int)f, (int)(f * 100) % 100); //visualizzo due cifre + due decimali
  } else
    dtostrf(f, 2, 2, str); //visualizzo numeri negativi e > 10 con due decimali

  Serial.println(str);
  delay(2000);
}

Corretto ?

Vero, dimenticavo che sprintf su Arduino non funziona con i numeri decimali (float o double quindi %f)

Mi pare il codice possa andare, non capisco però perché usi if, non va bene sempre la sprintf che hai messo ?

su un valore float negativo, se uso solo la sprintf mi restituisce un valore sballato sprintf non funziona su numeri float negativi.

esempio : float = -0.01 ottengo
Original value: -0.01
String value: 00.-1

e se uso solo il dtostrf i negativi li stampa correttamente, ma non ottengo lo zero davanti al valore sotto 10

esempio : float = 1.25 ottengo
Original value: 1.25
String value: 1.25

con l'utilizzo di if...else uso sia sprintf per i valori sotto 10 e dtostrf per i negativi e quelli sopra 10
cosi ho tutto corretto

esempio : float = -0.01 ottengo
Original value: -0.01
String value: -0.01 i miei 5 caratteri

float = 0.0 ottengo
Original value: 0.00
String value: 00.00 i miei 5 caratteri

float = 1.2 ottengo
Original value: 1.20
String value: 01.20 i miei 5 caratteri

float = 12.99 ottengo
Original value: 12.99
String value: 12.99 i miei 5 caratteri

Okay, capito.
Eventualmente, per usare solo sprintf, potresti mettere l'if per verifcare se il numero è negativo,
se negativo usi sprintf passandogli il valore -f (essendo negativo diventa positivo)

 char str[10];
  if (f >= 0 && f < 10) { // Aggiungo uno zero davanti
    sprintf(str, "String value: %02d.%02d", (int)f, (int)(f * 100) % 100); 
  } else
    sprintf(str, "String value: -%02d.%02d", -(int)f, -(int)(f * 100) % 100);
  Serial.println(str);

P.S. riguardando la documentazione di sprintf, prova "% 02d.%02" come formato, effettivamente -8 sarebbe -08 ovvero 3 caratteri; mi pare puoi usare uno spazio per il segno (non provato su Arduino)
quindi: printf("% 02d.%02d\n",(int)f, abs((int)(f*100)%100) );

Con i due sprintf ottengo

Original value: -1.99
String value: -⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮

idem con prontf
Original value: 1.99
String value: 0⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮

Original value: -1.99

penso che questa info sia vera

"A better solution is to use the dtostrf function. It it is more flexible and works well also with negative numbers."

Provato su Arduino IDE 1.8.7, core 1.23
effettivamente lo spazio non funziona molto... però non mi da quel casino che hai tu. Sbagli a sparare in buffer tutta la frasona. Ti obbliga a buffer da 50, rischi di uscire dalla memoria.

char str[10];
  f=-4.01;
  Serial.print("Original value: ");Serial.println(f);
  snprintf(str,10,"% 02d.%02d", (int)f, abs((int)(f * 100) % 100));
  Serial.print("String value: "); Serial.println(str);

P.S. fatte altre prove.
Mi pare se usi spazio, allora la dimensione %0xd deve tenere conto del carattere in più, ovvero % 03d

float f = 4.01;
char str[10];

void setup()
{ Serial.begin(9600);
  
  f=4.01;
  Serial.print("Original value: ");Serial.println(f);
  snprintf(str,10,"% 03d.%02d", (int)f, (int)(f * 100) % 100);
  Serial.print("String value: "); Serial.println(str);
  
  f=-4.01;
  Serial.print("Original value: ");Serial.println(f);
  snprintf(str,10,"% 03d.%02d", (int)f, abs((int)(f * 100) % 100));
  Serial.print("String value: "); Serial.println(str);

  f=-14.01;
  Serial.print("Original value: ");Serial.println(f);
  snprintf(str,10,"% 03d.%02d", (int)f, abs((int)(f * 100) % 100));
  Serial.print("String value: "); Serial.println(str);
}
 
void loop(){}

Ottengo:

Original value: 4.01
String value:  04.01
Original value: -4.01
String value: -04.01
Original value: -14.01
String value: -14.01

occupando per la parte intera sempre 3 caratteri (infatti -14 sono 3 caratteri)

nid69ita:
P.S. fatte altre prove.
Mi pare se usi spazio, allora la dimensione %0xd deve tenere conto del carattere in più, ovvero % 03d

Innanzitutto GRAZIE per il tuo tempo e per le prove, veramente grazie.

Ho preso il tuo codice e tutto funzione alla grande, tranne che sui valori negativi sotto il valore 1.00
infatti se inserisco un valore compreso tra -0.01 e -0.99 sprintf ti restituisce il valore in positivo

Original value: -0.99
String value: 00.99

come inserisci il valore -1.00 tutto torna a funzionare alla grande

Original value: -1.00
String value: -01.00

Come dicevo penso che la strada corretta sia sprintf per i valori sotto 10 e dtostrf per i negativi e quelli sopra 10 cosi ho tutto corretto

Non so se è un bug di sprintf/printf o se è voluto, ma i float sono sempre complessi da gestire (almeno per me)