- Akku Tests und Balkonkraftwerk Speicher         
Seite 2 von 2 ErsteErste 12
Ergebnis 11 bis 20 von 20

Thema: #Clocks für float division

  1. #11
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    05.09.2007
    Ort
    Preetz
    Alter
    36
    Beiträge
    150
    Anzeige

    Powerstation Test
    Hier noch ergänzend meine Signum funktionen.
    Code:
    inline int8_t signf(float number)
    {
    	if (signbit(number))
    		return -1;
    	else
    		return 1;
    }
    inline int8_t signi(int16_t number)
    {
    	if(number>>15)
    		return -1;
    	else
    		return 1;
    }
    inline int8_t signl(long number)
    {
    	if(number>>31)
    		return -1;
    	else
    		return 1;
    }
    nicht, dass dort der fehler herkommt
    (c) Rechtschreibfehler sind rechtmäßiges Eigentum des Autors (c)

  2. #12
    Erfahrener Benutzer Robotik Einstein Avatar von Felix G
    Registriert seit
    29.06.2004
    Ort
    49°32'N 8°40'E
    Alter
    41
    Beiträge
    1.780
    Erstmal hätte ich ein paar kleine Hinweise zur Performance:

    Code:
    if((x>>7)>W) x=-x+(W<<7);                  //x wird auf das Intervall [-W;W] normiert (aufgrund der Achsensymmetrie um x=0)
    if((x>>7)<-W) x=-x-(W<<7);
    Die Shifterei kannst du dir sparen, wenn du die Konstanten für 90°, 180° und 360° gleich in skalierter Form definierst. Das spart immerhin allein bei diesen 2 Zeilen schon 28 Shift-Operationen (der AVR muss ja für ein <<7 tatsächlich 7x shiften)

    Auch die Signum Funtionen lassen sich beschleunigen, indem du statt if(number >> 31) folgendes machst: if(number & (1 << 31)). Dafür braucht der AVR keine Shifts, da 1 << 31 als Konstante schon vom Compiler berechnet wird.


    Was den Überlauf.. bzw. die Überläufe betrifft sind mir mehrere Stellen aufgefallen:

    1. x hat den Typ int16_t und enthält den Winkel in Grad * 128, korrekt?
    Dann möchte ich mal anmerken, daß ein Winkel von 360° einem x von 46080 entspricht. Bei einem int16_t ist allerdings schon bei (2^15)-1 = 32767 Schluss.

    2. B und x sind beide int16_t und werden multipliziert, da ist es sicherer zuerst beide auf uint32_t zu casten, damit der Compiler nicht auf die Idee kommt das Ergebnis in 16 Bit quetschen zu wollen.

    Es sind noch mehr Probleme deser Art im Code zu finden, daher mein Tipp:

    Für jeden einzelnen Berechnungsschritt nochmal den worst-case Fall prüfen. Prinzipiell gilt: wenn irgendein Zwischenergebnis größer werden könnte als der Typ der beiden Operatoren, sollten beide vorher zur Sicherheit auf den nächst größeren Typ gecastet werden.
    So viele Treppen und so wenig Zeit!

  3. #13
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    05.09.2007
    Ort
    Preetz
    Alter
    36
    Beiträge
    150
    ok vielen dank,
    zu 1. meine funktion soll nur für die Rotation meiner Koordinaten verwendet werden. Den Torso kann ich nur um max 60° drehen um Z sogar nur um 15°, sonst kippt er um, daher war ich von maximal 180° ausgegangen, und dafür genügt ein int16_t mit 7 Festkommabits. Dadurch habe ich das leiche format wie bei meinen Drehwinkeln. Also bevor die funktion einen Überlauf hat, sind bereits meine Drehwinkel übergelaufen.

    Aber mit 2. hast du recht. Kann sehr gut sein, dass auf meinem 32Bit rechner die überläufe nicht auffielen, da er ehh mit "long" für AVRs arbeitet.

    mfg WarChild
    (c) Rechtschreibfehler sind rechtmäßiges Eigentum des Autors (c)

  4. #14
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    05.09.2007
    Ort
    Preetz
    Alter
    36
    Beiträge
    150
    So: Felix, du hattest recht
    jetzt habe ich die minimale Anzahl an Float operationen erreicht, es bleiben nur je sechs mal zwei Wurzeln, vier Winkelfunktionen und vier Divisionen bei der einen und sechs Winkelfunktionen bei der anderen Funktion, die ich nur durch eigene Festkommafunktionen beschleunigen könnte.

    vorher / nachher Funktion
    2500/325 Berechnung der benötigten Pulslängen (8 mal schneller)
    34000/382 Berechnung der Translation (100 mal schneller)
    175000/51000 Berechnung der Rotation (3.4 mal schneler)
    400000/276000 Berechnung der Gelenkwinkel IK (45% schneller)
    jetzt liege ich bei eine gesamten Rechndauer mit Interrups bei 22.5ms,
    also fast echtzeit. Eigentlich muss mich nurnoch die Beschleunigung von der IK Interessieren, da diese mit 17,5ms den größten Ausschlag macht.

    vielen Dank an Alle, ohne euch wäre ich vorher warscheinlich schon verzweifelt!!! =D>
    edit: meine Festpunkt Sinus/Cosinus Funktion mit max 0.0001 Abweichung funktioniert jetzt. Also:
    175000/11100 Berechnung der Rotation (15 mal schneler) \/
    Fehlt nurnoch eine Festpunkt Wurzel und Arkus-funktionen

    mfg WarChild
    (c) Rechtschreibfehler sind rechtmäßiges Eigentum des Autors (c)

  5. #15
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    05.09.2007
    Ort
    Preetz
    Alter
    36
    Beiträge
    150
    So meine Quadratwurzel ist fertig.
    Hab mir ein Iteratives VErfahren ausgedacht, dass nach dem Prinzip der Annäherung durch Intervallhalbierung funktioniert.
    dadurch konnte ich folgende verbesserung erziehlen:
    400000/232000 Berechnung der Gelenkwinkel IK (72% schneller)

    hat jemand von euch eine Idee wie man die Arkus Winkelfunktionen Approximieren kann? In Festkomma Arithmetik...
    Code:
    uint16_t sqroot(unsigned long number)				// O(n)=log_2(n) Max Abweichung meistens 0 oder 1, selten 2 bzw. 0.1% für große zahlen
    {
    	if(number==0) return 0;							//triviale Fälle abfangen
    	if(number==1) return 1;
    	
    	unsigned long r2;
    	uint16_t root=0,delta;
    	if(number>16777216UL)							//falls die Zahl größer als eine 24 Bit Zahl ist
    		delta=(number>>16);
    	else if(number>64536)							//falls die Zahl größer als eine 16 Bit Zahl ist
    		delta=(number>>8);							//günstigeren Anfangspunkt Wählen --> führt zu leichter Unschärfe 0.1%
    	else
    		delta=(number>>1);								//sonst beginn bei der Zahl selbst
    	
    	while (delta)									//sollte innerhalb von 16 Iterationen eine Lösung liefern
    	{
    		r2=(unsigned long)root*root;
    		if(r2>number)
    			root-=delta;
    		else
    			root+=delta;
    		delta=(delta>>1);
    	}
    	return (uint16_t)root;
    }
    mfg WarChild
    (c) Rechtschreibfehler sind rechtmäßiges Eigentum des Autors (c)

  6. #16
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Im Prinzip sollten die Potenzreihen auch in Festkommaarithmetik gehen. Die Reihe vom Arctan ist aber bekannt dafür, dass sie nicht besonders schnell konvertiert.

    Ein guter Link dazu :
    http://de.wikipedia.org/wiki/Arctan#...ise_Berechnung

  7. #17
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    05.09.2007
    Ort
    Preetz
    Alter
    36
    Beiträge
    150
    vielen Dank für den Tipp
    Der Arkustangens ist schon so gut wie erledigt.
    Das Problem bei den letzten beiden (Arkus-Co-Sinus) ist die abweichung in den Randbereichen. Selbst Taylorpolynome 7. Grades haben in der nähe um die -1 und 1 Abweichungen von bis zu 4 Grad. Mal sehen, vlt. nehm aber rotzdem ein Taylorpolynom, da meine mechanischen Gelenke abgesehen von der schulter nur in den Intervallen [5°;175°] und [10°;180°] arbeiten können. So wird eine Überstrapazierung der Getriebe durch das Erreichen des Endandschlages von vorn herein vermieden.
    (c) Rechtschreibfehler sind rechtmäßiges Eigentum des Autors (c)

  8. #18
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Beim ArcSin / cos macht es eventuell Sinn, den Wertebereich aufzuteilen. Bei Werten von etwa -0.5 ... 0.5 mit dem Arcussinus, von 0.5 ... 1 mit dem Arcus cosinus.
    Der Arccos um 1 ist etwas problematisch, schon wegen der großen Steigung. Eventuell wäre hier eine andere Näherung, z.B. über die Wurzel sinnvoller. Für Werte nahe 1 sollte sqrt(2-2*x)) ein brauchbare Näherung für Arccos(x) sein.

  9. #19
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    05.09.2007
    Ort
    Preetz
    Alter
    36
    Beiträge
    150
    Danke Beserwessi:
    Dank der Festkomma ArcTan(x) und ArcTan2(y,x) funktionen konnte ich wieder eine erhebliche Beschleunigung erziehlen.
    400000/149000 Berechnung der Gelenkwinkel IK (2.7 mal schneller)
    Aufgrund dieses Leistungssprungs schafft der µC alle nötigen berechnungen in nur 10ms zu erledigen. Also noch reichlich Zeit für die PWMs vlt. eine dynamische Fußnachsetz Funktion und I²C kommunikation.
    Allerdings reizt es mich die floats gänzlich aus meinem Bot zu verbannen.
    Vlt klapts ja noch mit den letzten beiden Funktionen, auch wenn mich die Überlaufkontrolle mitlerweile ankotzt.
    Code:
    //**************************************************//	974 Takte*
    int16_t arctan(long number)							//Eingabe mit Skalierung 1024 = 10 Festkommabits Ausgabe 7 Festkommabits
    {
    	int8_t v;
    	unsigned long x;
    	if (number==0)		return 0;
    	if (number>0)		{x= number;v=1;}			// Betrag und Vorzeichen von number
    	else				{x=-number;v=-1;}		
    	if (x> 8388608UL)	return (v* Wd2);			//für |x|>2^13 gilt +-90°
    	if (x<1024)													//für x<1 gilt allg.: x/(1+0.28x)
    		return v*(((209539UL*x)>>3)/(((x*x)>>10)+3657));		//zähler/nenner= 2^-17/2^-10=2^-7 
    	else if(x<60000UL)											// sonst gilt allg.: PI/2-x/(x²+0.28)
    		return v*(Wd2-((58671UL*(x>>3))/(((x*x)>>10)+287)));	//zähler/nenner= 2^-17/2^-10=2^-7
    	else
    	{
    		x=(x>>5);												//anpassung zum Schutz vor Überläufen
    		return v*(Wd2-(((58671UL*x)>>8)/(((x*x)+287)>>10)));	//zähler/nenner= 2^-7/2^0=2^-7
    	}
    }
    //**************************************************//
    
    //**************************************************//  1729 Takte*
    int16_t arctan2(int16_t y,int16_t x)				//Eingaben Ganzzahlig, Ausgabe 7 Festkommabits
    {
    	if(x==0)										//Vorzeichenorientierte Fallunterscheidung
    	{
    		if (y==0) 		return 0;
    		else 			return signi(y)*Wd2;
    	}
    	if(x>0)				return arctan(((long)y<<10)/x);
    	else				return arctan(((long)y<<10)/x)+signi(y)*W;
    }
    //**************************************************//
    mfg WarChild
    (c) Rechtschreibfehler sind rechtmäßiges Eigentum des Autors (c)

  10. #20
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    05.09.2007
    Ort
    Preetz
    Alter
    36
    Beiträge
    150
    @Besserwessi
    Ich hab mir mal die kurve der Arcos Funktion angesehen und der Tipp mit der Wurzel ist gar nicht schlecht. Ist ja auch logisch, wenn die Funktion einer Parabel Ähnelt, so muss die Umkehrfunktion einer Quadratwurzel ähneln.
    Hier also meine Formel zur Aproximation: -1<x<1
    für x==0 -->90 //Optionale abkürzungen, nicht notwendig
    für x==1 -->0
    für x==-1 -->180
    für x>=0 --> 0.822*90*sqrt(1-x)-0.178*90*(1-x)
    für x<0 --> 180-(0.822*90*sqrt(1+x)-0178*90*(1+x))

    Ich denke mit meiner Ganzzahligen Wurzel, als Festkomma Interpretiert sollte das recht schnell funktionieren.
    Diese Funktion hat eine maximale Absolute Abweichung bei 0.9 von 0.845°, die zweitgrößte Abweichung liegt bei 0.2 mit 0.6° aber an den Kritischen stellen stimmt Sie absolut.
    Ich habe die Linearfaktoren der Wurzelfunktion und der Korrekturgeraden auf das Minimale Integral der absoluten Abweichung justiert.

    naja und der Asin hat halt nur etwas andere Y-Verschiebung und eine Spiegelung. asin(x)=-acos(x)+90

    edit: Funktion ist implementiert:
    400000/78000 Berechnung der Gelenkwinkel (5.2 mal schneller)
    jetzt schaffe ich die gesamte IK und Transformation in nur 5.8ms. Bäm
    Keine Floats sind mehr vorhanden! Alles zusammen hat eine Verzehnfachung der Rechengeschwindigkeit bewirkt.

    mfg WarChild
    (c) Rechtschreibfehler sind rechtmäßiges Eigentum des Autors (c)

Seite 2 von 2 ErsteErste 12

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Solar Speicher und Akkus Tests