Forum: Compiler & IDEs float zu 4x8Bit und zurück


von qwertz (Gast)


Lesenswert?

Hallo,

ich messe mit dem ADC die Spannung eines Stromwandlers und berechne 
daraus einen Messwert. Dieser liegt mir als float Zahl vor.

Die float Zahl (vm) möchte ich via CAN-Nachricht verschicken und beim 
Empfänger wieder in eine float Zahl wandeln.

Das mache ich bisher so:

Senden:
1
uint8_t mm_data[4] = {0};
2
uint8_t *mm_data_ptr;
3
  
4
mm_data_ptr = mm_data;    
5
memcpy((void*)&mm_data, &vm, sizeof(float));
6
    
7
for(uint8_t i=0;i<4;i++)
8
{
9
msg.data[i] = *mm_data_ptr;
10
mm_data_ptr++;
11
}
12
can_send_message(&msg);
Empfangen:
1
float data;
2
memcpy(&data, can_dump_frame->data, sizeof(float));
3
printf("Value: %f A\n",data);
Ist es so richtig?
Oder würdet ihr es anders machen?
Bekomme irgendwie nicht das richtige angezeigt beim printf() ....


Grüße

: Bearbeitet durch User
von Johann L. (gjlayde) Benutzerseite


Lesenswert?

qwertz schrieb:
> Ist es so richtig?

Nur falls auf beiden Seiten float die gleiche Darstellung hat.

In dem Fall brauchst du auch kein mm_data sondern kannst die Adresse des 
float direkt in die Senderoutine (die wohl const void* nimmt) geben.

Ansonsten ist das Forum voll mit dem Thema, es wird gefühlt ca. 1x pro 
Woche durchgekaut.

: Bearbeitet durch User
von qwertz (Gast)


Lesenswert?

> Nur falls auf beiden Seiten float die gleiche Darstellung hat.
ATmega88 <--> RaspberryPi (Linux)

> In dem Fall brauchst du auch kein mm_data sondern kannst die Adresse des
> float direkt in die Senderoutine (die wohl const void* nimmt) geben.

Senderoutine?

von Karl H. (kbuchegg)


Lesenswert?

qwertz schrieb:

> uint8_t mm_data[4] = {0};
> uint8_t *mm_data_ptr;
>
> mm_data_ptr = mm_data;
> memcpy((void*)&mm_data, &vm, sizeof(float));

Da kopierst du ja schon die Bytes ins Array

> for(uint8_t i=0;i<4;i++)
> {
> msg.data[i] = *mm_data_ptr;
> mm_data_ptr++;
> }

wozu dann nochmal kopieren?

wozu eigentlich die extra Pointer Variable und das extra Array? Wenn in 
msg sowieso schon ein Byte Array enthalten ist, warum lässt du memcpy 
die Bytes nicht gleich dort hinein kopieren?

> Bekomme irgendwie nicht das richtige angezeigt beim printf() ....

Dann lass dir halt mal die Bytes ausgeben und sieh nach, ob die beim 
Sender und beim Empfänger identisch sind.

Wenn sie es sind, dann verwenden die beiden Parteien wohl 
unterschiedliche Floating Point Darstellungen. Muss nicht sein, kann 
aber sein. Der Bytevergleich macht dich sicher. Denn dann weißt du 
zumindest schon mal, dass auf der CAN Übertragung nichts passiert ist 
und der Empfänger genau das zu sehen kriegt, was der Sender auch 
weggeschickt hat.

von holger (Gast)


Lesenswert?

>Die float Zahl (vm) möchte ich via CAN-Nachricht verschicken und beim
>Empfänger wieder in eine float Zahl wandeln.

Verschick eine Ganzzahl die deinen Strom in uA darstellt.
Bei einer 32Bit Zahl sollte das für alles ausreichen was du
so an Strom messen kannst.

Mit float hast du nur Ärger am Hals.

von qwertz (Gast)


Lesenswert?

> Mit float hast du nur Ärger am Hals.

Okay, nun verpacke ich eine 32Bit zahl in den CAN_Frame. Das ganze wird 
zunächst in einen Ringpuffer geschrieben und später verschickt:

In Puffer:
1
memcpy((void*)&mm_buf[mm_buf_h], &vm, sizeof(uint32_t)); 
2
...

Senden:
1
for(tt; tt != th; tt = (tt + sizeof(uint32_t)) & (MM_BUFSIZE -1))
2
{
3
  msg.id=ID;    
4
  mm_buff_ptr = mm_buff + tt;
5
    
6
  for(i=0;i<4;i++)
7
  {
8
    msg.data[i] = *mm_buff_ptr;
9
    mm_buff_ptr++;
10
  }
11
  
12
  can_send_message(&msg);
Empfangen:
1
memcpy(&dat, can_dump_frame->data, sizeof(long));
2
3
printf("Value: %i A\n",dat);

Es erscheint der richtige Wert im Terminal.
Allerdings nur eine 4-Stellige Zahl.
Wo ist der Rest meiner 32 Bit geblieben?

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

%i und long passen nicht zueinander.

von qwertz (Gast)


Lesenswert?

> %i und long passen nicht zueinander.
Was nutze ich dann für long?
Durch %li ändert sich nichts.


Ich würde es ja eigentlich gern als float Zahl auf dem Terminal 
ausgeben:

long dat;

memcpy(&dat, can_dump_frame->data, sizeof(long));
float data = dat / 1000;
printf("Value: %f A\n",data);


Natürlich funktioniert es so nicht :(
Was mache ich falsch?

von qwertz (Gast)


Lesenswert?

okay - es klappt alles.

Danke für die Hilfe!

von holger (Gast)


Lesenswert?

>okay - es klappt alles.
>
>Danke für die Hilfe!

Als Gegenleistung könntest du mal die Lösung posten.
Oder der Thread kann gleich komplett gelöscht werden.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.