TIA Zählrichtung erkennen

litlegerman

Level-2
Beiträge
312
Reaktionspunkte
7
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,
nehmen wir an ich habe einen Drehgeber, bei dem ich die Anzahl der Umdrehungen messen will.
Der Drehgeber ist via IO-Link mit der SPS verbunden und gibt mir je nach lage des Schaft einen Wert zwischen 0 und 9999 an.
Jetzt habe ich das bis lang immer mit einfachen Inkremnetalgebern und Zählerbaugruppen gemacht, das ist ja recht einfach eine Länge mit einem Drehgeber zu erfassen.
Aber bei diesem IO-Link gerät muß ich ja quasie die umdrehungen zählen, ich scheitere aber grade schon daran die Drehrichtung sauber zu erfassen.
Prinzipiell kann ich ja einfach, wenn ich die Drehrichtung kenne bei Wert = 0 denz Zählwert + oder - 1000 nehmen und schon habe ich einen
Inkremnetalgeber daraus gemacht.
aber ich bekomme es irgendwie nicht hint sicher die Zählrichtung zu erfassen, kann mir da jemand helfen?
 
Das müsste funktionieren.
Code:
Input:
Value : DInt;

Output:
POS : Bool
NEG : Bool

Static:
OldValue : DInt

// Init
POS := NEG := FALSE;

IF Value > OldValue THEN
  POS := TRUE;
  OldValue := Value;
  
ELSIF Value < OldValue THEN
  NEG := TRUE;
  OldValue := Value;
  
END_IF;
 
Bzw. beim ersten Durchlauf wird auch eine Drehrichtung ausgewertet obwohl Achse evtl steht, für einen Zyklus ( OldValue auf 0 und irgendein Wert vom Geber )
 
Einfach nur vergleichen, ob der aktuelle Wert größer oder kleiner als der vorherige Wert ist funktioniert natürlich nicht, weil der Geberwert irgendwann mal überläuft (z.b. vorwärts von ca. 9999 nach ca. 0). Es muß die Differenz ausgewertet werden, die max +/- eine halbe Umdrehung groß sein darf.

Prinzipiell kann ich ja einfach, wenn ich die Drehrichtung kenne bei Wert = 0 denz Zählwert + oder - 1000 nehmen und schon habe ich einen
Inkremnetalgeber daraus gemacht.
Den "Ring" der Positionswerte schließt man mathematisch nicht mit + oder - Zählumfang, sondern Pos := Wert MOD Zählumfang
Außerdem ist es oft Zufall, ob man die Stellung Wert = 0 überhaupt mitkriegt.

Harald
 
Hi,

das letzte Mal als wir einen solchen Sensor hatten mussten wir einiges rumdrehen damit es überhaupt funktionierte. Problem war, das für eine Höhenpositionierung ein solcher Sensor durch IFM angeboten wurde, aber verschwiegen wurde das er bei Überdrehung einfach bei null wieder anfängt. Nächstes Mal selbst Handbuch lesen!

Also habe ich die Anzahl der Schritte pro Umdrehung sehr weit runtergeschraubt und dann die Übergänge mitgezählt.
Mit Beispielwerten:

Wenn alt=19 und neu=0 dann Index+20
Position=Index+neu
ergibt einen Wert zwischen 20 und 39. Also 20 Punkte pro Umdrehung, hochzählend.

Das ganze dann noch andersherum
Wenn alt=0 und neu=19 dann Index-20
Position=Index+neu

Konkret sieht das ganze in einer laufenden Anlage die keinerlei Störungen damit hat so aus:
Code:
// Baustein als Zähler für Positionsbestimmung
// Drehgeber gibt einen Wert zwischen 0 und 10000 aus, zählt entweder hoch oder runter und würde bei über oder unterschreiten
// dann beim oberen oder unteren Wert anfangen.
// Dies muss als Indexzähler neu realisiert werden.
// Der Geber muss so eingestellt werden das er nur noch von 0 bis 19 zählt pro Umdrehung, für genauere Ergebnisse höher setzen,
// aber Geschwindigkeit darf nicht zu hoch werden, da sonst die 0 bzw. letzte Zahl nicht erkannt wird.
// 
#"Zählerwert aktuell" := UINT_TO_INT(#Drehgeberwort);
IF #"Zählerwert aktuell" = 0
    AND
    #"Zählerwert alt" = 19
THEN
    #Zählindex := #Zählindex + 20;
ELSIF #"Zählerwert aktuell" = 19
    AND
    #"Zählerwert alt" = 0
THEN
    #Zählindex := #Zählindex - 20;
END_IF;
#Zählerwert := #Zählindex + #"Zählerwert aktuell";
IF #"Zählerwert alt" <> #"Zählerwert aktuell" THEN
    #"Zählerwert alt" := #"Zählerwert aktuell";
