Forum: Mikrocontroller und Digitale Elektronik Konvertiere float to uint8_t


von Pal .. (pal)


Lesenswert?

Hallo,

ich stehe gerade vor einem Anfängerproblem, welches ich nicht so ganz 
verstehe. Es geht um folgenden Code:
1
#define MSG_LEN 7
2
union MSG
3
{
4
  uint8_t data[MSG_LEN];
5
  struct
6
  {
7
    uint8_t b0;
8
    uint8_t b1;
9
    uint8_t b2;
10
    uint8_t b3;
11
    uint8_t b4;
12
    uint8_t pwmOut;
13
    uint8_t pwmVal;
14
  } bytes;
15
};

1
int16_t  aktDrehz = 50;
2
float liter, ber, pwm;
3
int ipwm;
4
uint8_t diffLiter = 50;
5
6
7
ber = ((100 - diffLiter) * aktDrehz / 100);
8
liter = pow(0.000000016886 * ber, 5) - pow(0.00000585112 * ber, 4) + pow(0.000648028 * ber, 3) - pow(0.0218385796 * ber, 2) + (0.534156384 * ber) - 0.4682274;
9
pwm   = pow(0.000888526 * liter, 3) -  pow(0.108956237 * liter, 2) + (5.900433784 * ber) + 77.628376829;
10
ipwm = (int)(round(pwm));
11
12
msg->bytes.pwmVal = (uint8_t)ipwm;

Warum bekomm ich hier folgende Fehlermeldung?
1
c:/winavr-20100110/bin/../lib/gcc/avr/4.3.3/../../../../avr/lib/avr5\libc.a(log.o): In function `log':
2
(.text.avr-libc.fplib+0x46): relocation truncated to fit: R_AVR_13_PCREL against symbol `__addsf3' defined in .text section in c:/winavr-20100110/bin/../lib/gcc/avr/4.3.3/avr5\libgcc.a(_addsub_sf.o)
3
c:/winavr-20100110/bin/../lib/gcc/avr/4.3.3/../../../../avr/lib/avr5\libc.a(log.o): In function `log':
4
(.text.avr-libc.fplib+0x4e): relocation truncated to fit: R_AVR_13_PCREL against symbol `__addsf3' defined in .text section in c:/winavr-20100110/bin/../lib/gcc/avr/4.3.3/avr5\libgcc.a(_addsub_sf.o)
5
c:/winavr-20100110/bin/../lib/gcc/avr/4.3.3/../../../../avr/lib/avr5\libc.a(modf.o): In function `modff':
6
(.text.avr-libc.fplib+0x3e): relocation truncated to fit: R_AVR_13_PCREL against symbol `__subsf3' defined in .text section in c:/winavr-20100110/bin/../lib/gcc/avr/4.3.3/avr5\libgcc.a(_addsub_sf.o)
7
make: *** [komfort_main.elf] Error 1
8
Build failed with 1 errors and 0 warnings...


Setze ich dann für "ipwm" eine natürliche Zahl ein, wird fehlerfrei 
compeliert.

Vielen Dank für Eure Hilfe!

von Peter II (Gast)


Lesenswert?

> Setze ich dann für "ipwm" eine natürliche Zahl ein, wird fehlerfrei
> compeliert.

ja, weil alles wegoptimiert wird.


schein mir ein Platz problem zu sein, du mustet die kleinen AVR ziemlich 
viel zu. Hast du mit lib m (-lm ) eingetragen?

von Pal .. (pal)


Angehängte Dateien:

Lesenswert?

> Hast du mit lib m (-lm ) eingetragen?

Was meinst du? Siehe Bild?

von Peter II (Gast)


Lesenswert?

pal ... schrieb:
> Was meinst du? Siehe Bild?

ja versuche dort mal mit libm.a einzutragen.

von Pal .. (pal)


Lesenswert?

Super, danke!!! Funktioniert :-)

Aber was hab ich jetzt damit bewirkt?

von Peter II (Gast)


Lesenswert?

pal ... schrieb:
> Aber was hab ich jetzt damit bewirkt?

jetzt sind die float berechnung etwas mehr für den AVR optimiert.

Aber du solltest auch mal Prüfen ob deine Berechnungen am ende ein 
sinnvolles ergebniss liefert. float ist nicht so genau wie man eventuell 
denkt. Außerdem is das schon harte arbeit für so eine AVR. und er wird 
dadurch auch recht stark ausgelastet sein. (wenn das nicht stört, ist es 
kein Problem)

von Pal .. (pal)


Lesenswert?

Die Berechnung wir nicht oft ausgeführt. Das ist überschaubar....

Was die float-Ausgabe angeht.. ich benötige später nur ganze Zahlen. Das 
Ergebnis schau ich mir noch mal durch eine UART-Ausgabe an.

Aber vielen Dank für die Hinweise.

SUPER!

von Peter II (Gast)


Lesenswert?

pal ... schrieb:
> Was die float-Ausgabe angeht.. ich benötige später nur ganze Zahlen.

Dann könnte man sich auch überlegen das als Tabelle im Flash zu 
hinterlegen, dann spart man sich die rechnerei.

von Pal .. (pal)


Lesenswert?

Das würde bedeuten, dass ich eine Tabelle anlege und die bei 
Initialisierung einlesen. Oder?

Aber mein Problem ist nur, dass die Variable "diffLiter" hier eine 
Unbekannte ist.
1
ber = ((100 - diffLiter) * aktDrehz / 100);

von Peter II (Gast)


Lesenswert?

pal ... schrieb:
> Das würde bedeuten, dass ich eine Tabelle anlege und die bei
> Initialisierung einlesen. Oder?

nein sie kann auch direkt aus dem flash verwendet werden.

> Aber mein Problem ist nur, dass die Variable "diffLiter" hier eine
> Unbekannte ist.

wert = tabelle[ diffLiter ];

das macht aber nur sinn wenn diffLiter eine überschaubare wertemenge hat 
(z.b. 0-255 )

von Pal .. (pal)


Lesenswert?

Wie würde denn solch eine Tabelle aussehen? Füge ich sie in die 
HeaderDatei ein?

Die Variable "diffLiter" kann max 0-100 groß sein

von Peter II (Gast)


Lesenswert?

pal ... schrieb:
> Wie würde denn solch eine Tabelle aussehen?

http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Programmspeicher_.28Flash.29


const int anArray[] PROGMEM = { 18, 3 ,70 ...  };
int wert = (int) pgm_read_word (&anArray[diffLiter]);

von Pal .. (pal)


Lesenswert?

Danke!

Ich werde mich mal daran begeben.

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.