Go Down

Topic: 4 char to 1 float---- problema concat char in stringa (Read 1 time) previous topic - next topic

aureliusss

Jan 29, 2013, 12:40 pm Last Edit: Jan 30, 2013, 03:45 pm by aureliusss Reason: 1
ciao a tutti,
ho già scritto nel forum riguardo il mio progetto per la tesi di usare arduino come ponte di comunicazione fra un TDR e un altro terminale di comunicazione.
cmq sono riuscito ad attivare la comunicazione fra il monitor seriale e lo strumento, ora però mi sono bloccato perchè non riesco a far interpretare i dati da arduino:

se allo strumento invio un comando che mi permette di acquisire una waveform esso mi restituisce questo tipo di stringa:
Code: [Select]

comando inviato -> :GWAV35
risposta ricevuta -> :#GWAV [byte1][byte2][byte3][byte4]...[byte n-esimo]


ora dovrei leggere 4 byte alla volta e accorparli per avere un float in formato standard ieee754(così me li trasmette lo strumento).

come faccio a fare un'operazione del genere?
che tipo di codifica usa arduino per i float?

ho tentato con un programma di test se potessi riuscire ad accorpare 4 byte in un'unica informazione di tipo float ma non ci sono riuscito:
questo il codice di prova che ho usato:
Code: [Select]
void setup(){
 Serial.begin(9600);
 float a = '?'; // bin =    00111111
 float b = 0x00;// bin = 00000000
 float c = 0x00;// bin = 00000000
 float d = 0x00;// bin = 00000000
 
 // accorpando in 4 bytes in formato ieee754 risulta:
 // bin(00111111|00000000|00000000|00000000) = float(0.5)
 
 float a1 = a<<24; //in teoria (00111111) 00000000 00000000 00000000
 float b1 = b<<16; //in teoria  00000000 (00000000) 00000000 00000000
 float c1 = c<<8;  //in teoria  00000000  00000000 (00000000) 00000000
 float d1 = d;     //in teoria  00000000  00000000 00000000 (00000000)
 
 float risultato = a1 | b1 | c1 | d1
 //bitwise or fra i 4 float per ottenere il float "finale"
 
 Serial.println(risultato);
 
}
void loop(){
}


ma il l'operazione di bitwise mi da errore di compilazione.
mi potete aiutare?

astrobeed


ma il l'operazione di bitwise mi da errore di compilazione.
mi potete aiutare?


Il problema non è l'errore di compilazione, è la logica che usi ad assere totalmente sbagliata, per via della natura esponenziale dei float non puoi ricostruirli shiftando i singoli byte, questo è applicabile solo per gli interi.
Puoi ricostruirlo con solo due modi, tramite puntatori o tramite una union, argomento che abbiamo trattato molte volte nel forum.
Usare il GOTO in C è ammettere la propria sconfitta come programmatore

lesto

scusa astro ma se i dati in arrivo sono un float "smontato" in byte tramite bitshift (come nel suo caso) dovrebbe essere possibile riscotsruirlo.. magri un pò di magia tipo
Code: [Select]

byte numero[4]={0x3f, 0x00, 0x00, 0x00}; //0x3f = B00111111
float *num;
num=numero;
float val = *nun;


ahhhh ora ho capito il suo errore, "a, b, c, d" li ha dichiarati come float e non come byte... quindi quel 0x3F era convertito nella sua rappresentazione float che non è quella che ci aspettiamo.
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

astrobeed


scusa astro ma se i dati in arrivo sono un float "smontato" in byte tramite bitshift (come nel suo caso) dovrebbe essere possibile riscotsruirlo.. magri un pò di magia tipo


E io che ho detto ? Devi usare i puntatori o una union.
Usare il GOTO in C è ammettere la propria sconfitta come programmatore

lesto

sisi, è che mi aspetto che funzioni questo:

Code: [Select]

long a = 0x3f<<24; // bin =    00111111
long b = 0x00<<16;// bin = 00000000
long c = 0x00<<8;// bin = 00000000
long d = 0x00;// bin = 00000000

float ris = a|b|c|d;
ù

come al solito sono al lavoro, quindi codice non testato

edit: ah ok, forse non funziona propio perchè questo valore viene tentato di essere convertito in notazione ieee754
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

astrobeed


sisi, è che mi aspetto che funzioni questo:


Non funziona, o meglio ti ritrovi nel float l'equivalente del valore 0x3F000000, cioè 1056964608.00, e non 0.5 come atteso.

