Hallo Leute,
ich brauche für mein Projekt sehr viele Berechnungen, die ich in
kürzester Zeit rechnen muss. Ich verwende einen 8bit-AVR(die bekanntlich
nicht die schnellsten sind). Auf einen ARM oder ähnliches umzusteigen
ist schon zu spät.
Lohnt es sich, einen math-Coprocessor zu benutzen? Hat man dadurch große
Ersparnisse?
Ich habe an sowas wie den hier gedacht:
http://www.sparkfun.com/commerce/pr.....info.php?products_id=8129
Hat jemand Erfahrungen mit sowas gemacht? Oder kennt jemand vielleicht
ein besseres Modell?
Gruß, Yaro
Hier gibt es so eine FPU (soll angeblich ein DSPIC sein) mit Beispielen:
http://www.micromegacorp.com/atmel.html
Aber man sollte eigentlich VORHER die Rechenleistung abschätzen
und dann erst den µC auswählen.
avr
Die FPU ist selber nicht die schnellste und wahrscheinlich nur eine
Software-FPU.
Alternativ kann man auch schnellere uCs nehmen z.B. mit 20Mhz oder eine
extra uC als FPU programmieren. Es gibt auch Look up Tabellen.
Ja... den Rechenaufwand abschätzen ist nicht ganz so einfach, wie ich es
mir vorgestellt hatte...
Hatte noch nie ein so Zeitintensives Projekt, dass ich jeden einzelnen
Takt zählen musste, wie ich es jetzt tue. Aber man lernt bekanntlich nie
aus.
Ist die Zeitersparniss mit diesem CoProzessor groß genug, dass es sich
empfielt, ihn zu benutzen?
Gruß, Yaro
Ich benutze schon einen 20MHz AVR.
Ich denke, ein FPU ist schneller, weil es 32bit Architektur hat.
Lookup-Tabellen habe ich schon einige implementiert, aber für einige
Anwendungen müssten sie so groß sein, dass sie nicht in den Flash
passen.
Gruß, Yaro
Edit: der Link am Anfang hat nicht funktioniert, hier ist er nochmal:
http://www.sparkfun.com/commerce/product_info.php?products_id=8129
moin moin,
als FPU nutze ich einen C8051F365( 1Takt Core) der mit 98MHz tackert.
In einem 8051ED2 (22MHz, 6Takte-Core) braucht ein SIN ca. 900µs.
Die FPU ist über SPI angebunden, der MainMC kann also auch was anderes
sein.
Mit FPU inklusive SPI braucht es für einen SIN-Wert nur 95µs.
Die FloatLib ist auch im MC vorhanden, teilweise rechnen beide
gleichzeitig und das spart.
Mit Gruß
Pieter
Eine gute FPU bringt sicher Zeitersparnis. Aber diese FPU ist nicht
sonderlich schnell (siehe Datenblatt). Sinus berechnen 100 µs - ohne
senden, empfangen, sonstiges.
Evtl kannst du mehrere nehmen oder eine andere.
Oder zusätzliche Lookup Tabelle in externem EEpron etc...
an einen AVR ne FPU stricken, naja...
Wenn man merkt, es reicht hinten und vorne nicht - umsteigen.
Ich behaupte mal, den Performance-Gewinn büsst du durch Transferzeiten
wieder ein. Sinn macht es erst dann, wenn du Funktionen auslagern
kannst, in der Zwischenzeit was anderes machst und dann weiter im
eigentlichen Text. Ob ein AVR-Compiler sowas kann? Eher wirst du stupide
warten müssen.
Gibt Rechenleistung satt, ARM.
> Hatte noch nie ein so Zeitintensives Projekt, dass ich jeden einzelnen
Takt zählen musste,
Ja was rechnest du denn ?
Wirklich floating point, oder taete es auch soundsoviel bit fixed point
?
Sinus und Wurzel, oder nur Addition und Multiplikation ?
Eine richtige floating-point-implementation auf einem 8 bit Rechner ist
langsam, locker 1000 mal langsamer als ein arithmetic-coprozessor, der
es meist in 1 Takt macht, aber in vielen Faellen braucht man gar keine
floating point Funktionen um etwas korrekt auszurechnen.
Ich brauche öfters Winkelfunktionen (sin, cos usw.), und muss auch ab
und zu floats teilen und multiplizieren. Wurzeln brauche ich auch
manchmal, aber meißt mit einer nicht ganz so großen genauigkeit, da habe
ich eine Ersatzfunktion geschrieben, die deutlich schneller ist.
Lookup-Tabellen habe ich auch schon einige erstellt, klappt aber leider
nicht für alle anwendungen. Optimirt habe ich auch schonn einge Menge,
nur scheints, als ob das alles nicht genug sein wird. Ich komme im
Moment mit der Leistung zwar noch hin, aber das sollte nicht mehr lange
der Fall sein, denn ich brauche immer mehr Winkelfunktionen, die ich
kaum ersetzen kann, und die Genaugkeit der floats ist auch z.T.
notwendig.
Der co.Prozessor hat eine 32bit Architektur, deswegen habe ich gehofft,
dass er viel schneller ist. Aber 100µs für einen sin, ist ja
genausoviel, wie ein ATmega (mit 16MHz) braucht, da kann ich ja gleich
einen zweiten ATmega anschließen...
Wie kann denn sowas eigentlich sein? das Ding arbeitet mit 30MHz mit
einer 32bit Architektur, und ist dabei genauso schnell, wie ein AVR mit
einer 8bit Architektur und 16MHz
Kennt jemand eine FPU, die deutlich schneller ist, als diese hier?
Den sonnst lohnt es sich ja wirklich nicht, sie anzuschließen...
Gruß, Yaro
Yaroslav Gevorkov schrieb:
> Wie kann denn sowas eigentlich sein? das Ding arbeitet mit 30MHz mit> einer 32bit Architektur, und ist dabei genauso schnell, wie ein AVR mit> einer 8bit Architektur und 16MHz
An 32 Bits glaube ich eher nicht. Das Äussere passt aber prima zu
Microchips 16bittern dsPIC30F2011 und 3012. Das Tempo auch.
Yaroslav Gevorkov schrieb:
> Kennt jemand eine FPU, die deutlich schneller ist, als diese hier?> Den sonnst lohnt es sich ja wirklich nicht, sie anzuschließen...
Anno 386/486 gab es mal ein paar fixe externe Varianten. Von Weitek und
so. Könnte aber sein, dass dir beim Anschluss rasch die Pins ausgehen.
;-)
Schnelle externe FPU und pinsparender serieller Anschluss beisst sich
etwas.
Aber komplette Controller, die sich für sowas ähnlich der uM-FPU
programmieren lassen, gibt es durchaus. Diverse ARM7 und Cortex-M3 in
TQFP48 beispielsweise. Weniger Pins gibt es zwar auch, aber kleiner ist
ein SO28 effektiv auch nicht.
Dann dürte das schnellste der Parallax Propeller sein, gibt's als DIP40.
Da streiten sich dann 8 Stück 32bit Prozessoren mit je 20 MIPS darum,
wer den Job übernehmen darf. Könnte bei geeigneter Programmierung
schnell genug sein, wobei aber kein Hardware-Multiplier mitspielt. Das
Interface darfst du selbst erfinden, denn konzeptbedingt hat der kein
vordefiniertes, und programmieren darfst du das in Assembler.
Grösstenteils jedenfalls.
Andere 32bit Typen als DIP kenne ich nicht. Höchstens als Header-Board.
Die neben dem Propeller vielleicht am fixesten rechnenden Controller in
DIP dürften die dsPIC33 sein. 40MHz 16-Bit, und die DSP-Funktionalität
nützt dir vielleicht sogar was.
Ich habe schon mit ASM Programmiert... nur habe ich für dieses Projekt
nicht sooo viel Zeit..
Fazit ist also, einfach einen zweiten (oder dritten) AVR anschließen,
und sich nicht so viel Zeit verschwenden. Richtig?
Gruß, Yaro
Richtig, denn bei allen diesen Lösungen kommt erst der Schweiss, dann
die Freude. Denn programmieren musst du sie erst einmal. Und wenn du
keine Zeit hast, dann bringt das alles wenig.
Ach ja: Andere Compiler andere Libraries. Vielleicht findet sich ein
AVR-Compiler, dessen Floating-Point Libs deutlich fixer sind als beim
bisher verwendeten.
Yaroslav Gevorkov schrieb:
> ich brauche für mein Projekt sehr viele Berechnungen, die ich in> kürzester Zeit rechnen muss.
Das ist Wischiwaschi ohne jede Aussage.
Bevor Du ein Problem löst, mußt Du es erstmal kennen.
Also schätze mal ab, wieviel Rechnungen welcher Art Du in welcher Zeit
benötigst.
Insbesondere beim Zeitbedarf verschätzen sich viele.
Letztens war hier auch einer, der wollte alle 10ms Werte auf ein LCD
ausgeben. Also völlig unsinnig schnell, das hätte keiner ablesen können.
Bei ergonomischer Ausgabe ergab sich dann eine CPU-Auslastung von gerade
mal 1%.
Peter
> Pins sind nicht das große Problem, 9 Stück hätte ich übrig,
Für mindestens 32 bit float coprozesor ?
Du beliebst zu scherzen.
Wie wäre es mit 102 pins ? 32 a Wert, 32 b Wert 32 Ergebnis, und 6 für
die Operation.
Vergiss den Ansatz, wechsel den Prozessor, gleich in einem mit schneller
Arithmetik.
Was ich nicht verstehe:
Warum ist es zu spät den µC zu wechseln, wenn du aber bereit bist noch
mal grundlegend die Hardwarekonfiguration (FPU hinzufügen) zu ändern?
Ich hab mal auf nem 32bit DSP (Blackfin) gemessen, was ne floatingpoint
library braucht und wies mit fixpoint arithmetik das verhältnis war
1:1000 also wirds mit nem 8bit processor mindestens 5 mal so lange
dauern.
Aber insgesammt schließe ich mich meinem vorschrebern an:
lös das ganze von anfang an in fixpoint.
was hast du den nfür ne anwendung? erzähl mal! wo kommen die
Eingangsdaten daten und was machst du damit und was soll rauskommen.
Es gibt zwar extreme Fälle, wo es mit 32bit fixpoint enorm schwierig ist
und man auf 64 asuweichen muss, aber die sind sehr speziell.
Im extremfall nimm nen SPI flash (SD-Karte) mit ein paar MB und pack den
randvoll mit LUTs für alle deine Funktionen. musst dann halt so
programmieren, dass due das ergebnis ein paar zyklen vorher anforderst.
Hab aber keine Ahnung ob sich das lohnt, oder ob die Kommunikation zu
langsam ist.
Wenn es bei einem AVR 8Bit bleiben muß (warum auch immer) ist
der XMega z.Zt. das schnellste (intern 32 MHz) und kann durch
DMA und Eventsystem den Kern deutlich entlasten.
Wenn es um große Tabellen geht wäre so ein Dataflasch mit SPI
eine Lösung:
http://www.atmel.com/products/DataFlash/default.asp
avr
@Yaroslav
überlege vllt dochmal nochmal ein externes flash (z.b. at45db161, das
hat 2mbyte) zu verwenden.
ich brauche z.b. filterkoeffizienten die ich im avr berechnen möchte.
die ursprüngliche formel enthält x^y (wobei x keineswegs eine schöne
gerade zahl ist, sondern 1,095irgendwas), tan div. divisionen
multiplikationen und additionen. ein sprung war es die berechnung von
x^y und tan in eine tabelle zu packen ... das hat mir einen enormen
geschwindigkeitszuwachs gegeben. nur bin ich aus speicherplatzgründen
dazu übergegangen die filterkoeffizienten vorberechnet in das flash zu
packen. von den 2 mbyte sind somit gerademal 128kbyte übriggeblieben.
nun hab ich 4 verschiedene filtertypen mit 512 frequenz und jeweils 64
verschiedenen resonanzpunkten.
und die geschwindigkeitssteigerung möcht ich gar nicht erst erwähnen.
ok ich habs noch nicht ermittelt wie schnell es ist, aber ich habe für
eine berechnung vorher 1.5ms benötigt (schon die erste
optimierungsstufe) und nun muß ich nur ein paar bytes an das dataflash
schicken und habe einen fast fertigen koeffizienten-satz (besteht aus 4
long worten).
@vlad: zu Spät den Controller zu wechseln ist es, weil ich das Projekt
zum Herbst fertig haben muss, und mir einfach die Zeit fehlt, 2Wochen zu
investiren, um z.B. mit einem ARM gut genug umgehen zu können.
Eine FPU kann ich über SPI anbinden und brauche nichtmal das
fertig-designte Board umzudesignen (es ist auch so schon kein Platz mehr
drauf).
Das mit externem Speicher habe ich mir auch schon überlegt, aber mir
scheint die Lösung mit 2 Prozessoren besser. (aber ich werde noch weiter
drüber nachdenken)
Das Projekt ist ein Hexapod. Er hat ziemlich lange beine und soll mit
denen auch elegant umgehen können. Dafür braucht man undglaublich viel
Mathematik, und leider auch sehr viele Winkelfunktionen.
@avr: Die xmegas sind schon tolle Dinger! Leider gibt es sie aber nur in
SMD, und auch auf sie muss man sich erstmal umstellen.
Ich verwende einen ATmega 644 mit 20MHz, das Board ist schon fertig.
Aber über den Dataflash werde ich nochmal nachdenken.
@TheMason:Ich habe auch schon einige Funktionen so beschleunigt, aber
bisher nur da, wo ich nur wenig Genauigkeit brauchte.
Das Problem beim jetzigen Projekt ist, dass ich wirklich die volle
Bandbreite der sin und arcsin Funktionen ausnutzen muss.
Ich werde mir nochmal überlegen, welche Genauigkeit ich brauche, und
vielleicht einen externen speicher verwenden.
Gruß, Yaro
>Eine FPU kann ich über SPI anbinden und brauche nichtmal das>fertig-designte Board umzudesignen (es ist auch so schon kein Platz mehr>drauf).
wenn kein Platz ist, wie bekommst du dann die FPU drauf?
aber egal
Ich würd wie gesagt das ganze in fixpoint rechnen.
Was ist das für ein Projekt? Uni/privat/job?
kannst du den Code Zeigen? interessiert mich einfach ob das wirklic so
schwierig ist. Was für ein AVR hast du? wenn du ne komplette float lib
(sin, tan, sqrt, ...) verwendest muss der doch schon davon recht voll
sein.
Machen auf Arbeit bei uns auch alles in fixpoint, weil unser Blackfin
(32bit 500MHz dualcore DSP - derer sind es zwei) keine FPU hat. Und es
geht natürlich auch.
> Das Projekt ist ein Hexapod. Er hat ziemlich lange beine und soll mit> denen auch elegant umgehen können. Dafür braucht man> undglaublich viel Mathematik, und leider auch sehr viele> Winkelfunktionen.
Und die müssen unbedingt in float sein? Du schriebst was von
Genauigkeit. float ist weniger genau als 32bit fixed-point. Nur der
Wertebereich ist größer, da sich die Schrittweite an den Wert anpasst.
> Das Problem beim jetzigen Projekt ist, dass ich wirklich die volle> Bandbreite der sin und arcsin Funktionen ausnutzen muss.
Naja, das Ergebnis eines sin liegt z.B. im Bereich +/- 1. Da würde dir
ein 32-bit-fixed-point-Wert eine Schrittweite von 4,7*10^-10 geben.
Floating-Point hatte da nur bei sehr kleinen Werten Vorteile, sonst nur
Nachteile, da die Mantisse inklusive Vorzeichen nur 24 Bit hat.
@vlad: ich benutze einen ATmega644p, er hat 64kB Flash, also genug
Platz, um funktionen unterzubringen.
tan brauche ich nicht, nur sin cos und arccos. Außerdem brauche ich
öfters Wurzeln.
Bei arccos brauche ich keine große Genauigkeit, deswegen habe ich das
mit einer lookup-Tabelle gemacht. (diese Funktionen habe ich nciht mit
reingestellt, weil sie nur sehr wenig Takte brauchen).
Die zusätzliche FPU hätte ich an ein seperates Board gehängt, dass ich
sowieso verwende. mit SPI könnte ich es dann gut anschließen.
Ich kann hier ja mal ein Beispiel geben (im Anhang). Dies ist eine
Funktion, der man einen bestimmten Punkt im Raum angibt, und sie dann
die jeweiligen Wiinkel der 3 Servos rausgibt. Hier habe ich auch die
erwähnten arccos lookups verwendet. Nicht über die vielen Casts wundern,
sie sind tatsächlich notwendig =). Die ausführung dieser Funktion dauert
zwischen 3 und 6 Tausend Takten (abhängig vom Punkt, der angefahren
werden soll).
Im moment bin ich gerade noch dabei, den Code zu schreiben, er ist also
lange noch nicht fertig, deswgen kann ich auch keinen vollen Code
zeigen.
Gerade jetzt arbeite ich daran, funktionen für den gang um einen
bestimmten Radius zu erstellen. Diese habe ich zwar zum großen Teil
schon auf Pappier, aber noch nicht in Code umgesetzt. Wenn ich das aber
tuhe, stoße ich bald schon an die leistungsgrenze.
Ich habe auch noch vor, sehr viele andere funktionen zu schreiben, die
sicherlich noch mehr Leistung brauchen werden, deswegen bemühe ich mich
jetzt schon darum, vorzusorgen, um später nicht das Nachsehen zu haben.
@Rolf: Das Projekt ist eigentlich Privat, aber ich will es als
"besondere Lernleistung" ins ABI mit einbringen, deswegen muss es auch
im Herbst fertig sein.
Mit fixpoint habe ich leider noch nie zutun gehabt, gut Möglich, dass es
tatsächlich besser geeignet ist.
Edit: ich habe mir gerade ein Tutorial angeschaut, und wenn das, was
dort gesagt urde richtig ist, dann habe ich Fixpoint schon verwendet,
nämlich bei meinen arccos-funktionen (habe dann allerdings die
Nachkommastellen vernachlässigt, weil ich sie nicht brauche).
Ich bruache insgesammt keine extrem große genauigkeit, allerdings
brauche ich bei einigen eher seltenen Anwendungen schon so ca. 10
Nachkommastellen. Deswegen habe ich da, wo ich diese Nachkommastellen
brauche, auch floats eingesetzt.
Kann man sin und cos in fixedpoint rechnen? Wenn ja, wieviel schneller
wird es dadurch (wenn man genauigkeit ungefähr beibehalten will)?
Insgesammt habe ich jetzt überlegt die Aufteilung der Rechenleistung
besser zu gestalten, indem ich auf Reaktionszeit verzichte. So wie ich
mir das jetzt überlegt habe (mit 2 Controllern), wobei der eine die
dringenden Aufgaben rechnet, und der andere die, die etwas warten
können, sollte ich mit der Zeit ganz gut hinkommen.
> brauche ich bei einigen eher seltenen Anwendungen schon so ca.> 10 Nachkommastellen. Deswegen habe ich da, wo ich diese> Nachkommastellen brauche, auch floats eingesetzt.
Diese Genauigkeit hat float aber gar nicht. Etwa 6 signifikante Stellen
(also Vor- und Nachkommastellen zusammen) hast du bei float.
> Kann man sin und cos in fixedpoint rechnen?
Klar. Vielleicht hilft dir das:
AVR-CORDIC könnte interessant sein, gefunden über
Beitrag "Sinus und Cosinus in einem µC ohne Fließkomma berechnen"
Im selben forum habe ich folgendes gelesen:
Der Hauptvorteil vom CORDIC ist, dass man keine Multiplikationen
braucht, deshalb wird er gerne für Hardwareimplementierungen verwendet.
Wenn man aber sowieso schon einen Multiplizierer im Controller hat ist
Cordic nicht mehr unbedingt die beste Wahl.
Die ATmegas haben einen hardware-multiplikator.
Aber der Einwand mit den Floats ist richtig! Die sin-Funktion der
Bibliothek liefert ja sowieso double zurück, da kann ich dann ja auch
gleich double verwenden, bringt ja nicht viel mehr Aufwand (außer später
dann, beim rechnen damit).
Aber wie gesagt, ich habe die Strukturierung des Programms nochmal
überdacht, und dadurch (allerdings mit einigen kleinen Verlusten bei der
Performance) eine Menge Zeit gewonnen. Die 1500Takte, die sin braucht,
wirken sich dann nicht mehr so dramatisch aus.
Gruß, Yaro
double ist auf dem AVR das selbe wie float.
schreib mal was zu den eingangsdaten, was für wertebereich, skalierung?
da du int8 werte reingibst und die du erwartest wette ich, dass sich das
ganze komplett in fixpoints rechnen lässt.
Ich denke, Du kannst noch einiges kürzen. Dadurch wird der Code auch
schneller.
Habe den folgenden Code leider nicht compilieren können, da ich auf den
System, auf dem ich hier arbeite, keinen C Compiler habe. Bin mir
deshalb fast sicher, dass noch ein paar Syntaxfehler drin sind.
Aber Du kannst Dir ja mal anschauen was ich gemacht habe, um die Idee zu
verstehen:
Wofür ich so genaue wert brauche ist z.B. folgendes:
Der Hexa muss um einen bestimmten Radius gehen (Kurve), dabei müssen die
Füße auch einem bestimmten Radius folgen. Der Radius solltte nicht
größer als 3m werden. Die auflösung, in der die Füße bewegt werden
sollen, soll 1-2mm sein. Die Drehung mache ich mit einer Drehmatrix, die
sin und cos des Winkels braucht, um den gedreht werden soll.
Bei maximalem Radius 2m und bester Auflösung 1mm ergibt sich mit
arctan(1/2000) ein Winkel von 0.02864788737°. Da der Radius so weit weg
ist, machen sich sogar kleine Veränderungen des Winkels auf die
Schrittweite bemerkbar. Bei kleinerem Radius ist die Genauigkeit dann
nicht mehr so wichtig.
Der Sinus von diesem (kleinstnötigen)Winkel ist 0,000499999°.
Eine Genauigkeit von mindestens 6 Nachkommastellen würde wahrscheinlich
ausreichen.
Wieso die Auflösung so ganau sein muss ist leicht zu erklären: wenn der
fuß auf dem Boden steht, und sich bewegt (d.h. den Körper bewegt), muss
er ziemlich genau sein, damit sich die Füße in ihrer gesammteheit nicht
in verscheidene Richtungen bewegen, und damit Spannungen erzeugen.
Kennt ihr vielleicht ein gutet tutorial, wo man fixpointrechnung gut
lernen kann?
Gruß, Yaro
Edit: hallo "Gast", du hast deinen Beitrag gerade dann geschrieben, als
ich meinen geschrieben habe, ich lese ihn mir gleich durch, und
beantworte ihn auch schnellstmöglich.
@Gast: Erstmal vielen Dank, dass du dir so viel Mühe gemacht hast, den
Code zu überarbeiten!
Viele Sachen, die du geändert hast, bringen aber leider keine
Verbesserung, weil der Preprozessor sie schon rechnet. Zum beispiel das
quadrieren der Konstanten gehört dazu. Moderne Compiler berücksichtigen
sowas.
das hier:
1
/* X1-Koordinate vorbereiten */
2
uint8_tx1=(uint8_t)x1signed;
3
4
if(x1signed<0)
5
{
6
x1*=-2;
7
}
8
else
9
{
10
x1*=2;
11
}
habe ich zum Anlass genommen, diese Routine noch weiter zu verbessern:
ist wirklich schlauer, als das, was ich gemacht habe. (mit 256 und dann
mit 4 multipliziert).
Gedacht war es von mir eigentlich so: warum eine 16bit Multiplikation
machen, wenn man eine 8bit Multiplikationen machen kann und sie dann 2
mal logisch nach links schieben kann (das mach der Compiler, wenn man *4
rechnet), was schneller ist (allerdings würde damit auch genauigkeit
eingebüßt werden). Berücksichtigt habe ich nicht, dass 256 ja keine 8bit
mehr sind...
das hier:
verfehlt den Zweck, denn so gibt es keinen genauigkeitsgewinn von
arccos1024flash auf arccos4096flashmini, weil der Wert gerundet wird,
bevor er mit 1024/4096 multipliziert wird. Er muss zuerst multipliziert
und anschlißend geteilt werden, sodass wenigstens einige
Nachkommastellen mehr vorhanden sind.
Genauso ist es bei den folgenden Berechnungen.
Totzdem einen herzlihen Dank, dass du dir die Mühe gemacht hast!
Verbessern kann man Code immer, egal wie durchdacht er ist!
Gruß, Yaro
> Kennt ihr vielleicht ein gutet tutorial, wo man fixpointrechnung gut
lernen kann?
Aber Jaroslav, Rechnen mit ganzen Zahlen sollte man in der Grundschule
gelernt haben. Du stellst deine Rechnungen so um, dass mit ganzen Zahlen
in ZehntelMillimeter und Bogensekunden gerechnet wird (dafür wirst du
dann mehr als 8 bit brauchen, selbst 32bit werden teilweise nicht
reichen), und fertig ist deine Fixpunktberechnung. Sie ist nur eine
Frage der Maßeinheit.
>Kennt ihr vielleicht ein gutet tutorial, wo man fixpointrechnung gut lernen kann?
Du scheinst ja von Mathematik etwas zu verstehen.
Somit sollte die grundlagen recht einfach zu verstehen sein.
der trick ist halt, dass man sich für seine Variable eine gewisse
skalierung sucht.
du willst eine genauigkeit von 0,0005 haben.
das sind 1/2000.
Das heißt am gbesten skalierst du diese Zahl mit 2048, das heißt 11bit
das heißt ab dem 12. beginnt dann der vorkomma-anteil.
24.54233 entspräche 50262
-> 24.54233 * 2048 = 24.54233 * 2^11 = 24.54233 * (1<<11)
wenn du zahlen addierst musst du darauf chaten, dass sie die selbe
skalierung haben.
beim Multiplizieren addieren sich die exponenten.
zu beachten ist immer, dass der wertebereich nicht überläuft.
Das härteste sind die mathematischen Basisfunktionen (integerwurzel,
fixpoint-sin, cos, tan, acos, asin) die man natürlich selbst
implementieren muss, oder man sucht sich ne kleine Bibliothek
Alles klar, dann ist es ja wirklich so einfach, wie ich es bereits
angewendet habe =)
Dabei ergebit sich dann das erwähnte Problem, dass man auf den Überlauf
achten muss.
Ein weiteres, weit größeres problem ist, dass der Code deutlich
unübersichtlicher wird. Das ist es, was mich die ganze Zeit davon
abhällt, Festkommazahlen zu verwenden. Die eine Sache ist, eine Seite
Code damit zu schreiben, aber eine andere ist es, 20Seiten Code so zu
schreiben.
Ich werde mir das alles nochmal anschauen, und dann entscheiden, wie ich
es mache.
Wahrscheinlich wird es darauf hinauslaufen, dass ich meißtens float
benutzen werde, und in Fällen, wo ich besondere Genauigkeit brauche,
dann mit Festkommazahlen Rechnen werde.
Vielen Dank für die kompetente Hilfe!
Yaroslav Gevorkov schrieb:
> Ein weiteres, weit größeres problem ist, dass der Code deutlich> unübersichtlicher wird. Das ist es, was mich die ganze Zeit davon> abhällt, Festkommazahlen zu verwenden. Die eine Sache ist, eine Seite> Code damit zu schreiben, aber eine andere ist es, 20Seiten Code so zu> schreiben.
Tja, umsonst ist nur der Tod ;-)
>> Ich werde mir das alles nochmal anschauen, und dann entscheiden, wie ich> es mache.> Wahrscheinlich wird es darauf hinauslaufen, dass ich meißtens float> benutzen werde, und in Fällen, wo ich besondere Genauigkeit brauche,> dann mit Festkommazahlen Rechnen werde.
Ich würde es genau umgedreht machen.
In derregel fixpoint und nur bei besonders kniffligen stellen floats
benutzen.
Das float per se ungenauer sind asl Fixpoint würd ich nicht behaupten.
In den meisten fällen ist es wahrscheinlich umgekehrt.
die genauigkeit von float, richtet sich nicht größe der Zahl.
Float ist quasi sowas wie die wissenschaftliche schreibweise mit
mantisse und exponenten. 1.434e+10. Wobei es so definiert ist, dass es
nur eine stelle vor dem Komma gibt.
also statt 100.23e+3 wird 1.0023e+5 gespeichert
da die erste Stelle ist immer 1 und wird nicht gespeichert.
das heist für den Nachkommateil der Zahl gibt es 23bit
dH wenn deine Zahl 1.irgendwas ist, sind 23bit tatsächlich
Nachkommapäzision, wenn du 100.irgendwas hast sind es nur noch 16bit.
bei 16.7Mio hast du gar keine Nachkommapräzision mehr.
Bei fixpoint, hast du zwar immer eine feste nachkommapräzision,
allerdings wirst du die Variablen nicht mit 2^16 skalieren wollen, da
dann multiplikationen schon kritisch werden, was überläufe angeht, da ja
eine 1 schon 17bit braucht und man 2 solche zahlen nicht mehr in 32bit
multiplizieren kann.
Bei fixpoint muss man halt bei jeder Rechenoperation wissen, was sind
die maximalen/minimalen Werte die eingehen können. Nur so kann man Über-
und Unterläufe verhindern.
Unterläufe treten auf, wenn man zB zwei fixpoints multipliziert und dann
auf die Ursprüngliche skalierung zurückschiftet.
Wenn di Zahlen zu klein waren ist das ergebnis 0.
Das mit den floats ist mir klar. Das gute ist, dass ich (in den meißten
Fällen) nur bei kleinen Winkeln hohe Präzision brauche, bei großen
Winkeln brauche ich nur wenige Nachkommastellen. Wenn mi die 23bit der
floats mal nicht ausreichen, werde ich auf fixpoint zurückgreifen.
Gruß, Yaro
moin moin,
>>kleinen Winkeln hohe Präzision brauche
kann man so nicht sagen. Mein dicker Bartsch (Matheformeln) sagt dazu:
Näherungsformeln für kleine Winkel
sin a ~ a ~ tan a
sin n a ~ n sin a
Die Berechnung zu den Füßen ist vergleichbar mit der
Fräsradienkorrektur.
Zum Platzbedarf: Der C8051F365 ist 5x5mm, braucht 3,3V.
Gruß
Pieter
Große Genauigkeit bei kleinen Winkeln brauche ich, weil:
Kleine Winkel habe ich (im Fall der gehens um einen Radius) dann, wenn
der Radius groß ist. Dann nämlich wirkt sich die änderung des Winkels
sehr stark auf den Bogen aus, der sich gegenüber dem Winkel öffnet, den
ich dazu benutze, meine Schritte zu setzten.
Bei kleinem Radius (und dabei dann großem Schrittwinkel) wirken sich
kleine Ungenauigkeiten weit weniger aus.
Gruß, Yaro
nur mal so als gedankenansatz :
- arbeite komplett mit fixed-point
- lege dir eine viertel sinusschwingung bei maximaler auflösung (32bit)
in ein 2mbyte daten-flash (das macht bei 4bytes pro wert -> 500k-werte
.. bei einer viertel schwingung (90°) -> 0,000171° auflösung)
- bilde sinus-cosinus-fkt aus dieser viertel schwinung
- bilde arccos/arcsin per wägeverfahren aus der sinus/cosinusfkt
(selbst wenn ich mich mit dem wägeverfahren nun in die nesseln setze,
aber ist brute-force und sollte auf jedenfall in akzeptabler zeit zum
ergebnis führen)
ich denke du wirst wenn du das konsequent anwendest mit 32-bit auflösung
am besten gehen bzw fahren :-)
vor allem hast du dann das genauigkeits-problem gelöst und bist zudem
noch ne ganze ecke schneller als floating point.
Zur Praezision von float und Integern. Also single precision float hat
eine mantisse von 23 bit, und einen exponent von 8 bit, plus ein sign.
Das naechst groessere ist double precision, mit etwas mehr von beidem.
Der Vorteil von integern ist, dass man deren Groesse selbst anpassen
kann.
Einen 40, 48 oder 56 bit integer mit seinen Additions- und
Multiplikations- grundfunktionen sind schnell und einfach geschrieben.
Falls Single nicht hinkommt, sollte man sich den Schritt zu 64bit gut
ueberlegen.
Wenn man die Winkelfunktionen nur bei kleinen Werten braucht, dann ist
die Potenzreihen Entwicklung gut:
sin x = x - 1/3 x^3 + 1/5 x^5 ...
Wobei man bei kleinen Werten halt schon relativ früh (z.B. schon nach
x^3) aufhören kann.
Der Arctan ist allerdings nicht ganz so gutmütig und braicht oft mehr
glieder.
Du kannst natürlich auch einen Mega32/644 o.ä. als Coprozessor per ISP
anbinden, der könnte intern mit FixPoint rechnen und dir das Ergebnis
dann einfach als Floatingpoint zurückgeben.
Ansosnten soll sich Fixedpoint vereinfachen wenn man alles auf 1...
-1skaliert, einige AVR haben sogar extra Multiplikationsbefehle dafür.
> als Coprozessor per ISP anbinden
ISP ?
In System Programming ?
Also jedesmal vor der Berechnung den Code rüberladen und brennen ?
Wozu, und warum sollte das schneller sein ?
Jetzt mal ein kleiner Mathe Grundkurs Mathematik. Man verwendet für die
Berechnung von Wickelfunktionen und Co die sog. Taylorreihe.
http://de.wikipedia.org/wiki/Taylorreihe
Diese reihe ermöglicht eine "APROXIMATION" für eine Funktion f(x).
Also das ist das was der Ulrich für den sin(x) aufgeschrieben hat.
Noch ne Kleinigkeit es ist blödsinn wenn man einem "Coprozessor" nur
dazu benutzt um die Winkelfunktionen zu berechnen. Sinnvoller wäre
gewisse Algorythmen direkt auf den zweiten Controller auszulagern zB die
Berechnung von 4 Füssen von den insgesamt 8 oder so ähnlich. Denn dan
würde die Latenzzeit wegen der Kommunikationsschnittstelle nicht mehr so
ins Gewicht fallen.
MFG Patrick
> Man verwendet für die Berechnung von Wickelfunktionen und Co die sog.
Taylorreihe.
Wer ist man?
Der Mathe-Professor?
Vielleicht.
Ein Micro(computer/controller/coprozessor) ?
Sicher nicht, konvergiert viel zu langsam, nicht effizient genug.
Also MaWin du meinst sicher Cordic ?
Auf das hab ich ganz vergessen mir sind spontan nur Taylorreihen
eingefallen.
Zu cordic gibt hier auch nen Artikel
http://www.mikrocontroller.net/articles/AVR-CORDIC
MFG Patrick
Taschenrechner und FPGAs meist Cordic, aber Pentiums verwenden wohl
relativ grosse Tabellen um die Iterationsanzahl seit dem 486 zu zehnteln
und einen speziell dafür entwickelten Algorithmus.
In Softwarebibliotheken werden zur Berechnung von Winkelfunktionen meist
Potenzreihen verwendet, deren Koeffizienten aber von den Taylor-Reihen
der zu approximierenden Funktionen geringfügig abweichen (mit steigendem
Index prozentual immer mehr). Die Koeffizienten sind daraufhin
optimiert, dass der maximale Fehler im genutzten Wertebereich minimal
wird. Taylor-Reihen, die nach n Gliedern abgeschnitten werden, schneiden
hierbei deutlich schlechter ab.
So beträgt bspw. der maximale Fehler des Sinus aus der AVR-Libc nur etwa
4% des Fehlers der Taylor-Reihe, die auf die gleiche Anzahl von Gliedern
(6) begrenzt wird.
Es gibt für die Winkelfunktionen die beiden Möglichkeiten Cordic oder
Taylorreihe. Welche Methode man nimmt hängt davon ab, was man braucht
(Sin und Cos, oder nur Sin), und was die Hardware gut kann.
Die AVRs haben einen HW Muplipier, aber keine Hardware füs Shiften. Das
spricht etwas für die Taylorreihen.
Bei den Taylorreihen wird normalerweise erst einmal dafür gesorgt, das
das Argument klein ist, um einen gute Konvergenz zu erreichen. Beim
Sinus / Cosinus wird man wohl wenigstens dafür sorgen, dass man unter 45
Grad (ca. 0.79 im Bogenmaß) bleibt. Man kann eventuell auch noch weiter
runter gehen durch Ausnutzen von anderen Identitäten.
Die Reihen für Sinus und Cosinus konvergieren dann schon nicht so
schlecht.
Gerade wenn man nur kleine Winkel braucht sind die Taylorreihen die
Methode der Wahl. Einige Reihen gehen dabei gut (exp, sin, cos), andere
weniger gut (Arctan, Wurzel, Logarithmus).
Wenn man geschickt rechnet, sind auch 5 oder mehr Glieder im Polynom
kein großes Problem.
Hab gerade gesehn: oben ist eine Fehler drin: die Vorfaktoren sind
-1/3! , 1/5! usw. die gehen also recht schnell gegen Null.
Das mit der Taylor-Reihe ist ja eine richtig tolle Erfindung!
Bei kleinen Winkeln sollte das mit einem AVR relativ schnell gemacht
sein. Schwierig wird es bei größeren Winkeln.
Problem ist aber auch hier: auf Grund der Brüche (z.B. 1/3*x³) muss man
einen relativ roßen skallierungsfaktor nehmen, um genug genauigkeit
hinzubekommen. Großer Skallierungsfaktor bedeutet große Variablen, was
widerum einen großen Rechenaufwand bedeutet.
Ich bin gerade dabei, das Programm zu schreiben, welches diese
sinusfunktionen braucht, ich werde mal testen, welche Genauigkeit ich
brauche, und welches Verfahren ich dann nehme. Werde bei sehr kleinen
Winkeln wahrscheinlich Taylor nehmen (mit fixpoint) und bei den anderen
wahrscheinlich die math-funktionen mit float.
Gruß, Yaro
Patrick Weinberger schrieb:
> Mal eine andere Frage ?> Können deine aktoren eine solche genauigkeit überhaupst wiedergeben ?
Das habe ich mich in dem Thread das erste mal gefragt, als das Wort
Hexapod fiel.
Ist die Hardware schon fertig und merkst du, dass die ungenauen
Rechnungen den Roboter schlecht machen? Das kann ich nämlich nicht
glauben.
Naja ich weiß Modellbauservos haben eine genuigkeit von 270°/5000=0,054.
Wegen 0,054 mach ich mir doch keine gedanken über einen genauen
Algorythmus ?
MFG
Moin
hat sich mal schon jeman die mühe gemacht eine Fehler / Toleranz
berechnung / bewertung zu machen? ggf ist das ganze mit der 7ten
nachkommastelle gar nicht so wichtig, wenn die hinterher gar nicht mehr
dargestellt werden können (8 bit ausgangswerte). bzw aufgrund von
mechanik, elektronik sowieso mehr fehler reinkommen, als einem lieb ist.
nur mal so zur info, der unterschied zwischen 8 16 und 32 bit
32 bit soll angeblich 48 mal schneller sein bei einer multiplikation als
ein 8 bitter ( nur von der anzahl der befehle )
http://www.elektroniknet.de/home/bauelemente/fachwissen/uebersicht/aktive-bauelemente/mikrocontroller-prozessoren-dsps/32-bit-mcu-soll-8-und-16-bit-markt-angreifen/druckversion/
und viel spass noch
Hallo,
ich habe für Winkelfunktionen auf dem AVR die 'Cephes Lib' benutzt. Die
darin verwendeten Reihenentwicklungen sind keine Taylorreihen, sondern
es werden zunächst die Argumente transformiert, bevor dann eine Reihe
mit wenigen Gliedern zum Einsatz kommt.
Als meine Assemblerroutinen fertig waren, habe ich sie gegen den PC mit
Zufallswerten geprüft und die Ergebnisse waren fast immer auf 15
Dezimalen identisch.
Meine Anwendung (Teleskopsteuerung) benutzt das 64bit Floating Point
Format, daher sind die Routinen wohl unnötig genau und vor allem zu
langsam für den Hexapod.
Hier sind meine Floating Point Routinen:
http://www.martin-cibulski.de/atm/mount_controller_4/mc_4_asm_main/index_de.htm
Hier findet man die Library für verschiedene Auflösungen:
http://www.moshier.net/#Cephes
Gruß,
Martin