# Programmierwettbewerb, 5. Aufgabe - Inkrementalgeber Korrektur



## Michael.Uray (28 November 2013)

Liebe Leute,

lange lange ist es her, seit unserem letzten Forumseintrag zum Thema Programmierwettbewerb.

Ein Freund von mir welcher auch in der Automatisierungs Branche arbeitet, hat mir letztens von einem Problem erzählt das er bei einer seiner Anlagen hatte.
Bei ihm ist ein Drehgeber direkt auf einem Motor montiert, nach welchem ein Getriebe geschaltet ist und dieses Getriebe hat eine kleine Ungenauigkeit in der Übersetzung.
Das bedeutet z.B. das Getrieb hat nicht eine Übersetzung von 4:1 sondern von 4:1,001.
Für die Applikation ist allerdings die Position nach dem Getriebe von Bedeutung und eine Referenzierung im laufendend Betrieb ist nicht möglich.

Der Wert vom Drehgeber selbst kann nicht beeinflusst werden und dieser Wert wird in einem geschlossenen Baustein weiterverarbeitet, welchem diese kleine Ungenauigkeit nicht übergeben werden kann. Dh. der Baustein nimmt z.b. nur ganze Zahlen wie 4:1 an.
Das bedeutet der Wert Drehgebebers (von 0-65535) muss z.B. alle 500 Einheiten um +/- 1 korrigiert werden, bevor er diesem Baustein übergeben wird, damit die Position nach dem Getriebe wieder stimmt.

Mich hat es nach diesem Gespräch selbst interessiert, wie sich so etwas lösen lassen könnte und ich bin dann auch auf eine entsprechende Lösung gekommen.
Nachdem allerdings die Progammierwettbewerbe hier inzwischen schon etwas eingeschlafen sind, dachte ich mir so etwas wäre eine ideale Aufgabe für unseren 5. Wettbewerb.

*Aufgabe des Bausteines:*
Ein Inkrementalgeberwert im Bereich von 0-65535 muss alle "x" Einheiten um + oder - "x" korrigiert werden.
Der Überlauf des Eingangswertes muss berücksichtigt werden.
Gesucht ist ein Funktionsbaustein, welcher den Inkrementalgeber Wert als Eingang annimmt und den korrigierten Wert als Ausgang ausgibt.
Die Drehbewegung kann in beide Richtungen statt finden.
Ein BOOL Eingang welcher den Inkrementalgeber Eingangs- und Ausgangswert dieses Bausteins im Falle einer Referenzierung gleichsetzen kann, ist gefordert.
Andere benötigte Eingänge dieses Bausteines bleiben euch überlasssen.

Mindestens geforderte Ein- und Ausgänge dieses Bausteins (Namen können bei Bedarf abweichen):

```
[COLOR=#0000ff]
FUNCTION_BLOCK[/COLOR] EncoderCorrection
[COLOR=#0000ff]    VAR_INPUT[/COLOR]
        EncoderValue : [COLOR=#ee82ee]UINT[/COLOR]; [COLOR=#008000](* Encoder value input *)[/COLOR]
        Reset : [COLOR=#ee82ee]BOOL[/COLOR]; [COLOR=#008000](* The reset adapts [COLOR=#008000]corrected value to [/COLOR]the input value *)[/COLOR]
[COLOR=#0000ff]    END_VAR
    VAR_OUTPUT[/COLOR]
        CorrectedValue : [COLOR=#ee82ee]UINT[/COLOR]; [COLOR=#008000](* Corrected value output *)[/COLOR]
[COLOR=#0000ff]    END_VAR
END_FUNCTION_BLOCK[/COLOR]
```
Es werden keine Anforderungen an eine spezielle Programmiersprache gestellt.
Über den Gewinner entscheiden die Anzahl an Dankessagungen der Forumsleser auf den jeweiligen Beitrag welcher eine funktionierende Lösung enthält.

Einsendeschluss: 15.12.2013 Ende des Tages.

Lg & viel Spass bei der Lösungsfindung
Michi


----------



## Mobi (28 November 2013)

Soll noch intern ein Überlaufschutz rein? D.h. wenn ich intern eine UINT-Variable hochzähle und ich bin bei 65535 und ich addiere z.B. 2 hinzu zählt meine SPS wieder von Anfang hoch, also dann 1. Oder wenn ich 4 addiere geht sie auf 3.


Und bis wann ist der Einsendeschluss?


----------



## Michael.Uray (28 November 2013)

Hallo Mobi,



MichaelUray schrieb:


> Der Überlauf des Eingangswertes muss berücksichtigt werden.



Das bedeutet der Geber läuft im Vorwärtsbetrieb bis auf 65535 hoch und zählt dann wieder bei 0 weiter, oder er zählt im Rückwärtsbetrieb bis 0 und dann von 65535 weiter hinunter.
Der korrigierte Ausgangswert muss dieses Verhalten dann natürlich genauso haben, nur dass er eben um x Einheiten pro x Einheiten korrigiert ist, das heißt dementsprechend dem echten Geber Wert vor- oder nachläuft.

Als Einsendeschluss lege ich den 15.12.2013 bis Ende des Tages fest. Das sind von jetzt weg etwa 2,5 Wochen.
Falls irgendjemand noch mit machen will und es bis dort hin aus irgend einem Grund nicht schaffen sollte, bitte um eine PM oder einen kurzen Post dazu, ich denke hier können wir auch etwas flexibel sein.

lg.
Michi


----------



## Mobi (28 November 2013)

Das der Ausgang das Verhalten haben soll ist logisch. Ich meine nur  manche Steuerungen gehen auf Error wenn ein Überlauf stattfindet, aber  einige fangen einfach wieder bei 0 an. Z.B. bei Epson, wenn man dort auf  65535 was addiert, geht die Steuerung auf Error.


----------



## Friedrich-Alexander (28 November 2013)

Servus Michael,

ich halte Deine Vorgabe für die Aufgabe mit der Korrektur "Ein Inkrementalgeberwert im Bereich von 0-65535 muss alle "x" Einheiten um + oder - "x" korrigiert werden" für unsauber. Nach dem was Du schreibst: "Dh. der Baustein nimmt z.b. nur ganze Zahlen wie 4:1 an."
Dann Schreib halt an den Baustein die Ganzen Zahlen 4000 und 1001 !

Gruß, FA


----------



## Michael.Uray (28 November 2013)

Mobi schrieb:


> Ich meine nur  manche Steuerungen gehen auf Error wenn ein Überlauf  stattfindet, aber  einige fangen einfach wieder bei 0 an. Z.B. bei  Epson, wenn man dort auf  65535 was addiert, geht die Steuerung auf  Error.


Wusste ich gar nicht, dass es so etwas auch gibt. Ist so ein Verhalten eigentlich in der IEC 61131-3 irgendwie definert?
Überlauf Stopps von Steuerungen die im Falle eines Überlaufes auf Error gehen, müssen nicht abgefangen werden.



Friedrich-Alexander schrieb:


> Dann Schreib halt an den Baustein die Ganzen Zahlen 4000 und 1001 !


Dies war nur als Beispiel gedacht um die Problemstellung zu verdeutlichen. Ich selbst habe das Programm nie gesehen, weiß aber nur, dass das Übersetzungsverhältnis nicht so genau (oder gar nicht) eingestellt werden kann.
Dies kann jetzt daran liegen das der Baustein z.B. zu ungenaue Eingänge (Bsp: USINT) hat, oder aber auch daran das dieses Verhältnis fix in diesen geschlossenen Baustein programmiert ist.
Wie und warum es sich nicht ändern lässt weiß ich nicht genau, aber spielt für die Aufgabenstellung dieses Programmierwettbewerbes eigentlich auch keine Rolle.


----------



## Onkel Dagobert (28 November 2013)

Hallo Michi,

wie weit soll denn maximal gezählt werden können, bzw. wie viele Umdrehungen sollen möglich sein?

Gruß, Onkel


----------



## Michael.Uray (28 November 2013)

Onkel Dagobert schrieb:


> wie weit soll denn maximal gezählt werden können, bzw. wie viele Umdrehungen sollen möglich sein?



Die Maschine wird einmal referenziert und läuft dann "ewig" vorwärts. Das bedeutet der Zähler läuft im Betrieb immer über. Der geforderte Baustein muss den Überlauf im Vorwärts- als wie auch im Rückwärtsbetrieb bewältigen können.
Es muss aber am Ende des Getriebes immer wieder wieder bei jeder Umdrehung an der selben Position irgend etwas gemacht werden, und diese Position verschiebt sich durch diese Ungenauigkeit je länger die Maschine läuft immer weiter. Wenn diese Abweichung zu groß wird, dann muss die Maschine gestoppt und wieder neu referenziert werden.
Dieser Baustein soll eben genau diese Ungenauigkeit die hier entsteht korrigieren.


----------



## hucki (28 November 2013)

MichaelUray schrieb:


> Mich hat es nach diesem Gespräch selbst interessiert, wie sich so etwas lösen lassen könnte und ich bin dann auch auf eine entsprechende Lösung gekommen.


Warum stellst Du denn Deine Lösung hier nicht mal als 1. Vorschlag ein, bevor noch mehr Vermutungen in Richtung kostenloser Lösungssuche aufkommen.


Oder ist Deine Lösung schon das Nonplusultra, was keiner mehr toppen kann?


PS: Was gibt's eigentlich zu gewinnen?


----------



## Mobi (28 November 2013)

Also ich kenne auch aus einem anderen Forum regelmäßige Programmierwettbewerbe. Dort wird auch kein Vorschlag am Anfang gegeben. Man muss ja nicht mitmachen, wenn man es für sinnlos hält. Ich mach es, weil mir programmieren Spaß macht und ich gerne Lösungen entwickle für besondere Aufgaben. Es ist halt Hobby und Beruf.


----------



## hucki (28 November 2013)

Mobi schrieb:


> Also ich kenne auch aus einem anderen Forum regelmäßige Programmierwettbewerbe. Dort wird auch kein Vorschlag am Anfang gegeben. Man muss ja nicht mitmachen, wenn man es für sinnlos hält.


Es find' es schon ein Unterschied, ob solche Sachen von den Admins/Mods veranstaltet werden oder von Usern wie Du und ich. Aber ich möchte da keinem zu nahe treten.

Und natürlich muss das jeder für sich selbst entscheiden, ob und wo er komplette Lösungen im Forum veröffentlicht.




Mobi schrieb:


> Ich mach es, weil mir programmieren Spaß macht und ich gerne Lösungen entwickle für besondere Aufgaben. Es ist halt Hobby und Beruf.


Geht mir ähnlich, nur das es nicht mein (Haupt-) Beruf ist. 


Und damit genug OT.
(Vlt. sollten die letzten Sachen auch besser zu dem anderen Thread verschoben werden.)


----------



## Michael.Uray (28 November 2013)

Wenn ich eine Lösung gesucht hätte, dann hätte ich euch um eine gefragt   und mir nicht die Arbeit angetan dies alles so als Wettbewerb   aufzubauen.

Meinen Code habe ich bewusst nicht gepostet, um andere auf eigene Lösungen kommen zu lassen.
Ich habe auch selbst beim 3. Programmierwettbewerb mitgemacht.
Wie Mobi schon schrieb, ist dies Hobby und Beruf.

Im Anhang befindet sich eine Kennwort geschütze ZIP Datei mit meinem Programmcode die sich ein jeder herunterladen kann.
Das Kennwort werde ich am Ende dieses Wettbewerbs oder sobald die ersten anderen Lösungen hier sind veröffentlichen. Dann kann sich ein jeder selbst ein Bild davon machen, ob es das Nonplusultra ist oder ob jemand eine bessere Lösung gefunden hat.


----------



## Sinix (29 November 2013)

MichaelUray schrieb:


> Die Maschine wird einmal referenziert und läuft dann "ewig" vorwärts...
> ...Wenn diese Abweichung zu groß wird, dann muss die Maschine gestoppt und wieder neu referenziert werden.



Das steht für mich im Widerspruch. Entweder läuft die Achse unendlich vorwärts und muss nur bei Aus/Einschalten/Wartung referenziert werden, oder
du musst eine Konstante/Variable als Maximum in der Aufgabenstellung vorgeben!

MfG


----------



## Mobi (29 November 2013)

Diese Konstante kannst du erst vor Ort herausfinden, deswegen sollte man dies als Eingangsvariable machen.


----------



## KingHelmer (29 November 2013)

> Dein Programmcode und der "nie gesehene" Programmcode sind zwei verschiedene Programme?
> 
> Harald



Das eine ist der Programmcode des Bausteins, der mit einem festen Verhältnis weiterrechnet. Dieser soll uns egal sein, wir sollen nur die Information FESTES VERHÄLTNIS davon mitnhemen.
Sein geposteter Code ist der Baustein vorher, welcher die Encoder-Werte korrigiert, um eine, am besten vor Ort einstellbare Ungenauigkeit.

Sind zwei verschiedene Dinge, passt schon so


----------



## hucki (29 November 2013)

KingHelmer schrieb:


> Das eine ist der Programmcode des Bausteins, der mit einem festen Verhältnis weiterrechnet. Dieser soll uns egal sein, wir sollen nur die Information FESTES VERHÄLTNIS davon mitnhemen.
> Sein geposteter Code ist der Baustein vorher, welcher die Encoder-Werte korrigiert, um eine, am besten vor Ort einstellbare Ungenauigkeit.


Das sehe ich nicht so.

Sein Freund hatte das Problem und einen entsprechenden Baustein für den realen Einsatz programmiert.
Und Michael hat dann aus Interesse (auch weil er den Baustein seines Freundes nicht gesehen hat) eine eigene Lösung entworfen, die sich zwar nicht im realen Einsatz aber dafür jetzt in obiger zip befindet.


----------



## Mobi (29 November 2013)

Sein Bekannter hat einen fertigen Baustein für den Geber zum auslesen. Dieser Baustein nimmt aber nur feste Übersetzungsverhältnisse an. Von dem Ausgang des Bausteins bekommen wir den Wert, den wir korrigieren müssen. Was ist an der Aufgabenstellung so schlecht zu verstehen? Das ist ja wie in der Schule. Die einen diskutieren noch mit dem Lehrer über die Aufgabe und haben noch nicht mal angefangen und die anderen sind schon fertig.


----------



## Michael.Uray (29 November 2013)

Hier nocheinmal die vereinfachte Aufgabenstellung:
[Wert von Inkrementalgeber] -> (unkorrigierter Wert) [Geforderter Baustein] (korrigierter Wert) -> [Baustein welcher die Positionierung durchführt]

Der geforderte Baustein muss die Ungenauigkeit welche vom Inkrementalgeber kommt korrigieren.
Man weiß z.B. das der Inkrementalgeber alle 1000 Einheiten um -1 korrigiert werden muss. Die Werte ab wie vielen Einheiten um wie viel korrigiert werden soll, muss natürlich dem geforderten Baustein irgendwie übergeben werden.
Dieser korrigierte Wert soll dann am Ausgang herauskommen und in danach folgenden Bausteinen weiterverarbeitet werden können.


Für alle die es interessiert, in Wirklichkeit kommt der Inkrementalgeber Wert von einem Frequenzumformer an den dieser angeschlossen ist und dieser wird über CANopen zur SPS übertragen.
Der Baustein welcher diesen Wert dann weiterverarbeitet ist geschlossen und hier findet dann anscheinen auch die Verhältnissberechnung statt.
Mein Freund programmiert dies nicht selbst, sondern es ist ein Kollege von ihm aus seiner Firma. Er selbst ist nur der Spezialist für die Antriebstechnik und wurde dadurch mit diesem Problem konfrontiert. Daher habe ich auch nur sehr rudimentäre Informationen darüber bekommen, wie das nachfolgende Progamm aufgebaut ist und warum sich der Wert dort nicht ändern lässt.
Es ist richtig, dass sich mein Baustein nicht im realen Einsatz befindet. Möglichweise sind daher auch in meinem Programmcode noch Fehler enthalten, ich selbst konnte bei meinen Versuchen keine mehr finden.


----------



## Onkel Dagobert (29 November 2013)

Mobi schrieb:


> .. Das ist ja wie in der Schule. Die einen diskutieren noch mit dem Lehrer über die Aufgabe und haben noch nicht mal angefangen und die anderen sind schon fertig.


Tja, die anderen haben wohl das Thema verfehlt. Auch Lernen will gelernt sein, Mobi.

Gruß, Onkel


----------



## Zottel (29 November 2013)

Also, wenn ich das jetzt richtig verstehe kommen z.B. nacheinender
492, 497, 100, 514,1016,198 Impulse
Die Ausgabe wäre:
492, 497, 101, 514,1017,198 Impulse (oder 492, 497, 99, 514,1015,198 Impulse) ?
Weil die Korrektur "klein" ist, unterscheidet sich der korrigierte Wert nur alle paar Mal vom Eingangswert. Innen im Baustein ist die Summe der Divisionsreste mitzuführen.

Was wenn nun gefordert wäre 823 für 747 Impulse auszugeben?

492*823/747 = 542 Rest 42
(42+497*823)/747 = 547 Rest 464
(464+100*823)/747 = 110 Rest 594
(594+514*823)/747 = 567 Rest 67
(67+1016*823)/747 = 1119 Rest 342
(342+198*823)/747 = 218 Rest 450


----------



## Michael.Uray (29 November 2013)

Nicht ganz, es kommt immer ein laufender Wert des Winkels, welcher durch die Vorwärtsbewegung immer erhöht wird, solange bis er überläuft und wieder von 0 anfängt.
Theoretisch sollte der bei jeder Umdrehung an der selben Stelle der selbe Wert vom Drehgeber kommen, aber diese Position verschiebt sich im Betrieb immer mehr durch die Ungenauigkeit des Getriebes.
Der Drehgeber sitzt vor dem Getriebe, die Position muss aber nach dem Getrieb bestimmt werden, daher auch die Getriebeungenauikeit und die notwendige Korrektur.

Beispiel für eine Korrektur von +1 alle 100 Einheiten:

*Geber Wert*
*Korrigierter Wert*
0
0
10
10
100
101
150
151
200
202
250
252
300
303
...
...
64800
65448
64850
65498
64900
13
64950
63
65000
114
...
...
65500
619
0
655
50
705
100
756
150
806
...
...


----------



## Onkel Dagobert (29 November 2013)

Nach 25 Beiträgen ist die Aufgabenstellung unmissverständlich erklärt  .
Mobi, wir können anfangen zu programmieren.


----------



## Mobi (29 November 2013)

Also sowie es in der Tabelle steht, hab ich es auch von Anfang an verstanden


----------



## Zottel (29 November 2013)

Ich habe es so aufgefasst, daß das Eingangssignal die Anzahl der Pulse seit der letzten Abfrage sei. Also 497, 101, 514... bedeutet keine Richtungsumkehr, sondern nur eine Geschwindigkeitsänderung.


----------



## Larry Laffer (1 Dezember 2013)

Ich habe hier mal die dem Sinn dieses Thread absolut abträgichen Beiträge in den ähnlich diesem Thread lautenden anderen Thread verschoben.
So macht es ja auch keinen Sinn. Irgendwelche merkwürdigen Neben-Diskussionen können und dürfen dann gerne dort stattfinden (bis dann der Thread im SV verschwindet 8)).

Gruß
Larry


----------



## UniMog (1 Dezember 2013)

Erst mal Danke für die Zensur und könntest Du deinen abträglichen Beitrag auch in den ähnlich diesem Thread lautenden anderen Thread verschieben


----------



## RobiHerb (1 Dezember 2013)

*Wo kommt es her?*

Ich hatte mal vor einigen Jahren ein vergleichbares Problem, in meinem Falle gab es keine Lösung (zumindest nicht für mich).

Mechanik: eine Feuerwehr Drehleiter oder Rettungsbühne, die im Einsatz beliebig oft den Oberwagen (Tuntable) drehen darf. Am Ende eines Einsatzes soll die Leiter vollautomatisch wieder eingefahren und auf die Halterung gesetzt werden.

Problem war, die Anzahl der Zähne
	

		
			
		

		
	



	

		
			
		

		
	
 auf den Getriebezahnrädern waren jeweils Primzahlen. Wir haben das Getriebe auf gerade Quotienten umbauen müssen.

Also ich habe kapituliert.


----------



## Mobi (2 Dezember 2013)

Frage zur Aufgabe: Wenn referenziert wird, läuft es dann nur vorwärts und ein paar mal rückwärts, aber nicht zurück über die Referenz hinaus oder vorwärts und rückwärts und über die Referenz hinaus ins "Minus"?


----------



## Michael.Uray (2 Dezember 2013)

Nach dem Getriebe ist ein induktiver Geber montiert, welcher der SPS die 0 Stellung mitteilt.
Die SPS fährt im Referenziermodus den Motor langsam bis in diese Position, stoppt dann und schickt dem Frequenzumformer ein Refernzierkommando welches den Wert des Inkrementalgebers im Umformer auf 0 setzt. Zu diesem Zeitpunkt wird dann auch der Reset Eingang des Bausteines gesetzt, um den korrigierten Ausgangswert des Bausteines an den neu Referenzierten Geberwert (der ja jetzt 0 ist) anzugleichen.
Dies ist im laufenden Betrieb nicht möglich, da der Zeitversatz vom Geber Eingang der SPS bis zu dem Zeitpunkt wo der Referenzierbefehl im Frequenzumformer ankommt zu groß ist die Position dann schon nicht mehr auf 0 wäre. Außerdem ist auch noch der SPS Eingang zu langsam, um im Normalbetrieb den Geber sicher erkennen zu können.
Der Baustein soll die Korrekturen in beide Richtungen durchführen können, falls die Maschine im Betrieb durch den Bediener bei einer Verklemmung rückwärts gefahren wird.

Michi


----------



## Mobi (2 Dezember 2013)

Aber kann er den rückwärts gefahren über die Ref. hinaus?


----------



## Michael.Uray (2 Dezember 2013)

Du meinst im Nomalbetrieb, rückwärts über den Punkt des induktiven Gebers, wo dann auch der korrigierte Wert auf 0 stehen sollte?
Ja durch den Bediener bei einer Blockade, dann gibt es einen negativen Überlauf und er fängt wieder bei 65535 rückwärts runter zu zählen an.

Michi


----------



## Michael.Uray (2 Dezember 2013)

Das Teil kann sich im Prinzip beliebig hin und her drehen, auch über die 0 Position hinweg. Im Normalbetrieb zwar immer vorwärts, aber auch rückwärts bei einer Blockade.
Wichtig ist nur, dass immer wieder die selbe Stelle von der Achsumdrehung nach dem Getriebe vom Inkrementalgeber erkannt wird da hier irgend etwas passieren muss. Diese Stelle verschiebt sich aber durch die Ungenauigkeit immer weiter, je länger die Maschine läuft und je mehr Umdrehungen gemacht werden und soll durch den Baustein korrigiert werden.

Michi


----------



## Mobi (3 Dezember 2013)

Das er dann beim Überlauf anfängt, weiß ich ja. Nur wenn immer draufgerechnet wird und die Achse läuft Rückwärts, dann wird das, was vorher draufgrechnet wurde, wieder abgezogen und wenn er dann die Ref. erreicht sind die beide Werte gleich und danach rechnet er weiter runter alle x Einheiten.


----------



## Sinix (3 Dezember 2013)

RobiHerb schrieb:


> Ich hatte mal vor einigen Jahren ein vergleichbares Problem, in meinem Falle gab es keine Lösung (zumindest nicht für mich).
> 
> Mechanik: eine Feuerwehr Drehleiter oder Rettungsbühne, die im Einsatz beliebig oft den Oberwagen (Tuntable) drehen darf. Am Ende eines Einsatzes soll die Leiter vollautomatisch wieder eingefahren und auf die Halterung gesetzt werden.
> 
> ...



Die Krux an der Sache ist das der Zugewinn an Korrektur ins Unendliche geht. 
Mathematisch ist es eine Sägezahnfunktion mit stetig steigender Amplitude.
Eine Lösung kann es nur geben, wenn die Korrektur endlich bleibt.


----------



## Michael.Uray (3 Dezember 2013)

Mobi schrieb:


> Nur wenn immer draufgerechnet wird und die Achse läuft Rückwärts, dann wird das, was vorher draufgrechnet wurde, wieder abgezogen und wenn er dann die Ref. erreicht sind die beide Werte gleich und danach rechnet er weiter runter alle x Einheiten.


Genau so ist es.

So sieht das vorher genannte Beispiel dann aus, wenn er rückwärts über den ursprünglich referenzierten 0 Punkt hinaus läuft:

*Geber Wert*
*Korrigierter Wert*
65436
65435
0
0
100
101


----------



## bits'bytes (3 Dezember 2013)

Hallo,
ich denke die Tabelle hat ein klitze-kleines Problem.
Beim Nachrechnen ergibt sich in der vorletzten Zeile dass der korrigierte Wert eigentlich noch 704 sein sollte. Ich habe für den Zweck der Kontrolle den Überlauf eliminiert und mit den tatsächlichen Werten gerechnet....




> 001010100101150151200202250252300303303......648006544865448648506549865498,5649001313649506363,565000114114......6550061961965536655655,3665585705704,8565636756756,36



bg
bb


----------



## bits'bytes (4 Dezember 2013)

*Eine Lösung....*

Hallo,
anbei als PDF mein Lösungsvorschlag.

(Automation Basic, B&R AS3.90)

bg
bb


----------



## Michael.Uray (4 Dezember 2013)

bits'bytes schrieb:


> ich denke die Tabelle hat ein klitze-kleines Problem.
> Beim Nachrechnen ergibt sich in der vorletzten Zeile dass der korrigierte Wert eigentlich noch 704 sein sollte. Ich habe für den Zweck der Kontrolle den Überlauf eliminiert und mit den tatsächlichen Werten gerechnet....



Ich glaube du hast hier die 0 bei der Überlauf Eliminierung nicht richtig berücksichtigt. Es sollte in deiner Tabelle 65586 anstatt 65585 stehen, dann stimmt es auch wieder.


65535
65535
0
65536
50
65586 (=65536+50)


Michi

PS:
Dein Programm werde ich dann gleich einmal austesten, könntest du hier die Source Dateien (*.vb, *.fun, *.var ist ausreichend) noch in einem ZIP File hochladen, dann brauche ich die Variablen Deklarationen nicht abzutippen. Oder sonst als Text einfügen, das wäre auch schon hilfreich.


----------



## Michael.Uray (4 Dezember 2013)

MichaelUray schrieb:


> Dein Programm werde ich dann gleich einmal austesten, könntest du hier die Source Dateien (*.vb, *.fun, *.var ist ausreichend) noch in einem ZIP File hochladen, dann brauche ich die Variablen Deklarationen nicht abzutippen. Oder sonst als Text einfügen, das wäre auch schon hilfreich.



Hat sich erledigt mit dem Hochladen, ich war zu ungeduldig und habe es dann doch gleich selbst abgetippt .

Also grundsätzlich rechnet dein Baustein richtig, auch bei Rückwärtsbetrieb.
Allerdings hat er ein Problem damit, wenn sich der Encoder zu schnell bewegt, da dein korrigierter Wert immer viele Zyklen braucht, bis er nachgezogen ist. Wenn er dann zu schnell fortschreitet und nicht mehr auf das Nachziehen gewartet wird, dann kommt er aus dem Tritt und zeigt einen falschen Wert an.
Siehe auch folgendes Video (der untere Baustein ist von dir):




Aber ich denke du bist schon mal auf dem richtigen Weg!

PS:
Einen ">" "<" Vergleich in deinem Progamm habe ich noch auf "=>" "<=" geändert, siehe Screenshot.


----------



## bits'bytes (4 Dezember 2013)

Hallo, schlafen wir jetzt schon  .



MichaelUray schrieb:


> Hat sich erledigt mit dem Hochladen, ich war zu ungeduldig und habe es dann doch gleich selbst abgetippt .


Ja, wollte ich gerade machen ...



MichaelUray schrieb:


> ...
> Allerdings hat er ein Problem damit, wenn sich der Encoder zu schnell bewegt, da dein korrigierter Wert immer viele Zyklen braucht, bis er nachgezogen ist. Wenn er dann zu schnell fortschreitet und nicht mehr auf das Nachziehen gewartet wird, dann kommt er aus dem Tritt und zeigt einen falschen Wert an.
> Siehe auch folgendes Video (der untere Baustein ist von dir):
> Aber ich denke du bist schon mal auf dem richtigen Weg!
> ...



Ah ja, also der Fall dass der Encoder-Fortschritt > Korrektur-Abstand ist ? Das habe ich nicht wirklich berücksichtigt da ich nicht annahm dass dieser Fall eintreten könnte. Werde das noch mal ansehen.

Danke fürs korrigieren ! 

bg
bb


----------



## bits'bytes (4 Dezember 2013)

MichaelUray schrieb:


> Ich glaube du hast hier die 0 bei der Überlauf Eliminierung nicht richtig berücksichtigt. Es sollte in deiner Tabelle 65586 anstatt 65585 stehen, dann stimmt es auch wieder.


Stimmt, genau das habe ich falsch gemacht


----------



## StructuredTrash (4 Dezember 2013)

Mag sein, dass ich mich am frühen Morgen täusche, aber ist das Ganze nicht einfach nur eine Skalierungsfunktion? 65536 Inkremente am Motor entsprechen (65536*Skalierungsfaktor) Inkrementen am Getriebeausgang bzw. am Eingang des Black Box-FB's, oder etwa nicht?

```
FUNCTION_BLOCK fblEncdScal (* Encoder-Istwert 16 Bit skalieren *)
VAR_INPUT
   setScalFact:REAL:=1.0; (* Skalierungsfaktor *)
   inpEncdCntr:UINT;  (* Eingabezähler Encoder *)
   inpReset:BOOL;  (* Reset *)
END_VAR
VAR_OUTPUT
   outScalCntr:UINT;  (* Skalierter Ausgabezähler *)
END_VAR
VAR
   varLastCntr:UINT;  (* Encoder-Istwert beim letzten FB-Aufruf *)
   varForwDiff:UINT;  (* Vorwärts-Zählerdifferenz gegenüber letztem Aufruf *)
   varRevsDiff:UINT;  (* Rückwärts-Zählerdifferenz gegenüber letztem Aufruf *)
END_VAR
(* Bei Reset Ausgabezähler auf Encoder-Istwert setzen *)
IF inpReset
THEN
   outScalCntr:=inpEncdCntr;
ELSE
(* Differenz gegenüber letztem Aufruf berechnen *)
   varForwDiff:=inpEncdCntr-varLastCntr;
   varRevsDiff:=varLastCntr-inpEncdCntr;
(* Skalierte Position berechnen, kleinere Differenz bestimmt Drehrichtung *)
   IF varForwDiff<=varRevsDiff
   THEN
      outScalCntr:=outScalCntr+REAL_TO_UINT(varForwDiff*setScalFact);
   ELSE
      outScalCntr:=outScalCntr-REAL_TO_UINT(varRevsDiff*setScalFact);
   END_IF
END_IF
(* Encoder-Istwert für nächsten Aufruf merken *)
varLastCntr:=inpEncdCntr;
```


----------



## Sinix (4 Dezember 2013)

StructuredTrash schrieb:


> Mag sein, dass ich mich am frühen Morgen täusche,



Ja du täuschst dich weil nach 65535 gehts wieder bei 0 los, aber deine Korrektur musst du mitführen.
Der TE hat nicht umsonst die Vorgabetabellen eingestellt


----------



## StructuredTrash (4 Dezember 2013)

Sinix schrieb:


> Ja du täuschst dich weil nach 65535 gehts wieder bei 0 los, aber deine Korrektur musst du mitführen.


Ja, das ist mir klar, und genau das tue ich doch auch. Der Positionsfortschritt wird immer auf die vorherige skalierte Position aufgerechnet.


----------



## Sinix (4 Dezember 2013)

Hast recht, scheint ein guter Lösungsansatz.


----------



## bits'bytes (4 Dezember 2013)

> StructuredTrash
> Mag sein, dass ich mich am frühen Morgen täusche, aber ist das Ganze nicht einfach nur eine Skalierungsfunktion? 65536 Inkremente am Motor entsprechen (65536*Skalierungsfaktor) Inkrementen am Getriebeausgang bzw. am Eingang des Black Box-FB's, oder etwa nicht?​



Ich glaube nicht dass es funktioniert.

Stell dir vor die Skalierung wäre 1:1,01

d.h alle 100 Encoder - Pulse kommt 1 dazu.

Nun berechnest du z.b. 5 mal in der Zeit, d.h bei gleichmässiger Aufteilung hast du 5 x 20 Differenz. Du rechnest aber bei einer Diff von 20 einen Korr-Wert = 0 aus, d.h. 5 x 0 = 0, in Wirklichkeit müsste dann aber schon mal 1 rauskommen.

bg
bb


----------



## StructuredTrash (4 Dezember 2013)

bits'bytes schrieb:


> Ich glaube nicht dass es funktioniert.


Da hast Du Recht, der Nachkommaanteil darf nicht unter den Tisch fallen. Hätte ich bloss nicht damit angefangen, jetzt muss ich mindestens noch eine Pause opfern.


----------



## StructuredTrash (4 Dezember 2013)

Mit der internen Verwaltung der skalierten Position als REAL sollte es klappen.

```
FUNCTION_BLOCK fblEncdScal (* Encoder-Istwert 16 Bit skalieren *)
VAR_INPUT
   setScalFact:REAL:=1.0; (* Skalierungsfaktor *)
   inpEncdCntr:UINT;  (* Eingabezähler Encoder *)
   inpReset:BOOL;  (* Reset *)
END_VAR
VAR_OUTPUT
   outScalCntr:UINT;  (* Skalierter Ausgabezähler *)
END_VAR
VAR
   varLastCntr:UINT;  (* Encoder-Istwert beim letzten FB-Aufruf *)
   varForwDiff:UINT;  (* Vorwärts-Zählerdifferenz gegenüber letztem Aufruf *)
   varRevsDiff:UINT;  (* Rückwärts-Zählerdifferenz gegenüber letztem Aufruf *)
   varScalReal:REAL;  (* Skalierter Wert Realformat *)
END_VAR
(* Bei Reset Ausgabezähler auf Encoder-Istwert setzen *)
IF inpReset
THEN
   outScalCntr:=inpEncdCntr;
   varScalReal:=REAL_TO_UINT(inpEncdCntr);
ELSE
(* Differenz gegenüber letztem Aufruf berechnen *)
   varForwDiff:=inpEncdCntr-varLastCntr;
   varRevsDiff:=varLastCntr-inpEncdCntr;
(* Skalierte Position berechnen, kleinere Differenz bestimmt Drehrichtung *)
   IF varForwDiff<=varRevsDiff
   THEN
      varScalReal:=varScalReal+varForwDiff*setScalFact;
      IF varScalReal>=65536.0
      THEN
         varScalReal:=varScalReal-65536.0;
      END_IF
   ELSE
      varScalReal:=varScalReal-varRevsDiff*setScalFact;
      IF varScalReal<0
      THEN
         varScalReal:=varScalReal+65536.0;
      END_IF
   END_IF
   outScalCntr:=REAL_TO_UINT(varScalReal);
END_IF
(* Encoder-Istwert für nächsten Aufruf merken *)
varLastCntr:=inpEncdCntr;
```
Ich habe es mal von 0 aus einmal ins Negative und zurück sowie bis zum zweiten Überlauf in positive Richtung getestet. Bis dahin sieht es gut aus.


----------



## bits'bytes (4 Dezember 2013)

bits'bytes schrieb:


> Ah ja, also der Fall dass der Encoder-Fortschritt > Korrektur-Abstand ist ? Das habe ich nicht wirklich berücksichtigt da ich nicht annahm dass dieser Fall eintreten könnte. Werde das noch mal ansehen.
> 
> bg
> bb



Hallo, ich hätte das jetzt mal korrigiert und hoffe das passt....
Achtung Michi: Variablen Datentypen haben sich geändert (fürs probieren).

bg
bb


----------



## bits'bytes (4 Dezember 2013)

StructuredTrash schrieb:


> Ich habe es mal von 0 aus einmal ins Negative und zurück sowie bis zum zweiten Überlauf in positive Richtung getestet. Bis dahin sieht es gut aus.



Hallo,
habe das mal durchlaufen lassen.

Bei mir summiert sich hier eine (wahrscheinliche) Ungenauigkeit auf 




Bei einem tatsächlichem Geber Stand von 62500 (Skalierung 1.01, d.h. 100 --> 101) sollte der korrigierte Geber 63125 sein. Mit deinem Code komme ich bei mir auf 63106.

bg
bb


----------



## Onkel Dagobert (5 Dezember 2013)

Hier ist meine Lösung in Step7-SCL. Ich wollte eigentlich noch eine kleine Testumgebung in Flexible mitliefern. Diese ist jedoch noch nicht so ganz publikumsreif.


```
(************************************************************************************************************************)
{SetOKFlag := 'y' ; OptimizeObjectCode := 'y'}
(************************************************************************************************************************)
FUNCTION_BLOCK "ABS_WERTGEBER_GETRIEBE_2"
TITLE = '' 
(************************************************************************************************************************)
// Beschreibung
// ¯¯¯¯¯¯¯¯¯¯¯¯
// Erfasst wird die Änderung "dX" des Eingangswertes "X" seit der letzten Abtastung. Hierzu ist es zunächst notwendig,
// den positiven und den negativen Überlauf zu erfassen. Aus den ermittelten Änderungen "dX" wird eine Summe für den
// Ausgangswert "iY" gebildet. Der Bereich für diesen Ausgangswert ergibt sich aus dem Eingangsbereich "RANGE" und dem
// Übersetzungsverhältnis "A:B". Bei RANGE=2^16=65536 und A:B=1:2 ergibt sich z.Bsp. ein Bereich
// Y_BEREICH=65536*A/B=32768. Bei einer Umdrehung des Eingangs ergeben sich bei diesem Beispiel zwei Umdrehungen am Ausgang.
// Nahezu beliebige Übersetzungsverhältnisse sind möglich, z.Bsp. auch 1000:1001. An der ermittelten Summe "iY" werden
// ebenfalls der positive und negative Überlauf, bezogen auf "Y_BEREICH" berücksichtigt. Um einen Incrementalgeber mit
// dem selben "RANGE" des Eingangs zu emulieren, wird "iY" am Ende ganz einfach auf "RANGE" normiert (Y2). Bei dem
// genannten Beispiel enstehen am Ausgang "Y2" zwei Umdrehungen von 0..65535 bei einer Umdrehung am Eingang. Da kein
// Increment des Eingangssignals verloren geht, wird eine höchst mögliche Genauigkeit umgesetzt.
//
// Einschränkungen
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// Zur Erfassung eines Überlaufs am Eingang muss das Eingangssignal mindestens mehr als 2x je Umdrehung abgefragt werden.
// Normalerweisekein Problem.
// Bei ungünstigen Parametern kann es zu einem Berechnungsfehler kommen. In diesem Fall wird der Ausgang "ERROR" gesetzt.
// Mit dem "RESET" wird der Ausgang "ERROR" zurückgesetzt.
//

VAR_INPUT
  X                         : WORD;                         // aktueller Wert vom Incrementalgeber, z.Bsp. 0..65535
  RANGE                     : DINT := 65536;                // Nennbereich, Anzahl Incremente, z.Bsp. 2^16=65536
  A                         : DINT := 1;                    // Übersetzungsverhältnis (A:B)
  B                         : DINT := 1;                    // Übersetzungsverhältnis (A:B)
  RESET                     : BOOL := false;                // Setzt den Ausgangswert auf den Eingangswert
END_VAR

VAR_OUTPUT
  Y1                        : DINT;                         // Ausgangswert, Bereich je nach Übersetzung
  Y2                        : DINT;                         // Ausgangswert, normiert auf "RANGE", z.Bsp. 2^16=65536
  ERROR                     : BOOL;                         // interner Fehler, Parameter überdenken
END_VAR

VAR
  aX                        : DINT;                         // Eingangswertes vom letzem Zyklus
  dX                        : DINT;                         // Änderung des Eingangswertes seit letzem Zyklus
  iX                        : DINT;                         // Eingangswert, als DINT
  iY                        : DINT;                         // Ausgangswert, Bereich je nach Übersetzung
  FLM_RESET                 : BOOL;                         // Flankenmerker
END_VAR

VAR_TEMP
  Y_BEREICH                 : DINT;                         // interner, korrigierter Bereich
END_VAR


BEGIN

   // Parameter umwandeln
   iX := WORD_TO_DINT(X);

   // Reset
   IF RESET AND NOT FLM_RESET THEN
      aX := iX;
      iY := iX * A DIV B;
      ERROR := false;
   END_IF;
   FLM_RESET := RESET;

   // Ausgangs-Bereich je nach Übersetzung
   Y_BEREICH := RANGE * A DIV B;

   // Änderung des Eingangswertes seit letzem Zyklus
   dX := iX - aX;
   aX := iX;

   // Eingang positiver Überlauf
   IF dX < -(RANGE DIV 2) THEN
      dX := dX + RANGE;

   // Eingang negativer Überlauf
   ELSIF dX >= (RANGE DIV 2) THEN
      dX := dX - RANGE;
   END_IF;

   // Ausgangswert, Bereich je nach Übersetzung
   iY := iY + dX;

   // Ausgang positiver Überlauf
   IF iY >= Y_BEREICH THEN
      iY := iY - Y_BEREICH;
   END_IF;

   // Ausgang negativer Überlauf
   IF iY < 0 THEN
      iY := iY + Y_BEREICH;
   END_IF;

   // Ausgabe
   Y1 := iY;
   Y2 := TRUNC(DINT_TO_REAL(iY) * RANGE / Y_BEREICH);

   // bei Berechnungsfehler, enstsprechende Ausgaben
   IF NOT OK THEN
      Y1 := 0;
      Y2 := 0;
      ERROR := true;
   END_IF;


END_FUNCTION_BLOCK
```