END_IF;

Für unsere Zwecke war das Ergebnis nur auf 1cm wichtig (Heben über 1,12m/400kg/1m/min Hebe-und Senkzeit), daher konnten wir mit 20 arbeiten. Der herausgekommene Wert wurde dann nochmals mit norm_X/scale_x auf cm verändert.
Falls es wirklich genauer werden muss, dann entweder Geschwindigkeit niedrig halten oder aber einen Bereich festlegen der den Index erhöht/verringert.

Anzumerken ist das ich das Ergebnis nicht für wirklich toll halte. Es muss bei einem Fehler ein Ini angefahren werden damit die Höhe neu "kalibriert" wird.
Ich würde daher vorschlagen den Sensor komplett gegen einen zu tauschen der nicht bei einer Umdrehung wieder bei 0 anfängt. Wir wurden eben schlecht beraten und mussten es auf der Baustelle Samstags schnell lösen.

edit: ups, falsch rum das Beispiel ;)
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Position mit Drehgeber, auch mehrere Umdrehungen

muß ich ja quasie die umdrehungen zählen, ich scheitere aber grade schon daran die Drehrichtung sauber zu erfassen.
Du brauchst weder die Umdrehungen zählen noch die Drehrichtung ermitteln, Du mußt nur sicherstellen, daß sich der Encoder zwischen den Wert-Abfragen nicht mehr als eine halbe Umdrehung dreht. Dann kannst Du einfach die Differenz (+/-) der Encoderstellung jetzt zur Encoderstellung vorher ermitteln und diese Differenz (max +/-5000 bei Encoder 0..9999) auf einen fast beliebig großen Positionswert verrechnen (z.B. DINT -2.147.483.648 .. +2.147.483.647).
Code:
[COLOR="#008000"]//Encoder 0..9999, Encoderwert_jetzt - Encoderwert_vorher[/COLOR]
      L     #iEnc_old                   [COLOR="#008000"]//(INT 16 Bit) Encoderwert_vorher[/COLOR]
      L     #iEnc_now                   [COLOR="#008000"]//Encoderwert_jetzt 0..9999[/COLOR]
      T     #iEnc_old                   [COLOR="#008000"]//als Encoderwert_vorher merken[/COLOR]
      TAK
      -I                                [COLOR="#008000"]//Diff Encoderwert_jetzt - Encoderwert_vorher[/COLOR]

[COLOR="#008000"]//wenn Diff > +5000 dann Diff -= 10000[/COLOR]
      L     5000
      >I
      TAK                               [COLOR="#008000"]//Diff zurück in AKKU1[/COLOR]
      SPBN  M1
      +     -10000
      SPA   M2

[COLOR="#008000"]//wenn Diff < -5000 dann Diff += 10000[/COLOR]
M1:   L     -5000
      <I
      TAK
      SPBN  M2
      +     10000
M2:   ITD

[COLOR="#008000"]//hier in AKKU1 die 32-Bit-Differenz L#-5000 .. L#+5000 ---> auf Position verrechnen[/COLOR]
      L     #diRel_Pos                  [COLOR="#008000"]//DINT rel.Position (bei Referenzieren auf 0 gesetzt)[/COLOR]
      +D                                [COLOR="#008000"]//die Encoderwert-Differenz (+/-) dazu[/COLOR]
      T     #diRel_Pos                  [COLOR="#008000"]// -xxx.xxx.xxx .. +yyy.yyy.yyy[/COLOR]

Harald
 
Position aus Inkrementalgeber SCL

... und in SCL
Code:
[COLOR="#008000"]// Position -xxx.xxx.xxx .. +yyy.yyy.yyy mit Encoder 0..9999[/COLOR]
#iDiff    := #iEnc_now - #iEnc_old;
#iEnc_old := #iEnc_now;

IF #iDiff > +5000 THEN
    #iDiff -= 10000;
ELSIF #iDiff < -5000 THEN
    #iDiff += 10000;
END_IF;

#diRel_Pos := #diRel_Pos + #iDiff;

Harald
 
Du brauchst weder die Umdrehungen zählen noch die Drehrichtung ermitteln, Du mußt nur sicherstellen, daß sich der Encoder zwischen den Wert-Abfragen nicht mehr als eine halbe Umdrehung dreht. Dann kannst Du einfach die Differenz (+/-) der Encoderstellung jetzt zur Encoderstellung vorher ermitteln und diese Differenz (max +/-5000 bei Encoder 0..9999) auf einen fast beliebig großen Positionswert verrechnen (z.B. DINT -2.147.483.648 .. +2.147.483.647).


Harald

Irgendwie wird die Anzahl Umdrehungen ja doch gezählt...
#iDiff += 10000;
#iDiff -= 10000;

