PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : ADC Auflösung umrechnen - Divisionsproblem



Barthimaeus
29.03.2010, 22:16
Ich beschäftige mich jetzt seit ein paar Tagen mit Schrittmotoren und nachdem ich nun einige Funktionen geschrieben habe, die mir deren Ansteuerung sehr erleichtern, dachte ich, es wäre schön, wenn ich den Schrittmotor über ein Poti steurn könnte - soll heißen der Schrittmotor fährt eine Position relativ zum Drehwinkel des Potis an. Das bedeutet, dass der ADC benötigt wird. Dieser hat beim Mega8 eine Auflösung von 10bit, was 1/1024 entspricht. Wenn ich das nun auf einen Schrittmotor mit 200 Schritten übertrage bedeutet dies das er 0 bis zu 5+(1/8) Drehungen ausführen wird, je nachdem, wie ich das Poti einstelle. Dies klappt auch wunderbar. Nun möchte ich jedoch, dass 1024/1024 nicht 5+(1/8) Drehungen, sondern nur 1 Drehung bedeuten. Mathematisch ist das Problem schnell gelöst:
(ADC/1024 )*200. Leider kommt der µC mit dieser Berechnung nicht klar, was wohl an der fehlenden Darstellungmöglichkeit von Fließkommazahlen (wie sie am PC dur IEEE754 definiert sind) liegt. Eigentlich hatte ich angenommen, der µC würde die entstehenden Nachkommastellen einfach abschneiden, denn der Verlust dürfte sich wohl in Grenzen halten - was ist schon ein 1,8° Schritt mehr oder weniger... Jedenfalls rechtfertigt es für meine Anwendung keine Nachbildung einer Fließkommaarithmetik.
Dem ist leider nicht so... Es tut sich nichts.
Habt ihr einen Vorschlag?

Srry, es ist wohl wieder ein Roman geworden...

yaro
29.03.2010, 22:33
(ADC*200)/1024 sollte besser gehen, wenn es nicht wegoptimiert wird.

ansonsten mit float rechnen.

ADC ist ein wert, der kleiner ist als 1024. Wenn du ihn durch 1024 teilst, kommt ein wert unter 1 raus. Dieser Wert wird auf int (ganze zahlen) abgerundet, was dann 0 ergibt...

Zuerst den Wert multiplizieren sollte dieses Poblem beheben.

Gruß, Yaro

Barthimaeus
29.03.2010, 23:11
Da hätt ich auch drauf kommen können...

Danke, ich werds gleich morgen ausprobieren ;)

oberallgeier
30.03.2010, 00:16
... hätt ich auch drauf kommen können ... ausprobieren ...Da bin ich ja gespannt, wie es der Compiler schafft, dem Controller für Werte über ADC = 328 die richtige Berechnungsvorschrift zu erstellen. Ich hab das Gefühl, dass er das nicht hinkriegt und dadurch der Überlauf der Grund für Fehler ist. 65500 ist ja schnell erreicht, und darüber bräuchte ich dann, rein gefühlsmässig, long integer (32 bit). Bei "ADC / 5" wäre der maximale Fehler schlappe 2,4 % im Vergleich zur genauen Rechnung. Ist ja nicht wenig, aber vielleicht reicht Dir das?

Barthimaeus
30.03.2010, 09:11
Hi Oberallgeier! Wie du bereits prognostiziert hattest, ist es zu dem Überlauffehler gekommen, was sich darin äußerte, dass der Motor nach ca 1/4 Drehung auf 0 zurückspringt und wieder von vorne anfing. Daraufhin habe ich auf den uint32_t Datentyp gewechselt, und jetzt läuft alles wie geschmiert - die 2,4° sind für mein "Funktionsmodell" nicht von Bedeutung.
Wenn ich das Poti voll aufdrehe fährt der Motor die gewünschten 200 Schritte ab, wenn ich zurückdrehe fährt er relativ zur Potidrehung rückwärts.

Vielen Dank

P.s.: Warum ist eigentlich die L297, L298 Schaltung so beliebt? Mit nur einem Mega8 zB. kann man doch locker drei Stepper ansteuern. Die Steuerung des µC könnte man dann per i2c realisieren -> mein nächstes (Ätz-)Projekt

Besserwessi
30.03.2010, 17:05
Der L297 ist schon ziehmlich alt, da waren µCs noch nicht so verbreitet.

Man könnte das meiste auch mit einem µC machen. Die PWM Werte werden dann zwar kaum nach dem aktuell gemesen Strom, sondern nach berechneten Werten eingestellt, aber das sollte auch gehen. Ganz ohne Strommessung wird es aber wohl nicht gehen - man muß ja auf ggf. variable Belastung des Motors reagieren.

