Concatenare stringa con float (per udp client)

Sto utilizzando Arduino con lo shield ethernet per farlo funzionare da client UDP solo che sto avendo problemi perchè la funzione udp.write() non accetta come parametro i numeri in virgola mobile, io avrei bisogno di inviare messaggi formati dall'unione di una stringa di testo con l'aggiunta del valore float che leggo da un sensore.

Non sto riuscendo a crearmi una stringa che comprenda sia i caratteri che il valore float da inviare e da passare come parametro a udp.write() perchè ottengo sempre errore.

Ho provato con stringa *= analog_variable; ma mi da errore.
Se provo con stringa.concat(analog_variable) funziona ma mi appende alla fine della stringa tutti i valori che legge quindi non mi va bene perchè non aggiorna la stringa ma mi appende tutti i valori float alla fine della stessa.

Come posso fare?

Al momento, ho provato ad inviare due pacchetti di seguito, prima la stringa e poi il float ma non funziona e poi come soluzione non sarebbe l'ideale:

char sonar[] = "stringa_da_inviare=";


void loop(){
float analog_variable = RightSonar.readData(RightSonar_Address, 2);
 Udp.beginPacket(remoteIp, remotePort);
 Udp.write(sonar);
 Udp.write(FrontSonar_Reading); <-- compila senza errori, ma non manda il valore float, manda solo valori errati
 Udp.endPacket();
}

Vorrei riuscire ad inviare una stringa con il valore float, tipo se il sonar mi legge 12.5 io vorrei inviare: stringa_da_inviare=12.5

Mi sapreste dare una mano, per favore?

Forse dtostrf() potrebbe fare al caso mio?

Esatto.
Se non hai risolto e se hai pazienza stasera quando torno a casa ti posto il codice per la conversione e la creazione della stringa.

Adesso con:

 dtostrf(FrontSonar_Reading,1,2,temp);

riesco ad ottenere in "temp" il valore float e ad inviarlo tramite udp.write();

Il problema è che, per ottimizzare il tutto, vorrei poter concatenare l'array di caratteri con "temp" ed inviare il tutto una sola volta invece di dover inviare due pacchetti distinti.

Non riesco a capire come fare a concatenare l'array di caratteri con "temp".
Se hai tempo, poi, mi daresti una mano?

Ti ringrazio!

se hai bisogno di un numero con precisione alla seconda cifra decimale, per esempio, basta che prendi il tuo float e lo moltiplichi per 100 (così da trasformarlo in un int) e poi lo spedisci normalmente, quando vorrai ritirare fuori il valore originale basterà dividerlo nuovamente per 100.
Quando non è strettamente necessario i float andrebbero evitati come la peste.

Ma mi sa che il problema resta lo stesso perchè comunque non posso passare a usp.write() un intero, devo sempre concatenarlo al vettore di caratteri e non so come fare. :~

in questo caso userai itoa e poi potrai concatenare le due stringhe
edit:
http://www.pierotofy.it/pages/guide_tutorials/C/itoa/

Ma itoa() non mi ritorna la stessa stringa che mi ritornerebbe anche dtostrf()?

Io vorrei sommare la stringa ritornata all'array di caratteri e poi inviare il tutto.

Allora non avevo individuato il problema :slight_smile:
metti in un buffer la stringa fissa e poi ti fai una funzioncina che aggiunge inumeri convertiti tipo:

