# A/B Drehgeber Auswerten



## Kuddel30 (17 November 2010)

Moin,Moin

Möchte Gerne mit einem Drehgeber (Spur A/B) die Richtung eines Zähler   Auswerten. D.H. Erst Spur A dann Spur B Zähler Positiv,Erst Spur B dann Spur A Zähler Negativ.Spuren sind um 90 Grad Versetzt. Hat Jemand Programmieransetze?


----------



## IBFS (17 November 2010)

Kuddel30 schrieb:


> Moin,Moin
> 
> Möchte Gerne mit einem Drehgeber (Spur A/B) die Richtung eines Zähler Auswerten. D.H. Erst Spur A dann Spur B Zähler Positiv,Erst Spur B dann Spur A Zähler Negativ.Spuren sind um 90 Grad Versetzt. Hat Jemand Programmieransetze?


 
Dazu gibt es doch Zählerkarten z.B. für die S7-300 oder ET200S.
Da kannst du den Gebertyp einstellen und auch parametrieren, ob
die in beide oder nur in eine Richtung zählen willst. 
Dazu gibt es dann typischerweise Programmbeispiele.
Das ist kein Hexenwerk.

Gruß

Frank


----------



## rostiger Nagel (17 November 2010)

Wenn es eine Übung sein soll und nicht mit Zählkarten gearbeitet 
werden soll, kannst du in dieser Richtung weiterdenken.

du erkennst den Stillstand des Zählers, vlt mit einer Zeit
mit einer steigender Flanke einer der Spuren kannst du den
Summanden für dein Zähler festlegen. Spur A zuerst Summand
positiv (+1), Spur B zuerst Summand negativ (-1)
Bei jeden impuls Addierst zu deinen Zähler den Summanden.
Steigerung Art der Flankenauswertung, 1-Flanke; 2-Flanken; 4-Flanken.


Beispiel für die festlegung des Sumanden mit Step 7

```
//Zählrichtung positiv
     U      Spur A
     UN    HM_Summand
     FP     HM_A
     SPBN ENDA
     L       L#1
     T      Summand
     SET
     =      HM_Summand
ENDA: NOP 0
 
//Zählrichtung negativ
     U      Spur B
     UN    HM_Summand
     FP     HM_B
     SPBN ENDB
     L       L#-1
     T      Summand
     SET
     =      HM_Summand
ENDB: NOP 0
```


----------



## Kai (17 November 2010)

Nachfolgend ein einfaches Programmbeispiel für die Auswertung der Drehrichtung eines A/B-Drehgebers:


```
FUNCTION_BLOCK FB 100
TITLE =Drehgeber
//14
AUTHOR : Kai
FAMILY : SPSForum
NAME : '40587'
VERSION : 1.0
 
VAR_INPUT
  Kanal_A : BOOL ; 
  Kanal_B : BOOL ; 
END_VAR
VAR_OUTPUT
  Zaehler : INT ; 
END_VAR
VAR
  Kanal_A_Flanke : BOOL ; 
  Kanal_B_Flanke : BOOL ; 
END_VAR
BEGIN
NETWORK
TITLE =Drehgeber - Zaehler positiv
//            _____       _____
//Kanal A    |     |     |     |
//         __|     |_____|     |_____
//
//               _____       _____
//Kanal B       |     |     |     |
//         _____|     |_____|     |__
//   
      U     #Kanal_B; 
      FP    #Kanal_B_Flanke; 
      U     #Kanal_A; 
      SPBNB _001; 
      L     #Zaehler; 
      L     1; 
      +I    ; 
      T     #Zaehler; 
_001: NOP   0; 
NETWORK
TITLE =Drehgeber - Zaehler negativ
//               _____       _____
//Kanal A       |     |     |     |
//         _____|     |_____|     |__
//
//            _____       _____
//Kanal B    |     |     |     |
//         __|     |_____|     |_____
//   
      U     #Kanal_A; 
      FP    #Kanal_A_Flanke; 
      U     #Kanal_B; 
      SPBNB _002; 
      L     #Zaehler; 
      L     1; 
      -I    ; 
      T     #Zaehler; 
_002: NOP   0; 
END_FUNCTION_BLOCK
```
 
Folgendes Problem kann aber bei dem Programmbeispiel auftreten:

Pendelt das Segment der Welle im Bereich der Sensoren, kann der Zähler falsche Werte liefern.

Beispiel:

Segment der Welle deckt den Sensor für Kanal A ab. 

Segment der Welle pendelt um den Sensor für Kanal B.