Usare il GOTO in C è ammettere la propria sconfitta come programmatore

lesto

ok, quindi entra in gioco un autoconversione nascosta.ora mi torna tutto
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

aureliusss

ragazzi dato che vi vedo appassionati  :P vi chiedo un'altra cosa.
ho uno strano comportamento con il concatenamento dei caratteri in una stringa:

Code: [Select]
while(tdr.available()){ //il write su Serial è di debug

    Serial.write(tdr.peek()); // per debug
    char inChar = tdr.read()
    response.concat(inChar);
  }


confrontando la stringa response con ciò che mi viene che viene scritto sul monitor seriale(so per certo che ciò che sta scritto sul monitor è giusto), allora, sulla stringa mi escono caratteri in più del tipo:
monitor seriale -> :DUMP?000[...]
response -> :DUMP?0P?000[...]
facendo anche altre prove sembra che nella stringa response, ad un certo punto vengano inseriti dei char già letti.

avete idee a riguardo?
P.S. response è un oggetto String

aureliusss

sono passato ad arduino due per non avere problemi di memoria e baudrate però ho cambiato il codice in questo:
Code: [Select]
while(Serial1.available()){
    inByte = Serial1.read();
    Serial.write(inByte);
    response+=inByte;
  }

  if(inByte == 13){
    char auxiliary[response.length()];
    response.toCharArray(auxiliary,response.length());
    for(int i=0;i<response.length();i++){
      Serial.print(auxiliary[i],HEX);
    }
    for(int i=6;i<response.length();i+=4){
      datum.byteData[3] = char(auxiliary[i]);
      delay(10);
      datum.byteData[2] = char(auxiliary[i+1]);
      delay(10);
      datum.byteData[1] = char(auxiliary[i+2]);
      delay(10);
      datum.byteData[0] = char(auxiliary[i+3]);
      delay(10);
      Serial.println(datum.floatDatum,5);
    }
  }

ho dei problemi perchè inByte = Serial.read() mirestituisce il valore decimale del carattere letto giusto? come faccio a trasformarlo in caratteri in maniera tale da far funzionare il for successivo per ottenere i float?

leo72

Serial.read restituisce il byte letto dal buffer seriale.
Tale byte va in valore da 0 a 255. Se lo devi convertire in stringa, potresti usare itoa:
http://www.cplusplus.com/reference/cstdlib/itoa/

aureliusss

ciò che non mi sembra chiaro è che cmq il valore binario del byte o carattere che sia dovrebbe essere lo stesso, giusto? ma allora perchè quando uso la union per i float mi escono numeri sbagliati?

leo72

NOn credo che con la Union ti possa aiutare. Un float occupa 4 byte ed è salvata in notazione mantissa+esponente. Un byte è un unsigned char. Ma recuperando 1 byte, non peschi tutto il valore del float.

astrobeed


NOn credo che con la Union ti possa aiutare. Un float occupa 4 byte ed è salvata in notazione mantissa+esponente. Un byte è un unsigned char


La union ti permette di ricostruire un qualunque tipo dato partendo da altri tipi dati, ovviamente devono essere compatibili, è perfetta, oltre che semplice ed elegante, per questo utilizzo.
Se hai i quattro byte che compongono il float tramite la union ottieni nuovamente il valore iniziale, però è indispensabile che l'ordine di caricamento dei singoli byte sull'array della union rispecchi l'ordine con cui è stato scomposta il float, ovvero può arrivarmi come primo valore sia il primo byte del float che l'ultimo, a seguire i restanti tre, se non li ricompongo nello stesso ordine ovviamente il valore della float non può essere corretto.
Altro requisito indispensabile è che lo standard di rappresentazione del float sia indentico tra l'apparato che lo trasmette e quello che lo riceve, in caso contrario si ottengono valori errati dopo la ricostruzione.
Usare il GOTO in C è ammettere la propria sconfitta come programmatore

aureliusss

il discorso è questo:
prima eseguivo la lettura dei caratteri in questa maniera:
Code: [Select]
while(Serial.available()){
inByte = Serial.read();
response.concat(char(inByte));
}


e la union funziona alla perfezione, se non fosse che, dovendo ricevere una stringa di 8/9000 caratteri, ricevevo risultati sbagliati, secondo me a causa del fatto che la concatenazione si imputtanasse con la conversione a char.
dunque ho riscritto l'acquisizione per renderla più semplice senza 'castare' la varibile già in lettura, con il codice che ho messo nel post precedente.
ora però la conversione da 4byte a float non funziona più

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy