Forum: Mikrocontroller und Digitale Elektronik Modulo Problem


von Daniel F. (Gast)


Lesenswert?

Hallo liebe Experten,

ich sitze hier vor einem Modulo Problem und komme nicht weiter:

Ich habe einen Schrittmotor mit einem Encoder, der in diesem immer eine 
ganze Umdrehung fährt, was genau 38000 Einheiten entspricht. Nun mache 
ich nach jedem Schittmotorbefehl eine Überprüfung der Position, ob 
motorposition und Encoderposition übereinstimmen bzw. innerhalb einenr 
gewissen Toleranz liegen.

Da es sich um eine Dreheinheit handelt, Ist die Position 38000 genau 
gleich der Position 0, 38001 gleich 1 etc...

Wenn ich nun mehrere Umdrehungen fahre, kommen höhere Positionen von 
Enocder und Motorcontroller zurück (z.B. bei 3 Umdrehungen 114000 etc). 
Ich will die Positionen immer in den Bereich 0-31999 Mappen.

Da erste was mit einfällt ist Modulo aber da gibt es folgendes Problem:
 Durch Ungenauigkeiten kann es sein, dass die Encoderposition z.B. nach 
einer Umdrehung nur bei 31997 liegt, die Motoposition aber genau bei 
32000. Wenn ich nun Modulo mache, kommt beim Motor 0 raus und beim 
Encoder bleibt die 31997. Das bedeutet für den Algorithmus, der die 
beiden Werte auf Abstand vergleicht, dass der Abstand zu hoch ist.

Ich bin echt schon verzweifelt, kann mir hier jemand weiterhelfen??

DANKE!

: Verschoben durch User
von Route_66 H. (route_66)


Lesenswert?

Daniel F. schrieb:
> Durch Ungenauigkeiten kann es sein, dass die Encoderposition z.B. nach
> einer Umdrehung nur bei 31997 liegt,

Wie das?
Wenn der Encoder etwas Anderes zeigt als Schritte angesteuert werden, 
dann verliert der Stepper Schritte (Schlupf). Dann müssen 
Korrekturschritte nachgeschickt werden.

von c-hater (Gast)


Lesenswert?

Daniel F. schrieb:

> Wenn ich nun mehrere Umdrehungen fahre, kommen höhere Positionen von
> Enocder und Motorcontroller zurück (z.B. bei 3 Umdrehungen 114000 etc).
> Ich will die Positionen immer in den Bereich 0-31999 Mappen.

Wenn man bereit wäre, eine Abweichung vom Soll (also Vielfachen von 
38000) zu akzeptieren, dann muss das Ergebnis natürlich signed sein, 
denn es wären ja sowohl positive als auch negative Abweichungen denkbar.

Also muss man nach dem Modulo noch mit der Hälfte der Encoderschritte 
vergleichen. Ist das Modulo kleiner als die Halfte der Encoderschritte, 
dann handelt es sich um eine positive Abweichung->der Fehlerwert 
entspricht direkt dem gefundenen Modulo-Wert.

Ist er hingegen größer als die Hälfte der Encoderschritte, dann ist die 
Abweichung negativ und man erhält sie, indem man das Modulo-Ergebnis von 
der Zahl der Encoderschritte/Umdrehung abzieht.

von Joe F. (easylife)


Lesenswert?

Ziehe die beiden Werte zuerst voneinander ab (als signed Variablen) und 
dann Modulo.
Eigentlich sollte das Modulo aber gar nicht nötig sein, denn so weit 
sollten die beiden Werte ja nicht auseinanderliegen...

: Bearbeitet durch User
von runden (Gast)


Lesenswert?

oder caste die zahl in ein float 31997.0 dann teilen durch 100 = 319.997 
und dann aufrunden 320 dann mal 100 = 32000 und wieder in int casten und 
dann modulo

von Mathematiker (Gast)


Lesenswert?

runden schrieb:
> oder caste die zahl in ein float 31997.0

Ich will's nicht fassen.

Es geht um diskrete Schrittzahlen. Dafür ist float nun wirklich 
denkbar ungünstig. Die Idee kann nur von einem Softwerker kommen, der 
für Zahlensysteme nicht eine Spur von Verständnis hat.

von Joe F. (easylife)


Lesenswert?

Mathematiker schrieb:
> Ich will's nicht fassen.

