Antwort schreiben 
 
Themabewertung:
  • 0 Bewertungen - 0 im Durchschnitt
  • 1
  • 2
  • 3
  • 4
  • 5
Rechenfunktionen des Kr-Mega
13.01.2008, 11:30
Beitrag #1
Rechenfunktionen des Kr-Mega
Hallo,

für eine besonders komplizierte Regelung der Motoren in meinem Roboter ist es notwendig mithilfe des Kr-Megas Sinus-, Kosinus- und Tangensfunktionen auf die, von den analogen Winkelsensoren gemessenen, Werte anzuwenden. Außerdem bräuchte ich eine Möglichkeit ihre Umkehrfunktionen sowie die Quadratwurzel von Zahlen auszurechnen.

Gibt es dafür schon vorgefertigte Routinen oder Funktionen?
Oder gibt es eine Möglichkeit solche Funktionen selbst zu programmieren?

Grüße

Frederik
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
16.01.2008, 11:37
Beitrag #2
RE: Rechenfunktionen des Kr-Mega
Hallo Frederik!

Es gibt in der Tat bereits mathematische Funktionen, die auch diese Winkelberechnungen durchführen. Da du diese Funktionen für die Regelung von Motoren verwenden willst, ein kleiner Hinweis vorweg.
Die Winkelfunktionen als auch die Wurzelfunktionen benötigen eigentlich eine Fließkommaberechnung. Da der Atmel jedoch von seiner Hardware her nur mit ganzen Zahlen rechnen kann, werden diese Fließkommazahlen mittels Software "simuliert". Das funktioniert genauso exakt, als wenn der Atmel dafür eine Hardwareeinheit hätte. Aber die Berechnungen mit Fließkommaeinheiten sind nicht mehr in einem Takt durchzuführen. Damit werden Operationen mit Fließkommazahlen wesentlich langsamer als mit anderen Zahlen. Zur Berechnung von Winkelfunktionen werden gleich mehrere solcher Fließkommaoperationen durchgeführt, was zur Folge hat, das diese Berechnungen ebenfalls langsam sind. Ob das nun für deine Anwendung evtl. doch noch schnell genug ist, musst du ausprobieren.