rossir
30.03.2010, 22:14
Noch ne Idee aus der Schulzeit: Kürzen. Hier kürzen durch 8.
Dann steht da: ADC*25/128
Dann geht es, selbst mit int16_t, so genau wie Deine Lösung mit uint32_t.

Bzw. Extremkürzing ;-), wenn es 2% ungenauer sein darf: ADC/5 (siehe auch oberallgeier)

oberallgeier
02.04.2010, 18:28
Baaaa - das wirklich Gute hätte ich fast übersehen:
Wenn man ADLAR verwendet, dann kriegt man die 1024er Auflösung nur noch von 0 bis 255 - das ist nach der Methode Milchmädchen fast 1 5tel. Und das recht genau (wie genau weiß ich nicht, weil ich die Arbeitsweise des ADwandlers nicht kenne, und daher seine Rundungstechnik nicht mal abschätzen kann). WENN so ein Ergebnis reicht, dann wäre das 1) s..kurz, 2) doch pfiffig (oder nicht?) und 3) s..schnell.

Sternthaler
17.04.2010, 00:48
Hallo zusammen,

nur mal so am Rande. (Weil oberallgeier die ADC-Geschichte anspricht.)

Alle 6 ADC-Kanäle vom mega8 können 10 Bits wandeln. Bei 2'en davon wird aber in der Doku nur eine 8 Bit-Wandlung empfohlen weil da irgendwelche Taktsignale in der Hardwarenähe sind. (Allerdings kann man auch da 10 Bit nutzen wen man den mega im ADC-Sleep-Mode fährt)
Bei der 8-Bit-Wandlung werden einfach nur die oberen Bits zurückgegeben. Intern macht die Kiste immer eine 10'ner Wandlung.

Aber auch mit nur diesen 8 Bit muss ja noch Dreisatz befragt werden um auf die 200 Stepperschritte runterzurechen. Leider ist mein Schulwissen in Bezug auf das Kürzen dem Taschenrechner zum Opfer gefallen ;-)

Gute Motersteuerung wünscht
Sternthaler

mare_crisium
17.04.2010, 07:40
Und selbst rossirs Extremkürzung (ADC/5) kann man genau machen (im langfristigen Mittel), indem man die Divisionsreste aufaddiert. Dem Divisionsergebnis muss man immer dann eine Eins dazuzählen, wenn die Divisionsrest-Summe 5 übersteigt. Dabei natürlich auch von der Summe 5 abziehen.

Analog immer Eins vom Ergebnis abziehen, wenn die Summe kleiner als -5 wird. Danach 5 zur Summe zuzählen. Bresenham lässt grüssen ;-) !

mare_crisium

Sternthaler
17.04.2010, 12:49
Hallo,

was ist mit der Variante, wenn man ein externes Hardware-Rechenwerk nutzt?
Hier kann man doch auch einfach einen zusätzlichen Widerstand rechnen lassen.

Poti mit 20kOhm und einen "Rechenwiderstand" mit 5,6kOhm davor gesetzt.
Fertig.

Gruß
Sternthaler

oberallgeier
17.04.2010, 17:22
... Variante ... ein externes Hardware-Rechenwerk ...Huiiiii - da ist schon wieder mal jemand, der (noch) EAI kennt. (http://www.analogmuseum.org/deutsch/collection/eai/tr10/) Diese Teile nannte man früher Analogrechner. Na ja, meist waren sie etwas komplexer als blos ein Widerstand - aber in der Kürze liegt eben wie immer die Würze.

s.frings
17.04.2010, 17:51
Den Überlauf Fehler behebt man folgendermaßen:

Aufgabe: x=(ADC/1024)*200

Lösung mit Fließkomma: x=(double) (ADC/1024)*200

Lösung ohne Fließkomma: x=(uint32_t) ADC*200/1024

Immer, wenn Du Ausdrücke in Klammer schreibst, besteht die Gefahr, dass der Compiler für das Zwischenergebnis eine zu kleine Variable verwendet. ADC ist 16bit, und 1024 passen auch in 16bit rein. Also verwendet der Compiler für den Ausdruck (ADC/1024) eine 16bit Integer Variable. Da das Ergebnis immer <1 ist, hast DU dann als Ergebnis eine Null.

Für den Ausdruck (ADC*200) verwendet der Compiler aus dem gleichen Grund eine 16bit Integer Variable. Der Wert kann bis zu 204.600 betragen, was in 16bit nicht mehr rein passt. Da werden dann die überschüssigen Bits einfach links abgeschnitten.

Durch die Angabe (double) bzw. (uint32_t) bestimmst Du, welchen Typ die Variable für das Zwischenergebnis haben soll.