Incredibile problema con DTOSTRF arduino 0023 e 1.0

Salve ragazzi giuro che distruggo tutto. Sono sullasoglia della crisi di nervi.

Dunque ho scritto tutto il codice con IDE 0023 ma sono costretto mio malgrado a passare alla 1.0 poichè su arduino mega non mi funziona la libreria SD ( poco male )

Ho ricorretto tutto il codice e tutto funziona ( in pratica il grosso era sostituire Wconstant.h con Arduino.h )
solo che ho circa 10 librerie incluse quindi lavoro laborioso.

Tutto funziona eccetto la gestione del sensore DHT22 o meglio funziona ma...

ecco il codice funzionante sulla 0023

myDHT22.readData();                              // avvio la lettura dei dati 
        float temp = myDHT22.getTemperatureC();
        float umidity = myDHT22.getHumidity();
    
        char buffert [10];
        dtostrf(temp, 4, 1, buffert);                    // tramite questo comando converto la variabile temp (float ) in buffer mantenedo 4 caratteri totali e 1 dopo la virgola
        
        ht1632_putchar( 42, 0, buffert[0], 3);
        ht1632_putchar(48, 0, buffert[1], 3);
        //ht1632_putchar(16, 9, buffert[2], 2);
        ht1632_plot (54, 6,2);
        ht1632_puttinychar(56, 2, buffert[3], 3);
        ht1632_puttinychar(61, 0, 'C', 2);
       
        char bufferu[10];
        dtostrf(umidity, 4, 1, bufferu);                    // tramiste questo comando converto la variabile temp (float ) in buffer mantenedo 4 caratteri totali e 1 dopo la virgola
      
        ht1632_putchar(42, 9, bufferu[0], 3);
        ht1632_putchar(48, 9, bufferu[1], 3);
        //ht1632_putchar(50, 9, bufferu[2], 1);
        ht1632_plot (54, 15,1);
        ht1632_puttinychar(56, 11, bufferu[3], 3);

ora guardate cosa succede.

Con la ide 0023 la funzione dtostrf sembra inserire nel buffer correttamente i valori

Mentre con la ide 1.0 NO

ho provato a cercare il mio errore ma non capisco.

Ho provato con l'esempio prensente dentro la libreria

char buf[128];
      sprintf(buf, "Integer-only reading: Temperature %hi.%01hi C, Humidity %i.%01i %% RH",
                   myDHT22.getTemperatureCInt()/10, abs(myDHT22.getTemperatureCInt()%10),
                   myDHT22.getHumidityInt()/10, myDHT22.getHumidityInt()%10);

ho aggiunto la libreria all'inizio

#include <stdio.h>

ma impapocchia numeri

come ne esco ?

Grazie mille

Daniele

IDE1.0.JPG

IDE0022.JPG

Forse la lib che usi per leggere il DHT ha dei problemi di compatibilità?
Hai provato a usarne un'altra? In rete ho visto che ce ne sono diverse.

è strano poichè se uso l'esempio preso dalla libreria e che restituisce la temperatura e l'umidità via seriale fnziona perfettamente sulla 1.0

dovrebbe restituire valori a casaccio ugualmente.

mi chiedo come cambiare la stringa
dtostrtf con sprintf ?

mi incasinano i caratteri %

ho letto in giro ma nessuno chiarisce

grazie mille

Daniele

djdanielb:
...
ho letto in giro ma nessuno chiarisce

QUESTO è piuttosto chiaro ... guarda l'esempio ... :wink:

Guglielmo

Guglielmo grazie mille. avevo trovato cosse simili ma NON spiegate in quel modo.

proviamo in questo modo

char buf[6];
      sprintf(buf, "%f  %f",
                   myDHT22.getTemperatureC, myDHT22.getHumidity ()  );

che ne dite oppure ho scritto castronerie pure ?

Grazie mille

Daniele

... sicuro che per due float ti bastino solo 6 char incluso il terminatore di stringa ??? :astonished:

