S7-200 Unterprogramme und Bits setzen/auslesen

D0m1n1k

Level-1
Beiträge
16
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,
in der Lehrwerkstatt haben wir uns ein wenig mit der S7-200 beschäftigt. Wir programmieren nur in FUP. Dabei habe ich folgende Probleme mit der Variabelübergabe von OB1 an Unterprogramm (SBR1):
Ich möchte meine Unterprogramm flexibel halten, so dass man es problemlos in andere Programme einfügen kann. Deshalb sollen globale Variablen nicht direkt verändert werden, sondern über ein Eingang übergeben. Also alle globalen Variablen, die im Unterprogramm verändert werden, sollen im OB1 and SBR1 übergeben werden. Für Bytes funktioniert das mit Pointer ganz gut. Allerdings nicht für Bits! So musste ich ziemlich aufwendig programmieren.

Beispiel: Das Bit A0.5 soll in einem Unterprogram gesetzt, bzw. rückgesetzt werden. Ich habe keinen anderen Weg gefunden als gleich zwei Werte an das Unterprogramm zu übergeben: Die Adresse von AB0 (&AB0) und das Bit (hier 5).
Um jetzt A0.5 zu setzen, habe ich in einer Hilfsvariable (byte) eine 2#00000001 übertragen und um die übergebenen Stellen (hier im Beispiel 5) nach links geschoben (SHL_B). Dann habe ich die Hilfvariable mit dem lokalen Pointer auf AB0 (z.B. *LD0) ODER verknüpft um den Ausgang zu setzen (Ergebnis direkt wieder nach *LD0 = AB0).

Rücksetzen ist nach meiner Methode noch aufwendiger: Ich schiebe wieder Bit-Stellen eine 2#00000001 und invertiere das Byte anschließend. Zuletzt verknüpfe ich das invertierte Byte mit dem AB0-Pointer UND, so dass A0.5 zurückgesetzt wird.

Gibt es da eine einfachere Methode? Kann ich nicht irgendwie z.B. A0.5 an ein Unterprogramm übergeben, so dass ich direkt mit A0.5 weiterarbeiten kann?


Noch komplizierter mache ich es, wenn der Status von Bits im Unterprogramm ausgelesen werden sollen, um ein Netzwerk zu triggern (meist an EN-Eingang von Bausteinen). Beispiel: Je nachdem ob A0.5 gesetzt ist, soll eine Aktion im Unterprogramm ausgeführt werden.
Wieder muss ich beide Werte (Pointer auf AB0 und Bitnummer) übergeben. Wieder eine Byte-Hilfsvariable mit 1 um Bitnummer Stellen schieben. Diese verknüpfe ich dann logisch UND mit dem Inhalt von AB0 (wo der Pointer drauf zeigt) und lege das Ergebnis wieder in der Hilfsvariable. Nun prüfe ich ob das Byte der Hilfsvariable 0 oder NICHT-0 ist (mit dem =B-Baustein, eventuell kann man nach der UND-Verknüpfung auch direkt ein Zero-Flag aus dem Sondermerkern auswerten?). Hiermit triggere ich dann die eigentliche Aktion.

Geht das nicht alles irgendwie auch einfacher? Ansonsten machen Unterprogramme ja wenig Sinn, wenn man die globalen Variablen fest einprogrammiert. Ich will ein Unterprogramm ja schließlich mehrfach für unterschiedliche Variablen verwenden.


TIA,
Dominik
 
Natürlich geht das einfacher.

Beim Variablentyp braucht man nur BOOL anzugeben.
Hab' Dir mal ein einfaches Beispiel angehangen.
Die Int-Variable hab' ich mal dazwischen gehangen, weil's eine Besonderheit gibt. Solange keine anderen Variablentypen vor der boolschen Variable sind, kannst du den Eingang als VKE-Ergebnis übergeben, danach nur noch als einzelne Varable/Merker. Wenn Du mal zur KOP-Ansicht umschaltest, sieht man den Unterschied zwischen den beiden Eingängen besonders gut.

