Step 7 Programm zur Drehzahlüberwachung mittels zweier induktiver Sensoren (TiaPortal v13)

Azubi94

Level-2
Beiträge
107
Reaktionspunkte
4
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo liebes SPS Forum,

ich bin Mechatronik Azubi im 2. Lehrjahr und habe ein Problem bei der Programmierung eines Programms für die Überwachung der Drehrichtung u. Drehzahl eines Drehstrommotors. Ich habe einen Motor auf eine Grundblatte montiert, und dazu zwei induktive Sensoren zur Auswertung der Drehrichtung u. der Drehzahl installiert. An der Welle des Motors habe ich eine Scheibe aus Kunststoff angebracht, an der an einer Stelle ein leitendes Blechteil angeschraubt ist. Im aktiven Betrieb läuft also das Stück Metall mit der Drehzahl x an meinen Sensoren vorbei, wodurch diese angesteuert werden.
Zum Realisierung benutze ich TiaPortal v13 und eine SPS vom Type CPU 314C-2 PN/DP. Das Programm für die Drehrichtungserkennung funktioniert, jedoch habe ich bei der Programmierung der Drehzahlüberwachung erhebliche Probleme.

Mein Programm soll folgende Funktion erfüllen:
Die Drehzahl, also die Nenndrehzahl des Motors, soll ausgelesen werde und im Fall einer Unterschreitung o. Überschreitung eines Sollwertes (den ich im OB angeben kann), soll eine Meldeleuchte dies melden. Diese Funktion soll im Betrieb des Motors durch einen Schalter aktiviert u. deaktiviert werden können.

Im Prinzip habe ich dies folgendermaßen realisiert: Ein Counter zählt über eine Zeit: X die Flanken meiner Sensoren (beide müssen aktiv sein). Die Werte werden in Vergleicher Bausteinen mit den Vorgabewerten verglichen und falls eine fehlerhafte Drehzahl vorliegt, wird die Meldeleuchte aktiviert. Diese wird wieder inaktiv, wenn in der nächsten "Auswertungsphase" die Drehzahl korrekt ist.
Ich wollte das Programm testen, jedoch erwies es sich als fehlerhaft. Im Anhang finden Sie Screenshots meines Funktionsbausteines und des OBs.
Der Zähler in Kombination mit dem Zeitglied funktioniert, heißt es werden 3s lang die eingehenden Flanken gezählt, bis die Zeit t abgelaufen ist. Daraufhin setzt sich das Zeitglied samt Counter zurück und die Auswertung beginnt von vorne. Im Moment des Setzens des Ausgang Q am Zeitglied in NW1, soll "tonZeitglied" (Q) in NW2 das Ergebnis der Vergleicher abfragen, wodurch die Meldeleuchte gesetzt o. rückgesetzt wird. (Beachte Screenshots im Anhang)

Ich habe den Verdacht, dass in NW1 nach dem Setzen von "tonZeitglied", das Signal Q nicht mehr in NW2 bei den Vergleicher Bausteinen "ankommt".
Ebenfalls gilt dies für die Zählerwerte,...
Generell vermute ich also, dass der Ausgang Q des Zeitbausteines aus NW1 nicht mehr in NW2 anliegt.
Ebenfalls, da ich versucht habe dies mit einem Speicherglied zu "fixen" indem ich das Signal von Q für NW2 speichere (nicht im Screenshot vorhanden), wurde mir im Diagnosefenster angezeigt, dass das von mir verwendete Gerät nicht in der Lage sei zwei Datentypen (ich vermute Int des Zählers und Time des Zeitbausteines) gemeinsam zu verarbeiten.
Mich würde daher brennend interessieren, ob der Fehler programmier- oder systembedingt ist und ob ich mit meiner Diagnose richtig liege.


Ich hoffe Sie können mir weiterhelfen, ich bin offen für alle Verbesserungsvorschläge. Meine Ausbilder haben nicht wirklich Zeit und meine Lehrer sind nicht in der Lage einen ausreichenden Unterricht zu führen. Ich bringe mir also sozusagen alles selber bei. Ich wäre ebenfalls sehr interessiert, wie ein Erfahrener Programmierer diese Aufgabe angehen würde und ob ich auf dem richtigen Weg bin...

Vielen Dank im voraus

Azubi94
 