Mi sa che ce ne vogliono un po' di più :grin: ... comincia con ... 20 char e guarda quanti effettivamente ne vengono usati. Altrimenti usa la forma estesa del %fW.P dove W è l'ampiezza totale e P il numero di decimali. :wink:

Guglielmo

ecco come ho provato ma nulla... =( =( =( =( =(

myDHT22.readData();                              // avvio la lettura dei dati 
        float temp = myDHT22.getTemperatureC();
        float umidity = myDHT22.getHumidity();
    
        char buf[7];
        sprintf(buf, "%f  %f",
                   myDHT22.getTemperatureC(), myDHT22.getHumidity ()  );
    
    
        ht1632_putchar( 42, 0, buf[0], 3);
        ht1632_putchar(48, 0, buf[1], 3);
        //ht1632_putchar(16, 9, buffert[2], 2);
        ht1632_plot (54, 6,2);
        ht1632_puttinychar(56, 2, buf[3], 3);
        ht1632_puttinychar(61, 0, 'C', 2);
       
       
        ht1632_putchar(42, 9, buf[4], 3);
        ht1632_putchar(48, 9, buf[5], 3);
        //ht1632_putchar(50, 9, bufferu[2], 1);
        ht1632_plot (54, 15,1);
        ht1632_puttinychar(56, 11, buf[7], 3);

djdanielb:
ecco come ho provato ma nulla... =( =( =( =( =(

...

char buf[7];
       sprintf(buf, "%f  %f", myDHT22.getTemperatureC(), myDHT22.getHumidity ()  );
...

Hai letto quello che ti ho scritto sopra ???

Fai un Serial.println(buf) per vedere quanti caratteri sono veramente usati ... :wink:

Guglielmo

Edit : ... oppure esamina il valore che ti ritorna : "If successful, the total number of characters written is returned excluding null-character appended at the end of the string, otherwise a negative number is returned in case of failure."

Almeno usa la snprintf() che ti obbliga a passare come parametro la dimensione massima di buf.
http://www.cplusplus.com/reference/cstdio/snprintf/?kw=snprintf

char buf[20];
snprintf(buf,20,"%f  %f",.....);

E come detto da @Guglielmo 7 char sono pochi. Dentro buf vengono messi anche i 2 spazi che hai messo tra i due %f. Un carattere è il fine stringa, Ti sei bruciato 3 caratteri. Ne rimangono 4 per le due cifre!!!
E se NON usi la snprintf(), la funzione non controlla la dimensione del buffer e può anche finire che scrivi oltre la dimensione del vettore buf (disastroso!!!)

l'arcano si complica...

non avevo pensato al Serial.println(buf)

visto e restituisce

? ?

in continuazione...

... ed aggiungere altre due Serial.println per myDHT22.getTemperatureC() e myDHT22.getHumidity() ??? :wink:

Così sai se tutto funziona e che valori tornano ???

Guglielmo

Nelle standard io i float sono disabilitati in arduino, cioè in avrlibc sono disabilitati, perchè le funzioni occupano molto spazio. Per abilitarle ci vuole un IDE che permetta di passare il giusto paramentro al linker g++. Il paramentro corretto lo trovi descritto nella doc di avrlibc disponibile anche online.

Con arduino l'unica è usare dtostrf, ma anche avendo la possibilità di passare il parametro al linker io preferisco usare sempre dtostrf.

Ciao.

Già ... difatti il doc riporta :

Since the full implementation of all the mentioned features becomes fairly large, three different flavours of vfprintf() can be selected using linker options. The default vfprintf() implements all the mentioned functionality except floating point conversions. A minimized version of vfprintf() is available that only implements the very basic integer and string conversion facilities, but only the # additional option can be specified using conversion flags (these flags are parsed correctly from the format specification, but then simply ignored). This version can be requested using the following compiler options:

-Wl,-u,vfprintf -lprintf_min

If the full functionality including the floating point conversions is required, the following options should be used:

-Wl,-u,vfprintf -lprintf_flt -lm

Limitations:
The specified width and precision can be at most 255.
Notes:
For floating-point conversions, if you link default or minimized version of vfprintf(), the symbol ? will be output and double argument will be skiped. So you output below will not be crashed. For default version the width field and the "pad to left" ( symbol minus ) option will work in this case.

Guglielmo

djdanielb:
Con la ide 0023 la funzione dtostrf sembra inserire nel buffer correttamente i valori
Mentre con la ide 1.0 NO

Vero che la %f e i float non funzionano per la vsprintf/snprintf/sprintf.
Ma a me con IDE 1.0.5 la dtostrf() funziona benissimo.
Prova con IDE 1.0.5 e con un esempio piccolo.

char buf[20];
float temp=123.45;

void setup()
{ delay(1000);
  Serial.begin(9600);

  int l=(temp-(int)temp)*100;
  snprintf(buf,40,"%d.%d",(int)temp,l);

  dtostrf(temp, 4, 1, buf);
  Serial.println(buf);  
}

void loop()
{
}

djdanielb:

char buf[128];

sprintf(buf, "Integer-only reading: Temperature %hi.%01hi C, Humidity %i.%01i %% RH",
                  myDHT22.getTemperatureCInt()/10, abs(myDHT22.getTemperatureCInt()%10),
                  myDHT22.getHumidityInt()/10, myDHT22.getHumidityInt()%10);

In questo caso %hi vuol dire short int (come se fosse %d ovvero decimale)
Stanno stampando prima la parte intera e poi la parte decimale dei numeri per ovviare al %f che non funziona

http://dotnetside.org/blogs/pixel/archive/2013/03/12/arduino-utilizzo-di-dtostrf-e-sprintf.aspx

Alternativa di @Gammon, formatDouble()
http://forum.arduino.cc/index.php?topic=148214.msg1114740#msg1114740

ragazzi NULLA. ha vinto lui. sono tornato alla 0023 e buonanotte.

Ogni uomo conosce i suoi limiti. Se sà fermarsi non incappa nelle disgrazie.

Grazie mille anche voi.

Daniele

leo72:
Forse la lib che usi per leggere il DHT ha dei problemi di compatibilità?
Hai provato a usarne un'altra? In rete ho visto che ce ne sono diverse.

Come detto da @Leo
Io quella libreria ho ultima versione e non c'e' bisogno di fare la myDHT22.readData();
Lo fanno internamente readTemperature() e readHumidity()
Perciò di sicuro abbiamo due versioni diverse della libreria.

Inoltre hai provato il piccolo mio esempio del post precedente con un float costante di cui è noto il valore ?
Hai provato a stampare su monitor seriale i valori float letti o li hai solo provati spedendoli al display?
La Serial.println(numerofloat,numdecimali); funziona. Questa è certa.

Come libreria per i DHT ti consiglio questa --> GitHub - adafruit/DHT-sensor-library: Arduino library for DHT11, DHT22, etc Temperature & Humidity Sensors
Per quanto riguarda "dtostrf" è una funzione che fa parte della stdio.h.
Non mi risulta, ma potrei sbagliarmi, che siano state modificate la toolchain e le librerie standard del C nel passaggio tra le due versioni, quindi l'errore deve essere del dato estratto dalla nuova lib per il DHT.

vi siete incarogniti a trovare un'alternativa senza fare dei cotrolli base.

per esempio: un piccolo sketch sulla 1.0 che prende 5 o 6 float di valore noto (attenzione all'approsimazione dei float), li mette in una stringa usando un metodo alla volta e lo stampa via seriale, oltre che via LCD.

nid69ita:
Ma a me con IDE 1.0.5 la dtostrf() funziona benissimo.
Prova con IDE 1.0.5 e con un esempio piccolo.

char buf[20];

float temp=123.45;
void setup()
{ delay(1000);
 Serial.begin(9600);
 int l=(temp-(int)temp)*100;
 snprintf(buf,40,"%d.%d",(int)temp,l);
 dtostrf(temp, 4, 1, buf);
 Serial.println(buf);  
}

void loop()
{}

Veramente, l'ho suggerito prima. :smiley: