Forum: Compiler & IDEs Float to Raw Bytes


von mgiaco (Gast)


Lesenswert?

Hallo wie kann ich am einfachsten ein float in Raw Bytes splitten (ARM 
GCC). Ich möchte float Zahlen übertragen. Auf der PC Seite verwende ich 
eine fertige funktion die in Java verfügbar ist, wie mach ich das auf 
der ARM Seite.

Besten Dank schon mal.

mgiaco

von mgiaco (Gast)


Lesenswert?

1
public static void floatToRawByteArray(float data, int buffpos, byte buff[]) 
2
{
3
        int temp = Float.floatToRawIntBits(data);
4
  intToRawByteArray(temp, buffpos, buff); 
5
}
6
  
7
public static void intToRawByteArray(int data, int buffpos, byte buff[]) 
8
{
9
  buff[buffpos++] = (byte)(data>>>24 & 0xFF);
10
  buff[buffpos++] = (byte)(data>>>16 & 0xFF);
11
  buff[buffpos++] = (byte)(data>>>8 & 0xFF); 
12
  buff[buffpos++] = (byte)(data & 0xFF);
13
}

So mache ich es in JAVA aber mir fehlt hier auf der gcc Seite die 
Funktion floatToRawIntBits(). Und nur mit einem Typecast geht es nicht. 
Wie kann ich von der float Zahl jedes Byte einzeln lesen?

danke

von Uhu U. (uhu)


Lesenswert?

Bist du sicher, daß der PC das binäre Float-Format auch richtig 
interpretiert?

In C kannst du es auf jeden Fall so machen:
1
typedef _float_to_raw union {
2
   float    v;
3
   char     r[sizeof (float)];
4
} float_to_raw;
5
6
float_to_raw R;
7
R.v = <float-wert>;
8
// In R.r steht jetzt der float-Wert als Bytefolge

von mgiaco (Gast)


Lesenswert?

Jepp bin ich sicher ich portier gerade eine funktionsfähiges Progamm von 
Java nach C, von dort stammt das von oben. Danke werde es gleich mal 
ausprobieren ich dachte nicht an union, sieht aber sehr einfach aus im 
Vergleich zu java.

mgiaco

von mgiaco (Gast)


Lesenswert?

Ach ja aufpassen muss man natürlich wegen big und littel endian, aber 
das ja eh klar. ==> Und das kann man ja schnell testen.

mgiaco

von G. B. (geri)


Lesenswert?

Hallo

Interessante Variante. Wie wird der Code aber nun übersetzt bzw. was ist 
v.a. schneller? Das Kopieren per Type-casting oder per memcpy für ARM 
mit gcc?

z.B.

char buf[4];
float f = 10;

memcpy(buf,f,sizeof(f);


Beste Grüsse

Geri

von Rolf Magnus (Gast)


Lesenswert?

Am schnellsten dürfte sowas sein:

float f = 10;
char* buf = (char*)&f;

Hier muß nämlich nicht kopiert werden. f wird direkt als Array aus char 
interpretiert.

von G. B. (geri)


Lesenswert?

Hallo Magnus

Vielen Dank für Deine Rückmeldung.

Dann würdest du s.w. auch eine effiziente Variablenübergabe so 
gestalten:

1
void doAny1(float* a)
2
{
3
    ..
4
}
5
6
void doAny2()
7
{
8
    char buf[20]; // enthält 5 floating point variablen
9
10
    DaAnything((float*)&buf[4]); // Übergabe des zweiten Wertes
11
}

Beste Grüsse

Geri

von Rolf Magnus (Gast)


Lesenswert?

Das würde ich so nicht schreiben, denn da ist ein passendes Alignment 
nicht garantiert. Es ist eine Sache, einen float als Array aus char zu 
interpretieren, denn das geht immer, da char kein spezielles Alignment 
braucht. Wenn du aber umgekehrt ein Array aus char als float 
interpretieren willst, sieht's anders aus, denn ein float muß beim ARM 
an einem vielfachen von 4 Bytes starten.

von mgiaco (Gast)


Lesenswert?

@ Magnus. Aha okay aber wie realisiere ich jetzt richtig eine 
floatToRawBytes() und eine RawBytesToFloat() auf dem ARM7? Ich brauch 
also beide Seiten (Senden und Empfangen).

besten dank schon mal.

von Karl H. (kbuchegg)


Lesenswert?

Da wirst du dann wohl nicht umhin kommen, das char Array
das du als Buffer benutzt richtig zu alignen.
zb so


float tmpBuffer[20];
char* buffer = (char*)buffer;


Jetzt hast du ein char Array bei dem du mittels
   (float*)&(buffer[NrFloat*sizeof(float)])

reinindizieren kannst, und wo das Alignment für float
passen müsste.

von mgiaco (Gast)


Lesenswert?

@karl heinz

>>float tmpBuffer[20];
>>char* buffer = (char*)buffer;

wiso float tmpBuffer[30] ?? verstehe ich nicht.

Ich brauche eine Funktion

Float -> 4Byte für Senden.

und eine

4Byte -> Float für Empfangen.

von mgiaco (Gast)


Lesenswert?

Eigentlich müsste das dann ja so sein nicht

float tmpBuffer[20];
char* buffer = (char*)tmpbuffer;

mathias

von Karl H. (kbuchegg)


Lesenswert?

mgiaco wrote:
> @karl heinz
>
>>>float tmpBuffer[20];
>>>char* buffer = (char*)buffer;
>
> wiso float tmpBuffer[30] ?? verstehe ich nicht.
>
> Ich brauche eine Funktion
>
> Float -> 4Byte für Senden.
>
> und eine
>
> 4Byte -> Float für Empfangen.

Dann machst du halt nur 1 float.
Ich kann ja nicht wissen, wieviele float du zu übertragen
hast

float tmpBuffer;
char* buffer = (char*)&tmpBuffer;

von mgiaco (Gast)


Lesenswert?

Okay super danke denn Buffer kann ich dann für Empfangen und Senden 
nehem.

mathias

von mgiaco (Gast)


Lesenswert?

Hallo es funktioniert leider noch nicht, ich denke ich mache generell 
was falsch. Habe verschiedenes probiert komme aber nicht zu einer Lösung 
die funktioniert. floatToRawByteArray ist nich das problem jedoch das 
zurück wandeln.
1
float rawByteArrayToFloat(uint8_t data[], uint8_t offset) 
2
{
3
    uint8_t i;  
4
    float tmpBuffer = 0.0f;
5
    char  *buffer = (char*)&tmpBuffer;
6
    
7
    for(i=0; i<4; i++)
8
    {
9
        buffer[i] = data[i+offset];
10
    }
11
    
12
    return *((float*)&(buffer[offset]));
13
}
14
15
void floatToRawByteArray(float data, uint8_t buffpos, uint8_t buff[]) 
16
{
17
    float_to_raw ufloat;
18
    ufloat.value = data;
19
    buff[buffpos++] = (uint8_t)ufloat.raw[0];
20
    buff[buffpos++] = (uint8_t)ufloat.raw[1];
21
    buff[buffpos++] = (uint8_t)ufloat.raw[2];
22
    buff[buffpos++] = (uint8_t)ufloat.raw[3];
23
          
24
}


danek

von mgiaco (Gast)


Angehängte Dateien:

Lesenswert?

Hier noch meine Testfiles

mgiaco

von Arc N. (arc)


Lesenswert?

return *((float*)&(buffer[offset]));
statt offset müsste da 0 stehen oder einfach return tmpBuffer oder das 
umkopieren weglassen und gleich return *((float *)&data[i + offset]); 
(falls die Byte-Order passt)

von mgiaco (Gast)


Lesenswert?

@Arc Net danke, aber wenn ich das umkopieren weglasse dann stimmt ja das 
alignment nicht, so habe ich es zumindestens verstanden. Deshalb das mit 
dem kopieren.

Zu offset super danke ich hab den Fehler nicht gesehen. Jetzt geht es ob 
es auch die schnellste implementierung ist weis ich nicht was meinen die 
Experten ?
1
//int32_t rawByteArrayToInt32(uint8_t data[], uint8_t offset) 
2
//{
3
//    int8_t i;
4
//    int32_t temp=0;
5
//    
6
//    for(i=0; i<4; i++)
7
//     temp = (temp + (data[i+offset]& 0xFF)) << 8;
8
//    return (temp>>8);
9
//}
10
11
//int32_t rawByteArrayToInt32(uint8_t data[], uint8_t offset) 
12
//{
13
//  return data[offset]<<24 | (data[offset+1]&0xff)<<16 | (data[offset+2]&0xff)<<8 | (data[offset+3]&0xff);  
14
//}
15
16
int32_t rawByteArrayToInt32(uint8_t data[], uint8_t offset) 
17
{  
18
  return (*(int32_t*)(&data[offset]));
19
}
20
21
void int32ToRawByteArray(int32_t data, uint8_t buffpos, uint8_t buff[]) 
22
{
23
    buff[buffpos++] = (uint8_t)(data & 0xFF);
24
    buff[buffpos++] = (uint8_t)(data>>8 & 0xFF); 
25
    buff[buffpos++] = (uint8_t)(data>>16 & 0xFF);
26
    buff[buffpos++] = (uint8_t)(data>>24 & 0xFF);
27
}
28
29
//int16_t rawByteArrayToInt16(uint8_t data[], uint8_t offset) 
30
//{
31
//  int8_t i;
32
//    int32_t temp=0;
33
//  
34
//    for(i=0; i<2; i++)
35
//    temp = (temp + (data[i+offset]& 0xFF)) << 8;
36
//  return (int16_t)(temp>>8);
37
//}
38
39
//int16_t rawByteArrayToInt16(uint8_t data[], uint8_t offset) 
40
//{
41
//  return data[offset+0]<<8 | (data[offset+1]&0xff);
42
//}
43
44
int16_t rawByteArrayToInt16(uint8_t data[], uint8_t offset) 
45
{
46
  return (*(int16_t*)(&data[offset]));
47
}
48
49
void int16ToRawByteArray(int16_t data, uint8_t buffpos, uint8_t buff[]) 
50
{
51
    buff[buffpos++] = (uint8_t)(data & 0xFF);
52
    buff[buffpos++] = (uint8_t)(data>>8 & 0xFF);
53
}
54
55
int8_t rawByteArrayToInt8(uint8_t data[], uint8_t offset) 
56
{
57
    return (int8_t)(data[offset]);
58
}
59
60
void int8ToRawByteArray(int8_t data, uint8_t buffpos, uint8_t buff[]) 
61
{
62
    buff[buffpos++] = (uint8_t)(data & 0xFF);
63
}
64
65
66
float rawByteArrayToFloat(uint8_t data[], uint8_t offset) 
67
{
68
    uint8_t i;  
69
    float tmpBuffer = 0.0f;
70
    char  *buffer = (char*)&tmpBuffer;
71
    
72
    for(i=0; i<4; i++)
73
    {
74
        buffer[i] = data[i+offset];
75
    }
76
    
77
    return *((float*)(buffer));
78
}
79
80
void floatToRawByteArray(float data, uint8_t buffpos, uint8_t buff[]) 
81
{
82
    float_to_raw ufloat;
83
    ufloat.value = data;
84
    buff[buffpos++] = (uint8_t)ufloat.raw[0];
85
    buff[buffpos++] = (uint8_t)ufloat.raw[1];
86
    buff[buffpos++] = (uint8_t)ufloat.raw[2];
87
    buff[buffpos++] = (uint8_t)ufloat.raw[3];
88
}

Was könnte man noch optimieren? Die rawToInt32 und rawToInt16 ist 
deutlich geschrupft zur Java Version.

Danke an alle

mgiaco

von mgiaco (Gast)


Lesenswert?

Wäre echt super wenn da noch ein Profi drüberschauen könnte.

Karlheinz, Magnus ... ?

Danke schon mal

von Arc N. (arc)


Lesenswert?

Warum? Das einzige wäre vielleicht noch das schon angesprochene 
rawByteArrayToFloat, das man genauso wie die Int32-Version 
implementieren könnte.
Je nach Compiler und/oder Architektur könnte bei der anderen Richtung 
auch eine Variante ohne Shifts schneller/kürzer sein.
1
void int32ToRawByteArray(int32_t data, uint8_t buffpos, uint8_t buff[]) 
2
{
3
    register uint8_t* dp = (uint8_t *)&data;
4
    buff[buffpos++] = dp[0];
5
    buff[buffpos++] = dp[1];
6
    buff[buffpos++] = dp[2];
7
    buff[buffpos++] = dp[3];
8
}

von mgiaco (Gast)


Lesenswert?

@ Arc Net

Super danke.

mgiaco

von Code (Gast)


Lesenswert?

Danke für die schöne Lösung..

hatte genau das gleiche Problem aber dank diesen Thread habe ich die 
Lösung zu meinem Problem ;-)

Dankeeee

von Karl H. (kbuchegg)


Lesenswert?

mgiaco wrote:

> Was könnte man noch optimieren?

Ich würde die Funktionen noch mehr 'symetrisch' implementieren.

Wenn das hier
1
void floatToRawByteArray(float data, uint8_t buffpos, uint8_t buff[]) 
2
{
3
    float_to_raw ufloat;
4
    ufloat.value = data;
5
    buff[buffpos++] = (uint8_t)ufloat.raw[0];
6
    buff[buffpos++] = (uint8_t)ufloat.raw[1];
7
    buff[buffpos++] = (uint8_t)ufloat.raw[2];
8
    buff[buffpos++] = (uint8_t)ufloat.raw[3];
9
}

die Funktion für float -> raw ist, dann wäre für mich
eine naheliegende Implementierung für die Umkehrung
1
float rawByteArrayToFloat(uint8_t data[], uint8_t offset) 
2
{
3
    float_to_raw ufloat;
4
5
    ufloat.raw[0] = data[offset++];
6
    ufloat.raw[1] = data[offset++];
7
    ufloat.raw[2] = data[offset++];
8
    ufloat.raw[3] = data[offset++];
9
10
    return ufloat.value;
11
}

Da sind jetzt dieselben Elemente wie in der 'Hin-Version' enthalten,
nur alles genau anders rum. Dementsprechend weniger muss ich überlegen,
ob diese Operation das Gegenteil der Hin-Operation ist.

Deine Version ist zwar nicht falsch, kommt mir aber so vor wie
wenn du eine hypotetische Hin-Operation mit einer Division
implementierst, während du die Rückoperation mittels fortgesetzter
Addition in einer Schleife (anstelle einer Multiplikation) machst.

Edit: Ooops. Sehe gerade, dass die relevanten Codeteile vom
August stammen. Da wird der Poster wohl hier nicht mehr rumlungern :-)

von Code (Gast)


Lesenswert?

naja es gibt auch andere die das selbe Problem haben und da ist es sehr 
hilfreich hier reinzuschauen..

>Edit: Ooops. Sehe gerade, dass die relevanten Codeteile vom
>August stammen. Da wird der Poster wohl hier nicht mehr rumlungern :-)

es muss ja nicht für den OP sein, ich bin ja auch noch da und kann es 
bei mir einsetzten. Dein Vorschlag finde ich super, echt einfach und 
geschickt ;-)

von Karl H. (kbuchegg)


Lesenswert?

Code wrote:

> es muss ja nicht für den OP sein, ich bin ja auch noch da und kann es
> bei mir einsetzten. Dein Vorschlag finde ich super, echt einfach und
> geschickt ;-)

OK.
Wenn wir schon bei Code-Aufräumarbeiten sind.
vergleiche mal die beiden Funktionen

void floatToRawByteArray(float data, uint8_t buffpos, uint8_t buff[])
float rawByteArrayToFloat(uint8_t data[], uint8_t offset)

fällt dir dabei was auf?

Betrachte die Interfaces.
In der ersten Funktion ist die Reihenfolge
  zuerst den Offset und dann der Buffer
in der zweiten Funktion ist es genau umgekehrt.

(Wenn wir jetzt mal davon abehen, dass die eine Funktion ihr
Ergebnis per Returnwert liefert während die andere die
Ausgabe über einen Parameter abliefert)

Sowas ist zwar kein Beinbruch, aber in einem ordentlichen
Interface ordnet man die Argumente in der logischen Reihenfolge
immer gleich an. Das spart Nachdenken, Nachsehen welche
Reihenfolge richtig ist und in weiterer Folge spart das auch
so manchen logischen Fehler.

von Code (Gast)


Lesenswert?