Kanal A = 1, Kanal B = 0 -> 1, Zähler + 1

Kanal A = 1, Kanal B = 1 -> 0, Zähler unverändert

Kanal A = 1, Kanal B = 0 -> 1, Zähler + 1 

Gruß Kai


----------



## Perfektionist (18 November 2010)

```
ON    #Spur_A
      O     #f_Spur_A
      O     #Spur_B
      SPB   m001
      L     #Zaehler
      +     1
      T     #Zaehler
m001: O     #Spur_A
      ON    #f_Spur_A
      O     #Spur_B
      SPB   m002
      L     #Zaehler
      +     -1
      T     #Zaehler
m002: ON    #Spur_A
      O     #f_Spur_A
      ON    #Spur_B
      SPB   m003
      L     #Zaehler
      +     -1
      T     #Zaehler
m003: O     #Spur_A
      ON    #f_Spur_A
      ON    #Spur_B
      SPB   m004
      L     #Zaehler
      +     1
      T     #Zaehler
m004: ON    #Spur_B
      O     #f_Spur_B
      ON    #Spur_A
      SPB   m005
      L     #Zaehler
      +     1
      T     #Zaehler
m005: O     #Spur_B
      ON    #f_Spur_B
      ON    #Spur_A
      SPB   m006
      L     #Zaehler
      +     -1
      T     #Zaehler
m006: ON    #Spur_B
      O     #f_Spur_B
      O     #Spur_A
      SPB   m007
      L     #Zaehler
      +     -1
      T     #Zaehler
m007: O     #Spur_B
      ON    #f_Spur_B
      O     #Spur_A
      SPB   m008
      L     #Zaehler
      +     1
      T     #Zaehler
 
m008: U     #Spur_A
      UN    #f_Spur_A
      U     #Spur_B
      UN    #f_Spur_B
      O     
      U     #Spur_A
      UN    #f_Spur_A
      UN    #Spur_B
      U     #f_Spur_B
      O     
      UN    #Spur_A
      U     #f_Spur_A
      U     #Spur_B
      UN    #f_Spur_B
      O     
      UN    #Spur_A
      U     #f_Spur_A
      UN    #Spur_B
      U     #f_Spur_B
      =     #Stoerung
 
      U     #Spur_A
      =     #f_Spur_A
      U     #Spur_B
      =     #f_Spur_B
```


----------



## rostiger Nagel (18 November 2010)

Danke Kai,
du siehst auch alles :-D, deine Beiträge sind klasse.



Kai schrieb:


> Nachfolgend ein einfaches Programmbeispiel für die Auswertung der Drehrichtung eines A/B-Drehgebers:
> 
> 
> ```
> ...


----------



## Perfektionist (18 November 2010)

jetzt hab ich doch noch was gefunden, das so auch mal in Betrieb war/ist ...
	
	



```
FUNCTION_BLOCK "ZweiSpurZaehler"
TITLE =
VERSION : 0.1

VAR_INPUT
  IN_Spur_A : BOOL ; //Phasenversatz 0°, sozusagen Referenzspur
  IN_Spur_B : BOOL ; //Phasenversatz 90°, bei Rechtsdrehung nacheilendes Signal
END_VAR
VAR_OUTPUT
  OUT_Zaehler : INT ; //laeuft bei 32767 auf -32768 über (und umgekehrt)
  OUT_dreht_rechts : BOOL ; //zeigt die aktuelle bzw. letzte Drehrichtung an
  OUT_Bewegung_vorhanden : BOOL ; //zeigt an, dass aktuell eine Änderung an den Spureingängen vorlag
  OUT_Doppelzaehlung : BOOL ; //Änderung an beiden Spureingängen, Zählung anhand der letzten Drehrichtung
  OUT_Spurverlust : BOOL ; //wenn mehrere Signalwechsel an nur einem Spureingang vorliegen
  OUT_UEberlauf : BOOL ; //wenn die Drehrichtung ohne Stillstand wechselt
END_VAR
VAR
  f_IN_Spur_A : BOOL ; 
  f_IN_Spur_B : BOOL ; 
  UEberwachungszaehlerA : BYTE ; 
  UEberwachungszaehlerB : BYTE ; 
END_VAR
BEGIN
NETWORK
TITLE =
// Version 020315  2002041216Co  auf 315-2DP: 0,15..0,31 Millisekunden
// **********************************
// ***** Zähler mit zwei Spuren *****
// **********************************

