Hallo,
ich dachte, man kann mit dem WINAVR-GCC einfach floats verwenden und
damit rechnen wie bei jedem anderen compiler...
folgendes hab ich definiert:
#include <math.h>
float x,y,jamp,jalpha;
jalpha = atan(y/x);
jamp = sqrt(x*x + y*y);
Es kommt nix heraus, was ich fuer richtig halten koennte...
Was macht man um auf einem uC mit asin, cos, sin usw rechnen zu
koennen?(Rechenzeit relativ wurscht)
mg,
Johannes
wer hat schon einmal mit der asin, atan, sin oder cos-Funktion
gearbeitet die mit WINAVR mitgeliefert wird?
kann man float-Variablen auf dem ATMega16 verwenden? oder muss man da
irgendwie tricksen?
Johannes
int16_t x,y;
float jalpha;
....
x=10;
y=5;
jalpha = atan(y/x)*100; //atan(0.5)*100 = 0.4636*100 = 46.36
UDR = (uint8_t)(jalpha); //casten und auf UART schieben
Uebertragen wird leider eine glatte Null anstatt 46. Wenn ich
atan(1000) berechnen lasse (atan(1000)=1.569) dann kommt eine 100
rueber was auch stimmt. Meine Schlussfolgerung, die float Variablen
werden im ATMega falsch gehandelt. Alles was kleiner als 1 ist bleibt
offensichtlich eine Null;
oder seht ihr da einen Fehler bei meinen Ueberlegungen?
mg,
Johannes
Genau. y/x mit int in der genannten Aufgabe ergibt:
atan(y/x) = atan(5/10) = atan(0), solange y<x gilt.
Aber es ist deklariert: double atan(double __x), so dass du
atan(5.0/10.0) wählen musst.
Gruß Marco
yuhuuuu!
Dankeschoen. Tja, irgendwannmal hatte ich das ja "gelernt" gehabt,
wie der compiler bei solchen Sachen arbeitet...
ich denke jetzt hab ichs echt gelernt!
mg,
Johannes
Uebrigens:
mit der atan() Funktion kann man meist nichts rechtes
machen. Besser ist atan2(). Die bestimmt Dir dann auch noch
den Quadranten richtig und den Fehler in der Division
haettest Du auch nicht gemacht.
Seid gegruesst,
die Variante mit der union gefaellt mir ganz gut, nur funktioniert sie
nicht wie ich will. Hier meine relevanten CodeBeispiele vom
Mikorcontroller.
union UART_ANGLE
{
float ang;
char aux[4];
};
volatile union UART_ANGLE angle;
volatile float winkel[2];
....
//byte-Uebernahme aus dem Protokoll
angle.aux[0] = rec_command[2];
angle.aux[1] = rec_command[3];
angle.aux[2] = rec_command[4];
angle.aux[3] = rec_command[5];
winkel = angle.ang;
und wenn ich mir jetzt "winkel" anschaue steht da eine glatte Null,
obwohl die Variablen angle.aux die vier bytes einer float-Variable sind
(hab ich ueberprueft):
angle.aux[0] = 0x41
angle.aux[1] = 0xA8
angle.aux[2] = 0x00
angle.aux[3] = 0x00
0x41 A8 00 00 is die Darstellung in hex der Zahl 10.5:
Vorzeichenbit:0
Charakteristik:10000011
Mantisse: 0101000 00000000 00000000
was mach ich falsch?
Oder:
was gibt es sonst noch fuer Moeglichkeiten aus 4 einzelnen bytes eine
float-Variable zu machen?
Tipps sind wilkommen. Wenns mal funktioniert gibts den Code in der
Sammlung.
mg,
Johannes
den Namen winkel hab ich fuers Forum geaendert... damits richtig ist
denk euch anstatt der Zeile:
winkel = angle.ang;
diese hier:
winkel[0] = angle.ang;
sorry,
Johannes
> was gibt es sonst noch fuer Moeglichkeiten aus 4 einzelnen> bytes eine float-Variable zu machen?
Ne Menge.
Im Ernst: float oder double binaer von einem Rechner zum
anderen zu uebertragen ist 'Russisch Roulett'. Das kann
gehen, wenn beide Compiler das gleiche Floatingpoint Format
verwenden, muss aber nicht.
Also: Hast Du schon ueberprueft ob der Sender und der Empfaenger
das gleiche floating point Format benutzen?
Hallo Karl Heinz,
ne, hab ich nicht überprüft. Wie macht man das?
Der C-Code für den uC ist mit WinAVR compiliert und die serielle
Schnittstelle am Rechner ist Standard. Vorlaeufig schick ich
selbstgebastelte Befehle mit den 4bytes nach IEEE-Norm fuer einfache
Genauigkeit (Beispiel siehe Beitrag oben).
mg,
Johannes
> Wie macht man das?
Indem Du Dir zb fuer ein paar Zahlen die
binaere Repräsentation (sprich: die Bytes)
auf beiden Systemen anschaust und vergleichst.
Sind sie identisch, dann ist das schon mal gut.
Wenn nicht: viel Spass.
Wenn du deine Ergebnisse mit printf() über die serielle Schnittstelle
überträgst, kann es mit float auch zu problemen kommen, wenn du die
falsche lib eingebunden hast (MAKEFILE).
PRINTF_LIB = $(PRINTF_LIB_FLOAT)
solltest du verwenden
Hallo zusammen,
also mein Rechner und der uC stellen die floats beide in little endian
darstellung dar. die bytes werden als "verkehrt" herum uebertragen.
Habs getestet. Daran lag es auch, dass es nicht funktioniert hat mit
der Uebertragung.
Mein naechstes Problem ist die serielle Schnittstelle anzusprechen aus
Windows; programmiere mit VisualC++. Mal sehen was es da alles im Forum
schon gibt!
Danke fuer eure Tipps und Hinweise.
mg,
Johannes