Forum: Mikrocontroller und Digitale Elektronik Float to Int?


von Lea Weiss (Gast)


Lesenswert?

Hey Leute, ich möchte gerne meine Output Compare Register mit einer 
Variable laden
1
OCR1A=k;
dies funktioniert nicht weil k ein Float Wert ist.

wie kann ich k in einen Int Wert konvertieren?

MFG Lea

von Karl H. (kbuchegg)


Lesenswert?

Lea Weiss schrieb:
> Hey Leute, ich möchte gerne meine Output Compare Register mit einer
> Variable laden
>
1
> OCR1A=k;
2
>
> dies funktioniert nicht weil k ein Float Wert ist.

Nö. das funktioniert schon.
Bei der Zuweisung eines float an einen int werden alle Kommastellen 
abgeschnitten und das Ergebnis als int weiterbehandelt.

von Thomas K. (muetze1)


Lesenswert?

Wäre mir neu, mWn muss man diesen Verlust an Informationen explizit 
erlauben mit einem Cast zu einem int.
1
OCR1A = (int)k;

Eine Erweiterung mit Informationen, also einen int einem Float zuweisen, 
das ist aber ohne Cast möglich.

von Karl H. (kbuchegg)


Lesenswert?

Thomas K. schrieb:
> Wäre mir neu, mWn muss man diesen Verlust an Informationen explizit
> erlauben

Nö, muss man nicht.
Einige Compiler warnen, wenn so etwas passiert. Aber grundsätzlich ist 
das nicht verboten.

von Thomas K. (muetze1)


Lesenswert?

Aber genau das war doch der Unterschied zwischen expliziten und 
impliziten Casts. Implizite macht der Compiler stillschweigend (und alle 
samt ohne Datenverlust) und explizite waren immer bei Datenverlust nötig 
(oder bei komplexen Typen).

Ok, das war nun nicht der Unterschied der definiert was implizit und 
explizit Casts sind. Sondern der Unterschied der die Anwendung dieser 
beschreibt/nötig macht.

/EDIT: Aber du hast Recht. Habe mich nochmal kundig gemacht und 
getestet. Bin wohl noch etwas von Delphi/Pascal geschädigt, da ist es 
wie ich es geschrieben hatte. Aber eine strenge Typprüfung ist ja einer 
der Punkte von Delphi Language/Pascal. In C/C++ ist kein Cast notwendig.

von Karl H. (kbuchegg)


Lesenswert?

Thomas K. schrieb:
> Aber genau das war doch der Unterschied zwischen expliziten und
> impliziten Casts. Implizite macht der Compiler stillschweigend (und alle
> samt ohne Datenverlust) und explizite waren immer bei Datenverlust nötig
> (oder bei komplexen Typen).

Du must unterscheiden zwischen einem Fehler, von dem die 
Sprachdefinition fordert, das er angemäkelt wird und einer Warnung, die 
ein Compilerbauer von sich aus, aus freien Stücken, eingebaut hat.

Die Zuweisung eines float an einen int ist kein Fehler. Selbst wenn 
einige Compiler (aus guten Gründen) eine Warnung geben. So nach dem 
Motto: "Ich tu schon was du von mir willst, aber bist du dir da wirklich 
sicher? Oft ist das ein Flüchtigkeitsfehler, drum werfe ich mal 
sicherheitshalber eine Warnung."

Aber auf jeden Fall ist das kein Kandidat für
<Zitat>
dies funktioniert nicht
</Zitat>

Im übrigen ist diese Version, die auch noch rundet
1
  OCR1A = (int)( k + 0.5);
meistens die bessere Wahl. Sonst kann es nämlich ganz schnell passieren, 
das aus 5.99999999 (also praktisch 6) trotzdem 5 wird und nicht 6.

von Lea Weiss (Gast)


Lesenswert?

habe es so versucht:

  OCR1A=(int)k;


funktioniert auch nicht...

fehler meldung ist für mich auch nicht verständlich:

Build started 30.4.2010 at 21:14:40
avr-gcc  -mmcu=atmega32 -Wall -gdwarf-2 -Os -std=gnu99 -funsigned-char 
-funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT 
Pflichtsoftware1.o -MF dep/Pflichtsoftware1.o.d  -c 
../Pflichtsoftware1.c
avr-gcc -mmcu=atmega32 -Wl,-Map=Pflichtsoftware1.map Pflichtsoftware1.o 
-o Pflichtsoftware1.elf
c:/winavr-20090313/bin/../lib/gcc/avr/4.3.2/../../../../avr/lib/avr5\lib 
c.a(log.o):  In function `log':
(.text.fplib+0x46): relocation truncated to fit: R_AVR_13_PCREL against 
symbol `__addsf3' defined in .text section in 
c:/winavr-20090313/bin/../lib/gcc/avr/4.3.2/avr5\libgcc.a(_addsub_sf.o)
c:/winavr-20090313/bin/../lib/gcc/avr/4.3.2/../../../../avr/lib/avr5\lib 
c.a(log.o):  In function `log':
(.text.fplib+0x4e): relocation truncated to fit: R_AVR_13_PCREL against 
symbol `__addsf3' defined in .text section in 
c:/winavr-20090313/bin/../lib/gcc/avr/4.3.2/avr5\libgcc.a(_addsub_sf.o)
make: *** [Pflichtsoftware1.elf] Error 1
Build failed with 1 errors and 0 warnings...

von Karl H. (kbuchegg)


Lesenswert?

Das müsste sein:
Du hast die Floating Point Library nicht eingebunden, oder mit deiner 
Installation stimmt etwas nicht.

von Thomas K. (muetze1)


Lesenswert?

Und wie zum Teufel kommst du von der Fehlermeldung auf die o.g. 
Fehlerzeile?

@khbuchegg: hatte oben schon editiert, du hast vollkommen Recht. Hatte 
das noch anders im Kopf aufgrund der langen Delphi/Pascal 
Programmierung. Hatte es auch schon ausprobiert.

von Lea Weiss (Gast)


Lesenswert?

das ist halt die Fehlermeldung die kommt..

wenn ich die Zeile auskommentiere funktioniert alles wunderbar.

von Lea Weiss (Gast)


Lesenswert?

<float.h> wurde eingebunden.

von Lea Weiss (Gast)


Lesenswert?

hier der Code... kann mir niemand helfen?
1
int main(void)
2
{
3
float temperatur_soll_LM45 = 0;
4
float k=0;
5
6
float Kp=200;
7
float Ki=2;
8
float Ta=20;
9
10
float e=0;
11
float esum=0;
12
13
DDRC=0xFF;
14
DDRD=0xFF;
15
16
PORTC=0;
17
PORTD=0xFF;
18
PORTB=0xFF;
19
20
Initialize_Timer0(2,2,256);
21
TIMSK |= (1<<TOIE0);
22
23
ADMUX   |=   (   1<<REFS0   |  1<<MUX0);
24
ADCSRA   |=  (   1<<ADEN    );
25
26
TCCR1A   |=  (  1<<COM1A1  |  1<<WGM10  |  1<<WGM11);
27
TCCR1B  |=  (  1<<CS10    |  1<<CS12);
28
29
OCR1A=0;
30
31
lcd_init();
32
lcd_clear();
33
sei();
34
35
while(1)
36
    {      
37
  temperatur_soll_LM45 = temperatur_ist_NTC+2;
38
  e=temperatur_soll_LM45-temperatur_ist_LM45;
39
  esum+=e;
40
41
  if(esum<-300)esum=-300;
42
  if(esum>300)esum=300;
43
44
  k=e*Kp+Ki*Ta*esum;
45
46
47
  if(k>1021)k=1021;
48
  if(k<0)k=0;
49
50
  OCR1A=(int)k;
51
52
  _delay_ms(250);
53
    {
54
    // Daten an Display ausgeben
55
    char Buffer[20]; // in diesem {} lokal
56
    set_cursor(0,1);lcd_string(" Temp1:");
57
    set_cursor(6,1);lcd_string("     ");set_cursor(6,1);
58
    dtostrf(temperatur_ist_LM45,7,2, Buffer );
59
    lcd_string( Buffer );lcd_data(223);lcd_data('C');
60
61
    set_cursor(0,2);lcd_string(" Temp2:");
62
    set_cursor(6,2);lcd_string("     ");set_cursor(6,2);
63
    dtostrf(temperatur_ist_NTC, 7, 2, Buffer );
64
    lcd_string( Buffer );lcd_data(223);lcd_data('C');
65
66
  /*  set_cursor(0,4);lcd_string("     ");set_cursor(0,4);
67
    itoa(OCR1A, Buffer, 10 );
68
    lcd_string( Buffer );*/
69
    }
70
    }
71
 
72
    return 0;
73
}

von Klaus W. (mfgkw)


Lesenswert?

Die float.h hilft nur dem Compiler.
Wenn der Linker Fehlermeldungen spuckt, fehlt meist die libm,
und die wird mit -lm eingebunden.

Das war damit wohl gemeint:
Karl heinz Buchegger schrieb:
> Du hast die Floating Point Library nicht eingebunden, oder mit deiner
> Installation stimmt etwas nicht.

von Karl H. (kbuchegg)


Lesenswert?

Klaus Wachtler schrieb:
> Die float.h hilft nur dem Compiler.
> Wenn der Linker Fehlermeldungen spuckt, fehlt meist die libm,
> und die wird mit -lm eingebunden.
>
> Das war damit wohl gemeint:
> Karl heinz Buchegger schrieb:
>> Du hast die Floating Point Library nicht eingebunden, oder mit deiner
>> Installation stimmt etwas nicht.

Genau.
Aber ich wusste nicht mehr auswendig, wie man das im AVR-Studio macht 
:-)

Inzwischen hab ich nachgesehen:

Menüpunkt "Project" / "Configuration Options"
Im Dialog dann links "Libraries" anklicken
Im linken Listfeld die libm.a auswählen und "Add Library"

Alles mit OK bestätigen und erneut Builden lassen.

von Guest (Gast)


Lesenswert?

Hallo,

wieso verwendest du überhaupt "float" Variablen? Sollte auch ohne gehen.
Denn ich sehe nur ganzzahlige Werte. Und eine Division kommt auch nicht 
vor ...
Verwende einfach Int16 bzw. Int32. Das macht auch den Code deutlich 
kleiner.

von Lea Weiss (Gast)


Lesenswert?

hm das Problem ist aber nur beim laden ins OCR1A Register.. ich konnte 
mit float rechnen, diese Werte ans Display übergeben, das hat keine 
Probleme verursacht..

float Bibliothek ist vorhanden, hab es soeben überprüft.

von Lea Weiss (Gast)


Lesenswert?

In der Subroutione wird mit einer Log() funktion gerechnet, daher 
entstehen Zahlen mit Kommastellen

[C]
ISR(TIMER0_OVF_vect){

// Sensor1 auslesen
  ADMUX   =   (   1<<REFS0   |  0<<MUX0  );   // AVcc als 
Referenzspannung, Multiplexer auf Position 0
  ADCSRA   |=  (   1<<ADSC  );           // Start einer Wandlung
  while(CHECKBIT(ADCSRA,ADIF)==0);
  SETBIT(ADCSRA,ADIF);//clear Interupt Flag

// Sensor 1 als LM45 auswerten
  ADC_Wert_LM45=ADCL;
  ADC_Wert_LM45+=ADCH<<8;
  temperatur_ist_LM45=50*ADC_Wert_LM45/102.4;

// Sensor2 auslesen
  ADMUX   =   (   1<<REFS0   |  1<<MUX0  ); // AVcc als 
Referenzspannung, Multiplexer auf Position 1
  ADCSRA   |=  (   1<<ADSC  );           // Start einer Wandlung
  while(CHECKBIT(ADCSRA,ADIF)==0);
  SETBIT(ADCSRA,ADIF);//clear Interupt Flag

// Sensor 2 als NTC behandeln
  ADC_Wert_NTC=ADCL;
  ADC_Wert_NTC+=ADCH<<8;
  temperatur_ist_NTC=(108025/(3625+log(1024/ADC_Wert_NTC-1)*298))*10-273;
  }
[\C]

von Karl H. (kbuchegg)


Lesenswert?

Lea Weiss schrieb:
> In der Subroutione wird mit einer Log() funktion gerechnet, daher
> entstehen Zahlen mit Kommastellen

LOL.
Wusste gar nicht das der gcc soooo gut ist.

Die Fehlermledung beschwert sich dass etwas mit log nicht stimmt.

In function `log':
(.text.fplib+0x46): relocation truncated to fit: R_AVR_13_PCREL against
symbol `__addsf3' defined in .text section in
c:/winavr-20090313/bin/../lib/gcc/avr/4.3.2/avr5\libgcc.a(_addsub_sf.o)


und in deiner ISR kommt ein log vor.
Was ist dein logischer Schluss?

> das Problem ist aber nur beim laden ins OCR1A Register.

Das ist der falsche Schluss. Der hat damit nichts oder nur auf Umwegen 
zu tun.

von Lea Weiss (Gast)


Lesenswert?

also Leute, ich habe jetzt folgendes gemacht:

1
int k;
2
int esum;

restliche Variablen float Zahlen, so funktioniert es..

wenn
1
float k;
2
float esum;

funktioniert es nicht...

wtf? :)

von Lea Weiss (Gast)


Lesenswert?

mein lieber  Karl heinz Buchegger,
variable k und esum kommen in der Subroutine nicht vor...

von Karl H. (kbuchegg)


Lesenswert?

Aber temperatur_ist_NTC

Ist die volatile?

Im übrigen brauchst du nicht mit mir streiten, denn: Der Compiler/Linker 
hat immer recht. Und dein Linker (nicht der Compiler) beschwert sich, 
dass er ein Problem mit der Funktion log() hat. Steht schwarz auf weiß 
dort.

Das kann nichts mit der Zuweisung zu tun haben. Ausser: Lässt du die 
Zuweisung weg, kann es sein, dass die Voraussetzung für die Berechnung 
des log() in der ISR wegfällt und der Optimizer den log ganz einfach 
rauswirft. Kein log() mehr, kein Problem für den Linker.

von Lea Weiss (Gast)


Lesenswert?

ist nicht volatile..

von Lea Weiss (Gast)


Lesenswert?

habe mit volatile ausprobiert, hatte keinen Einfluss, die selbe 
Fehlermeldung.

von Karl H. (kbuchegg)


Lesenswert?

Lea Weiss schrieb:
> ist nicht volatile..

Dann solltest du die ganz schnell volatile machen. Genauso wie alle 
anderen Variablen, die sowohl in der ISR als auch in main() benutzt 
werden. Und eine Absicherung auf atomaren Zugriff wäre auch dringend 
angeraten. Vor allen Dingen dann, wenn du darauf bestehst alles in float 
zu lassen.

von Lea Weiss (Gast)


Lesenswert?

Karl heinz Buchegger, sie haben recht, wenn ich die Log funktion 
ausklammere kommt die Fehlermeldung nicht...

aber ich kann auf diese Funktion leider nicht verzichten...

von Karl H. (kbuchegg)


Lesenswert?

Es ist irgendein Problem in deiner Konfiguration.
Die libm.a sagst du hast du beim Projekt dabei.

Hmm.
Dein WinAVR ist schon reichlich angestaubt. Nimm mal eine andere 
Version.

von Guest (Gast)


Lesenswert?