Jo. Und ausserdem, was soll das runden bringen?
Der Fehler entsteht ja durch das Modulo, das auf 2 Werte angewandt wird, 
die dann voneinander abgezogen werden.
Dadurch entsteht eine falsche Differenz.

Der Weg ist wie gesagt, erst abziehen, und dann modulo (wenn überhaupt 
nötig).

von Possetitjel (Gast)


Lesenswert?

Daniel F. schrieb:

> Ich will die Positionen immer in den Bereich 0-31999 Mappen.

Warum?

> Durch Ungenauigkeiten kann es sein, dass die Encoderposition
> z.B. nach einer Umdrehung nur bei 31997 liegt, die Motoposition
> aber genau bei 32000. Wenn ich nun Modulo mache, kommt beim
> Motor 0 raus und beim Encoder bleibt die 31997.

Eben. Wuerdest Du direkt 31997 und 32000 vergleichen, haettest
Du das Problem gar nicht.

Merke: Den Hauptwert erst ganz am Schluss bilden; Rechnungen
wenn moeglich alle vorher erledigen.

von Patrick J. (ho-bit-hun-ter)


Lesenswert?

Hi

So wie ich Das verstehe, 'schwanken' die Encoder-Schritte um +/-1
Das wäre kein Problem, da dieser Abstand wohl 'im grünen Bereich' ist.
Das Problem wird erst Eins, wenn die Soll-Position 'normiert' wird, also 
von 38000 auf 0 gesetzt wird, wodurch die Differenz auf 37999 anwächst, 
was wohl einen Schlepp-Fehler anzeigen wird (+Abbruch).

Kann der Motor auch anders herum verfahren, oder wird Dieser IMMER nur 
in eine Richtung angesteuert, da so an eine Verriegelung angefahren 
wird?

Wenn KEINE andere Drehrichtung benötigt wird, könntest Du auch 'einfach' 
erst 'Normieren', wenn beide Werte über dem Maximal-Wert liegen.

So hast Du immer die Abweichung und von 38000 bis zur nächsten 2er 
Potenz sind's noch >28000, sollte zur Schleppfehlererkennung reichen, 
ohne, daß Dir einer der Zähler überläuft.

MfG

von Theor (Gast)


Lesenswert?

@ Daniel

Es scheint mir richtig, nicht die Symptome zu beheben, sondern die 
Ursache.

Für Schrittverluste bzw. überschüssige Schritte gibt es, allgemein 
gesprochen, die Ursache, dass bewegte Masse und Schrittfrequenz nicht 
zueinander passen.

Wenn das Problem gelöst ist, gibt es auch nicht mehr die Notwendigkeit, 
durch willkürliches Gleichsetzen, etwaige Unterschiede zwischen 
Projektion und Messung, zu beseitigen. Das Ergebnis der Modulo-Operation 
ist ja nur deswegen unbefriedigend, weil überhaupt Schritt-Differenzen 
vorkommen. Es liegt also nicht am Modulo.


Nun schreibst Du in Deinem Eröffnungspost von Schrittverlusten. Im 
allgemeinen ist dann die Last zu groß bzw. die Schrittfrequenz. Um das 
wenigstens grob bestätigen zu können, hast Du die Möglichkeit die 
Schrittfrequenz bzw. die Rate, mit der sie erhöht wird, zu verringern.

Mit einem binären Verfahren kannst Du (im allgemeinen) eine minimale 
Schrittfrequenz bzw. minimale Änderungsrate finden, bei der es keine 
Verluste mehr gibt. Vermutlich wird die zu gering sein, aber es geht 
hier nur darum, ob es überhaupt geht. Falls es selbst bei extrem 
geringen Frequenzen bzw. Raten nicht geht, liegt vermutlich ein 
SW-Problem oder ein mechanisches Problem vor.


Falls Du eine gezielte Bewertung möchtest, wäre es zweckmäßig, wenn Du 
uns mal folgende Angaben machst:

1. Motor, Typ, Link auf Datenblatt
2. Angaben zur Last und des dynamischen Verhaltens (falls anwendbar). Am 
besten eine Zeichnung mit Massenangaben.
3. Quellcode des Codes der die Schrittfolge erzeugt (bitte auf das 
wesentliche reduzieren; das Ergebnis sollte compilierbar sein).
4. Schaltung

von Motorenfütterer (Gast)


Lesenswert?

Daniel F. schrieb:

> ganze Umdrehung fährt, was genau 38000 Einheiten entspricht. Nun mache

> Da es sich um eine Dreheinheit handelt, Ist die Position 38000 genau
> gleich der Position 0, 38001 gleich 1 etc...

ACHTUNG: GLEICH GEHEN 6000 SCHRITTE VERLOREN!

> Wenn ich nun mehrere Umdrehungen fahre, kommen höhere Positionen von
> Enocder und Motorcontroller zurück (z.B. bei 3 Umdrehungen 114000 etc).
> Ich will die Positionen immer in den Bereich 0-31999 Mappen.

> einer Umdrehung nur bei 31997 liegt, die Motoposition aber genau bei
> 32000. Wenn ich nun Modulo mache, kommt beim Motor 0 raus und beim
> Encoder bleibt die 31997. Das bedeutet für den Algorithmus, der die

> Ich bin echt schon verzweifelt, kann mir hier jemand weiterhelfen??

Bitte, ab solchem Zahlensalat verzweifele auch ich ganz von alleine, 
ohne weiter Hilfe...

von Wolfgang (Gast)


Lesenswert?

Daniel F. schrieb:
> Wenn ich nun Modulo mache, kommt beim Motor 0 raus und beim
> Encoder bleibt die 31997.

Lass es einfach mit Modulo. Rechne einfach mit der Differenz. Das 
entlastet dich und deinen Prozessor. Wenn die Differenz größer als 16000 
oder kleiner als -16000 wird, korrigiere einfach mit 32000.

von Daniel F. (Gast)


Lesenswert?

c-hater schrieb:
> Wenn man bereit wäre, eine Abweichung vom Soll (also Vielfachen von
> 38000) zu akzeptieren, dann muss das Ergebnis natürlich signed sein,
> denn es wären ja sowohl positive als auch negative Abweichungen denkbar.

Ja, die Abweichungen sind akzeptierbar und summieren sich über die Zeit 
auch nicht, das wurde intensiv getestet, die Abweichungen liegen auch 
innerhalb der Toleranz. Es handelt sich um eine Dreheinheit, d.h. es 
wird in beide Richtungen gefahren, je nachdem in welche Richtung die 
Zielposition näher ist.

c-hater schrieb:
> Also muss man nach dem Modulo noch mit der Hälfte der Encoderschritte
> vergleichen. Ist das Modulo kleiner als die Halfte der Encoderschritte,
> dann handelt es sich um eine positive Abweichung->der Fehlerwert
> entspricht direkt dem gefundenen Modulo-Wert.
>
> Ist er hingegen größer als die Hälfte der Encoderschritte, dann ist die
> Abweichung negativ und man erhält sie, indem man das Modulo-Ergebnis von
> der Zahl der Encoderschritte/Umdrehung abzieht.

Das Problem ist, dass die Dreheinheit, wenn sie gerade keine genaue 
Position anfahren muss, in einem sogenannten Idle Mode immer ganzzahlige 
Umdrehungen fährt (z.B. 3 Umdrehungen alle 30 Sekunden). D.h. der 
Motortreiber zählt die Schritte mit, die dann natürlich weit über 32000 
liegen (Sorry, der erste Post mit den 38000 war tatsächlich falsch, es 
handelt sich bei einer Umdrehung genau um 32000 Einheiten). Annahme: 
Motor steht bei Position null nach referentfahrt und macht dann 3 ganze 
Umdrehungen: nach Ausführung steht Motor bei 96000, der Encoder irgendwo 
in der Nähe, Beispiel 95998. Nun gibt es natürlich nur die Positionen 
0-31999, was auch logisch ist, denn im normalen betrieb (nicht Idle) 
wird auch immer nur eine von 80 Positionen am Kreis angefahren, es ist 
sonst nie eine ganze Umdrehung notwendig. Deswegen will ich nach so eine 
IDLE Umdrehung die Position wieder in den Bereich 0-31999 Mappen, damit 
bei eine normalen Positionierung (außerhalb Idle mode, wo die 
Zielposition zwischen 0 und 31999 liegt) nicht die ganezn Umdrehungen 
wieder zurück gefahren werden müssen. Man stelle sich nur vor, wenn die 
Anzahl der Idle Umdrehungen nicht 3, sondern 10 oder noch höher wird...

