Come leggere dei Float da una seriale

Ciao a tutti , sono qui a chiedervi aiuto :slight_smile:
ho cercato nel forum delle risposte , ma non sono riuscito a troverle =(
qualcuno di voi mi sa dire o spiegare come un arduino uno o mega possa acquisire dei float che gli vengano inviati tramite porta seriale, nel dettaglio ho una seriale che mi invia 3 float nella stessa "stringa" e non so come estrapolarli per poi metterli in 3 variabili float distine .
:slight_smile: grazie per un eventuale aiuto

La seriale trasmette 1 byte alla volta.
Quindi una variabile numerica potrebbe essere spedita come stringa (esempio "1000"), nei singoli byte che ne rappresentano il suo valore in memoria (esempio $DA56 spedito come $DA e poi $56) oppure con qualche altro sistema.
Per capire come puoi recuperare i dati devi prima capire come vengono spediti. Conosci il protocollo di trasmissione di questi numeri in virgola mobile?

Grazie Leo per la tua risposta, io ho un sensore "9DOF Razor IMU" il quale in seriale mi fornisce questa stringa :

#YPR=11.71,-0.32,32.26

io vorrei riuscire a prelevare questi numeri e inserirli in singole variabili float

in allegato ho messo un "foto" prelevata dal serial monitor di Arduino

Io pensavo di usare la funzione "parseFloat() ", ma se ho capito bene questa funzione mi acquisirebbe solo il primo float

di nuovo grazie per il vostro aiuto :slight_smile:

Serial-Monitor.png

ginboni:
io ho un sensore "9DOF Razor IMU" il quale in seriale mi fornisce questa stringa :
#YPR=11.71,-0.32,32.26

Devi usare la funzione atof() per convertire una stringa in float e devi eseguire una scansione della stringa, byte a byte, per isolare i singoli componenti.
In pratica scansioni la stringa fino a trovare "=", da questo momento fino alla prima "," poni tutti i byte letti in una stringa temporanea di appoggio, che poi userai per la conversione, e continui così di virgola in virgola fino alla fine della stringa.

Consiglio il seguente metodo:

Numero da inviare 1234,56

Moltiplica x 100 = 123456

Invio 123456

Una volta ricevuto

123456/100 = 1234,56

Carletto

carletto:
Consiglio il seguente metodo:

Numero da inviare 1234,56

Moltiplica x 100 = 123456

Ma così si presuppone di poter manipolare il dispositivo inviante. Però lui usa un sensore che spedisce in quel formato per cui può lavorare solo sui dati in arrivo, non su quelli in partenza.

leo72:
Ma così si presuppone di poter manipolare il dispositivo inviante. Però lui usa un sensore che spedisce in quel formato per cui può lavorare solo sui dati in arrivo, non su quelli in partenza.

Volendo può facilmente modificare il software della Razor imu, sopra c'è un 328 e il relativo sketch Arduino è disponibile, anzi esistono più varianti di quel software.

astrobeed:

leo72:
Ma così si presuppone di poter manipolare il dispositivo inviante. Però lui usa un sensore che spedisce in quel formato per cui può lavorare solo sui dati in arrivo, non su quelli in partenza.

Volendo può facilmente modificare il software della Razor imu, sopra c'è un 328 e il relativo sketch Arduino è disponibile, anzi esistono più varianti di quel software.

Bene, non lo sapevo.

grazie per i vari interventi :slight_smile:
astrobeed is è vero che sulla Razor IMU c'è un 328, ma tale sensore comunica con il mondo "esterno" tramite seriale o in "Wire" per cui non mi serve modificare il SW interno a sensore :slight_smile:
Ho guardato in giro e ho scritto 2 righe di programma che è il seguente :

String Str_Sensore = String("#YPR=1.71,0.32,2.26");

int Pos_Carattere_1;
int Pos_Carattere_2;
int Pos_Carattere_3;

String Di_Servizio_1;
String Di_Servizio_2;
String Di_Servizio_3;

float Variabile_1;
float Variabile_2;
float Variabile_3;

void setup() {

Serial.begin(9600);

delay(3000);

Serial.println(Str_Sensore);

Pos_Carattere_1 = Str_Sensore.indexOf('='); // trova la posizione di "="
Pos_Carattere_2 = Str_Sensore.indexOf(',', Pos_Carattere_1 + 1); // trova la posizione della prima virgola
Pos_Carattere_3 = Str_Sensore.indexOf(',', Pos_Carattere_2 + 1); // trova la posizione della seconda virgola

Di_Servizio_1 = Str_Sensore.substring(Pos_Carattere_1 + 1, Pos_Carattere_2 ); // leggo il valore che mi interessa
Di_Servizio_2 = Str_Sensore.substring(Pos_Carattere_2 + 1, Pos_Carattere_3 ); // leggo il valore che mi interessa
Di_Servizio_3 = Str_Sensore.substring(Pos_Carattere_3 + 1 ); // leggo il valore che mi interessa

//Variabile_1 = atof(Di_Servizio_1.getChars());
//Variabile_2 = atof(Di_Servizio_2.getChars());
//Variabile_3 = atof(Di_Servizio_3.getChars());

Serial.println(Di_Servizio_1); // per controllare se la separazione sia avvenuta con successo
Serial.println(Di_Servizio_2);
Serial.println(Di_Servizio_3);

}

void loop() { }

con questo riesco a separare i vari valori , ma restano ancora delle strighe, non riesco a convertirle in variabili float vere propie ,
ho provato usate la funzione "atof()" , ma il compilatore mi da un errore , che il seguente :

'Class String' has no member named'getChars'

Ho cercato in internet la funzione "atof()" , funzione di C, ma non ho capito come usarla in Arduino :slight_smile:

ginboni:
ho provato usate la funzione "atof()" , ma il compilatore mi da un errore , che il seguente :

'Class String' has no member named'getChars'

Ho cercato in internet la funzione "atof()" , funzione di C, ma non ho capito come usarla in Arduino :slight_smile:

Il compilatore ha ragione dato che l'oggetto String di Arduino non ha il metodo getChars ma bensì toCharArray():

Copia in un array di char* il contenuto della stringa DiServizio e poi il risultato dallo in pasto a atof.

grazie Leo , dal sito arduino/reference non ho capito come usare la funzione toCharArray() :slight_smile:
mi sa che sono duro di "comprendonio" :stuck_out_tongue:
Leo gentilmente riusciresti fare un esempio di come andrebbe usato , grazie per eventuale risposta :slight_smile:

Tipo questo:

char* tempChar;
DiServizio.toCharArray(tempChar, lunghezza_che_ti_serve);

grazie delle delucidazioni Leo, per la funzione "toCharArray" ho usato: "char tempChar[10];" e non "char* tempChar;" se usavo i pointer il compilatore non mi dava errori , ma una volta provato con Arduino 2009 i valori dei float erano sempre a "0" .
Alla fine il programma prova di conversione e acquisizione mi risulta cosi :

String Str_Sensore = "#YPR=-171.11,-156.32,-162.26";

int Pos_Carattere_1;
int Pos_Carattere_2;
int Pos_Carattere_3;

String Di_Servizio_1;
String Di_Servizio_2;
String Di_Servizio_3;

char output_1[9];
char output_2[9];
char output_3[9];

float Variabile_1;
float Variabile_2;
float Variabile_3;

void setup() {

Serial.begin(9600);

delay(3000);

Serial.println(Str_Sensore);

Pos_Carattere_1 = Str_Sensore.indexOf('='); // trova la posizione di "="
Pos_Carattere_2 = Str_Sensore.indexOf(',', Pos_Carattere_1 + 1); // trova la posizione della prima virgola
Pos_Carattere_3 = Str_Sensore.indexOf(',', Pos_Carattere_2 + 1); // trova la posizione della seconda virgola

Di_Servizio_1 = Str_Sensore.substring(Pos_Carattere_1 + 1, Pos_Carattere_2 ); // leggo il primo valore
Di_Servizio_2 = Str_Sensore.substring(Pos_Carattere_2 + 1, Pos_Carattere_3 ); // leggo il secondo valore
Di_Servizio_3 = Str_Sensore.substring(Pos_Carattere_3 + 1 ); // leggo il terzo valore

Di_Servizio_1.toCharArray(output_1, 9); // copio il tutto in Arry di char
Di_Servizio_2.toCharArray(output_2, 9);
Di_Servizio_3.toCharArray(output_3, 9);

Variabile_1 = atof(output_1); // estraggo i float
Variabile_2 = atof(output_2);
Variabile_3 = atof(output_3);

Serial.println(Variabile_1); // per controllare se la separazione sia avvenuta con successo
Serial.println(Variabile_2);
Serial.println(Variabile_3);

}

void loop() { }

grazie a tutti per l'aiuto :slight_smile:

ora mi sorge un dubbio c'è un modeo per semplificare questa operazione o programma ?? :astonished: :grin:

ginboni:
grazie delle delucidazioni Leo, per la funzione "toCharArray" ho usato: "char tempChar[10];" e non "char* tempChar;" se usavo i pointer il compilatore non mi dava errori , ma una volta provato con Arduino 2009 i valori dei float erano sempre a "0" .

L'avevo usata tempo fa, mi pareva di aver usare i puntatori. Ho sbagliato :sweat_smile:

Alla fine il programma prova di conversione e acquisizione mi risulta cosi :
.............

Ricordati di allegare il codice cliccando sull'icona a forma di cancelletto (#) che trovi sopra alle faccine quando scrivi un messaggio, si legge meglio.

ora mi sorge un dubbio c'è un modeo per semplificare questa operazione o programma ?? :astonished:

Non sempre si può ottimizzare più di tanto. Nel tuo caso non saprei se le ottimizzazioni vanno a complicare il codice oppure a semplificarlo. Se ti funziona e deve fare questo, lascialo com'è.

ok , grazie di nuovo per le varie dritte :slight_smile: