www.mikrocontroller.net

Forum: Compiler & IDEs Float to Raw Bytes


Autor: mgiaco (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: mgiaco (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
public static void floatToRawByteArray(float data, int buffpos, byte buff[]) 
{
        int temp = Float.floatToRawIntBits(data);
  intToRawByteArray(temp, buffpos, buff); 
}
  
public static void intToRawByteArray(int data, int buffpos, byte buff[]) 
{
  buff[buffpos++] = (byte)(data>>>24 & 0xFF);
  buff[buffpos++] = (byte)(data>>>16 & 0xFF);
  buff[buffpos++] = (byte)(data>>>8 & 0xFF); 
  buff[buffpos++] = (byte)(data & 0xFF);
}

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

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht 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:
typedef _float_to_raw union {
   float    v;
   char     r[sizeof (float)];
} float_to_raw;

float_to_raw R;
R.v = <float-wert>;
// In R.r steht jetzt der float-Wert als Bytefolge

Autor: mgiaco (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: mgiaco (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: G. B. (geri)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: G. B. (geri)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Magnus

Vielen Dank für Deine Rückmeldung.

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

void doAny1(float* a)
{
    ..
}

void doAny2()
{
    char buf[20]; // enthält 5 floating point variablen

    DaAnything((float*)&buf[4]); // Übergabe des zweiten Wertes
}

Beste Grüsse

Geri

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: mgiaco (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: mgiaco (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: mgiaco (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eigentlich müsste das dann ja so sein nicht

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

mathias

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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;

Autor: mgiaco (Gast)
Datum:

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

mathias

Autor: mgiaco (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

float rawByteArrayToFloat(uint8_t data[], uint8_t offset) 
{
    uint8_t i;  
    float tmpBuffer = 0.0f;
    char  *buffer = (char*)&tmpBuffer;
    
    for(i=0; i<4; i++)
    {
        buffer[i] = data[i+offset];
    }
    
    return *((float*)&(buffer[offset]));
}

void floatToRawByteArray(float data, uint8_t buffpos, uint8_t buff[]) 
{
    float_to_raw ufloat;
    ufloat.value = data;
    buff[buffpos++] = (uint8_t)ufloat.raw[0];
    buff[buffpos++] = (uint8_t)ufloat.raw[1];
    buff[buffpos++] = (uint8_t)ufloat.raw[2];
    buff[buffpos++] = (uint8_t)ufloat.raw[3];
          
}



danek

Autor: mgiaco (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hier noch meine Testfiles

mgiaco

Autor: Arc Net (arc)
Datum:

Bewertung
0 lesenswert
nicht 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)

Autor: mgiaco (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 ?

//int32_t rawByteArrayToInt32(uint8_t data[], uint8_t offset) 
//{
//    int8_t i;
//    int32_t temp=0;
//    
//    for(i=0; i<4; i++)
//     temp = (temp + (data[i+offset]& 0xFF)) << 8;
//    return (temp>>8);
//}

//int32_t rawByteArrayToInt32(uint8_t data[], uint8_t offset) 
//{
//  return data[offset]<<24 | (data[offset+1]&0xff)<<16 | (data[offset+2]&0xff)<<8 | (data[offset+3]&0xff);  
//}

int32_t rawByteArrayToInt32(uint8_t data[], uint8_t offset) 
{  
  return (*(int32_t*)(&data[offset]));
}

void int32ToRawByteArray(int32_t data, uint8_t buffpos, uint8_t buff[]) 
{
    buff[buffpos++] = (uint8_t)(data & 0xFF);
    buff[buffpos++] = (uint8_t)(data>>8 & 0xFF); 
    buff[buffpos++] = (uint8_t)(data>>16 & 0xFF);
    buff[buffpos++] = (uint8_t)(data>>24 & 0xFF);
}

//int16_t rawByteArrayToInt16(uint8_t data[], uint8_t offset) 
//{
//  int8_t i;
//    int32_t temp=0;
//  
//    for(i=0; i<2; i++)
//    temp = (temp + (data[i+offset]& 0xFF)) << 8;
//  return (int16_t)(temp>>8);
//}

//int16_t rawByteArrayToInt16(uint8_t data[], uint8_t offset) 
//{
//  return data[offset+0]<<8 | (data[offset+1]&0xff);
//}

int16_t rawByteArrayToInt16(uint8_t data[], uint8_t offset) 
{
  return (*(int16_t*)(&data[offset]));
}

void int16ToRawByteArray(int16_t data, uint8_t buffpos, uint8_t buff[]) 
{
    buff[buffpos++] = (uint8_t)(data & 0xFF);
    buff[buffpos++] = (uint8_t)(data>>8 & 0xFF);
}

int8_t rawByteArrayToInt8(uint8_t data[], uint8_t offset) 
{
    return (int8_t)(data[offset]);
}

void int8ToRawByteArray(int8_t data, uint8_t buffpos, uint8_t buff[]) 
{
    buff[buffpos++] = (uint8_t)(data & 0xFF);
}


float rawByteArrayToFloat(uint8_t data[], uint8_t offset) 
{
    uint8_t i;  
    float tmpBuffer = 0.0f;
    char  *buffer = (char*)&tmpBuffer;
    
    for(i=0; i<4; i++)
    {
        buffer[i] = data[i+offset];
    }
    
    return *((float*)(buffer));
}

void floatToRawByteArray(float data, uint8_t buffpos, uint8_t buff[]) 
{
    float_to_raw ufloat;
    ufloat.value = data;
    buff[buffpos++] = (uint8_t)ufloat.raw[0];
    buff[buffpos++] = (uint8_t)ufloat.raw[1];
    buff[buffpos++] = (uint8_t)ufloat.raw[2];
    buff[buffpos++] = (uint8_t)ufloat.raw[3];
}


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

Danke an alle

mgiaco

Autor: mgiaco (Gast)
Datum:

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

Karlheinz, Magnus ... ?

Danke schon mal

Autor: Arc Net (arc)
Datum:

Bewertung
0 lesenswert
nicht 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.
void int32ToRawByteArray(int32_t data, uint8_t buffpos, uint8_t buff[]) 
{
    register uint8_t* dp = (uint8_t *)&data;
    buff[buffpos++] = dp[0];
    buff[buffpos++] = dp[1];
    buff[buffpos++] = dp[2];
    buff[buffpos++] = dp[3];
}

Autor: mgiaco (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Arc Net

Super danke.

mgiaco

Autor: Code (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
mgiaco wrote:

> Was könnte man noch optimieren?

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

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

die Funktion für float -> raw ist, dann wäre für mich
eine naheliegende Implementierung für die Umkehrung
float rawByteArrayToFloat(uint8_t data[], uint8_t offset) 
{
    float_to_raw ufloat;

    ufloat.raw[0] = data[offset++];
    ufloat.raw[1] = data[offset++];
    ufloat.raw[2] = data[offset++];
    ufloat.raw[3] = data[offset++];

    return ufloat.value;
}

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 :-)

Autor: Code (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 ;-)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Code (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
eins verstehe ich nicht :-(
/* für float to Raw-Byte */
typedef union{
  float value;
  char raw[sizeof(float)];
}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?!?!

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Code wrote:
> eins verstehe ich nicht :-(
>
>
> /* für float to Raw-Byte */
> typedef union{
>   float value;
>   char raw[sizeof(float)];
> }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.

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.

Autor: Code (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Christian Paier (christian_paier)
Datum:

Bewertung
0 lesenswert
nicht 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.
#include <avr/io.h>
#include <stdint.h>

typedef union
{
  float value;
  char raw[sizeof(float)];
}float_to_raw;

void ftor(float data,char raw_buff[]) //FLOAT TO RAW
{
  float_to_raw ufloat;
  ufloat.value = data;
  raw_buff[0] = ufloat.raw[0];
  raw_buff[1] = ufloat.raw[1];
  raw_buff[2] = ufloat.raw[2];
  raw_buff[3] = ufloat.raw[3];
}

float rtof(char raw_buffer[])  //RAW TO FLOAT
{
  float_to_raw ufloat;
  ufloat.raw[0] = raw_buffer[0];
  ufloat.raw[1] = raw_buffer[1];
  ufloat.raw[2] = raw_buffer[2];
  ufloat.raw[3] = raw_buffer[3];

  return ufloat.value;
}

int main()
{
  char buffer[4];

  float f=13.7603;
  float g=0;

ftor(f,buffer);
g =rtof(buffer);

  while(1)
  {
    asm volatile("nop");
  }

  return 0;
}

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Christian Paier (christian_paier)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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]; }

Autor: Christian Paier (christian_paier)
Datum:

Bewertung
0 lesenswert
nicht 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:
...
float stromwert=(read_adc()-512)/23.1424;
ftor(stromwert,Buffer);
USI_TWI_Slave_WriteBytes(Buffer,4);
...

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

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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);

Autor: Christian Paier (christian_paier)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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.

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
 .text          0x000002c2      0x14a c:/winavr-20080411/bin/../lib/gcc/avr/4.3.0/avr25\libgcc.a(_div_sf.o)
                0x000002c2                __divsf3
 .text          0x0000040c        0x0 c:/winavr-20080411/bin/../lib/gcc/avr/4.3.0/avr25\libgcc.a(_thenan_sf.o)
 .text          0x0000040c       0xea c:/winavr-20080411/bin/../lib/gcc/avr/4.3.0/avr25\libgcc.a(_usi_to_sf.o)
                0x0000040c                __floatunsisf
 .text          0x000004f6        0x0 c:/winavr-20080411/bin/../lib/gcc/avr/4.3.0/avr25\libgcc.a(_prologue.o)
 .text          0x000004f6        0x0 c:/winavr-20080411/bin/../lib/gcc/avr/4.3.0/avr25\libgcc.a(_epilogue.o)
 .text          0x000004f6       0x9e c:/winavr-20080411/bin/../lib/gcc/avr/4.3.0/avr25\libgcc.a(_clzsi2.o)
                0x000004f6                __clzsi2
 .text          0x00000594      0x1aa c:/winavr-20080411/bin/../lib/gcc/avr/4.3.0/avr25\libgcc.a(_pack_sf.o)
                0x00000594                __pack_f
 .text          0x0000073e       0xf0 c:/winavr-20080411/bin/../lib/gcc/avr/4.3.0/avr25\libgcc.a(_unpack_sf.o)
                0x0000073e                __unpack_f
 .text          0x0000082e        0x0 c:/winavr-20080411/bin/../lib/gcc/avr/4.3.0/avr25\libgcc.a(_clz.o)
                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.

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich würde auf Festkommazahlen übergehen.

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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:
>
>
> ...
> float stromwert=(read_adc()-512)/23.1424;
> ftor(stromwert,Buffer);
> USI_TWI_Slave_WriteBytes(Buffer,4);
> ...
> 
>
> 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
...
  float stromwert = ( read_adc()-512 )/23.1424;
  USI_TWI_Slave_WriteBytes( (char*)stromwert, 4 );
  ...

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger wrote:

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


Fehler. Muss natürlich heissen

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

Autor: Christian Paier (christian_paier)
Datum:

Bewertung
0 lesenswert
nicht 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??
unsigned int adcwert=0;
unsigned int mittelwert=0;
signed long stromwert=0;
...
  for(unsigned char i=0;i<=5;i++)
  {
    ADC_conversion;
    while(ADC_busyflag);
    adcwert = ADCL;
    adcwert += (ADCH<<8);
    mittelwert+=adcwert;
  }
  ADC_deactivate;

  mittelwert/=5;

  stromwert= (mittelwert-512)*2831858;

  Buffer[0]=stromwert&255;
  Buffer[1]=(stromwert>>8)&255;
  Buffer[2]=(stromwert>>16)&255;
  Buffer[3]=(stromwert>>24)&255;
...

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
gerne ... !

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
sorry:

1000*65536/23.1424 = 2831858,4070796460176991150442478

Gruß

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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];

Autor: Christian Paier (christian_paier)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja mein Taschenrechner brachte auch schon die Antwort.
Danke

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.