Patrick J. schrieb:
> So wie ich Das verstehe, 'schwanken' die Encoder-Schritte um +/-1
> Das wäre kein Problem, da dieser Abstand wohl 'im grünen Bereich' ist.
> Das Problem wird erst Eins, wenn die Soll-Position 'normiert' wird, also
> von 38000 auf 0 gesetzt wird, wodurch die Differenz auf 37999 anwächst,
> was wohl einen Schlepp-Fehler anzeigen wird (+Abbruch).

Richtig!

Patrick J. schrieb:
> Kann der Motor auch anders herum verfahren, oder wird Dieser IMMER nur
> in eine Richtung angesteuert, da so an eine Verriegelung angefahren
> wird?

Ja genau, es wird in beide Richtungen gefahren, siehe Beschreibung oben.

Motorenfütterer schrieb:
> ACHTUNG: GLEICH GEHEN 6000 SCHRITTE VERLOREN!

Sorry, wie bereits erwähnt, war dies falsch, es handelt sich um 32000 
Einheiten bei einer ganzen Umdrehung.

DANKE!

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Daniel F. schrieb:
> Durch Ungenauigkeiten kann es sein, dass die Encoderposition z.B. nach
> einer Umdrehung nur bei 31997 liegt, die Motoposition aber genau bei
> 32000.

 LOL.
 Wenn du dich aufs zählen der Schritte verlässt und dein Encoder so
 ungenau ist, wozu brauchst du es dann überhaupt ?
 Entweder stimmen die Schritte, dann brauchst du normallerweise keinen
 Encoder, oder die Schritte stimmen nicht, dann musst du dich aber auf
 den Encoder verlassen können.
 Schritte (die nach deinen Angaben genau sind) mit einem Encoder zu
 kontrollieren (der nach deinen Angaben ungenau ist) - ist ein
 bisschen schizophren, oder ?


> Wenn ich nun Modulo mache, kommt beim Motor 0 raus und beim
> Encoder bleibt die 31997. Das bedeutet für den Algorithmus, der die
> beiden Werte auf Abstand vergleicht, dass der Abstand zu hoch ist.

 So etwas nennt man Tolleranz. Entweder bleibt diese in Grenzen, dann
 wird der Fehler auf erlaubten Wert geprüft, oder nicht - dann wird
 der Encoder weggeschmissen, so einfach ist das.
 Und das kann mit einem Vergleich auf:
1
 (WERT - MaxFehler) && (WERT + MaxFehler)
 ganz einfach festgestellt werden.
 Falls true, EncoderWert = SollPosition und weiter geht es mit Modulo...

: Bearbeitet durch User
von Daniel F. (Gast)


Lesenswert?

Marc V. schrieb:
> So etwas nennt man Tolleranz. Entweder bleibt diese in Grenzen, dann
>  wird der Fehler auf erlaubten Wert geprüft, oder nicht - dann wird
>  der Encoder weggeschmissen, so einfach ist das.
>  Und das kann mit einem Vergleich auf: (WERT - MaxFehler) && (WERT +
> MaxFehler)
>  ganz einfach festgestellt werden.
>  Falls true, EncoderWert = SollPosition und weiter geht es mit Modulo...

Ich glaube du verstehst mein Problem nicht ganz... es ist nicht die 
Überprüfung das Problem, sondern dass nach dem Move die werte nicht mehr 
zwischen 0-31999 liegen. natürlich könnte ich die Überprüfung vorher 
machen, das ändert aber nichts daran, dass die werte danach nicht im 
definierten Bereich liegen.

Danke,lG

von Klaus (Gast)


Lesenswert?

Das ist ein klassisches Problem. Tritt auch bei jedem Ringpuffer auf, da 
ja dort auch bei einem Überlauf vorne wieder angefangen wird. 
Reinschreiben und Auslesen, kein Problem. Aber wieviel ist drin oder 
frei?

Das gleiche gilt auch für Timer mit Überlauf. Im Umfeld einer dieser 
beiden Anwendungen würde ich mal nach Lösungen suchen.

MfG Klaus

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Daniel F. schrieb:
> Ich glaube du verstehst mein Problem nicht ganz... es ist nicht die
> Überprüfung das Problem, sondern dass nach dem Move die werte nicht mehr
> zwischen 0-31999 liegen. natürlich könnte ich die Überprüfung vorher

Marc V. schrieb:
1
 (WERT - MaxFehler) && (WERT + MaxFehler)
 Falls true,
 EncoderWert = SollPosition

 und weiter geht es mit
 EncoderWert % WomitAuchImmer
 ...

von Daniel F. (Gast)


Lesenswert?