Gruß, Onkel


----------



## Michael.Uray (5 Dezember 2013)

bits'bytes schrieb:


> Hallo, ich hätte das jetzt mal korrigiert und hoffe das passt....



Leider nicht, gib einmal folgende Geberwerte der Reihe nach ein:
20000, 40000, 60000, 50
Dann kommt nach dem Überlauf Sprung von 60000 auf 50 nicht 705 als korrigierter Wert wie in unserer Tabelle heraus, sondern 50.
Siehe auch Screenshot.
Ist mir da was beim kopieren und einfügen vom Code passiert, oder ist das bei dir auch so?


Michi


----------



## Michael.Uray (5 Dezember 2013)

StructuredTrash schrieb:


> Mit der internen Verwaltung der skalierten Position als REAL sollte es klappen.
> Ich  habe es mal von 0 aus einmal ins Negative und zurück sowie bis zum  zweiten Überlauf in positive Richtung getestet. Bis dahin sieht es gut  aus.





bits'bytes schrieb:


> Bei mir summiert sich hier eine (wahrscheinliche) Ungenauigkeit auf
> Bei einem tatsächlichem Geber Stand von 62500 (Skalierung 1.01, d.h. 100 --> 101) sollte der korrigierte Geber 63125 sein. Mit deinem Code komme ich bei mir auf 63106.



Bei mir taucht das selbe Problem auf.
Wenn ich ihn länger vorwärts laufen lasse und dann wieder zurück, dann kammt er nicht wieder auf seinen 0 Punkt zurück.
Siehe auch Screenshots.


----------



## Michael.Uray (5 Dezember 2013)

Hallo Onkel,

schaut gut aus dein Programm und sehr schön dokumentiert.
Allerdings habe ich nach mehreren Umdrehungen eine kleine Abweichung zwischen meinem und deinem Baustein und ich weiß im Moment noch nicht genau, welcher von beiden Bausteinen daneben liegt.

Das "DIV" im Code habe ich durch eine normale Division ersetzt das dies bei B&R nicht erkannt wurde. Das ist hoffentlich eh nichts anderes als eine normale Division, oder? (Bin nicht so fit auf Siemens)
"Y_BEREICH := RANGE * A DIV B;" -> "Y_BEREICH := RANGE * A / B;"

Oder gibt es hier bei der Verhältnis Rechnung irgendwo eine Ungenauigkeit?
Eingestellt habe ich 100:101.

Ich werde mal meinen Code posten, eventuell findest du hier noch irgendwas warum die beiden anfangen abzuweichen. - Genug für heute, jetzt brauche ich mal wieder ein bißchen Schlaf.

Michi


----------



## Michael.Uray (5 Dezember 2013)

Nachdem die ersten Programmvorschläge ja schon gekommen sind, findet ihr hier den Programmcode meines Bausteins:

Bausteindeklaration:

```
FUNCTION_BLOCK EncoderCorrection
    VAR_INPUT
        EncoderValue : UINT; (*Encoder value input*)
        CorrectAtValue : INT; (*If the encoder moves more than this value, then the output value gets corrected by CorrectByValue*)
        CorrectByValue : INT; (*The output value gets corrected by this value*)
        Reset : BOOL; (*The reset adapts the input to the corrected value*)
    END_VAR
    VAR_OUTPUT
        CorrectedValue : UINT; (*Corrected value output*)
    END_VAR
    VAR
        EncoderValueOld : UINT; (*Stores the last encoder value*)
        EncoderChangeSinceLastCorrection : INT; (*Positive / negative change since the last correction*)
    END_VAR
END_FUNCTION_BLOCK
```

Funktionsblock:

```
(*
 ********************************************************************
 * COPYRIGHT --  
 ********************************************************************
 * Library: EncHelper
 * Datei: EncoderCorrection.st
 * Autor: MichaelUray
 * Erstellt: 22. November 2013
 ********************************************************************
 * Implementierung der Library EncHelper
 ********************************************************************
 This function block corrects an input encoder value by two given
 parameters.
 If the encoder moves more than "CorrectAtValue" the encoder output
 gets corrected by "CorrectByValue".
 If the change of the encoder input is more than the half of UINT
 an overflow of the input value is assumed.
*)

 
FUNCTION_BLOCK EncoderCorrection
    (* Calculate internal encoder value by the change of the input since the last call *)
    CorrectedValue := CorrectedValue + (EncoderValue - EncoderValueOld);
    EncoderChangeSinceLastCorrection := EncoderChangeSinceLastCorrection + (EncoderValue - EncoderValueOld);
    EncoderValueOld := EncoderValue;

    IF Reset THEN
        (* Adapts the input encoder value to the corrected value *)
        CorrectedValue := EncoderValue;
        EncoderChangeSinceLastCorrection := 0;
    ELSE
        (* Positive change *)
        IF EncoderChangeSinceLastCorrection > 0 AND EncoderChangeSinceLastCorrection >= CorrectAtValue AND CorrectAtValue <> 0 THEN
            (* Calculate how often the correction is required and correct it with the correction factor multiplied by this value *)
            CorrectedValue := CorrectedValue + (CorrectByValue * (EncoderChangeSinceLastCorrection / CorrectAtValue));
            (* Keep the remainder of the division on the encoder change *)
            EncoderChangeSinceLastCorrection := EncoderChangeSinceLastCorrection MOD CorrectAtValue;
        END_IF
        
        (* Negative change *)
        IF EncoderChangeSinceLastCorrection < 0 AND 0-EncoderChangeSinceLastCorrection >= CorrectAtValue AND CorrectAtValue <> 0 THEN
            (* Calculate how often the correction is required and correct it with the correction factor multiplied by this value *)
            CorrectedValue := CorrectedValue - (CorrectByValue * (0-EncoderChangeSinceLastCorrection / CorrectAtValue));
            (* Keep the remainder of the division on the encoder change *)
            EncoderChangeSinceLastCorrection := EncoderChangeSinceLastCorrection MOD CorrectAtValue;
        END_IF
    END_IF
END_FUNCTION_BLOCK
```


Der Test Code (in C):

Deklaration:

```
_LOCAL                                     plcbit                boReset;
_LOCAL                                     plcbit                boFwd;
_LOCAL                                     plcbit                boBwd;
_LOCAL                 signed         short    int                    siTurnCount;
_LOCAL                unsigned     short     int                 Encoder_M;

_LOCAL                EncoderCorrection_typ                    ENC_CORR;
```

Initialisierung:

```
ENC_CORR.CorrectAtValue = 100;
    ENC_CORR.CorrectByValue = 1;
```


Tesprogramm (Cyclic):

```
if (boReset)
    {
        if (!Encoder) boReset = 0;
        Encoder = 0;
        Encoder_M = 0;
        siTurnCount = 0;
    }
    
    /* Turn counter */
    if (Encoder_M != Encoder)
    {
        if (Encoder > Encoder_M)
        {
            if (Encoder - Encoder_M > 32767)
                siTurnCount--;
        }
        else
        {
            if (Encoder_M - Encoder > 32767)
                siTurnCount++;
        }
        Encoder_M = Encoder;
    }

    /* Forward / Backward with randomized numbers */
    if (boFwd)                
        Encoder += 5000 + rand() % 100;
    if (boBwd)
        Encoder -= 5000 + rand() % 100;
    
    /* Funktion call */
    ENC_CORR.Reset = boReset;
    ENC_CORR.EncoderValue = Encoder;
    EncoderCorrection(&ENC_CORR);
```


Michi

PS:
Achja, falls noch jemanden das Kennwort des ZIP Files intessiert, es lautet "Vermutungen".


----------



## StructuredTrash (5 Dezember 2013)

bits'bytes schrieb:


> Hallo,
> habe das mal durchlaufen lassen.
> 
> Bei mir summiert sich hier eine (wahrscheinliche) Ungenauigkeit auf



Ja, bei kleinen Schrittweiten (<50) macht die Real-Ungenauigkeit mir auch einen Strich durch die Rechnung. Mit setScalFact und varScalReal als LREAL wird es natürlich wesentlich besser, aber eine kleine Ungenauigkeit bleibt immer (von 0 bis 62500 mit Schrittweite 1 -> varScalReal = 63125.0000000383). Wahrscheinlich wird man das in der Praxis hinnehmen können, es sei denn, der Antrieb wird nur an hohen Feiertagen referenziert.


----------



## Onkel Dagobert (5 Dezember 2013)

Hallo Michi



MichaelUray schrieb:


> ..Allerdings habe ich nach mehreren Umdrehungen eine kleine Abweichung zwischen meinem und deinem Baustein ..


Eine Ungenauigkeit bei der Real-Berechnung könnte bei ungünstigen Werten bei mir möglich sein. Einen Fehler, welcher sich mit jeder Undrehung aufsummiert, kann ich jedoch ausschließen.


Gruß, Onkel


----------



## Mobi (5 Dezember 2013)

Ich dachte der Einsendeschluss wäre der 15.12.
Davor sollte eigentlich nichts veröffenlich werden. Mit Wettbewerb hat das nix mehr zutun.
Warum Ungenauigkeit und warum REAL? Man muss doch nur hoch- oder runterzählen.


----------



## PN/DP (5 Dezember 2013)

Mobi schrieb:


> Ich dachte der Einsendeschluss wäre der 15.12.
> Davor sollte eigentlich nichts veröffenlich werden. Mit Wettbewerb hat das nix mehr zutun.


*ACK*




> Warum Ungenauigkeit und warum REAL? Man muss doch nur hoch- oder runterzählen.


*ACK*

Harald


----------



## Sioan (5 Dezember 2013)

Hallo allerseits !

-Was würde passieren wenn der Inkrementalwert über den Höchstwert hin und her pendelt , wie könnte  man dann die Motordrehrichtung erkennen , ohne sich die letzten 2 zyklen zu merken  ?

-Könnte man die Motordrehrichtung nicht als IN -Parameter eingeben (die ist doch wilkürlich gewählt . oder )?
( ... könnte auch sein das ich was falsch verstehe !)


----------



## StructuredTrash (5 Dezember 2013)

Mobi schrieb:


> Warum Ungenauigkeit und warum REAL? Man muss doch nur hoch- oder runterzählen.


Weil ich gehofft hatte, damit eine einfachere Lösung hinzukriegen als auf dem durch die Aufgabenstellung vorgegebenen Weg. Habe mich aber getäuscht.


----------



## Mobi (5 Dezember 2013)

Deswegen muss dann auch die Zykluszeit mitspielen, damit man jede Änderung des Wertes mitbekommt und nicht große Sprünge bekommt.