// Code zeitoptimiert für 312/313/314/315/316-CPU (8-Bit-Zugriffe).
// Bei Power-Up können Fehlermeldungen generiert werden, weil die remanenten
// Daten dieses Bausteins dann eventuell inkonsistent zum Prozess sind.
// Fehlermeldungen treten nur temporär auf und quittieren sich selbstätig.
// Der Zähler ist nicht null-stellbar. Da dies häufig mit Randbedingungen
// verknüpft ist, wird eine Nullstellung durch das aufrufende Programm
// empfohlen:
//   wenn Referenz, dann aktueller Zählerstand --> Nullstand (oder Referenzstand).
//   Anwenderzähler = aktueller Stand minus Nullstand (Integersubtraktion!).
// So können mehrere Zähler aus diesem einen abgeleitet werden und auch
// Varianten wie z.B. Nullung nur bei Rechtsdrehung o.ä. realisiert werden.
// Soll durch das aufrufende Programm die Drehrichtung überprüft werden,
// so empfiehlt sich die Verknüpfung mit dem Signal Bewegung (ggf zeitverzögert).
// Für das Signal Spurverlust ist  e i n e  Drehrichtungsumkehr berücksichtigt,
// jedoch müssen danach wenigstens zwei Zählungen in die andere Richtung erfolgen.
// Wenn dies nicht grundsätzlich gewährleistet ist, sollte Spurverlust erst
// zeitverzögert nach Anlauf des Antriebs ausgewertet werden. Die Auswertung
// des Ausgangs Bewegung erfolgt zweckmäßigerweise:
//     und "Bewegung_vorhanden"
//     starte auschaltverzögert die Zeit "verlaengert_Bewegung_vorhanden"
//     und "verlaengert_Bewegung_vorhanden"
//     starte einschaltverzögert die Zeit "zuegige_Bewegung_vorhanden"
// Ggf. kann bzw. sollte der Steuerzustand des Antriebs (mit) ausgewertet werden.
// Das Signal Doppelzählung kann zum Auslösen einer Störung verwendet werden,
// normalerweise hat es nur informativen Charakter, um zu beurteilen, inwieweit
// Reserven bei der SPS-Zykluszeit vorhanden sind. Bei Doppelzählung wird anhand
// der letzten Drehrichtung weitergezählt, da die Ermittlung der Drehrichtung
// dann aktuell nicht möglich ist. Das Signal Doppelzählung wird bei Vorliegen einer
// solchen gesetzt und bei Stillstand rückgesetzt.
// Das Signal Überlauf zeigt an, dass ein Drehrichtungswechsel vorlag, ohne dass
// dazwischen ein Stillstand auftrat. Dies tritt ein, wenn die Zykluszeit zu gross
// ist in Relation zum Spursignal. Warnung: einzelne zu lange SPS-Zyklen führen
// nicht zwangsläufig zur Auslösung dieser Fehlermeldung (z.B. PG-Zugriff Baustein
// übertragen). Ggf. ist es empfehlenswert, neben der Auswertung der Fehlermeldungen
// des Zählbausteins zusätzlich die Zykluszeit der SPS zu überwachen.
// Ein Standartmotor mit 1500U/min, ausgerüstet mit einem Zweipuls-Zählrad
// (Flanken im 90°-Winkel, Initiatoren im 45°-Winkel angeordnet) generiert bei einer
// Motorfrequenz von 100Hz alle 2,5 Millisekunden einen Flankenwechsel. Wird
// Doppelzählung zugelassen, so kann dieses Signal mit einer Zykluszeit von 
// 5 Millisekunden eingelesen werden. Beschränkt man sich auf ein Einpuls-Zählrad
// und eine Motorfrequenz von 50Hz, so ist eine Zykluszeit von weniger als 20ms
// ausreichend. Sollte die damit erzielbare Auflösung zu gering sein, kann durch
// eine Zeitsteuerung das Positionsergebnis optimiert werden.

      UN    #IN_Spur_A; 
      X     #f_IN_Spur_A; 
      SPB   m050; // wenn kein Wechsel auf Spur A --> weiter Spur B
      U     #IN_Spur_B; 
      X     #f_IN_Spur_B; 
      SPB   ctdd; // wenn auch Wechsel auf Spur B --> Doppelzaehlung
      L     #UEberwachungszaehlerA; // Überwachung Spurverlust
      +     1; 
      T     #UEberwachungszaehlerA; 
      L     2; 
      >I    ; 
      =     #OUT_Spurverlust; 
      L     0; 
      T     #UEberwachungszaehlerB; 
      U     #IN_Spur_A; 
      X     #IN_Spur_B; 
      SPB   ctup; // hochzaehlen
      SPA   ctdn; // bzw. herabzaehlen