Drehrichtung wird auch irgendwie ermittelt...
#iDiff > +5000 then
#iDiff < -5000 then

Seh ich das falsch?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Irgendwie wird die Anzahl Umdrehungen ja doch gezählt...
#iDiff += 10000;
#iDiff -= 10000;

[...]
Seh ich das falsch?
Ja, das siehst Du falsch. In dem Code werden nirgendwo Umdrehungen irgendwie gezählt, sondern nur Drehgeberpositions-Differenzen (Wegstrecken) ermittelt und addiert. Im Gegenteil, mit dem zitierten Code wird dafür gesorgt daß #iDiff immer im Bereich von -5000 .. +5000 liegt, völlig unabhängig davon wie viele Umdrehungen der Drehgeber in der Vergangenheit gemacht hat.

Durch das #iDiff += 10000/-= 10000 wird lediglich die Differenz korrigiert, falls beim Drehen die 9999/0-Stelle vorwärts oder rückwärts überschritten wurde, so daß bei einer Vorwärts-Drehung die Differenz immer positiv ist, auch wenn über 9999-->0 gedreht wurde; und bei einer Rückwärts-Drehung die Differenz immer negativ ist, auch wenn über 0-->9999 gedreht wurde. Die Berechnung schließt die Drehgeber-Positionen zu einem Kreis.

Die Stelle, wo die Anzahl Drehgeber-Umdrehungen in der Vergangenheit "irgendwie" gespeichert wird, ist "#diRel_Pos := #diRel_Pos + #iDiff;" - coolerweise geht bei der Berechnung nicht direkt ein, wie viele Umdrehungen es waren und wie viele Positionen pro Umdrehung der Drehgeber hat.


Drehrichtung wird auch irgendwie ermittelt...
#iDiff > +5000 then
#iDiff < -5000 then
Das würde ich nicht als "Ermittlung der Drehrichtung" bezeichnen, weil in den allermeisten Fällen wenn sich der Drehgeber vorwärts oder rückwärts dreht, liefert dieser Code keine Aussage über die Drehrichtung (beide Bedingungen sind nicht erfüllt). Der Code prüft nur, ob beim Drehen die 9999/0-Stelle rückwärts oder vorwärts überschritten wurde oder sonstwie eine "unmögliche" Differenz zustande kam.

Harald
 
Das ist genau das was ich gesucht habe...
ich probiere das mal aus, wie schon richtig erkannt muss Ich lediglich drauf achten das eine Umdrehung länger als ein Zyklus dauert, das sollte bei einer Zykluszeit von 10ms ein leichtes sein denke ich...
also vielen Dank für eure Hilfe
 
Ja, das siehst Du falsch. In dem Code werden nirgendwo Umdrehungen irgendwie gezählt, sondern nur Drehgeberpositions-Differenzen (Wegstrecken) ermittelt und addiert. Im Gegenteil, mit dem zitierten Code wird dafür gesorgt daß #iDiff immer im Bereich von -5000 .. +5000 liegt, völlig unabhängig davon wie viele Umdrehungen der Drehgeber in der Vergangenheit gemacht hat.

Durch das #iDiff += 10000/-= 10000 wird lediglich die Differenz korrigiert, falls beim Drehen die 9999/0-Stelle vorwärts oder rückwärts überschritten wurde, so daß bei einer Vorwärts-Drehung die Differenz immer positiv ist, auch wenn über 9999-->0 gedreht wurde; und bei einer Rückwärts-Drehung die Differenz immer negativ ist, auch wenn über 0-->9999 gedreht wurde. Die Berechnung schließt die Drehgeber-Positionen zu einem Kreis.

Die Stelle, wo die Anzahl Drehgeber-Umdrehungen in der Vergangenheit "irgendwie" gespeichert wird, ist "#diRel_Pos := #diRel_Pos + #iDiff;" - coolerweise geht bei der Berechnung nicht direkt ein, wie viele Umdrehungen es waren und wie viele Positionen pro Umdrehung der Drehgeber hat.



Das würde ich nicht als "Ermittlung der Drehrichtung" bezeichnen, weil in den allermeisten Fällen wenn sich der Drehgeber vorwärts oder rückwärts dreht, liefert dieser Code keine Aussage über die Drehrichtung (beide Bedingungen sind nicht erfüllt). Der Code prüft nur, ob beim Drehen die 9999/0-Stelle rückwärts oder vorwärts überschritten wurde oder sonstwie eine "unmögliche" Differenz zustande kam.

Harald

Das ist interessant. Ich werd mir am WE mal daheim das simulieren. Vielleicht hilfts mir in der Zukunft falls ich nochmal einen solchen Encoder bekomme. Danke für die Erklärung.
 
Zurück
Oben