----------



## Sioan (5 Dezember 2013)

(...nur) Eine Idee :
IN-Parameter :Unkorrigierter Datenwert  
                      Motordrehrichtung

OUT-Parameter : Korrigierter Wert KW

STAT:

Algorithm :

Unkorrigierter Datenwert am Zyklusende extra speichern . (zB als UD0)
Falls Motordrehrichtung R ( aus Links oder Rechts , als Bool speichern) UND 
Aktueller Unkorrigierter Datenwert < UD0
jedesmal 65536 einem Zwieschenspeicher dazu addieren ( in einem Speicher wo das Inkrementalabstand zu einem Absolutabstand gerechnet wird ). Zwieschenspeicher ZS .

Korrigierter Datenwert (KW) = ZS +(ZS/100) ... als DWORD in  einem  Speicher KW ...als WORD transferieren (als  schnellere 65536-MOD Funktion hier passend) ! ( ganze Arithmetik mit DWORD )

Falls Motordrehrichtung L ... siemetrisch anpassen .

Also aus dem Inkrementalen Unkorrigierten Datenwert ein Absolutwert ausrechnen und mit dem rechnen... etc !

(alles AWL)


----------



## Mobi (5 Dezember 2013)

Wie wäre es mit schreiben und hochladen?


----------



## Sioan (5 Dezember 2013)

Sobald ich Zeit habe ! 
(Falls ich gemeint war!)


----------



## Onkel Dagobert (5 Dezember 2013)

Hallo Mobi,

sorry, Einsenden habe ich mit Veröffentlichen gleichgesetzt. War das nicht schon immer so? Naja, wenigstens war ich nicht der Erste. Löschen bringt jetzt wohl auch nichts mehr. Ignoriert meine Lösung einfach beim Bewerten, habe kein Problem damit.

Andererseits gibt es doch viele Wege, die zum Ziel führen. Genauigkeitsverluste wird es sicherlich bei jeder Umwandlung geben. Die Frage ist nur, an welcher Stelle man sie am leichtesten tolerieren kann.



Mobi schrieb:


> .. Man muss doch nur hoch- oder runterzählen.


Wie willst du das mit "nur" Zählen hinbekommen?


Gruß, Onkel


----------



## Sioan (8 Dezember 2013)

```
FUNCTION_BLOCK FB 1TITLE =
VERSION : 0.1




VAR_INPUT
  Set : BOOL ;    //REFERENTIEREN
  MotDR : BOOL ;    //Motor Drehrichtung(L,R)
  AktW : DINT ;    //Aktueller Wert (unkorrigiert)
  Quant : DINT ;    //?(zB 1:100 -> Quant=100)
END_VAR
VAR_OUTPUT
  KorrW : WORD ;    //KORRIGIERTER WERT
END_VAR
VAR
  SetFP : BOOL ;    //Set Flanke
  Preset : DINT ;    //Verschiebung
  UberL : DINT ;    //Überlaufspeicher
  VorW : DINT ;    //Vorzyklus Wert (unkorrigiert)
END_VAR
BEGIN
NETWORK
TITLE =PRESET


      U     #Set; 
      FP    #SetFP; 
      SPBN  IF1; //    "IF THEN ELSE" - Ersatz ! 
      L     #AktW; 
      T     #Preset; 
      L     L#0; 
      T     #UberL; 
IF1:  NOP   0; 
NETWORK
TITLE =UBERLAUF


      U(    ; 
      L     #AktW; 
      L     #VorW; 
      -D    ; 
      L     L#-32768; 
      <D    ; 
      )     ; 
      U     #MotDR; 
      SPBN  IF2; //    "IF THEN ELSE" - Ersatz ! 
      L     #UberL; 
      +     L#65536; 
      T     #UberL; 
IF2:  NOP   0; 


      U(    ; 
      L     #AktW; 
      L     #VorW; 
      -D    ; 
      L     L#32768; 
      >D    ; 
      )     ; 
      UN    #MotDR; 
      SPBN  IF3; //    "IF THEN ELSE" - Ersatz ! 
      L     #UberL; 
      +     L#-65536; 
      T     #UberL; 
IF3:  NOP   0; 
NETWORK
TITLE =KORREKTUR


      L     #AktW; 
      L     #UberL; 
      +D    ; 
      L     #Preset; 
      -D    ; 
      L     #Quant; 
      /D    ; 
      L     #AktW; 
      +D    ; 
      T     #KorrW; 
NETWORK
TITLE =Vergleich ermoglichen


      L     #AktW; 
      T     #VorW; 


END_FUNCTION_BLOCK
```


Anhang anzeigen TEST.txt


----------



## Mobi (8 Dezember 2013)

@Onkel Dagobert: Ich meinete damit den TE, da er der Aufgabensteller ist. Das wir es reinstellen müssen ist schon klar, alleine wegen den Danksagungen. Also ich hab es mit "nur" Zählen hinbekommen, vorausgesetzt natürlich, der Baustein bekommte jede Wertänderung um eine Einheit mit.


----------



## Sioan (10 Dezember 2013)

*Reicht es* wenn das Signal vom Geber MINDESTENS einmal pro 0-65536 Periode gelesen wird oder  soll man mit "trends(differentiale)" und/oder  Stochastik programmieren ?

Die Motor Drehrichtung könnte man auch aus 3 Geberwerte ausrechnen ... falls man mit Eingänge sparen soll !


----------



## Mobi (10 Dezember 2013)

Also ich zähle einfach nebenbei einen Zähler runter und wenn der bei 0 angelangt ist, zähle ich einen hoch oder runter je nach Drehrichtung. Und dann beginnt der Zähler wieder von neuem.

Warum sollte man mit Eingänge sparen? Kostet doch kein Geld.


----------



## Sioan (10 Dezember 2013)

Mobi schrieb:


> Also ich zähle einfach nebenbei einen Zähler runter und wenn der bei 0 angelangt ist, zähle ich einen hoch oder runter je nach Drehrichtung. Und dann beginnt der Zähler wieder von neuem.
> 
> Warum sollte man mit Eingänge sparen? Kostet doch kein Geld.


 Hast Recht ! Soft Eingänge sind billig , habe die Verkabelung  gemeint!
