4 char to 1 float---- problema concat char in stringa

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:

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:

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?

aureliusss:
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.

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

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.

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

E io che ho detto ? Devi usare i puntatori o una union.

sisi, è che mi aspetto che funzioni questo:

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

lesto:
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.

ok, quindi entra in gioco un autoconversione nascosta.ora mi torna tutto

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

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

sono passato ad arduino due per non avere problemi di memoria e baudrate però ho cambiato il codice in questo:

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?

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/

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?

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.

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

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.

il discorso è questo:
prima eseguivo la lettura dei caratteri in questa maniera:

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ù