FB Aufruf Pointer auf globale Variable Codesys

Yojimbo

Level-1
Beiträge
5
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo! Da ich trotz intensiven Recherche im Forum keine Lösung für mein Problem finde, möchte ich euch um eure Hilfe bitten.
Vorweg möchte ich erwähnen, dass ich mich im Rahmen meines Studiums erst seit kurzem mit SPSen beschäftige und keinerlei Vorkenntnisse hatte. Das erwähne ich nur, falls ich allzu triviale Fragen stellen sollte :)

Ich habe mehrere Rollenförderer, deren Aktoren und Sensoren im Programm als globale Variablen vorliegen und schon adressiert sind.
Ich möchte einen universellen FB für diese Förderer schreiben und diese beim Aufruf durch das Programm von außen vollständig parametrieren. Dazu müssen zwei Sensoren, ein Motor und eine Zustandsvariable übergeben werden. Mittels der Zustandsvariable wird im FB über eine CASE Anweisung festgelegt, welche Aktion der FB ausführen soll. Das ganze habe ich auch schon programmiert, nur dass ich jetzt daran scheitere, dass das Stellsignal für den Motor nicht aus dem FB "rauskommt". Ich hab versucht das über VAR_IN_OUT zu realisieren, musste aber nach kurzer Recherche einsehen, dass das anscheinend nicht ganz trivial ist. Über VAR_OUT möchte ich das auch nicht realisieren, da letztlich alles im inneren des FB ablaufen soll, so dass ich in meinem Programm nur hintereinander die FB instanziieren und mit den Sensoren/Aktoren sowie der Zustandsvariable füttern möchte.