(NUR)Zählen (ohne adaptierte Geradengleichung) geht auch , aber ... nur bei kleinere Drehzahlen ( man darf keine relevante Inkrementmenge verpassen , im Beispiel nicht über die 100 Ink springen !


----------



## Mobi (10 Dezember 2013)

Mit den hardwaremäßigen Eingängen hast du ja nichts zutun. Und da es sich anscheinend um eine Achse handelt und es eine Übersetzung von 4:1 (oder heißt es 1:4 , jedenfalls ist es am Ende 4-mal langsamer) handelt ist die Drehzahl womöglich niedrig.


----------



## Sioan (10 Dezember 2013)

Mobi schrieb:


> Mit den hardwaremäßigen Eingängen hast du ja nichts zutun. Und da es sich anscheinend um eine Achse handelt und es eine Übersetzung von 4:1 (oder heißt es 1:4 , jedenfalls ist es am Ende 4-mal langsamer) handelt ist die Drehzahl womöglich niedrig.



Weis die SPS wann der Motor gestartet wird (überhaupt)?
 Wenn JA dann hat man schon ein Eingang (und eine Motordrehrichtung auch!).
( 1:4  beim PHI 12 mm sind höhe Drehzahlen).

Wie funktioniert "zählen" wenn man 60000 Perioden hat ?
 (... muss dir *graphisch* zwei Wellen mit verschiedener Frequenz vorstelen ... etc)


----------



## PN/DP (11 Dezember 2013)

Alex?

Harald


----------



## Sioan (11 Dezember 2013)

PN/DP schrieb:


> Alex?
> 
> Harald


Mein kleines  vielleicht fehlerhaften Programmchen , geht davon aus das der Motor sich nicht "unendlich" in eine Richtung drehen muss , deswegen der Absolutwert ! 
Und daß das Gerät eine gewisse Trägheit hat ( nicht "instantan/shockartig" beschleunigt/bremst ).
(maximal 65535 Umdrehungen/Drehrichtung).

Falls nötig man kann es aber auch anders schreiben (... die variable Zyklizität des Überlaufs beachteten).


----------



## PN/DP (11 Dezember 2013)

Ich behaupte mal es ist sehr unwahrscheinlich, daß der Encoderwert sich von einem zum nächsten Bausteinaufruf um mehr als 30.000 Inkremente ändert. Falls doch, dann ist der Encoder falsch gewählt.

Harald


----------



## Sioan (11 Dezember 2013)

Hängt davon ab wie "gross" das Programm insgesamt ist .... (falls keine Weckalarmprogramme  noch übrig )
( ... wie oft darf sich der Motor *nur* in eine Richtung drehen , "unendlich" ?)


----------



## Mobi (11 Dezember 2013)

Sioan schrieb:


> Hängt davon ab wie "gross" das Programm insgesamt ist .... (falls keine Weckalarmprogramme  noch übrig )
> ( ... wie oft darf sich der Motor *nur* in eine Richtung drehen , "unendlich" ?)



Siehe hier Post #8: http://www.sps-forum.de/stammtisch/...be-inkrementalgeber-korrektur.html#post470939


----------



## sps-concept (11 Dezember 2013)

00alex reloaded


----------



## Onkel Dagobert (11 Dezember 2013)

Who the fuck is Alex?


----------



## rostiger Nagel (11 Dezember 2013)

PN/DP schrieb:


> Alex?
> 
> Harald



Dann wird die besinnliche Zeit bestimmt nicht Langweilig.
Art der Beiträge und Code, mit Sprungorgien sehen sehr nach
dem eingeschläferten 00alex aus.


----------



## Sioan (11 Dezember 2013)

Mobi schrieb:


> Siehe hier Post #8:





Mobi schrieb:


> http://www.sps-forum.de/stammtisch/...be-inkrementalgeber-korrektur.html#post470939




Hab nur gefragt weil "ewig" auch nur 65535 Umdrehungen sein könnte .
REAL Zahlen sind auch nur "real" ...


Sprünge hier sind nur "if then else" -ERSATZ um bedingtausführbare Code zu überspringen !!!
( Die Kontrollstrukturen : Folge , *Auswahl* , Wiederholung - genügen um ein jedes Programm zu schreiben).

Wie könnte man ein allgemeines Programm schreiben ohne "if then else " schreiben ? ... (sogar eine Routine/Funktionsaufruf ist ein *Auswahl*sprung..etc)

(Schau mal die "if then else" SCL-Sprungorgien sogar mit innere Schleifen)


----------



## Sioan (11 Dezember 2013)

Onkel Dagobert schrieb:


> Who the fuck is Alex?



Genau ! 
Wer ist Alex?


----------



## bike (11 Dezember 2013)

Sioan schrieb:


> Genau !
> Wer ist Alex?



Du        


bike


----------



## Michael.Uray (11 Dezember 2013)

Mobi schrieb:


> Ich meinete damit den TE, da er der Aufgabensteller ist. Das wir es reinstellen müssen ist schon klar, alleine wegen den Danksagungen.


Ich meine ich kann hier mit meinem Programmbeispiel genauso mit am Wettbewerb teilnehmen, wie die Anderen auch.
Mein Baustein erhebt ja nicht den Anspruch die optimale Lösung zu sein nur weil ich die Aufgabe gestellt habe. Es ist ja durchaus möglich, dass andere Teilnehmer hier etwas besseres auf die Beine stellen.
Durch die ganzen Beträge hier, bin ich inzwischen auch schon auf ein paar Ideen gekommen, was bei meinem Baustein noch verbessert werden könnte.

Für mich persönlich werde ich die eingereichten Programme danach beurteilen ob sie grundlegend funktionieren und die Anforderungen erfüllen (also auch keine Abweichungen bei längerem Betrieb durch float Berechnungen) und wenn diese Voraussetzung erfüllt ist, nach dem Umfang der Funktionalität und der Bausteindokumentation (eventuell noch die Einfachheit der Lösung).

Michi


----------



## Sioan (11 Dezember 2013)

```
FUNCTION_BLOCK FB 1TITLE =
VERSION : 0.1




VAR_INPUT
  Set : BOOL ;    //REFERENTIEREN
  MotDR : BOOL ;    //Motor Drehrichtung(L,R)
  AktW : DINT ;    //Aktueller Wert (unkorrigiert)
  Quant : DINT ;    //? (zB Quant=100)
END_VAR
VAR_OUTPUT
  KorrW : WORD ;    //KORRIGIERTER WERT
END_VAR
VAR
  SetFP : BOOL ;    //Set Flanke
  UberL : DINT ;    //Überlaufspeicher
  VorW : DINT ;    //Vorzyklus Wert (unkorrigiert)
  PRESET : DINT ;    
END_VAR
BEGIN
NETWORK
TITLE =PRESET


      U     #Set; 
      FP    #SetFP; 
      SPBN  IF1; //IF THEN ELSE -Ersatz 
      L     #AktW; 
      T     #PRESET; 
      L     L#0; 
      T     #UberL; 
IF1:  NOP   0; 
NETWORK
TITLE =UBERLAUF


      U(    ; 
      L     #AktW; 
      L     #VorW; 
      -D    ; 
      L     L#-32768; 
      <D    ; 
      )     ; 
      U     #MotDR; 
      SPBN  IF2; //IF THEN ELSE -Ersatz 
      L     #UberL; 
      +     L#65536; 
      T     #UberL; 
IF2:  NOP   0; 


      U(    ; 
      L     #AktW; 
      L     #VorW; 
      -D    ; 
      L     L#32768; 
      >D    ; 
      )     ; 
      UN    #MotDR; 
      SPBN  IF3; //IF THEN ELSE -Ersatz 
      L     #UberL; 
      +     L#-65536; 
      T     #UberL; 
IF3:  NOP   0; 
NETWORK
[B]TITLE =UBERLAUF KORRIGIEREN[/B]

[B]      O(    ; [/B]
[B]      L     #UberL;
[/B]      SSD   16;
[B]      L     #Quant; [/B]
[B]      ==D   ; [/B]
[B]      )     ; [/B]
[B]      O(    ; [/B]
[B]      L     #Quant; [/B]
[B]      NEGD  ; [/B]
[B]      L     #UberL;
[/B]      SSD 16;
[B]      ==D   ; [/B]
[B]      )     ; [/B]
[B]      SPBN  IF4; //IF THEN ELSE -Ersatz ![/B]
[B]      L     L#0; [/B]
[B]      T     #UberL; [/B]
[B]IF4:  NOP   0; [/B]
NETWORK
TITLE =KORREKTUR


      L     #AktW; 
      L     #UberL; 
      +D    ; 
      L     #PRESET; 
      -D    ; 
      L     #Quant; 
      /D    ; 
      L     #AktW; 
      +D    ; 
      T     #KorrW; 
NETWORK
TITLE =Vergleich ermoglichen


      L     #AktW; 
      T     #VorW; 
END_FUNCTION_BLOCK
```


----------



## Michael.Uray (11 Dezember 2013)

Sioan schrieb:


> Weis die SPS wann der Motor gestartet wird (überhaupt)?
> Wenn JA dann hat man schon ein Eingang (und eine Motordrehrichtung auch!).



Die Drehrichtung des Motors ist in der SPS vorhanden und kann bei Bedarf auch dem Baustein übergeben werden.
Werte vom Drehgeber kommen in entsprechenden Abständen in die Steuerung, so dass die Drehrichtung damit noch erkannt werden kann. 
In meinem Bausten darf der neue Wert nicht mehr als die Hälfte von UINT abweichen. Dh. der Sprung zwischen 2 Werten darf nicht größer als 32767 sein, da sonst ein Überlauf in die andere Richtung angenommen wird. Mit einem Eingang der Motordrehrichtung würde sich dieser Bereich noch vergrößern lassen.


----------



## Sioan (11 Dezember 2013)

MUSS der  Überlauf (#UberL)  zyklisch zu Null gebracht werden ?
... so daß der  DINT Maximum nicht überschritten wird ?


----------



## Michael.Uray (11 Dezember 2013)

Sioan schrieb:


> MUSS der  Überlauf (#UberL)  zyklisch zu Null gebracht werden ?
> ... so daß der  DINT Maximum nicht überschritten wird ?



Das weiß ich nicht ob das notwendig ist in deinem Progamm um die Aufgabenstellung zu erfüllen.

Ich habe dein Programm bisher noch nicht zm Erstellen bekommen, da ich mit B&R Automation Studio arbeite und dieses nur AWL Code nach IEC 1131-3 untersützt.
Das letzte mal habe ich vor 15 Jahren einen AWL Code geschrieben und ich habe jetzt nicht wirklich die Zeit mich mit den beiden AWL Syntaxen auseinanderzusetzen.
Hast du eine Möglichkeit das Programm auch in IEC 1131-3 Code umzuwandeln? Ich würde es zumindest gerne einmal auf meiner Steuerung teste.

Off Topic:
Wird AWL heute eigentlich wirklich noch in der Realität verwendet, oder geht es hier nur um die Herausforderung dies auch in AWL zu lösen?


----------



## Sioan (11 Dezember 2013)

Wäre mir lieber dir den Algorithmus zu beschreiben als ...  übersetzen ! (ist ganz einfach).

Off Topic:
Keine Ahnung ! Habe keine SPS Praxis !
AWL soll aber auch bei den neueren Siemens CPU-s zumindest der SCL gleichwertig sein ... der KOP , FUP wird AWL immer überlegen (kann/könnte einfach mehr) !


----------



## Michael.Uray (11 Dezember 2013)

Hallo Onkel Dagobert,



Onkel Dagobert schrieb:


> Eine Ungenauigkeit bei der Real-Berechnung könnte bei ungünstigen Werten bei mir möglich sein. Einen Fehler, welcher sich mit jeder Undrehung aufsummiert, kann ich jedoch ausschließen.



Ich habe deinen Baustein jetzt einmal etwas weiter laufen lassen und je länger er läuft, desto größer wird die Abweichung.
Das bedeutet der Fehler summiert sich fortlaufend auf. Siehe auch den Screenshot mit 501 Umdrehungen aus meinem Test.

Michi


----------



## Sioan (12 Dezember 2013)

Wenn man #Quant als Variable ( nicht als Konstante ) eingibt ...  könnte man "kurvenscheiben" simulieren ... (


----------



## Onkel Dagobert (12 Dezember 2013)

Hallo Michael,

ich hatte auch mal deinen und meinen Baustein laufen lassen und ich habe auch bemerkt dass eine Abweichung ensteht. Allerdings bin ich der Sache bisher nicht weiter nachgegangen.

Was wahrscheinlich sein wird ist dass mein Übersetzungsverhältnis Rundungsfehler enthält. Ich berechne ja "Y_BEREICH := RANGE * A DIV B". Ursprünglich hatte ich die Übersetzung als Real-Parameter übergeben, diese Berechnung mit Realzahlen realisiert und das Ergebnis wieder nach DINT gewandelt. Wenn ich mal wieder Muse habe, nehme ich mir das Problem noch mal vor.

Kann mir jemand eine Empfehlung für ein einfaches Video-Capture-Tool geben? Ich hatte eine kleine Visu mit Zeigerinstrumenten gemacht, an der man die Umdrehungen und Werte gut beobachten kann. Vielleicht kann ich das dann mal irgendwo hochladen.


Gruß, Onkel


----------



## hucki (12 Dezember 2013)

Onkel Dagobert schrieb:


> Kann mir jemand eine Empfehlung für ein einfaches Video-Capture-Tool geben? Ich hatte eine kleine Visu mit Zeigerinstrumenten gemacht, an der man die Umdrehungen und Werte gut beobachten kann. Vielleicht kann ich das dann mal irgendwo hochladen.


Wenn Du Win7 hast, ist die psr.exe serienmäßig dabei. Hier ein Beispiel von vollmi.


----------



## Sioan (12 Dezember 2013)

```
[B]FUNCTION_BLOCK FB 1TITLE =
VERSION : 0.1




VAR_INPUT
  Set : BOOL ;    //REFERENTIEREN
  MotDR : BOOL ;    //Motor Drehrichtung(L,R)
  AktW : DINT ;    //Aktueller Wert (unkorrigiert)
  Quant : DINT ;    //? (zB Quant=100)
END_VAR
VAR_OUTPUT
  KorrW : WORD ;    //KORRIGIERTER WERT
END_VAR
VAR
  SetFP : BOOL ;    //Set Flanke
  UberL : DINT ;    //Überlaufspeicher
  VorW : DINT ;    //Vorzyklus Wert (unkorrigiert)
  PRESET : DINT ;    
END_VAR
BEGIN
NETWORK
TITLE =PRESET[/B]
[B]

      [COLOR=#008000]U     #Set; 
      FP    #SetFP; [/COLOR]
      [COLOR=#a9a9a9]SPBN  IF1; //[/COLOR]    [COLOR=#008000]IF [/COLOR][COLOR=#0000ff]THEN [/COLOR][COLOR=#b22222]ELSE[/COLOR][COLOR=#0000ff] -[/COLOR][COLOR=#d3d3d3]Ersatz [/COLOR][COLOR=#0000ff]
      L     #AktW; 
      T     #PRESET; 
      L     L#0; 
      T     #UberL; [/COLOR]
[COLOR=#a9a9a9]IF1:[/COLOR][COLOR=#b22222]  NOP   0;[/COLOR] 
NETWORK
TITLE =UBERLAUF


 [COLOR=#008000]     U(    ; 
      L     #AktW; 
      L     #VorW; 
      <D    ; 
      )     ; 
      U     #MotDR; [/COLOR]
     [COLOR=#a9a9a9] SPBN  IF2; //   [/COLOR][COLOR=#008000]IF [/COLOR][COLOR=#0000FF]THEN [/COLOR][COLOR=#B22222]ELSE[/COLOR][COLOR=#0000ff] -[/COLOR][COLOR=#D3D3D3]Ersatz[/COLOR][COLOR=#0000ff] 
      L     #UberL; 
      +     L#65536; 
      T     #UberL; [/COLOR]
[COLOR=#a9a9a9]IF2:[/COLOR] [COLOR=#b22222] NOP   0; [/COLOR]


     [COLOR=#008000] U(    ; 
      L     #AktW; 
      L     #VorW; 
      >D    ; 
      )     ; 
      UN    #MotDR; [/COLOR]
    [COLOR=#a9a9a9]  SPBN  IF3; //    [/COLOR][COLOR=#008000]IF [/COLOR][COLOR=#0000FF]THEN [/COLOR][COLOR=#B22222]ELSE[/COLOR][COLOR=#0000ff] -[/COLOR][COLOR=#D3D3D3]Ersatz[/COLOR][COLOR=#0000ff]
      L     #UberL; 
      +     L#-65536; 
      T     #UberL; [/COLOR]
[COLOR=#a9a9a9]IF3: [/COLOR][COLOR=#b22222] NOP   0; [/COLOR]
NETWORK
TITLE =UBERLAUF KORRIGIEREN

[COLOR=#008000]     O(    ; 
     L     #UberL;
     SSD   16;
     L     #Quant; 
     ==D   ; 
     )     ; 
     O(    ; 
     L     #UberL;
     SSD 16;
​     L     #Quant; 
     NEGD  ;
     ==D   ; 
     )     ; [/COLOR]
    [COLOR=#a9a9a9] SPBN  IF4; //[/COLOR]    [COLOR=#008000]IF [/COLOR][COLOR=#0000FF]THEN [/COLOR][COLOR=#B22222]ELSE[/COLOR][COLOR=#0000ff] -[/COLOR][COLOR=#D3D3D3]Ersatz[/COLOR][COLOR=#0000ff]
     L     L#0; 
     T     #UberL; [/COLOR]
[COLOR=#a9a9a9]IF4:[/COLOR][COLOR=#b22222] NOP   0; [/COLOR]
NETWORK
TITLE =KORREKTUR


      L     #AktW; 
      L     #UberL; 
      +D    ; 
      L     #PRESET; 
      -D    ; 
      L     #Quant; 
      /D    ; 
      L     #AktW; 
      +D    ; 
      T     #KorrW; 
NETWORK
TITLE =Vergleich ermoglichen


      L     #AktW; 
      T     #VorW; 
END_FUNCTION_BLOCK


[/B]
```

So sieht man besser , warum man "Sprungorgien" in  AWL erzeugen MUSS !
AWL muss nicht unbedingt schwer LESBAR sein ... veraltet auch nicht !
_Könnte BITTE jemand es nach SCL portieren ?_


----------



## rostiger Nagel (16 Dezember 2013)

Liebe Kollegen, ab hier ist alles in den SV verschoben, da das Niveau mal wieder
weit Weg, jeder Zivilisierter Umgangsform war.


----------



## bike (16 Dezember 2013)

rostiger Nagel schrieb:


> Liebe Kollegen, ab hier ist alles in den SV verschoben, da das Niveau mal wieder
> weit Weg, jeder Zivilisierter Umgangsform war.



Warum habe ich darauf gewartet? 

Ein kleiner Hinweis:
http://de.wikipedia.org/wiki/Eigenschaftswort

Helmut von der Reparatur ist ein Held.


bike


----------



## Sioan (16 Dezember 2013)

... der Motor hat einem vonn 3 Zustände L (links) , R(rechts) ,S(stop) !

Ich glaube man soll sie (L,R,S) *unbedingt* beachten , und man soll es auch so programmieren das es wenn  S(stop) gilt und man die Achsen mit der Hand innerhalb gewisser Toleranzen bewegt den errechnete *pseudo*-absolutwert nicht verloren geht ... 

So wie es jetzt ist ,das Programmchen  funktioniert auch , aber an gewisse Positionen bei S(stop) eine 1 Inkrementbewegung kann stören ...etc.

PS: Wahrlich wenn man es darauf kommt ist es eine nicht so leichte ... Aufgabe !


----------



## Sioan (16 Dezember 2013)

Falls jemand ein BUG findet soll es nicht für sich behalten  !


----------



## hucki (16 Dezember 2013)

Sioan schrieb:


> ```
> [B]
> [COLOR=#008000]U     #Set;
> FP    #SetFP; [/COLOR]
> ...


Bevor Du das hier noch weiter verbreitest - das ist kein IF-THEN-ELSE-Ersatz, sondern entspricht nur einem IF-THEN *ohne* ELSE.
Alles was bei Dir ab der Marke IFx folgt, wird immer verarbeitet, egal ob die Bedingung erfüllt wird oder nicht. Ein ELSE-Zweig würde aber nur bei Nichterfüllung der Bedingung bearbeitet werden! Auch wenn Dir das *vlt.* bewußt ist, vielen Anfängern bestimmt nicht.

Und btw - warum benötigt das SET 'ne Flanke? Ist doch irgendwie überflüssig, oder?


----------



## Sioan (16 Dezember 2013)

Mein Fehler ! 
Hab mir gedacht das NOP (no operation) zu einem ELSE passt ! IF xxx THEN yyy ELSE nop !
Set ohne Flanke geht auch aber nur wenn die ACHSEN stehen so lange SET true ist ...
*
Bitte nicht falsch verstehen: Das ganze grüne ist IF .... das ganze blaue ist THEN ... das ganze braune ist ELSE !*

Danke !


----------



## hucki (16 Dezember 2013)

Sioan schrieb:


> Mein Fehler !
> Hab mir gedacht das NOP (no operation) zu einem ELSE passt !


Nein, das wäre die Stelle nach *END_IF*!



Sioan schrieb:


> *Was nach THEN kommt wird nicht immer bearbeitet !*


Ja, aber das nach ELSE auch nicht!


----------



## Sioan (16 Dezember 2013)

Muss die FARBEN beachten nicht die LABELS !


----------



## hucki (16 Dezember 2013)

Sioan schrieb:


> Set ohne Flanke geht auch aber nur wenn die ACHSEN stehen so lange SET true ist ...


Ist 'ne Ansichtssache.
M.M.n. - wenn SET, dann SET! Bis ich was anderes will.


----------



## Sioan (16 Dezember 2013)

Hast recht mit  ELSE ...der würde immer bearbeitet werden ...also nenn ihn END IF !

DANKE !


----------



## hucki (16 Dezember 2013)

Sioan schrieb:


> Muss die FARBEN beachten nicht die LABELS !


Gerade dann bleibts dabei.

IF-THEN-*ELSE* sähe z.B. so aus:

```
[B]       [COLOR=#008000]U     #Set; 
[/COLOR]       [COLOR=#a9a9a9]SPBN  ELSE; //[/COLOR]    [COLOR=#008000]IF [/COLOR][COLOR=#0000ff]THEN [/COLOR][COLOR=#b22222]ELSE[/COLOR][COLOR=#0000ff] -[/COLOR][COLOR=#d3d3d3]Ersatz [/COLOR][COLOR=#0000ff]
       L     #AktW; 
       T     #PRESET; 
       L     L#0; 
       T     #UberL; 
[/COLOR][/B][COLOR=#ff0000][B]       SPA END;   //das ist der Unterschied![/B][/COLOR][B] 
[COLOR=#a9a9a9]ELSE:[/COLOR][COLOR=#b22222]  L ...;
[/COLOR][/B][B][COLOR=#b22222]       T ...;[/COLOR] 
[/B][B][COLOR=#a9a9a9]END:   [/COLOR]NOP 0[/B]
```


----------



## 190B (16 Dezember 2013)

hucki schrieb:


> Nein, das wäre die Stelle nach *END_IF*!
> 
> Ja, aber das nach ELSE auch nicht!



hucki,

schmeiße doch bitte Deine mühsam erarbeiteten Perlen nicht vor die Säue.....

Du kannst antworten was Du willst, 00AlexSioan wird ein wie auch immer geartetes Gegenargument starten und denThread weiter zerschiessen. Am besten nur noch ignorieren....

PS: RN, in den Startlöchern hängen geblieben?


----------



## Sioan (16 Dezember 2013)

Hab's so programmiert aber wäre zu verwirrend (laut RN) ...deswegen habe ich es gelöscht !:TOOL:


----------



## hucki (16 Dezember 2013)

190B schrieb:


> schmeiße doch bitte Deine mühsam erarbeiteten Perlen nicht vor die ... 00AlexSioan


Es geht mir dabei weniger um ihn.


----------



## Sioan (16 Dezember 2013)

190B schrieb:


> hucki,
> 
> schmeiße doch bitte Deine mühsam erarbeiteten Perlen nicht vor die Säue.....
> 
> ...



*hucki *verdient RESPECT !


----------



## Onkel Dagobert (16 Dezember 2013)

Ihr seid ja ein paar bunte Vögel  .


----------



## 190B (16 Dezember 2013)

Onkel Dagobert schrieb:


> Ihr seid ja ein paar bunte Vögel  .



Du hast ja fast alle Koalitionsmöglichkeiten drin, aber die Grünen fehlen auch jeden Fall (naja, und gelb und...)


----------



## KingHelmer (16 Dezember 2013)

00AlexSioan... zum schießen


----------



## Sioan (17 Dezember 2013)

KingHelmer schrieb:


> 00AlexSioan... zum schießen


... du hast mich aber nicht falsch verstanden , oder  ?


----------



## bike (17 Dezember 2013)

KingHelmer schrieb:


> 00AlexSioan... zum schießen



Du hast ein "er" fairgessen 


bike


----------



## Sioan (21 Dezember 2013)

@MichaelUray soll ich das Programm noch ergänzen oder ... passt so ?

Frohes Fest !


----------



## UniMog (25 Dezember 2013)

Wer ist denn der Sieger oder läuft das noch weiter ????


----------