Anhänge

  • OB1.jpg
    OB1.jpg
    59,2 KB · Aufrufe: 166
  • fbDrehzahlüberwachung_NW1.jpg
    fbDrehzahlüberwachung_NW1.jpg
    62 KB · Aufrufe: 163
  • fbDrehzahlüberwachung_NW2_Part1.jpg
    fbDrehzahlüberwachung_NW2_Part1.jpg
    59,1 KB · Aufrufe: 137
  • fbDrehzahlüberwachung_NW2_Part2.jpg
    fbDrehzahlüberwachung_NW2_Part2.jpg
    58,9 KB · Aufrufe: 121
Ich bin immer wieder erstaunt, was man mit FUP allles so hinbekommt ;)

Zu deiner Aufgabe :
Das, was du da beschreibst ist eine Schrittkette und genau so würde ich es auch (erstmal) programmieren :
- Schritt 1 : Timer Ein, Freigabe für Zähler
-> wenn Timer abgelaufen dann Schritt = 2
- Schritt 2 : Zählerstand speichern und verrechnen
-> wenn Ergebnis dann wieder Schritt = 1

Gruß
Larry
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Dein Fehler:
Wenn Du in Netzwerk 2 die Zählerstände auswertest um #xSP2 zu setzen (UND "tonZeitglied".Q) dann wurde vorher schon in Netzwerk 1 der Zähler gelöscht/rückgesetzt. Du müsstest den Zählerstand sichern/umspeichern vor dem Rücksetzen des Zählers.

Ich meine, Du denkst außerdem etwas zu kompliziert.
Ein paar Tipps:

Du brauchst einen Timer für die Messperiode (3s), der am Ende einen Puls ausgibt für die Auswertung des Zählerstands und Löschen des Zählerstands. Der Timer muß eigentlich nicht auf die Sensorpulse synchronisiert werden (dann würde er ohne Sensorpulse überhaupt nicht starten) - besser er läuft freilaufend und startet sich nach Ablauf selber neu.
Timer-Ausgänge (.Q) vorsichtshalber im Programm immer nur ein einziges Mal lesen, weil es Timer gibt, die asynchron zum OB1 arbeiten und .Q irgendwann aktualisieren und mehrmals Abfragen von Q dann zu verschiedenen Ergebnissen führen kann. Also den Timer-Ausgang auf eine Variable umspeichern und dann nur die Variable weiterverknüpfen.

Der Zähler sollte immer Zählen. Der Zähler-Eingang braucht nicht mit dem Timer verknüpft werden wenn es keine Pausen in den Messperioden gibt (außer dem 1-Zyklus-Timer-Puls). Der Timer-Puls am R-Eingang hat sowieso Vorrang.
Beim Timer-Puls den Zähler löschen/rücksetzen und VORHER den Zähler-Endstand sichern/umspeichern.

Design-Entscheidung: Beim Timer-Puls den Zählerstand umspeichern und dauerhaft merken für die Auswertung, oder die Auswertung nur beim Puls machen. Mit gemerktem Zähler-Endstand immer auswerten ist einfacher.

Wenn Du den Drehzahlüberwachungsbaustein als FB schreibst, dann kannst Du den Timer und den Zähler besser als Multiinstanz in Static des FB deklarieren. (Bei lange laufenden Zählern ist es oft vorteilhaft, den Zählerstand außerhalb der Instanz zu speichern, damit man Programmänderungen durchführen kann ohne den Zählerstand zu verlieren)

3 FUP-Netzwerke nach dieser Beschreibung würden viel einfacher als Dein Programm aussehen :cool:

Harald
 
Code:
Netzwerk 1: Freilaufender Timer Messperiode

                   #tonZeitglied
                   +-----------+  #xTimerPuls
                   |    TON    |    +-----+
      #xTimerPuls-o|IN       ET|-   |  =  |
       #tZeitwert--|PT        Q|----|     |-
                   +-----------+    +-----+

Netzwerk 2: Zähler

                                    +-----+   #IEC_Counter_1
                                    |  &  |    +-----------+
                         #xSensor1--|     |    |    CTU    |
                         #xSensor2--|     |----|CU         |
                                    +-----+    |           |
                                               |           |
                   +--------+                  |           |
                   |  MOVE  |  #iZählerwert_   |           |
      #xTimerPuls--|EN  OUT1|--gespeichert     |           |
#IEC_Counter_1.CV--|IN   ENO|------------------|R        CV|--#iZählerwert_Ist
                   +--------+               1--|PV        Q|-
                                               +-----------+