Um die mathematischen Funktionen nutzen zu können, musst du in dein Programm die Kopfdatei "math.h" einbinden (#include "math.h")

Dann stehen dir folgende Befehle zur verfügung:

Functions
• double cos (double x)
• double fabs (double x)
• double fmod (double x, double y)
• double modf (double value, double  iptr)
• double sin (double x) ATTR CONST
• double sqrt (double x) ATTR CONST
• double tan (double x) ATTR CONST
• double floor (double x) ATTR CONST
• double ceil (double x) ATTR CONST
• double frexp (double value, int  exp)
• double ldexp (double x, int exp)
• double exp (double x)
• double cosh (double x)
• double sinh (double x)
• double tanh (double x)
• double acos (double x)
• double asin (double x)
• double atan (double x)
• double atan2 (double y, double x)
• double log (double x)
• double log10 (double x)
• double pow (double x, double y)
• int isnan (double x)
• int isinf (double x)
• double square (double x)
• double inverse (double)

Einige Funktionen ergeben sich bereits aus dem Namen. Die komplette Dokumentation zu diesen Funktionen findest du in der Dokumentation zur avrlibc, die mit WinAVR mit kommt. Wenn WinAVR installiert ist, findest du die Datei im Anstallationsordner im Unterordner "doc/avr-lbc". Im PDF werden Die Funktionen im Kapitel 5.12 ab Seite 31 beschrieben.

Sollten die Funktionen für deine Anwendung zu langsam sein, gibt es noch die Möglichkeit, eine eigene Funktion mit einer Lookuptable zu verwenden.
Das geht im Groben so, dass du dir überlegst wie genau du die Berechnung benötigst und dann so viele "Ergebnisse" wie für die Genauigkeit notwendig sind, in eine Feldvariable speicherst. Dann baust du dir eine Funktion, die je nach Wert, der übergeben wird, das richtige Feld der Feldvariable zurück gibt, oder besser, den Wert des Feldes. Das könnte zum Beispiel so aussehen:


//Gibt den Wert des Sinus mal 100 aus. So dass er im Programm für Festkommarechnungen genutzt werden kann.
int sinus(int winkel)
{
int LUT[] = {0, 17, 34, 50, 64, 77, 87, 94, 98, 100, 98, 94, 87, 77, 64, 50, 34, 17, 0, -17, -34, -50, -64, -77, -87, -94, -98, -100, -98, -94, -87, -77, -64, -50, -34, -17, 0};
int wert = 0;

winkel /= 10;


while (winkel > 36) winkel -= 36;
while (winkel < 0) winkel += 36;
wert = LUT[winkel];

return wert;
}


Damit man mit den Werten rechnen kann, werden sie mal 100 gerechnet. Das bedeutet, dass der Rückgabewert 17 eigentlich dem Wert 0,17 entspricht. Aber 17 kann der Atmel wesentlich schneller verarbeiten, als 0,17. Und wenn man nach der Berechnung im Hauptprogramm das Ergebnis wieder durch 100 teilt, hat man ebenfalls wieder das richtige Ergebnis.



Grüße

Thomas
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
27.01.2008, 17:30
Beitrag #3
RE: Rechenfunktionen des Kr-Mega
Hallo Thomas,

danke für die Tipps.
Da die Berechnung der Sinusfunktion, wie du gesagt hast, für den Kr-Mega zu rechenaufwendig und damit zu langsam für meine Anwendung ist, habe ich sie wie beschrieben mit der Lookuptable simuliert und in mein Programm eingebunden.
Das funktionert wirklich wesentlich schneller und einfacher!!


Jedoch gibt es bei der Berechung der Wurzel noch ein Problem:
Für meine Anwendung wäre es hilfreich die Qurdratwurzel von zahlen von 0 bis 10000 zu berechnen. Da dieser
Definitionsbereich für eine Lookuptable zu groß ist, versuchte ich mit der, in C mitgeliferten, Wurzelfunktion die Werte zu berechnen.

#include "kr-mega32v23.h"
#include "math.h"

void wurzeltest(void);
int main(void);
{
double a;
double sqrt (double x) ATTR CONST;
a=sqrt(2);
return 0;
}

Leider zeigt der Compiler den Fehler

error: parse error before "ATTR"
error: parm types given both in parmlist and separately
an.

Befindet sich vielleicht in der Schreibweise oder im Syntax ein Fehler?


Abgesehen von diesem Thema hätte ich noch eine Frage zur Verwendung der Lookuptable.

Bei der Feldvariable beginnen die x-Werte mit 0.
Ist es mögliche diese auch mit einer negativen Zahl beginnen zu lassen? (zB. Sodass der eingesetzte Wert -1 den Wert 2 ,oder der Wert -17 den Wert -5 ausgibt)

Grüße

       Frederik
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
01.02.2008, 11:36
Beitrag #4
RE: Rechenfunktionen des Kr-Mega
Hallo Frederik!

Zunächst darf hinter "int void(main) kein Semikolon.
Du startest dort die Funktion. In den geschweiften Klammern hast du danach den Inhalt der Funktion. Bei der Funktionsdefinition oben drüber must du dahinter das Semikolon setzen, da sie dort nur definiert wird und irgendwo weiter unten erst gefüllt wird. Daher ist nach der Definition, der Befehl zu Ende und wird mit einem Semikolon quittiert.

Dann benötigst du die Zeile:
" double sqrt (double x) ATTR CONST;"
gar nicht.
Das ist "nur" eine Funktionsdefinition in der AVRlib zum Compiler.
Durch das Einbinden der Datei "math.h" ist diese Definition bereits eingebunden worden und der Compiler kennt nun diesen Befehl. Also nicht noch mal definieren.

Wenn du einen Index verschieben willst, kannst du das mit einfachen Rechenvorschriften beim Feldaufruf machen.
Ein Beispiel:
Du hast ein Feld von 16 Felder. Der Index geht damit von 0 bis 15.
Du möchtest, dass der Index von -5 bis 10 geht.
Wenn du die Feldvariable aufrufst, mach das folgendermaßen:
eigeneVariable = feldvariable[index + 5];
Ist dein Index nun zum Beispiel -3 bekommst du das Feld Nummer 2 zurück. Also das dritte Feld.

Grüße

Thomas
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
Antwort schreiben 


Gehe zu:


Benutzer, die gerade dieses Thema anschauen: 1 Gast/Gäste

Kontakt | Krause Robotik | Nach oben | Zum Inhalt | Archiv-Modus | RSS-Synchronisation