Ansonsten kannst Du Dir mal diese Rolladensteuerung ansehen, da werden Bits durch mehrere Unterprogramme durchgereicht.
 

Anhänge

  • SBR.rar
    6,8 KB · Aufrufe: 72
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Da sind aber nur lokale Bool-Variablen im Unterprogramm. Im Unterprogramm kann ich nicht A0.0 setzen. Du hast A0.0 an einem Ausgang des Unterprogrammes gehangen, welches zudem dazu noch immer ausgeführt wird (EN mit SM0.0 auf Immer_Ein). Das will ich aber nicht: Ich will das Unterprogramm nur unter bestimmten Bedingungen ausführen und A0.0 dann nur einmal setzen. Im Hauptprogramm kann man beispielsweise mit der Setzen/Rücksetzen Bitverknüpfung (S oder R - nicht zu verwechseln mit RS oder SR!) ein Bit (z.B. A0.0) setzen, so dass es gesetzt bleibt. Im Unterprogramm geht das nicht. Wenn ich mit Setzen die lokale Ausgangsvariable setze, an der A0.0 hängt, dann bleibt sie offenbar auch gesetzt, wenn ich das Unterprogramm noch einmal in einem anderen Zusammenhang nutze.
Auch nervt es mich total, dass man an einem Bit-Ausgang eines Unterprogrammes nur eine Variable schreiben kann und nicht direkt einen Baustein hängen. So muss man eine Zwischenvariable nehmen, die den EN-Eingang des Bausteines im nächsten Netzwerk triggert.
 
Ich habe mal ein stark vereinfachstes Beispiel gemacht zur Veranschaulichung was ich meine:
Ein Unterprogramm Setzen, indem A0.5 gesetzt wird
Ein Unterprogramm Rücksetzen, wo A0.5 rückgesetzt wird
Ein Unterprogramm Bit_Auslesen, wo A0.5 ausgelesen wird und nur wenn es 1 ist, wird ein z.B. ein Starttimer ausgelöst (aktuelle Prozessorzeit in VD0).
Kann sein, dass ein paar kleine Fehler drin sind. Habe mir gerade nur die Evaluation von STEP 7-Micro installiert und habe hier keine SPS zum Testen
 

Anhänge

  • SBR_BSP.rar
    7,5 KB · Aufrufe: 21
Hab's mal nach meiner Interpretation umgewandelt.
Bei Netzwerk 3 hab' ich nur die Flanke weggelassen, damit man besser beobachten kann, was passiert.

PS: Bei Setzen/Rücksetzen ist es wichtig In/Out zu nehmen, da der Ausgang ja vorher einen Wert hat und diesen eventuell behalten soll.

Ich hoffe, ich hab' Dein Problem jetzt richtig verstanden.


Ein Unterprogramm Bit_Auslesen, wo A0.5 ausgelesen wird und nur wenn es 1 ist, wird ein z.B. ein Starttimer ausgelöst (aktuelle Prozessorzeit in VD0).
Hast ein |NOT| drinne, also wenn A0.5=0 ist, wird die Prozessorzeit übertragen. Hab's jetzt bei mir so gelassen. Die Funktion ist ja vom Prinzip gleich.
 

Anhänge

  • SBR1.rar
    7,2 KB · Aufrufe: 17
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,
erstmal danke für den Tipp.
So ähnlich hatte ich das (Setzen und Rücksetzen) schon probiert, und es klappte nicht. Allerdings hatte ich auch nicht IN_OUT benutzt:
Mit einem einzigen Unterprogrammaufruf war das kein Problem. Wenn ich aber mehrere benutzt habe, hat es nicht so funktioniert, wie es sollte. Werde das am Montag noch einmal ausprobieren mit Deiner Lösung! Ich glaube das ist es!