Eine Frage am Rande: wie oft wird der Timer0-Interrupt aufgerufen? Ich 
werde aus
> Initialize_Timer0(2,2,256);
nicht schlau ...

Unabhängig vom Compilier-Fehler: In einer ISR fasst man sich kurz. Hier 
solltest du nur die Messwerte der Sensoren einlesen und sie dann im 
Hauptprogramm bearbeiten.
Gerade Floating Point Berechnungen brauchen viel Zeit ... (und die hat 
man in einer ISR normalerweise nicht.)

von Lea Weiss (Gast)


Lesenswert?

libm.a??
sry bin halt kein Profi, ich hol mir mal die neuste version des winavr 
und schau ob das was bringt..

von Karl H. (kbuchegg)


Lesenswert?

Spielt kaum eine Rolle. Dieser PID Regler wird, wenn überhaupt, nur 
durch Zufall funktionieren.
Das ist wie wenn du einem 100-m Sprinter einen Betonklotz ans Bein 
bindest. Der kommt auch nicht weit.

von Lea Weiss (Gast)


Lesenswert?

der timer interrupt wird alle 131ms aufgerufen

Initialize_Timer0(2,2,256);// phasecorrectmode(2), set upcounting(2), 
prescaler(256)

von Karl H. (kbuchegg)


Lesenswert?

Lea Weiss schrieb:
> libm.a??

Ich habs dir doch weiter oben aufgeschrieben
Beitrag "Re: Float to Int?"

von Lea Weiss (Gast)


Lesenswert?

soso, wie würdest du es denn machen?

bisher hats nicht so schlecht funktioniert ;)

von Karl H. (kbuchegg)


Lesenswert?

Lea Weiss schrieb:
> soso, wie würdest du es denn machen?

Auf jeden Fall nicht mit float

> bisher hats nicht so schlecht funktioniert ;)

Ach. Ich dachte du konntest es bisher noch gar nicht linken.-)

von Lea Weiss (Gast)


Lesenswert?

ach scheisse, das hab ich gar nicht gesehen... du bist ein Held, es war 
tatsächlich wegen dem...

danke dir viel mal...!!!! danke danke danke

von Lea Weiss (Gast)


Lesenswert?

verdammt, von wo weisst du das eigentlich alles??? :)

von Karl H. (kbuchegg)


Lesenswert?

Du bist nicht die erste mit so einer (oder so einer ähnlichen) 
Fehlermeldung :-)

von Lea Weiss (Gast)


Lesenswert?

voll nett echt, da hast du mir viel Ärger ersparrt ;)

wünsche dir ein schönes WE

tschüss

von ... (Gast)


Lesenswert?

Ist bei der Fehlermmeldung eigentlich eindeutig. Wenn der Linker 
versucht Fließkommaroutinen (wie log) aus der libc.a zu benutzen, fehlt 
immer die libm.a. Entweder weil sie nicht mit angegeben wurde oder wenn 
doch, dann aber an der falschen Stelle.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Karl heinz Buchegger schrieb:

> In function `log':
> (.text.fplib+0x46): relocation truncated to fit: R_AVR_13_PCREL against
> symbol `__addsf3' defined in .text section in
> c:/winavr-20090313/bin/../lib/gcc/avr/4.3.2/avr5\libgcc.a(_addsub_sf.o)

Das Problem ist also, daß bestimmte Relocs nicht passen, weil Offsets 
für PC-relative Adressierung zu groß werden. Irgendwer ruft da die 
__addsf3 auf, und das kann eigentlich nur avr-gcc sein, weil die 
__addsf3 zur libgcc gehört. Möglicherweise kann der Linker das 
ausbügeln, wenn man ihn Sprünge relaxen lässt.

Daß das Problem (zunächst) verschwindet, wenn man das Programm kleiner 
macht, hat nix zu sagen. Dadurch passt die Adresslage wieder, weil dann 
anders lokatiert wird. Irgendwann hat man das Ding aber wieder am 
Schenkel kleben...

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.