Netzwerk 3: Auswertung

                   +-----+
                   |  >  |
    #iZählerwert_  |     |    +-----+
      gespeichert--|IN1  |    | >=1 |
 #iZählerwert_max--|IN2  |----|     |
                   +-----+    |     |
                              |     |
                   +-----+    |     |
                   |  <  |    |     |
    #iZählerwert_  |     |    |     |    +-----+
      gespeichert--|IN1  |    |     |    |  &  |
 #iZählerwert_min--|IN2  |----|     |----|     |  #"xP3_(rot)"
                   +-----+    +-----+    |     |    +-----+
                                         |     |    |  =  |
                         #xWahlschalter--|     |----|     |
                                         +-----+    +-----+
In Static des FB deklarieren:
- tonZeitglied : TON
- IEC_Counter_1 : CTU
- xTimerPuls : Bool
- iZählerwert_gespeichert : Int
 
Hallo Harald,

vielen vielen Dank für deine schnelle Antwort und deine Bemühungen :D. Ich habe bereits versuch deine Ratschläge umzusetzen, bin dabei jedoch auf einige neue Fragen gestoßen, die du teilweise aber schon in deiner zweiten Antwort erläuterst.
Jedoch ist mir folgendes noch unklar:

In NW2, so verstehe ich es, speicherst du den Zähler-Endstandswert, welchen du für die Weiterverarbeitung in NW3 benötigst. Dafür verwendest du dieses "MOVE Glied", welches bei eingehendem "xTime_Puls" den Counter zurücksetzt und dabei den an IN anliegenden Zähler Wert ("#IEC_Counter_1.CV") kopiert/speichert, sodass die Int Variable iZählerwert_gespeichert in NW3 weiter verarbeitet werden kann.

Meine erste Frage bezieht sich auf NW2, und zwar auf das Move Glied und dessen IN Variable: "IEC_Counter_1". Wieso kann ich hier nicht als IN den
"iZählerwert_Ist" des Counters verwenden? Und warum muss ich die Variable als CTU deklarieren und steht diese für Count? Eigentlich lässt sich dies doch mit einer als Int deklarierten Variable wie eben "iZählerwert_Ist" umsetzen oder? Ich frage nur, weil ich ja dadurch die Deklaration der Variabel IEC_Count1.CV vermeiden könnte...(Anhang beachten)

Ebenfalls wollte ich fragen, ob der MOVE Baustein die Eigenschaft besitzt, die kopierte Variabel äber den Arbeitszyklus einer SPS hinaus zu speichern, da du in NW3 keine Speicherglieder verwendet hast um die Meldeleuchte zu schalten.

PS: hatten diesen Baustein noch nicht in der Schule, darum ist das etwas neu für mich..

MfG

Jens
 

Anhänge

  • fbDrehzahlüberwachung NW1, NW2.jpg
    fbDrehzahlüberwachung NW1, NW2.jpg
    52,8 KB · Aufrufe: 61
  • fbDrehzahlüberwachung NW3.jpg
    fbDrehzahlüberwachung NW3.jpg
    46,4 KB · Aufrufe: 51
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Ebenfalls wollte ich fragen, ob der MOVE Baustein die Eigenschaft besitzt, die kopierte Variabel äber den Arbeitszyklus einer SPS hinaus zu speichern, da du in NW3 keine Speicherglieder verwendet hast um die Meldeleuchte zu schalten.
Nein der Move besitzt keine speichernde Eigenschaft.
Bei True an EN Eingang wird die Variable am Eingang IN auf die Variable OUT kopiert und anschließend ENO auf TRUE gesetzt.

Nach dem Ablauf des TON wird Variable xAusgang.. auf TRUE gesetzt. jetzt kopiert der Move die IN Variable auf den OUT. beim nächsten Zyklus ist der Ausgang des TON FALSE da die Eingangsbedingungen nicht erfüllt sind. Der Move wird nicht ausgeführt da EN FALSE ist. somit bleibt der Wert in Zählwert_Speicher erhalten.
Holger
 
Hallo Jens

Wieso kann ich hier nicht als IN den "iZählerwert_Ist" des Counters verwenden?
Du könntest ihn verwenden doch dann würdest Du den Wert speichern, der im vorherigen OB1-Zyklus in dem Zähler war (und in iZählerwert_Ist kopiert wurde). Es könnte aber gerade eben im aktuellen Zyklus noch ein Impuls weiter gezählt worden sein (CU wird noch vor dem MOVE ausgeführt), deshalb wird mit IEC_Counter_1.CV der ganz aktuelle Zählerstand aus dem Zähler IEC_Counter_1 in die Variable iZählerwert_gespeichert kopiert.