eins verstehe ich nicht :-(
1
/* für float to Raw-Byte */
2
typedef union{
3
  float value;
4
  char raw[sizeof(float)];
5
}float_to_raw;

da ich union nie benutzt habe, weiß ich nicht recht was es genau macht.
Ist es richtig wenn ich sage, dass union die Typumwandlung erzeugt. 
float-Wert wird sofort in char umgewandelt (und umgekerht) und bekommt 
es auch als Wert zugewissen. Und sobald sich irgendwo etwas ändert, 
aktuallisiert union den Rest?!?!

von Karl H. (kbuchegg)


Lesenswert?

Code wrote:
> eins verstehe ich nicht :-(
>
>
1
> /* für float to Raw-Byte */
2
> typedef union{
3
>   float value;
4
>   char raw[sizeof(float)];
5
> }float_to_raw;
6
>
>
> da ich union nie benutzt habe, weiß ich nicht recht was es genau macht.
> Ist es richtig wenn ich sage, dass union die Typumwandlung erzeugt.

Jein

> float-Wert wird sofort in char umgewandelt (und umgekerht) und bekommt
> es auch als Wert zugewissen.

Da wird nicht gewandelt.

In einer union belegen die Member denselben Speicherbereich.
Im Grunde wird derselbe Speicher einfach nur auf 2 verschiedene
Arten genutzt. Stelle es dir so vor, dass beide Variablen
übereinander liegen.


PS: Eine derartige Verwendung einer union ist eigentlich laut
C-Standard verboten. Zumindest ist nicht garantiert, dass das
so klappt. In der Praxis ist aber kein Compiler bekannt, bei dem
das nicht klappen würde.

von Code (Gast)


Lesenswert?

danke für die Erklärung.

das ist ja echt praktisch, dann kann man ja durch Unions ohne viel 
Aufwand jede mögliche "Typumwandlung" durchführen.

von Christian P. (christian_paier)


Lesenswert?

Hallo.

Da ich zufälligerweise auch gerade nach sowas gesucht habe war ich sehr 
froh als ich auf diesen Tread gestoßen bin und wollt den Code gleich in 
ein projekt integrieren.
1
#include <avr/io.h>
2
#include <stdint.h>
3
4
typedef union
5
{
6
  float value;
7
  char raw[sizeof(float)];
8
}float_to_raw;
9
10
void ftor(float data,char raw_buff[]) //FLOAT TO RAW
11
{
12
  float_to_raw ufloat;
13
  ufloat.value = data;
14
  raw_buff[0] = ufloat.raw[0];
15
  raw_buff[1] = ufloat.raw[1];
16
  raw_buff[2] = ufloat.raw[2];
17
  raw_buff[3] = ufloat.raw[3];
18
}
19
20
float rtof(char raw_buffer[])  //RAW TO FLOAT
21
{
22
  float_to_raw ufloat;
23
  ufloat.raw[0] = raw_buffer[0];
24
  ufloat.raw[1] = raw_buffer[1];
25
  ufloat.raw[2] = raw_buffer[2];
26
  ufloat.raw[3] = raw_buffer[3];
27
28
  return ufloat.value;
29
}
30
31
int main()
32
{
33
  char buffer[4];
34
35
  float f=13.7603;
36
  float g=0;
37
38
ftor(f,buffer);
39
g =rtof(buffer);
40
41
  while(1)
42
  {
43
    asm volatile("nop");
44
  }
45
46
  return 0;
47
}

Funktioniert auch gut. Aber...

Ich brauche dafür 452 Byte Memory. Kann das sein???

oder habe ich oben irgendwo einen Fehler eingebaut???

mfg Christian Paier

von Karl H. (kbuchegg)


Lesenswert?

Christian Paier wrote:

> Ich brauche dafür 452 Byte Memory. Kann das sein???

Optimierung eingeschaltet?

Ansonsten: könnte ich mir schon vorstellen, das das real ist.
Mit etwas Pech wurde durch die Verwendung von float die komplette
Floating Point Library ins Programm mit reingezogen.

von Christian P. (christian_paier)


Lesenswert?

-0s

Inzwischen wollte ich die Konvertierung auch in einem Anderen programm 
nutzen, aber da braucht es sagenhafte 1,8KB was die Kapazitäten meines 
Tiny25 zusammen mit den anderen 700Byte Code sprengt.

Gäbe es irgendeine Möglichkeit das kleiner zu implementieren?

von Gast (Gast)


Lesenswert?

Warum wird der Float denn als solcher definiert, wenn keine Berechnungen 
stattfinden!

Kann man nicht einfach einen eigenen Typ definieren mit 4 Bytes Grösse 
oder einfach einen int64 nehmen.

Sowas wie:

typedef myfloat
{ char f[4]; }

von Christian P. (christian_paier)


Lesenswert?

Ja das würde schon funktionieren.

Leider ist man hin und wieder leider doch auf berechnungen angewiesen, 
und so auch im oben erwähnten Tiny - Programm:
1
...
2
float stromwert=(read_adc()-512)/23.1424;
3
ftor(stromwert,Buffer);
4
USI_TWI_Slave_WriteBytes(Buffer,4);
5
...

wenn ich ftor(stromwert,Buffer); auskommentier habe ich dan wie gesagt 
1,8KB Code Weniger.

von Gast (Gast)


Lesenswert?

Hallo,
versuche es doch mal mit:

  union {
    float *f32;
    char *c;
  } stromwert;

float *stromwert.f32=(read_adc()-512)/23.1424;
//ftor(stromwert,Buffer);
USI_TWI_Slave_WriteBytes(stromwert.c,4);

von Christian P. (christian_paier)


Angehängte Dateien:

Lesenswert?

beiin der Zeile

float *stromwert.f32=(read_adc()-512)/23.1424;

kommt der Compiler nicht richtig zurecht.

wenn ich float weglasse funktioniert es, wenn man davon absieht das der 
Code immer noch riesig ist.

Ich hab das Projekt mal in den Anhang gehängt.

von Gast (Gast)


Lesenswert?

1
 .text          0x000002c2      0x14a c:/winavr-20080411/bin/../lib/gcc/avr/4.3.0/avr25\libgcc.a(_div_sf.o)
2
                0x000002c2                __divsf3
3
 .text          0x0000040c        0x0 c:/winavr-20080411/bin/../lib/gcc/avr/4.3.0/avr25\libgcc.a(_thenan_sf.o)
4
 .text          0x0000040c       0xea c:/winavr-20080411/bin/../lib/gcc/avr/4.3.0/avr25\libgcc.a(_usi_to_sf.o)
5
                0x0000040c                __floatunsisf
6
 .text          0x000004f6        0x0 c:/winavr-20080411/bin/../lib/gcc/avr/4.3.0/avr25\libgcc.a(_prologue.o)
7
 .text          0x000004f6        0x0 c:/winavr-20080411/bin/../lib/gcc/avr/4.3.0/avr25\libgcc.a(_epilogue.o)
8
 .text          0x000004f6       0x9e c:/winavr-20080411/bin/../lib/gcc/avr/4.3.0/avr25\libgcc.a(_clzsi2.o)
9
                0x000004f6                __clzsi2
10
 .text          0x00000594      0x1aa c:/winavr-20080411/bin/../lib/gcc/avr/4.3.0/avr25\libgcc.a(_pack_sf.o)
11
                0x00000594                __pack_f
12
 .text          0x0000073e       0xf0 c:/winavr-20080411/bin/../lib/gcc/avr/4.3.0/avr25\libgcc.a(_unpack_sf.o)
13
                0x0000073e                __unpack_f
14
 .text          0x0000082e        0x0 c:/winavr-20080411/bin/../lib/gcc/avr/4.3.0/avr25\libgcc.a(_clz.o)
15
                0x0000082e                . = ALIGN (0x2)

obiger Auszug aus der .map-Datei zeigt meiner Meinung nach, dass alles 
aus der Floatverarbeitung kommt. Von 02c2 bis 082e sind einige Module 
mit _sf im Namen aus libgcc eingebaut.
Das sind ca. 6*256 also ca 1500 Bytes.

von Gast (Gast)


Lesenswert?

Ich würde auf Festkommazahlen übergehen.

von Gast (Gast)


Lesenswert?

Mit einem 32Bit Signed Integer und 10Bit ADC mit 0 bei 512:

Messwert(i32) = (ADC-512)*2831858

bekommt man ein Ergebnis das wie folgt zu interpretieren ist:

Stromwert = Messwert / (1000 * 65536)

Wenn man also die oberen 16 Bit des Messwerts nimmt, hat man den Strom * 
1000, also den Strom mit (+/-32.767) 3 Nachkommastellen.

Also einfach den oberen 16Bit Wert nach dezimal wandeln und das Komma 
vor die Hunderterstelle.

von Karl H. (kbuchegg)


Lesenswert?

Christian Paier wrote:
> Ja das würde schon funktionieren.
>
> Leider ist man hin und wieder leider doch auf berechnungen angewiesen,
> und so auch im oben erwähnten Tiny - Programm:
>
>
1
> ...
2
> float stromwert=(read_adc()-512)/23.1424;
3
> ftor(stromwert,Buffer);
4
> USI_TWI_Slave_WriteBytes(Buffer,4);
5
> ...
6
>
>
> wenn ich ftor(stromwert,Buffer); auskommentier habe ich dan wie gesagt
> 1,8KB Code Weniger.

Da würde ich doch glatt mal darauf wetten, dass dein schlauer
Compiler bemerkt, dass ohne diesen Aufruf der Umwandlungsfunktion
mit der Variablen stromwert nichts gemacht wird. Folgerichtig
schliesst er dann messerscharf, dass eigentlich niemand eine
Berechnung benötigt, wenn mit dem Ergebnis sowieso nichts gemacht
wird und man die Berechnung als Ganzes dann auch rauswerfen könnte.
Ist die Berechnung nicht mehr vorhanden braucht auch niemand mehr
die Floating Point Library und so werden 1.8Kb weniger verbrutzelt.

Dein Problem ist also nicht die Umwandlungsfunktion, sondern
die floating Point Berechnung da im Code.

Aber, du kannst es auch mal ohne die Umwandlungsfunktion versuchen
1
...
2
  float stromwert = ( read_adc()-512 )/23.1424;
3
  USI_TWI_Slave_WriteBytes( (char*)stromwert, 4 );
4
  ...

Ich glaube aber, das das dein Speicherproblem nicht lösen wird.

von Karl H. (kbuchegg)


Lesenswert?

Karl heinz Buchegger wrote:

>
1
> ...
2
>   float stromwert = ( read_adc()-512 )/23.1424;
3
>   USI_TWI_Slave_WriteBytes( (char*)stromwert, 4 );
4
>   ...
5
>


Fehler. Muss natürlich heissen

   USI_TWI_Slave_WriteBytes( (char*)&stromwert, 4 );

von Christian P. (christian_paier)


Lesenswert?

So da bin ich wieder, war die die letzten beiden Tage nicht daheim.

Ertmals danke für die vielen Antworten.
Ich hätt nie gedacht des es so schwer ist einem Tiny floats 
einzutrichtern.

Ja kbuchegg du hast recht, es würde so auch gehen löst das 
Speicherproblem aber nicht. Nichts desto trotz habe ich im Laufe des 
Threads jede Menge über floats von euch gelernt, dafür sage ich nochmal 
Danke @ all.

Ich habs jetzt so implementiert wie es mir der Gast (3 Beiträge weiter 
oben) empfohlen hat. Danke @ Gast

Aber eine letze Frage hät ich da noch da ich diesen Trick auch in 
Zukunft noch brachen werde: Wie ist Gast auf den Wert 2831858 gekommen??
1
unsigned int adcwert=0;
2
unsigned int mittelwert=0;
3
signed long stromwert=0;
4
...
5
  for(unsigned char i=0;i<=5;i++)
6
  {
7
    ADC_conversion;
8
    while(ADC_busyflag);
9
    adcwert = ADCL;
10
    adcwert += (ADCH<<8);
11
    mittelwert+=adcwert;
12
  }
13
  ADC_deactivate;
14
15
  mittelwert/=5;
16
17
  stromwert= (mittelwert-512)*2831858;
18
19
  Buffer[0]=stromwert&255;
20
  Buffer[1]=(stromwert>>8)&255;
21
  Buffer[2]=(stromwert>>16)&255;
22
  Buffer[3]=(stromwert>>24)&255;
23
...

von Gast (Gast)


Lesenswert?

gerne ... !

von Gast (Gast)


Lesenswert?

sorry:

1000*65536/23.1424 = 2831858,4070796460176991150442478

Gruß

von Gast (Gast)


Lesenswert?

evtl.:

  union {
    signed long *i32;
    char *c;
  } stromwert;


*stromwert.i64= (mittelwert-512)*2831858;

  Buffer[0]=stromwert.c[0];
  Buffer[1]=stromwert.c[1];
  Buffer[2]=stromwert.c[2];
  Buffer[3]=stromwert.c[3];

von Christian P. (christian_paier)


Lesenswert?

Ja mein Taschenrechner brachte auch schon die Antwort.
Danke

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.