m050: UN    #IN_Spur_B; 
      X     #f_IN_Spur_B; 
      SPB   ctnt; // keine Änderung Spur B --> keine Zählung
      L     #UEberwachungszaehlerB; // Überwachung Spurverlust
      +     1; 
      T     #UEberwachungszaehlerB; 
      L     2; 
      >I    ; 
      =     #OUT_Spurverlust; 
      L     0; 
      T     #UEberwachungszaehlerA; 
      UN    #IN_Spur_A; 
      X     #IN_Spur_B; 
      SPB   ctup; // hochzaehlen
      SPA   ctdn; // bzw. herabzaehlen
ctdd: =     #OUT_Doppelzaehlung; // Doppelzählung
      =     #OUT_Bewegung_vorhanden; 
      L     1; 
      T     #UEberwachungszaehlerA; 
      T     #UEberwachungszaehlerB; 
      L     #OUT_Zaehler; 
      +     -2; 
      UN    #OUT_dreht_rechts; 
      SPB   m005; 
      +     4; 
m005: T     #OUT_Zaehler; 
      SPA   ende; 
ctup: U     #OUT_Bewegung_vorhanden; // Einfachzählung aufwärts
      UN    #OUT_dreht_rechts; 
      =     #OUT_UEberlauf; 
      SET   ; 
      =     #OUT_Bewegung_vorhanden; 
      =     #OUT_dreht_rechts; 
      L     #OUT_Zaehler; 
      +     1; 
      T     #OUT_Zaehler; 
      SPA   ende; 
ctdn: U     #OUT_Bewegung_vorhanden; // Einfachzählung abwärts
      U     #OUT_dreht_rechts; 
      =     #OUT_UEberlauf; 
      SET   ; 
      =     #OUT_Bewegung_vorhanden; 
      CLR   ; 
      =     #OUT_dreht_rechts; 
      L     #OUT_Zaehler; 
      +     -1; 
      T     #OUT_Zaehler; 
      SPA   ende; 
ctnt: CLR   ; // keine Zählung, Quittungsfunktion
      =     #OUT_Spurverlust; 
      =     #OUT_UEberlauf; 
      =     #OUT_Doppelzaehlung; 
      =     #OUT_Bewegung_vorhanden; 
ende: U     #IN_Spur_A; // Flankenerkennung
      =     #f_IN_Spur_A; 
      U     #IN_Spur_B; 
      =     #f_IN_Spur_B; 

END_FUNCTION_BLOCK
```


----------



## Waldi1954 (18 November 2010)

Beispiel für 4 Fach Auswertung

Gruß Waldi


----------



## Kai (22 November 2010)

Helmut_von_der_Reparatur schrieb:


> Danke Kai,
> du siehst auch alles :-D, deine Beiträge sind klasse.


 
Danke schön. 

Gruß Kai


----------



## Heinileini (26 Juni 2017)

Perfektionist schrieb:


> ```
> L     #Zaehler        (einfügen)
> ON    #Spur_A
> O     #f_Spur_A
> ...



Hallo Perfektionist!
           Sauber und gut lesbar (nachvollziehbar) programmiert!!!
Die StoerungsErkennung ist genau richtig, da sie nur(!) prüft, ob sich beide EingangsSignale gleichzeitig gegenüber dem vorherigen PLC-Zyklus geändert haben.
Mehr lässt sich einfach nicht prüfen, obwohl man häufig sieht, dass auf weitere vermeintliche(!) Stoerungen zu prüfen versucht wird.
Die StoerungsErkennung spricht an, wenn die PLC-ZyklusZeit zu lang ist für die EingangsFrequenz oder, wenn durch StoerImpulse beide EingangsSignale gleichzeitig verfälscht werden.
Eine Verfälschung nur eines EingangsSignals durch einen StoerImpuls führt zu einem "ZuvielZählen" in einer Richtung, wird aber durch ein entsprechendes "ZuvielZählen" in der umgekehrten Richtung korrigiert. Dies führt aber korrekterweise(!) nicht zur Erkennung einer Stoerung.

Habe oben im Code EinsparPotenzial entdeckt:
7 der 8 Lade- und 7 der 8 Transfer-Befehle können entfallen, allerdings müssen der verbleibende LadeBefehl vor den ersten SprungBefehl vorgezogen und der verbleibende TransferBefehl hinter die SprungMarke m008 verschoben werden, damit sie nicht übersprungen werden. Habe im Code in Klammern die ÄnderungsHinweise eingetragen.

Gruss, Heinileini


----------