Beachte die zyklische Arbeitsweise einer SPS mit der zyklischen Programmabarbeitung von oben nach unten von links nach rechts. Bei dem Zähler CTU wird zuerst die CU-Anweisung ausgeführt (gezählt), dann die R-Anweisung, dann wird der eventuell angegebene Wert in PV kopiert, dann wird der Zählerstand CV in die angeschlossene Variable kopiert und zuletzt wird CV mit PV verglichen und das Ergebnis an Q zugewiesen. (Bei Step7 "classic" V5.x kann man die Ansicht des FUP-Programms zu AWL umstellen und dadurch genau die Abarbeitungsreihenfolge sehen).


Und warum muss ich die Variable als CTU deklarieren und steht diese für Count?
Du brauchst auf jedem Fall einen Zähler, dafür könntest Du einfach eine Int-Variable nehmen und beim Zähl-Ereignis eine 1 dazu addieren, oder Du nimmst einen fertigen Zähler, der macht das Zählen übersichtlicher (CTU hat z.B. schon eine Flankenerkennung dabei).

Du hast in Deiner Programmversion den Zähler CTU verwendet, allerdings als globale Instanz %DB2 (IEC_Counter_0_DB). Wenn Du Deinen FB2 zur Überwachung von mehreren Motoren mehrmals aufrufen würdest, dann würden alle Deine Überwachungs-Instanzen den selben Zähler benutzen (die Instanz %DB2) - was natürlich Mist ist.

Ich habe wie Du ebenfalls den Zähler CTU verwendet, ihn aber in der Instanz des FB2 als Static deklariert (IEC_Counter_1), dadurch benutzen verschiedene Instanzen des FB2 automatisch verschiedene eigene Zähler.

Aus genau dem selben Grund habe ich auch den Timer TON als Static-Instanz im FB2 deklariert, damit jede FB2-Instanz einen eigenen unabhängigen Timer verwendet. Bei Dir würden alle FB2-Instanzen den selben Timer verwenden (die globale Instanz %DB4).
Übrigens: das Deklarieren von mehreren FB-Instanzen in einem FB (die Instanzen sind dadurch im selben Instanz-Datenbaustein) nennt man "Multiinstanz".


Ich frage nur, weil ich ja dadurch die Deklaration der Variabel IEC_Count1.CV vermeiden könnte...
IEC_Counter_1.CV ist keine eigenständig deklarierte Variable sondern der Ausgangsparameter CV des CTU-Zählers IEC_Counter_1 - und der Zähler muß ja zwingend irgendwie angelegt werden.


Ebenfalls wollte ich fragen, ob der MOVE Baustein die Eigenschaft besitzt, die kopierte Variabel äber den Arbeitszyklus einer SPS hinaus zu speichern
Die Anweisung MOVE ist zum Kopieren von Variablen oder Schreiben von Werten in Variablen.
Wie lange der Wert in der Zielvariable gespeichert bleibt hängt davon ab, was das für eine Variable ist und ob sie vielleicht anderweitig überschrieben wird.
iZählerwert_gespeichert ist eine Static-Variable in der Instanz eines FB, der Inhalt bleibt so lange erhalten, bis etwas anderes in die Variable gespeichert wird. Es reicht, mit dem MOVE ein einziges mal einen Wert in die Variable zu schreiben.

Harald
 
Hallo Harald,

erst mal vielen Dank für deine Hilfe, habe das Programm angepasst/abgewandelt und es funktioniert einwandfrei!
Mein Ausbilder war fasziniert:)

Habe nun den fb für die Drehzahlüberwachung mit einem weiterem fb in einem "fbMulti" aufgerufen, um einen Multiinstanz DB erstellen zu können. So wie ich das nun verstanden habe, kann das nur funktionieren wenn ich den counter und den timer in dem jeweiligen fb deklariere (also in dem fall static). Somit können beide einen DB nutzen. Anders hätten beide jeweils einen eigenen DB benötigt, was die CPU unnötig belasten würde.

Gruß Jens
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Anders hätten beide jeweils einen eigenen DB benötigt, was die CPU unnötig belasten würde.
Hallo Jens,

eigene DB "belasten" die CPU nicht mehr als Multiinstanz-DB, man braucht nur mehr DBs bzw. mehr DB-Nummern.
Es ist eher umgekehrt, weil Adressberechnungen in Multiinstanz-DB aufwändiger sind.

Harald
 
Zuletzt bearbeitet:
Zurück
Oben