Ok, angenommen, die beiden Positionen sind nach einem Idle Move bei:
motorpos: 96000
encoderpos: 96003

Nehmen wir weiters an, dass die maxuimale Abweichung bei +/- 10 liegt, 
d.h. Abweichungen innerhalb dieser Toleranz werden akzeptiert.

Was ist in diesem Fall die Variable "WERT" in deinem beschriebenen 
Algorithmus?

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Daniel F. schrieb:
> Was ist in diesem Fall die Variable "WERT" in deinem beschriebenen
> Algorithmus?
1
 if( (motorpos >= (encoderpos - Fehler)) && (motorpos <= (encoderpos + Fehler)) ) encoderpos = motorpos;

von Peter D. (peda)


Lesenswert?

Wenn ich einen Encoder habe, dann ist der doch bindend. D.h. ich 
berechne die nächste Schrittzahl des Motors ausgehend von der 
Encoderposition.
Ansonsten kann ich mir den Encoder doch gleich schenken.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Peter D. schrieb:
> Ansonsten kann ich mir den Encoder doch gleich schenken.

 LOL.
 Ja.

Marc V. schrieb:
> So etwas nennt man Tolleranz. Entweder bleibt diese in Grenzen, dann
>  wird der Fehler auf erlaubten Wert geprüft, oder nicht - dann wird
>  der Encoder weggeschmissen, so einfach ist das.

von Hmmhmm (Gast)


Lesenswert?

Marc V. schrieb:
> So etwas nennt man Tolleranz.

Toll.

Nur was ist eine Tolleranz?

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Hmmhmm schrieb:
> Nur was ist eine Tolleranz?

 Beschwer dich bei meiner Tastaturrrrrrrrrrrrrrr

von c-hater (Gast)


Lesenswert?

Daniel F. schrieb:

> Das Problem ist, dass die Dreheinheit, wenn sie gerade keine genaue
> Position anfahren muss, in einem sogenannten Idle Mode immer ganzzahlige
> Umdrehungen fährt (z.B. 3 Umdrehungen alle 30 Sekunden).

Erstmal: Warum tut sie das? Welcher grenzdebile Vollidiot hat ihr das 
befohlen? Das ergibt doch überhaupt keinen Sinn...

Und selbst wenn irgendwo ein verborgener Sinn dahinterstecken sollte: 
Das ändert rein garnix. Es gilt immer noch der von mir beschriebene 
Algorithmus als bestmögliche Näherung. Funktioniert definitiv so lange, 
wie der Fehler jederzeit kleiner bleibt als die Hälfte des 
Encoder-Zählumfangs.

Was natürlich jedem Nicht-Vollidioten unmittelbar klar sein sollte. Der 
wäre allerdings auch selber auf den Algorithmus gekommen. Ist ja 
schließlich nicht gerade höhere Mathematik...

von Possetitjel (Gast)


Lesenswert?

Daniel F. schrieb:

> Ok, angenommen, die beiden Positionen sind nach einem
> Idle Move  bei:
> motorpos: 96000
> encoderpos: 96003

Okay.

> Nehmen wir weiters an, dass die maxuimale Abweichung
> bei +/- 10 liegt, d.h. Abweichungen innerhalb dieser
> Toleranz werden akzeptiert.

Okay. Also berechnest Du "diff:=motorpos-encoderpos",
da kommt also diff=-3 heraus.

Jetzt reduzierst Du encoderpos auf den Hauptwert, da kommt
3 heraus.

Wo ist das Problem?

Wenn es mit zwei Absolutpositionen PARTOUT nicht klappen
will, dann versuche es doch mal mit einer Position und einer
Differenz...

von Possetitjel (Gast)


Lesenswert?

Klaus schrieb:

> Das gleiche gilt auch für Timer mit Überlauf. Im Umfeld
> einer dieser beiden Anwendungen würde ich mal nach Lösungen
> suchen.

Sehr guter Tipp.

Das mentale Problem ist, dass man Ueberlauf i.d.R. im
Zusammenhang mit vorzeichenlosen Zahlen hat, Differenzen
aber positiv und negativ sein koennen.

Die Diskussion ueber Timer hat (bei mir) die Erkenntniss
reaktiviert, dass alles perfekt funktioniert, wenn man
1. alle Absolutwerte vorzeichenbehaftet speichert und
2. sicherstellt, dass die DIFFERENZ keinen Ueberlauf
   (weder positiv noch negativ) erleidet.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.