www.mikrocontroller.net

Forum: GCC Float to Raw Bytes

Autor: mgiaco (Gast)
Datum: 05.08.2007 17:55

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: 05.08.2007 18:01

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: 05.08.2007 19:26

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: 05.08.2007 20:05

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: 05.08.2007 20:06

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: Gerhard Burger (geri)
Datum: 08.08.2007 01:42

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: 08.08.2007 07:58

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: Gerhard Burger (geri)
Datum: 08.08.2007 10:40

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: 08.08.2007 11:23

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: 08.08.2007 14:02

@ 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 Buchegger (kbuchegg) (Moderator)
Datum: 08.08.2007 14:08

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: 08.08.2007 14:26

@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: 08.08.2007 14:28

Eigentlich müsste das dann ja so sein nicht

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

mathias
Autor: Karl heinz Buchegger (kbuchegg) (Moderator)
Datum: 08.08.2007 14:36

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: 08.08.2007 14:40

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

mathias
Autor: mgiaco (Gast)
Datum: 13.08.2007 22:07

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: 13.08.2007 22:08
Dateianhang: Test.zip (2,2 KB, 33 Downloads)

Hier noch meine Testfiles

mgiaco
Autor: Arc Net (arc)
Datum: 13.08.2007 22:46

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: 13.08.2007 23:03

@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: 14.08.2007 16:52

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

Karlheinz, Magnus ... ?

Danke schon mal
Autor: Arc Net (arc)
Datum: 14.08.2007 17:16

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: 14.08.2007 17:24

@ Arc Net

Super danke.

mgiaco
Autor: Code (Gast)
Datum: 14.01.2008 11:32

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 Buchegger (kbuchegg) (Moderator)
Datum: 14.01.2008 11:48

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: 14.01.2008 15:21

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 Buchegger (kbuchegg) (Moderator)
Datum: 14.01.2008 15:37

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: 14.01.2008 15:37

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 Buchegger (kbuchegg) (Moderator)
Datum: 14.01.2008 16:01

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: 14.01.2008 20:45

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: 15.05.2008 14:57

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 Buchegger (kbuchegg) (Moderator)
Datum: 15.05.2008 15:36

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: 15.05.2008 16:06

-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: 15.05.2008 16:14

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: 15.05.2008 16:20

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: 15.05.2008 16:29

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: 15.05.2008 16:37
Dateianhang: Main.zip (33,2 KB, 9 Downloads)

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: 15.05.2008 16:48

 .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: 15.05.2008 16:50

Ich würde auf Festkommazahlen übergehen.
Autor: Gast (Gast)
Datum: 15.05.2008 17:23

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 Buchegger (kbuchegg) (Moderator)
Datum: 15.05.2008 17:51

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 Buchegger (kbuchegg) (Moderator)
Datum: 15.05.2008 18:09

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: 17.05.2008 17:37

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: 17.05.2008 18:02

gerne ... !
Autor: Gast (Gast)
Datum: 17.05.2008 18:06

sorry:

1000*65536/23.1424 = 2831858,4070796460176991150442478

Gruß
Autor: Gast (Gast)
Datum: 17.05.2008 18:19

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: 17.05.2008 18:20

Ja mein Taschenrechner brachte auch schon die Antwort.
Danke

Antwort schreiben

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

Wichtige Regeln - erst lesen, dann posten!

  • Suchfunktion und Betreffsuche benutzen - vielleicht gibt es schon einen ähnlichen Beitrag
  • Aussagekräftigen Betreff wählen
  • Im Betreff angeben um welchen Controllertyp es geht (AVR, PIC, ...)
  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang
  • JPEG-Dateien (.jpg) nur für Fotos und Scans verwenden
  • Schaltpläne, Screenshots usw. als PNG oder GIF anhängen

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [pre]vorformatierter Text (z.B. Code in anderen Sprachen)[/pre]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel





Hinweis: der Originalbeitrag ist mehr als 6 Monate alt.

webmaster@mikrocontroller.netImpressumWerbung auf Mikrocontroller.net