void BufferInsertStringValue(char * s,int startingPosition) {
  int stringLength=strlen(s)-1;
  for (int i = 0;i <= stringLength;i++) {
    stringBuffer[startingPosition + i - 1] = s[i];
  }

o se vuoi usare String fai:
String stringaDaInviare = String(stringaFissa + NomeroDaItoa);

Ti ringrazio molto!

Sembra funzionare, l'ho appena testata!

Ma secondo te, però, può essere una soluzione robusta?
Non potrebbe generare errori di memoria?

L'ho modificata per aggiungere il carattere di terminazione, non so se è giusto:

void BufferInsertStringValue(char * s,int startingPosition) {
  int i = 0;
  int stringLength=strlen(s)-1;
  for ( i = 0;i <= stringLength;i++) {
    sonar_center[startingPosition + i - 1] = s[i];
     }
  sonar_center[startingPosition + i] = '\0';  <-- CORRETTO??
}

Ho cambiato la funzione in questa:

char * BufferInsertStringValue(char * s,int startingPosition, char * command) {
  int i = 0;
  int stringLength=strlen(s)-1;
  for ( i = 0;i <= stringLength;i++) {
    command[startingPosition + i - 1] = s[i];
     }
  command[startingPosition + i] = '\0';
  return command;
}

per farla quanto più generica possibile in modo da poter usare anche altri vettori di caratteri.

Poi la richiamo con:

char * vett;
vett = BufferInsertStringValue(temp, 14, sonar_center);

Secondo voi, può essere una funzione sicura?

Vedo che sei già andato molto avanti :slight_smile:
Ti pasto il codice che usavo io per creare una stringa mista float caratteri.
E' una soluzione molto robusta, l'ho testata con una PUT per pachube.
Vedi se ti torna utile, l'unica pecca è che non è molto economica in termini di sketch.

// buffer per la conversione delle variabili
    char charbuffertout[6]; // t_out
    
// conversione delle variabili in ASCII
// conversione float dtostrf(floatVar, minStringWidthIncDecimalPoint, numVarsAfterDecimal, charBuf);
    dtostrf(mydata.toutES,4,1,charbuffertout); 
   
// composizione della stringa 
    char stringaTs[100] = "prova"; // prefisso
    strcat(stringaTs, charbuffertout);  // Field 1 t_out
    strcat(stringaTs, "ciao");  // aggiunta caratteri
    strcat ecc...

Questo codice, data una float di 12.34, tirerebbe fuori la stringa prova12.3ciao

Ti ringrazio :slight_smile:

Credo mi sia molto utile!
Vorrei solo capire la differenza nell'uso della memoria tra la soluzione di prima e quella proposta da te basata su strcat() in modo da usare quella meno dispendiosa.

Però se mi dici che l'hai usata con successo su Pachube..

Per pachube alla fine io ho scelto un approccio diverso, lasciando da parte completamente le stringe.
In generale tutto ciò che ha a che fare con queste consuma spazio in sketch e ram.
Sul codice che ti ho suggerito le note dolenti sono diverse:
L'uso di dtostrf aumenta considerevolmente (>1k) lo spazio utilizzato in sketch.
Richiede inoltre un buffer singolo (ram consumata).
Al quale va aggiunto il buffer della stringa vera e propria.
strcat di per se nn consuma molto.
Il miglior modo per renderti conto delle differenze è testarle sul campo.
Scrivi due versioni del tuo codice e compila, vedendo come varia sketch e ram.

Non so cosa devi farci di preciso con le stringhe, non ho mai usato un client udp, ma dai un occhio qui:
http://arduino.cc/forum/index.php/topic,94445.0.html
Buon lavoro!

Sì, a me potrebbe servire; se la posti mi faresti un piacere.

Per ora vado con la funzione BufferInsertStringValue() che ritorna il vettore contenente la stringa e il float (o l'int) perchè quella con strcat() mi sembra che consumi un pò di più.

A me farebbe sicuramente comodo vedere la tua soluzione;)

lavorare con i char è la soluzione più parsimoniosa in termini ri risorse, le scorciatoie come l'uso di String, dtostrf, (per le conversioni) o peggio sprintf sono comodissime, ma altrettanto pesanti, quindi sta a tè sapere quando puoi usarle, per esempio nei piccoli progetti sono stracomode, mentre se sei già con poca ram possono essere fonte di comportamenti strani e difficili da debuggare.

Grazie, ragazzi! :slight_smile:

Voi che metodo usat per capire quanta ram libera resta al vostro arduino?

Io ho un arduino mega2560 e per capire se ce la fa mi attengo solo alla grandezza dello sketch ed alla velocità di esecuzione dei calcoli.

Ci sono dei metodi precisi o più esatti per capire l'aumento o il decadimento delle prestazioni e delle risorse utilizzate a runtime?

Grazie