BR-Studio und Strukturierter Text - Problem

Kirpitsch

Level-1
Beiträge
25
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo alle zammen :) Ich muss ein Programm mit BR-Studio in Verbindung mit der ST (Strukturierter Text) Programmiersprache schreiben.

Folgendes ist meine Aufgabe:
Ich habe einen pneumatischen Zylinder (doppeltwirkend) und 2 stück 3/2-Magnetventile (pneumatische Rückstellung) welche den Zylinder hin- und herfahren lassen sollen.


So sieht mein Quellcode aus:

//////////////////////////////////
// Steuerung Magnetventil 1 //
//////////////////////////////////

// Variable setzen
input_1 := TRUE;

// Zeitverzögerung beim Ausschalten des Ventils
TP_01( IN:=input_1, PT:=T#3s500ms );

// input_1 + Zeitverzögerung an Magnetventil_1 senden
magnetventil_1_do := TP_01.Q;
elapsedTime_1 := TP_01.ET;

// Variable Rücksetzen
input_1 := FALSE;



//////////////////////////////////
// Steuerung Magnetventil 2 //
//////////////////////////////////

IF (elapsedTime_1 = T#3s500ms) THEN

// Variable setzen
input_2 := TRUE;

// Zeitverzögerung beim Ausschalten des Ventils
TP_02( IN:=input_2, PT:=T#3s500ms );

// input_2 + Zeitverzögerung an Magnetventil_2 senden
magnetventil_2_do := TP_02.Q;
elapsedTime_2 := TP_02.ET;

// Variable Rücksetzen
input_2 := FALSE;

END_IF

Problem ist, dass der Zylinder bei diesem Code nur einmal hin- und zurück fährt. Ich will aber dass er das z.B. 10 mal tut, so oft ich es eben will.

BR-Studio arbeitet ja mit den Cyclic#1 - Cyclic#8 Dingern (weis grade nicht wie ich das nennen soll^^) welche ja z.B. alle 10ms wiederholt werden. Also dachte ich, dass meine Ventile bei meinem Code endlos ein und ausgehen müssten, das ist aber nicht der Fall. Das ganze passiert nur einmal, dann ist schluß.

Wie könnte ich das umsetzen, dass es funktioniert?

Ich hoffe, dass ich einigermaßen erklären konnte was ich möchte. Wenn mein Code nicht gut ist, dann korrigiert mich auch bitte.

Gruß
Kirpitsch
 
Code:
// Variable setzen
input_1 := TRUE;
Deine Zeit wird so nur einmal gestartet (kein Flankenwechsel)

Also der Input_1 sollte für ein neues Ansteuern der Zeit sein Signal wechseln
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich setze ihn doch am Ende auch wieder auf FALSE. Oder verstehe ich was falsch? kannst das in meinem Quellcode evtl. ändern und nochmal posten? Wäre echt hilfreich.
 
Ich setze ihn doch am Ende auch wieder auf FALSE. Oder verstehe ich was falsch? kannst das in meinem Quellcode evtl. ändern und nochmal posten? Wäre echt hilfreich.
Hi,
du musst in einmal auf FALSE haben wenn du den PULS-Fub (TP_...) aufrufst. Da setzt du ihn aber immer vorher auf true.
Code:
TP_01( IN:=input_1, PT:=T#3s500ms );

input_1 = true

...
code
...
if (was weiss ich) then
  input_1 = false           ; erzeugt einen startpuls, da in einem durchgang = 0
endif
 
@bits'bytes

Den besten Dank dir, mit deinem Code hats funktioniert!!! :D

Habe außerdem bemerkt, dass meine CPU jede Milisekunde das Programm durchgearbeitet hat, d.h. ich konnte nicht erkennen, dass das Ventil für diese 1ms sich kurz ausschaltet und dann sofort wieder ein ist.

Danke dir nochmals :D
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hi,
besser wäre es allerdings wenn du sowas machen würdest..., dann hast du keinen Zyklus Verzögerung
Code:
TP_01( IN:=input_1, PT:=T#3s500ms );
input_1 = false

...
code
...
if (was weiss ich) then
  input_1 = true           ; erzeugt einen startpuls, da ein durchgang = 1
endif

; wenn du sofort wieder zurückfahren willst
  
TP_02( IN:=EDGENEG(TP_01.Q), PT:=T#3s500ms );
 
So habe das mal ausprobiert aber es funzt nicht, das Ventil 1 wird innerhalb 1ms dauernd eingeschaltet wenns ausgeht....

So hab ich deinen Code umgesetzt, ich hab wohl nen Fehler drin:

TP_01( IN:=input_1, PT:=T#1500ms );
input_1 := FALSE;

magnetventil_1_do := TP_01.Q;

IF (magnetventil_1_do = FALSE) THEN
input_1 := TRUE; //erzeugt einen startpuls, da ein durchgang = 1
END_IF



TP_02( IN:=EDGENEG(TP_01.Q), PT:=T#1500ms );
magnetventil_2_do := TP_02.Q;
 
eine kleine Ergänzung:

Dein erstes Codebeispiel habe ich so umgesetzt:

// Magnetventil 1
IF (magnetventil_1_do = TRUE) OR (magnetventil_2_do = FALSE) THEN

TP_01( IN:=input_1, PT:=schalten_ms );
input_1 := TRUE;

magnetventil_1_do := TP_01.Q;

IF (TP_01.ET = schalten_ms) THEN

input_1 := FALSE;

END_IF

END_IF





// Magnetventil 2
IF (magnetventil_1_do = FALSE) THEN

TP_02( IN:=input_2, PT:=schalten_ms );
input_2 := TRUE;

magnetventil_2_do := TP_02.Q;


IF (TP_02.ET = schalten_ms) THEN

input_2 := FALSE;

END_IF

END_IF

Das hat verzögerungsfrei funktioniert. Mit Verzögerungsfrei meine ich natürlich dass die Verzögerung von 1ms meiner Taskklasse nicht berücksichtigt wird. Oder habe ich doch eine Verzögerung beim Umschalten meiner Ventile die ich im Code nur nicht bemerkt habe?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
So habe das mal ausprobiert aber es funzt nicht, das Ventil 1 wird innerhalb 1ms dauernd eingeschaltet wenns ausgeht....

So hab ich deinen Code umgesetzt, ich hab wohl nen Fehler drin:
...
IF (magnetventil_1_do = FALSE) THEN
input_1 := TRUE; //erzeugt einen startpuls, da ein durchgang = 1
END_IF

Hi,
wenn du do_1 sofort mit der negativen Flanke seiner selbst setzt ist do_1 ja quasi dauernd aktiv....

siehe mal folgendes Beispiel, habe jetzt den Wiederstart einfach mit einem Zeitglied verzögert....

Code:
PROGRAM _INIT
    TON_01.PT    := T#7s;        // Nach sieben Sekunden wieder starten
    magnetventil_1_do := 0;
    magnetventil_2_do := 0;
END_PROGRAM

PROGRAM _CYCLIC
    // neuen Zyklus starten wenn beide DO's 0 sind 7 Sekunden warten
    IF (magnetventil_1_do = 0) AND (magnetventil_2_do = 0) THEN
        TON_01.IN := 1;
    END_IF
    TON_01 (IN:= TON_01.IN, PT:= TON_01.PT);
    IF (TON_01.Q = 1) THEN
        TON_01.IN := 0;
        input_1 := 1;
    END_IF
        
    // Ventil auf
    TP_01( IN:=input_1, PT:=T#1500ms );
    input_1 := FALSE;
    magnetventil_1_do := TP_01.Q;

    // Ventil zu...
    TP_02( IN:=EDGENEG(TP_01.Q), PT:=T#1500ms );
    magnetventil_2_do := TP_02.Q;
END_PROGRAM
 

Anhänge

  • PLTrend_003.jpg
    PLTrend_003.jpg
    66,1 KB · Aufrufe: 19
Hi, habe den Code gleich mal in mein PowerPanel übertragen und es tut perfekt. Und dass ich damit sogar den Startzyklus gewollt verzögern kann ist natürlich eine tolle Sache. An dieser Stelle vielen Dank.

Ich habe natürlich auch versucht den Code zu verstehen und an einer Stelle habe ich noch ne Frage. Kurz nachdem du prüfst ob beide DO's = 0 sind, kommt der folgende Quelltext:

TON_01 (IN:= TON_01.IN, PT:= TON_01.PT);
IF (TON_01.Q = 1) THEN
TON_01.Q := 0;
input_1 : = 1;
END_IF

Hier machst du ja den Funktionsaufruf der Einschaltverzögerung mit Parameterübergabe. Dann fragst du, ob der Ausgang von TON_01 auf TRUE gesetzt ist. Ist dies der Fall, dann wird input_1 ebenfalls auf TRUE gesetzt. Diese IF-Bedingung muss also zwingend erfüllt sein, da sonst meine Ventile niemals schalten werden oder? Ich habe aber im ganzen Quelltext keine einzige Zeile mit TON_01.Q := TRUE gesehen.

Heist das jetzt, dass wenn ich den Funktionsaufruf TON_01 (IN:= TON_01.IN, PT:= TON_01.PT); mit Parameterübergabe mache, dass dann automatisch mein Ausgang TON_01.Q auf TRUE gesetzt wird? :confused:

Und noch eine Frage zum InitCode, wird dieser, wenn meine Taskklasse alle 10ms neu durchläuft, auch alle 10ms neu aufgerufen?

Gruß
 
Hi!

Hi, habe den Code gleich mal in mein PowerPanel übertragen und es tut perfekt. Und dass ich damit sogar den Startzyklus gewollt verzögern kann ist natürlich eine tolle Sache. An dieser Stelle vielen Dank
Freut mich :)

..Kurz nachdem du prüfst ob beide DO's = 0 sind, kommt der folgende Quelltext:
Code:
TON_01 (IN:= TON_01.IN, PT:= TON_01.PT);
        IF (TON_01.Q = 1) THEN
            [COLOR=Red] TON_01.Q := 0;[/COLOR]
             input_1 : = 1;
        END_IF
Das ist falsch, ich setzte nicht .Q auf := 0 sondern .IN, hast du falsch abgeschrieben.

Ich habe aber im ganzen Quelltext keine einzige Zeile mit TON_01.Q := TRUE gesehen
Du hast recht, es handelt sich hier um ein TON() Zeitglied, wo .Q = 1 wird nach Ablauf der parametrierten Zeit. Mit "input_1" wird ja dann dein Puls-Zeitglied gestartet...
Heist das jetzt, dass wenn ich den Funktionsaufruf TON_01 (IN:= TON_01.IN, PT:= TON_01.PT); mit Parameterübergabe mache, dass dann automatisch mein Ausgang TON_01.Q auf TRUE gesetzt wird? :confused:
Ja genau! Diese Schreibweise ist etwas komisch für mich, da ich normalerweise Automation Basic verwende. In Automation Basic würde ich das so schreiben
Code:
TON_01 FUB TON()
if (TON_01.Q = 1) then
...
...
Du hast ja die Variable TON_01 als TON Zeitglied definiert, oder nicht ?


Und noch eine Frage zum InitCode, wird dieser, wenn meine Taskklasse alle 10ms neu durchläuft, auch alle 10ms neu aufgerufen?
Nein, der wird nur nach dem Einschalten ausgeführt. Während der Programmerstellung nach dem Download, nach einem Kalt- oder Warmstart....

bg
bb
 
So es hat sich doch wieder ein Problem aufgetan.

Ich möchte zählen wie oft mein Zylinder eine bestimmte Position durchfährt. So sieht mein Code aus:


IF (druckregelvenil_druck = 0) THEN // Bei jedem Neustart oder
// Programmabruch der Fall
wegmitte := sensor_weg;
zeit_wegmitte := 0;
n := 0;
END_IF

IF (sensor_weg = wegmitte) AND (n = 1) THEN
n := 0;
zeit_wegmitte := 0;
IF(startbutton = TRUE) THEN
zyklenzahl := zyklenzahl + 1;
END_IF
END_IF

IF (sensor_weg <> wegmitte) THEN
zeit_wegmitte := zeit_wegmitte + 1;
n := 1;
END_IF

IF (startbutton = FALSE) THEN
zyklenzahl := 0;
END_IF



So und eigentlich tut das auch (hoffe ich hab beim schreiben keinen Fehler im Code) aber wenn ich einen Neustart des Systems (Stromausfall ^^) mache, dann zählt er die Zyklen zwar auch, aber fängt dann z.B. gleich bei 10 an, dannach zählt er normal weiter. Wie könnte ich den Fehler drin haben?
 
Hallo ,

kurz einige Punkte

a) du solltest den Code mittels # des Editors hier einfügen, dann kann man in auch leichter (eventuell :) lesen

b) du solltest Copy/Paste verwenden, dann kannst du dich auch nicht verschreiben


c) zu deinem Code

- ist kein Code-Fragment sondern der gesamte Code, oder ?
- wozu ist die Variable "zeit_wegmitte", wird nicht verwendet

- "zyklenzahl" wird beim INIT nicht gelöscht, (da kein INIT ?)

- ist "startbutton" eine IO-Variable oder ein Merker ?

- du solltest keine Variablen verwenden wie "n" oder "i"


Code:
IF (druckregelvenil_druck = 0) THEN // Bei jedem Neustart oder // Programmabruch der Fall
    wegmitte := sensor_weg;
    zeit_wegmitte := 0;
    n := 0;
END_IF

IF (sensor_weg = wegmitte) AND (n = 1) THEN
    n := 0;
    zeit_wegmitte := 0;
    IF(startbutton = TRUE) THEN
        zyklenzahl := zyklenzahl + 1;
    END_IF
END_IF

IF (sensor_weg <> wegmitte) THEN
    zeit_wegmitte := zeit_wegmitte + 1;
    n := 1;
END_IF

IF (startbutton = FALSE) THEN
    zyklenzahl := 0;
END_IF
so kommts mir ein bisschen übersichtlicher vor (achtung: syntax ist nicht structured text, sondern misch-masch)

Code:
if (EDGEPOS(startbutton)) then
     zyklenzahl = 0
endif

if (sensor_weg = wegmitte) then   // ist wieder auf Position die geprüft werden soll
    zyklenzahl = zyklenzahl + war_weg and startbutton
    war_weg = 0
else
    war_weg = 1    // ist weg von prüfposition, wenn er wieder drauf fährt, zählen
endif
 
Zurück
Oben