Das Bit-Auslesen direkt über den Eingang hätte ich natürlich auch so machen können. Aber das ich in dem Unterprogramm bereits den Pointer auf AB und die Bitnummer übergeben habe (eben wegen dem umständlichen Setzen/Rücksetzen), wollte ich für A0.5 nicht auch noch einen dritten Eingang verschwenden. Wenn das tatsächlich mit IN_OUT klappt, hat sich das Problem von alleine erledigt.

Nichtsdestotrotz: Wenn ich ein Byte habe und die Nummer des Bits. Dann bietet die SPS wohl keine andere Möglichkeit als die Umwege, die ich benutzt habe, um das Bit zu lesen/schreiben?
In der Assembler-Programmierung von Mikrocontrollern bin ich so Befehle gewöhnt wie
bsf PORTA,5 ; Setze das 5.Bit von Byte PORTA
bcf PORTA,5 ; Lösche das 5.Bit von Byte PORTA
btfsc PORTA,5 ; Prüfe ob das 5.Bit von Byte PORTA gesetzt ist. Wenn nicht, dann überspringe den nächsten Befehl.

Oder gibt es irgendeine Möglichkeit, ein bestimmtes Bit zu manipulieren? Also das ich den Variablenausdruck zusammensetze *Pointer.Bitnummer für A0.0 (klappt so nicht, aber von Prinzip her meine ich).
Schön wäre auch ein Setzen-Baustein, wo ich einfach beides angebe. Ich dachte erst, der N-Eingang beim S-Baustein, wäre das Bit und ich müsste ein Byte als Ziel angeben. Dem war leider nicht so :(

Nochmals besten Dank und ich hoffe es klappt am Montag so, wie ich es mir vorstelle.


PS: Die Negierung im Bit-Auslesen Baustein kam dadurch, dass ich mit dem =B auf 0 geprüft habe. Wenn das Byte 00000000 ist, dann gibt der Ausgang schließlich eine 1, die negiert wird. Stattdessen hätte ich den <>B-Baustein nehmen können und mir die Negierung sparen.
 
Zuletzt bearbeitet:
...
So ähnlich hatte ich das (Setzen und Rücksetzen) schon probiert, und es klappte nicht. Allerdings hatte ich auch nicht IN_OUT benutzt:
Mit einem einzigen Unterprogrammaufruf war das kein Problem. Wenn ich aber mehrere benutzt habe, hat es nicht so funktioniert, wie es sollte.
...
Wenn Du nur Out nimmst, dann ist der Ausgang am Anfang immer 0 und nur wenn Du ihn im Unterprogramm auf 1 bringst, kommt am Ende eine 1 raus. Rufst Du den Baustein ein zweites mal auf, wird der Ausgang erst mal wieder 0, egal was vorher war. Deswegen In/Out, dann wird der Istzustand mit übergeben.


...
Nichtsdestotrotz: Wenn ich ein Byte habe und die Nummer des Bits. Dann bietet die SPS wohl keine andere Möglichkeit als die Umwege, die ich benutzt habe, um das Bit zu lesen/schreiben?
In der Assembler-Programmierung von Mikrocontrollern bin ich so Befehle gewöhnt wie
bsf PORTA,5 ; Setze das 5.Bit von Byte PORTA
bcf PORTA,5 ; Lösche das 5.Bit von Byte PORTA
btfsc PORTA,5 ; Prüfe ob das 5.Bit von Byte PORTA gesetzt ist. Wenn nicht, dann überspringe den nächsten Befehl.
...
Hilfe Microwin schrieb:
Indirekte Adressierung
Die indirekte Adressierung verwendet Pointer, um auf Daten im Speicher zuzugreifen. Pointer sind Doppelwortwerte, die eine Adresse im Speicher enthalten. Als Pointer können Sie nur Adressen des Variablen- und Lokaldatenspeichers bzw. einen der Akkumulatoren (AC1, AC2 oder AC3) angeben. Zum Erstellen eines Pointers verwenden Sie die Operation Doppelwort übertragen. Diese Operation überträgt die indirekt adressierte Adresse an die Adresse des Pointers. Pointer können auch als Parameter an ein Unterprogramm übergeben werden.
Bei der S7-200 können Sie mit einem Pointer auf die folgenden Speicherbereiche zugreifen: E, A, V, M, S, T (nur auf den aktuellen Wert) und Z (nur auf den aktuellen Wert). Mit der indirekten Adressierung können Sie nicht auf einzelne Bits oder auf die Speicherbereiche AE, AA, HC, SM oder L zugreifen.


...
Oder gibt es irgendeine Möglichkeit, ein bestimmtes Bit zu manipulieren? Also das ich den Variablenausdruck zusammensetze *Pointer.Bitnummer für A0.0 (klappt so nicht, aber von Prinzip her meine ich).
Schön wäre auch ein Setzen-Baustein, wo ich einfach beides angebe.
...
Hast doch in Deinem Beispiel Bausteine mit m.M.n. recht einfachem/wenig Code für gebaut. Set und Reset kann man in einen Baustein packen, Auslesen in einen Zweiten. Dann machst Du 'ne Bibliothek daraus und die von Dir gewünschten Funktionen stehen Dir in jedem neuen Projekt zur Verfügung.
Hab' das mal gemacht und Dir noch 2 Beispiele für unterschiedliche Aufrufe von Unterprogrammen mit der Setzfunktion und die Auswirkung auf den Programmablauf bzw. das Verhalten der Ausgangsvariablen durch den zyklischen Ablauf in das Beispiel-Programm eingefügt.


Ansonsten viel Erfolg am Montag.
 

Anhänge

  • Bit-Manipulation.rar
    17 KB · Aufrufe: 38
Hallo,
die Unterprogramme mit den inout-Variablen haben bestens funktioniert! So konnte ich mir die umständliche, indirekte Adressierung komplett sparen.
Nochmals vielen Dank!

Mein Ziel habe ich heute dennoch nicht erreicht. Aufgabe war eine individuelle Treppenhausbeleuchtung mit einigen Features. Ich wollte einen einzigen Universalbaustein, den ich pro Etage anwenden kann. Gescheitert bin ich an Flanken in Unterprogrammen. Eine positive Flanke im Unterprogrammbaustein, welcher mehrfach verwendet wird, löst bei jeden Zyklus immer wieder aus. Außen im OB1 kann ich an den SBR-Baustein an den selbst definierten Eingängen keine Flanken setzen (das geht leider nur am en-Eingang). Dazu müsste ich wieder Umwege über eine Zwischenvariable in einem weiteren Netzwerk machen, was die Idee mit den Einheitsbaustein schon zunichte machen würde. Daran ist es leider gescheitert.
Zudem stören globale Merker in Unterprogrammen. Ich habe es geschaft, nur einen zu brauchen, dem ich jeden Unterprogramm als inout-Variable übergebe. Für (manuelle) Flankenauswertungen hätte ich wohl weitere gebraucht.
Die S7 200 ist was Unterprogramm betrifft ziemlich unflexibel.

Das mit den Bibliotheken habe ich auch nicht hinbekommen, obwohl ich mich streng an die Hilfe gehalten habe. Ich habe Bibliothek erstellen gemacht und die gewünschten Unterprogramme ausgewählt. Name/Speicherort angegeben (kein Passwort) und mit OK hat er die Bibliothek fehlerfrei erstellt und übersetzt. Wenn ich die in einem leeren Projekt einfüge (Bibliothek ergänzen), dann wird sie offenbar geladen, aber ich sehe die Bausteine/Unterprogramme nirgends. (Das Symbol bei Bibliothek ist auch nicht wie in der Hilfe abgebildet aufklapptbar).
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Sorry, konnte nicht antworten, bin gerade auf Dienstreise. Hier ist man mit dem freien Internet in Hotels noch nicht so weit und T-Mobil-Hotspots sind mir mit 8€ für 'n Stunde zu teuer.

Wie wär's, wenn Du Dein Programm mal rüberschiebst (wenn nicht öffentlich, dann per PN), damit man sich's mal ansieht. Ist zumindest für mich immer wieder interessant, wie andere Lösungswege aussehen und alles weitere ist Übung. Hab' ja Dein Beispielprogramm auch zur Bibliothek gemacht, vlt. braucht man mal was ähnliches.

Hast Du diese übrigens mal versucht, bei Dir einzubinden. Bei mir funktioniert das einwandfrei und dann kannst Du zumindest erst mal sagen, ob das Problem beim Anlegen oder beim Verwenden liegt. Pack Deine Bibliothek und das Originalprogramm am Besten auch mit zu dem obigen, dann kann ich's bei mir auch testen.


D0m1n1k schrieb:
...Gescheitert bin ich an Flanken in Unterprogrammen. Eine positive Flanke im Unterprogrammbaustein, welcher mehrfach verwendet wird, löst bei jeden Zyklus immer wieder aus...
Ja, die Flankenmerker müssen raus oder eigene bauen.
Dazu eine boolsche In/Out-Variable erstellen, in der Du Dir den Zustand des vorherigen Zyklus merkst. Dann den Zustand von Deinem Eingang, den Du auf Flanke testen willst, abfragen und mit dem Zustand der In/Out-Variable für den vorherigen Zustand vergleichen (Vergleich je nach gebrauchtem Flankentyp gestalten). Anschließend der boolschen In/Out-Variablen den Zustand des geprüften Eingangs übergeben.

D0m1n1k schrieb:
...Außen im OB1 kann ich an den SBR-Baustein an den selbst definierten Eingängen keine Flanken setzen (das geht leider nur am en-Eingang)...
Wer sagt das? Bei mir funktioniert das an jedem boolschen Eingang, vorausgesetzt es sind die ersten Eingänge des SBR. Sowie ein anderer Eingangstyp davor liegt, geht's allerdings nur noch über Hilfsvariablen, da Du dann kein VKE an diesem Eingang mehr bilden kannst. In dem Beispiel aus meiner ersten Antwort hatte ich beide Möglichkeiten mit aufgezeigt.


D0m1n1k schrieb:
...Die S7 200 ist was Unterprogramm betrifft ziemlich unflexibel...
Naja, ist keine 300/400er. Dafür hat sie aber auch nicht deren Preis. Und wenn man sich mit eingearbeitet hat, ist's schon erstaunlich, was die "Kleine" alles kann. Und ich geh' mal davon aus, das ich persönlich, seit dem ich mit ihr arbeite, gerade mal an der Oberfläche gekratzt habe.


D0m1n1k schrieb:
...ich sehe die Bausteine/Unterprogramme nirgends. (Das Symbol bei Bibliothek ist auch nicht wie in der Hilfe abgebildet aufklapptbar).
Normalerweise sind sie ganz unten im Verzeichnis Operationen über den Unterprogrammen zu finden. (Siehe Bild unten links)

So, dann bis zum Wochende, da sollte ich wieder zu Hause sein.
Bis dahin ärgere ich mich mit dem Programm anderer in unserer neuen Anlage rum, die zwar bestimmt toll programmieren können, aber die Sollfunktionen nur aus der Auftrags-Beschreibung des Schweizer Herstellers kennen. Die scheint dann doch etwas unvollständig gewesen zu sein und ich komm' hier nicht an das Programm ran, um zu korrigieren.:cry:
Und der Kunde steht dahinter und will natürlich mit der neuen Anlage endlich produzieren.:sw3::sw13:
 

Anhänge

  • Microwin.jpg
    Microwin.jpg
    176,3 KB · Aufrufe: 36
Zurück
Oben