Wie bekomme ich das am besten hin? Ich vermute, dass ich das mit Pointern lösen könnte, doch da scheitere ich kläglich dran. Ich konnte bisher noch keine gute Erklärung dazu finden :(

Ich arbeite mit Codesys V2.3 und die SPS ist von WAGO.
Hier das ganze mal beispielhaft:

Code:
[FONT=courier new]Aufruf des FB Band im Programm:

Band1(Sensor1:=T1Sensor1, Sensor2:=T1Sensor2, Zustand:=1, Motor:=T1Bandmotor)       Sensoren und Aktoren liegen als boolsche globale Variablen vor


Variablendeklaration FB:

VAR_INPUT
Sensor1: BOOL;
Sensor2: BOOL;
Zustand: INT;
    ?????  wie deklariere ich den Motor, so dass das Stellsignal den den Motor rausgeht? 
END_VAR
[COLOR=#FFFFFF]
[/COLOR]IF Sensor1=TRUE OR Sensor2=TRUE AND....    Das ist jetzt nur beispielhaft der Inhalt des FB. Wie würde ich das mit Pointern realisieren?
THEN Motor:=TRUE;
ELSE Motor:=FALSE;
END_IF;[/FONT]
Ich hoffe ich konnte mein Problem halbwegs gut veranschaulichen und würde mich über Hilfe sehr freuen.

Beste Grüße
 
Das Stellsignal für den Motor ist ein einfaches Bool (An/Aus)? Dann verstehe ich nicht warum du kein Var_OUT nutzen möchtest. Das Signal für den Motor musst du ja so oder so ausgeben.

Du kannst das ganze natürlich auch mit Pointern lösen. Aber dann musst du trotzdem noch die Adressen der Variablen in den FB übergeben. Damit würdest du in deinem Fall nichts gewinnen. Ganz im Gegenteil sogar. Pointeroperationen können im schlimmsten Fall gehörig daneben gehen und dir dein Programm an Stellen zerschießen wo du überhaupt nicht mit rechnest.

Bsp. mit Pointern:

Code:
var_input
  Sensor1 :Pointer TO Bool;
  Sensor2 :Pointer TO Bool;
  Motor :Pointer to Bool;
end_var

if Sensor1^ OR Sensor2^ .....  then
  Motor^ := true;
ELSE
  Motor^:= false;
END_IF


Bausteinaufruf

Band(Sensor1 := ADR(T1Sensor1), Sensor2 := ADR(T1Sensor2), Zustand := 1, Motor := ADR(T1Motor));
Bringt also nicht wirklich was in deinem Fall.

Du du wirklich alles kapseln willst, kannst du die Hardware EAs auch im FB direkt deklarieren. Dann würdest du mit jeder neuen Instanz des Band FBs einen neuen Satz EA Variablen bekommen, die du dann noch mit der Hardware verknüpfen müsstest. So mache ich das z.B. wenn ich in sich geschlossene Funktionsgruppen erstelle, die nur über Befehls- und Statusdaten mit dem Rest des Programms kommunizieren. Ich bin kein großer Fan von globalen Variablen...
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Danke für deine Antwort!

Das Stellsignal für den Motor ist ein einfaches Bool. VAR_OUT wollte ich nicht nutzen, weil ich wollte, dass alles direkt im FB abläuft. Wenn da noch eine Variable "rauskommt", müsste ich die ja noch im Programm weiterverarbeiten. Oder verstehe ich da jetzt was grundsätzlich falsch?
Im FB selber wollte ich nichts direkt deklarieren, weil ich nur beim Aufruf die nötigen globalen Variablen übergeben und im FB selber nichts verändern wollte. Ich muss leider globale Variablen benutzen, weil die in einem Basisprogramm schon fertig deklariert und die entsprechenden Ein- und Ausgängen adressiert sind. außerdem traue ich mir das auch nicht selber zu, da was selber zu adressieren, weil es knapp 70 Sensoren und Aktoren sind und ich fürchte, dass mich das überfordert.

Mein eigentliches Problem ist ja nur, dass ich dem FB irgendwie sagen muss, an welchen Motor er sein Stellsignal ausgeben soll und das direkt beim Aufruf des FB. Da dachte ich, dass das mit einem Pointer auf den Motor am einfachsten gehen würde. Die Sensoren kann ich ja ganz normal übergeben. Nur mit dem Motor ist das irgendwie tricky. Gibt es da ein elegantere Lösung, wenn ich die strikte Kapselung meines FB beibehalten und diesen nur von außen mit Variablen füttern möchte?

Beste Grüße!
 
Also du hast für jeden Motor die EA Signale global deklariert?

Code:
T1Sensor1 AT%I*:BOOL;
T1Sensor2 AT%I* :BOOL;
T1Motor AT%Q* :BOOL;

T2Sensor1 AT%I* :BOOL; 
.... usw usf.

Ich verstehe immernoch nicht so genau was dich jetzt daran stört die Ausgangsvariable für den Motor auf ein VAR_OUT deines FBs zu legen.
Du erstellst ja für jeden Motor eine Instanz deines Band FBs. Jede Instanz musst du aufrufen. Beim Aufruf übergibst du dann einfach die Variablen.

Code:
Band1(Sensor1 := T1Sensor1, Sensor2 := T1Sensor2, Motor => T1Motor);
Band2(Sensor1 := T2Sensor1, Sensor2 := T2Sensor2, Motor => T2Motor);

Oder willst du mehrere Motoren mit einer Instanz deines FBs steuern oder die Motoren dynamisch dem FB zuweisen?
 
Ah ok. Ich hatte bisher das Problem, dass ich nicht wusste, wie ich den entsprechenden Motor an den FB übergebe und dann das Signal an diesen Motor aus dem FB wieder raus bekomme. Daher dachte ich zuerst an VAR_IN_OUT, was dann aber auch wieder nicht geklappt hat. Bei VAR_OUT dachte ich bisher immer, dass ich da dann ein Signal aus dem FB erhalte, welches noch weiter mit dem Motor verknüpft werden müsste. Dass das mit diesem Pfeilchen im FB Aufruf geht, war mir nicht bekannt.
Mit deiner Lösung wird also das Stellsignal für Motor an T1 Motor übergeben? Also muss ich im FB nur Motor als VAR_OUT deklarieren? Das wäre eine feine Sache.

Ich muss noch mal ausdrücklich darauf hinweisen, dass ich mich erst seit kurzer Zeit mit SPS Programmierung beschäftige. Das entschuldigt hoffentlich meine dummen Fragen :D
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich hab wieder eine Frage. Diesmal geht es um Timer.

Code:
VAR_INPUT    Sensor1: BOOL;
    Sensor2: BOOL;
END_VAR
VAR_OUTPUT
    Motor: BOOL;
END_VAR
VAR
    Status: INT;
    Timer: TOF;


END_VAR

IF Sensor1=TRUE AND Sensor2=FALSE THEN Status:=1        (*Werkstück kommt auf Band*)
END_IF;


IF Sensor1=TRUE  AND Sensor2=TRUE THEN Status:=2        (*Werkstück liegt mittig auf Band*)
END_IF;


IF Sensor1=FALSE AND Sensor2=TRUE THEN Status:=3        (*Werkstück verlässt Band*)
END_IF;


CASE Status OF


0:    Motor:=FALSE;


1:      Motor:=TRUE;


2:     Motor:=TRUE;


3:    Timer( IN:=TRUE, PT:=T#5s, Q:=Motor);                        (* Band schaltet sich nach 5s aus und schaltet zurück in Status 0*)
    Status:=0;


END_CASE;

Ich möchte dass das Förderband die drei Zustände anhand der Sensoren erfasst und den Motor entsprechend schaltet. Im dritten Zustand möchte ich, dass das Band noch 5s Nachlauf hat, den Zustand des Bandes zurücksetzt und dann ausgeht. Nur mag das nicht so recht funktionieren. Ich hab die Forensuche schon bemüht, werde aus Timern aber immer noch nicht schlau.
Könnt ihr mir noch mal helfen? :)
 
Der Ansatz ist doch garnichtmal so schlecht.


  1. Wenn du eine Schrittkette mit einem CASE realisierst, kannst du den Schrittzähler (Status) auch in der CASE-Verzweigung setzen.
  2. In Schritt 3 setzt du den Schrittzähler sofort auf 0 ohne auf den Timer zu warten.
  3. Der Timer muss irgendwo auch zurückgesetzt werden, sonst läuft er nur einmal ab.

Ein mögliches Beispiel:

Code:
Timer :TON;   (*Anstatt des von dir verwendeten TOF*)

CASE Status OF

0:  Motor := FALSE;
     IF Sensor1 THEN    (*Ob man hier Sensor2 auch abfragen sollte wäre zu diskutieren. Für eine Fehlerfall-Erkennung wäre es sicher sinnvoll.*)
        Status := 1;
     END_IF

1:  Motor := TRUE;
     IF Sensor2 THEN    (*Hier das gleiche mit Sensor1. Eigentlich muss er nicht abgefragt werden, weil die Transitionsbedingung ja von Sensor2 abhängt.*)
        Status := 2;
     END_IF

2:  Motor := TRUE;  (*Ansichstsache ob man hier nochmal den Befehl setzen sollte oder nicht. Motor ist aus dem vorherigen Schritt bereits TRUE.*)
     IF NOT Sensor1 THEN (*Hier wieder das gleiche Spiel, zum Weiterschalten ist eigentlich nur die Information von Sensor1 von Interesse.*)
       Status := 3;
     END_IF

3:  Timer.IN := TRUE;
     IF Timer.Q THEN  (*Timer löst aus*)
       Status := 0;
       Motor := FALSE;   (*Ob man hier den Motor schon auf FALSE setzt oder das einfach dem Schritt 0 überlässt,  hängt davon ab ob man noch einen Zyklus abwarten kann.*)
       Timer.IN := FALSE;  (*Timer zurücksetzen*)
     END_IF
     Timer(PT := t#5s);  (*Aufruf der Timer-Instanz*)

END_CASE

Wie gesagt nur eine mögliche Lösung.
Bei den Transistionen habe ich immer nur die Sensor-Variablen abgefragt die vom logischen Ablauf her von Belang sind. Du kannst natürlich auch beide Sensoren abfragen um damit ungewollte Zustände der Anlage zu erfassen und zu verarbeiten.
 
Super! Das hat mir sehr geholfen. Vielen Dank! Die lange Antwortzeit ist der Ermangelung an Internet geschuldet :D
 
Zurück
Oben