TIA Problem mit CASE-Anweisung

Hardy81

Level-2
Beiträge
126
Reaktionspunkte
8
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen,

ich steh irgendwie auf dem Schlauch und das ganz bös...

Hab in meinem Programm 3 Maschinen die nacheinander laufen sollen. Soweit so gut. Sind alle 3 Maschinen bereit, schalte ich diese mit einem Schieberegister nacheinander durch, indem ich eine "1" immer um eine Stelle weiter nach links schiebe in einem Byte (Befehl SHL).

Ist jetzt eine Maschine gestört (Störung, Hand aus, ...), soll diese nicht mehr angesteuert werden. Soweit auch noch gut.


Jetzt kommt der Punkt, an dem ich den Wald vor lauter Bäumen nicht mehr sehe... Warum funktioniert das Umschalten bei der 1. Case-Anweisung, bei der 2. aber nicht???


16#01 ist meine Schieberegisterposition für Maschine 1.
16#02 ist meine Schieberegisterposition für Maschine 3.
16#04 ist meine Schieberegisterposition für Maschine 2.

Also im Prinzip Bit .0, .1 und .2.




Die Umschaltung wird über eine Flankenauswertung (R_TRIG) angetriggert.


Das hier funktioniert ohne Probleme. Bei jedem Impuls zum Wechseln wird entweder Maschine 2 oder 3 angewählt. Maschine 1 ist nicht bereit.

Code:
   REGION KKM 1 hat Fehler
                        IF ((#I_Bereit_KKM_1 = false) AND (#I_Bereit_KKM_2 = true) AND (#I_Bereit_KKM_3 = true)) THEN
                            CASE #s_Schieberegister.Schieberegister OF
                                16#01:
                                    #s_Schieberegister.Schieberegister := 16#02;    // --> Umschalten von Maschine 1 (sollte die gestörte Maschine noch angewählt sein) auf Maschine 3
                                16#02:
                                    #s_Schieberegister.Schieberegister := 16#04;    // --> Umschalten von Maschine 3 auf Maschine 2
                                16#04:
                                    #s_Schieberegister.Schieberegister := 16#02;    // --> Umschalten von Maschine 2 auf Maschine 3
                            END_CASE;
                        END_IF;
                    END_REGION ;


Das hier, steht im gleichen Netzwerk direkt unter der 1. Case-Anweisung funktioniert nicht!?!?!?!
Maschine 1 und 3 sollten angeschaltet werden. Maschine 2 ist gestört.


Code:
                    REGION KKM 2 hat Fehler
                        IF ((#I_Bereit_KKM_1 = true) AND (#I_Bereit_KKM_2 = false) AND (#I_Bereit_KKM_3 = true)) THEN
                            CASE #s_Schieberegister.Schieberegister OF
                                16#01:
                                    #s_Schieberegister.Schieberegister := 16#02;    // --> Umschalten von Maschine 1 auf Maschine 3
                                16#02:
                                    #s_Schieberegister.Schieberegister := 16#01;    // --> Umschalten von Maschine 3 auf Maschine 1
                                16#04:
                                    #s_Schieberegister.Schieberegister := 16#02;    // --> Umschalten von Maschine 2 (gesört) auf Maschine 3
                            END_CASE;
                        END_IF;
                    END_REGION ;


Bitte nicht von der Reihenfolge der Maschinen verwirren lassen. Das ist schon ok so ;-)


Jemand ne Idee?
 
Zuletzt bearbeitet:
Welchen Wert hatte Maschine 3 nochmal, 2 richtig? ;)
Im Prinzip Jain, denn ...
16#01 ist meine Schieberegisterposition für Maschine 1.
16#02 ist meine Schieberegisterposition für Maschine 2.
16#04 ist meine Schieberegisterposition für Maschine 3.

Also im Prinzip Bit .0, .1 und .2.
Aber laut Case-Selektionen und Kommentaren ist die Maschine 2 die Maschine 3 und umgekehrt.
Bitte nicht von der Reihenfolge der Maschinen verwirren lassen. Das ist schon ok so ;-)
Das ist zwar verwirrend (nicht nur für uns, auch für den TE) aber immerhin OK. ;)
 
Unabhängig von deinem Problem
Code:
If ((#I_Bereit_KKM_1 = true) AND (#I_Bereit_KKM_2 = false) AND (#I_Bereit_KKM_3 = true)) THEN

Kann man auch viel schöner und ohne Angstklammern schreiben:
Code:
If #I_Bereit_KKM_1 AND NOT #I_Bereit_KKM_2 AND #I_Bereit_KKM_3 THEN
 
16#01 ist meine Schieberegisterposition für Maschine 1.
16#02 ist meine Schieberegisterposition für Maschine 2.
16#04 ist meine Schieberegisterposition für Maschine 3.

Hier ist tatsächlich Maschine 2 und 3 vertauscht. Habs mal geändert im 1. Post. Nach 11 Stunden ist man nicht mehr so klar im Kopf.
 
@Hardy81 Schau dir mal die Querverweise für deine Schieberegistervariable an. Ich vermute, dass sie innerhalb eines Zyklus die Variabel mehrmals überschrieben wird. Z.B. Prüfung des Maschinenzustandes, setzen des Ersatzwertes und danach evtl. nochmals das Schieben des Bits durch SHL Funktion.

Evtl. hilft dir hier auch eine Trace Aufzeichnung um die Signalverläufe zu sehen.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Unabhängig von deinem Problem
Code:
If ((#I_Bereit_KKM_1 = true) AND (#I_Bereit_KKM_2 = false) AND (#I_Bereit_KKM_3 = true)) THEN

Kann man auch viel schöner und ohne Angstklammern schreiben:
Code:
If #I_Bereit_KKM_1 AND NOT #I_Bereit_KKM_2 AND #I_Bereit_KKM_3 THEN
Kann man machen. Ich schreibs der Übersichtlichkeit wegen lieber mit Klammern...
 
Kann man machen. Ich schreibs der Übersichtlichkeit wegen lieber mit Klammern...
... und die verliert man recht schnell, wenn man's mit '= true' und mit '= false' schreibt.

Die Schiebe(Registe)rei mag manchmal vorteilhaft sein, ist hier aber nicht konsequent "ausgereizt" und vermutlich deshalb irreführend.
Was soll die Schaltung machen, wenn ...
- unmittelbar zuvor keine Maschine eingeschaltet war? Immer mit Maschine 1 beginnen oder merken, welche Maschine zuletzt aktiv war und anhängig davon die nächste aktivieren?
- was soll passieren, wenn 2 der Maschinen nicht einsatzbereit sind? Rücksichtslos immer nur die eine einsatzbereite aktivieren? Oder werden ZwangsPausen für diese eine Maschine fällig?
- wenn keine der Maschinen einsatzbereit ist? FehlerMeldung und gut is?
- die gerade aktive Maschine ausfällt? Sofort die nächste aktivieren oder warten, bis der nächste "Impuls zum Wechseln" den Wechsel einleitet?

Wichtig (wie von Michitronik schon gesagt): sobald ein Ergebnis gefunden wurde, nicht nach weiteren Ergebnissen (für die bereits veränderte Situation) weitersuchen!
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
@Hardy81 Reicht es nicht anstelle von Case jeweils in einem IF abzuhandeln?

REGION KKM 1 hat Fehler
IF ((#I_Bereit_KKM_1 = false) AND (#I_Bereit_KKM_2 = true) AND (#I_Bereit_KKM_3 = true) AND (#s_Schieberegister.Schieberegister = 16#01)) THEN
// Setzen eines Ersatzwertes für Maschine 1
#s_Schieberegister.Schieberegister := 16#02; // --> Umschalten von Maschine 1 (sollte die gestörte Maschine noch angewählt sein) auf Maschine 2
END_IF;
END_REGION

REGION KKM 2 hat Fehler
IF ((#I_Bereit_KKM_1 = true) AND (#I_Bereit_KKM_2 = false) AND (#I_Bereit_KKM_3 = true) AND (#s_Schieberegister.Schieberegister = 16#02)) THEN
// Setzen eines Ersatzwertes für Maschine 2
#s_Schieberegister.Schieberegister := 16#04; // --> Umschalten von Maschine 2 (sollte die gestörte Maschine noch angewählt sein) auf Maschine 3
END_IF;
END_REGION

REGION KKM 3 hat Fehler
IF ((#I_Bereit_KKM_1 = true) AND (#I_Bereit_KKM_2 = true) AND (#I_Bereit_KKM_3 = false) AND (#s_Schieberegister.Schieberegister = 16#04)) THEN
// Setzen eines Ersatzwertes für Maschine 3
#s_Schieberegister.Schieberegister := 16#01; // --> Umschalten von Maschine 3 (sollte die gestörte Maschine noch angewählt sein) auf Maschine 1
END_IF;
END_REGION
1625768968991.png
 
@Hardy81 Schau dir mal die Querverweise für deine Schieberegistervariable an. Ich vermute, dass sie innerhalb eines Zyklus die Variabel mehrmals überschrieben wird. Z.B. Prüfung des Maschinenzustandes, setzen des Ersatzwertes und danach evtl. nochmals das Schieben des Bits durch SHL Funktion.

Evtl. hilft dir hier auch eine Trace Aufzeichnung um die Signalverläufe zu sehen.
Danke... für den Hinweis... Es war zwar kein schreibender Zugriff der nicht gewollt ist, aber etwas sehr banales... :rolleyes:

Es kam von der fehlerabhängigen Umschaltung. D.h. wenn die aktuell aktive Maschine in Störung geht, oder nicht mehr bereit meldel, wird automatisch zur nächsten verfügbaren umgeschaltet. Das sollte man allerdings dann auch so programmieren, dass es sich auch mit anderen Sachen verträgt...

Was mal ne Nacht drüber schlafen ausmacht - noch keine 5 Minuten und der Fehler war gefunden...
 
Zuviel Werbung?
-> Hier kostenlos registrieren
... und die verliert man recht schnell, wenn man's mit '= true' und mit '= false' schreibt.

Die Schiebe(Registe)rei mag manchmal vorteilhaft sein, ist hier aber nicht konsequent "ausgereizt" und vermutlich deshalb irreführend.
Was soll die Schaltung machen, wenn ...
- unmittelbar zuvor keine Maschine eingeschaltet war? Immer mit Maschine 1 beginnen oder merken, welche Maschine zuletzt aktiv war und anhängig davon die nächste aktivieren?
- was soll passieren, wenn 2 der Maschinen nicht einsatzbereit sind? Rücksichtslos immer nur die eine einsatzbereite aktivieren? Oder werden ZwangsPausen für diese eine Maschine fällig?
- wenn keine der Maschinen einsatzbereit ist? FehlerMeldung und gut is?
- die gerade aktive Maschine ausfällt? Sofort die nächste aktivieren oder warten, bis der nächste "Impuls zum Wechseln" den Wechsel einleitet?

Wichtig (wie von Michitronik schon gesagt): sobald ein Ergebnis gefunden wurde, nicht nach weiteren Ergebnissen (für die bereits veränderte Situation) weitersuchen!
Wenn man die Klammererei mit true und false gewöhnt ist, machts nix aus.

Zu deinen Fragen...
Es wird immer die Maschine als erste gestartet, die die wenigsten Betriebsstunden hat.

Wenn zwei Maschinen nicht einsatzbereit sind, läuft zwangsläufig die dritte an. Pausen können nicht vorkommen. Es muss immer eine Maschine laufen.

Wenn keine Maschine einsatzbereit ist, haben wir ganz andere Probleme als eine einfache Fehlermeldung.

Wenn eine Maschine ausfällt, die gerade aktiv ist, wir automatisch zur nächsten umgeschaltet.


Das ist im Code, nicht zu sehen, da das nur ein kleiner Ausschnitt dessen ist, was ich hier am programmieren bin. Den kompletten Code zu posten würde den Rahmen sprengen.
 
... führt aber dazu das bei allen Maschinen die Verschleißgrenze relativ gleichzeitig erreicht wird.

Wenn keine Maschine einsatzbereit ist, haben wir ganz andere Probleme als eine einfache Fehlermeldung.

Ebendrum sollte man sich schon frühzeitig Gedanken machen, wie der "Plan B" aussehen soll und, was man tun könnte, damit "Plan B" möglichst selten erforderlich wird.
 
Es wird immer die Maschine als erste gestartet, die die wenigsten Betriebsstunden hat.
Abweichend von dieser Vorgabe habe ich's mal mit SchiebeRegister und LOGO umgesetzt.
BetriebsStunden werden nicht ermittelt und können somit auch nicht berücksichtigt werden.

Der Inhalt des SchiebeRegisters ist "remanent", so dass immer der jeweils nächste bereite Motor gestartet wird ...
- beim Einschalten (I4)
- mit dem Aggregate-Wechsel-Impuls (der z.Z. alle 4 s erfolgt - mit Rücksicht auf ungeduldige Tester/Simulanten ;o)
- wenn die Freigabe eines laufenden Motors wegfällt (I1..I3).

Zum SchiebeRegister:
Ist Bit-0 = 0 und Bit-1 = 0, dann wird 'true' am seriellen Eingang angelegt, so dass beim nächsten Schiebe-Impuls eine '1' "eingesogen" wird.
Es ist also egal, welchen Inhalt das SchiebeRegister anfangs hat. Nach spätestens zwei Schiebe-Impulsen hat - wie gewünscht - immer genau 1 der 3 Bits Bit-0 .. Bit-2 den Zustand '1'. Bei der LOGO heissen bzw. sind diese 3 Bits die Blöcke S1.1, S1.2 und S1.3.
Jedem dieser 3 Bits ist je ein Motor fest zugeordnet.
Gibt das SchiebeRegister vor, einen nicht betriebsbereiten Motor anzuwählen, so wird dies erkannt (B003, B004, B005 und B009) und damit ein extra "Such-Impuls" gebildet und dem SchiebeRegister "zugeführt". Somit wird also ein nicht betriebsbereiter Motor bei der Auswahl übersprungen.

Damit in der "SuchPhase" noch kein (neuer) Motor angesteuert wird, gibt es für jeden Motor eine EinschaltVerzögerung (B017, B018 und B019).
Damit ein noch aktiver Motor während der SuchPhase weiterhin aktiv bleibt, wird sein "EIN-Zustand" in einem RS-FF gespeichert (B022, B023 und B024). Rückgesetzt wird ein RS-FF erst durch das Setzen eines der beiden anderen.
Ein RS-FF kann also gesetzt bleiben, wenn kein anderes gesetzt wird, weil der entsprechende Motor nicht betriebsbereit ist.
Auch wenn keiner der drei Motoren betriebsbereit ist, bleibt das zuletzt aktive RS-FF gesetzt.
Dies ist zwar nicht erwünscht aber "harmlos", da die Zustände der RS-FFs noch mit den Freigaben für die Motoren verUNDet werden und dann erst auf die Ausgänge Q1 .. Q3 gelangen.
Damit nach dem WiederEinschalten per I4 nicht der zuletzt gelaufen habende Motor nochmal kurz gestartet wird, wird das Anlaufen aller Motoren durch die EinschaltVerzögerung (B032) kurzzeitig unterbunden.

Wenn keine Maschine einsatzbereit ist, haben wir ganz andere Probleme als eine einfache Fehlermeldung.
Deshalb habe ich statt einer simplen FehlerMeldung einen dreistufigen Alarm spendiert. Nicht genug damit. diesen Alarm sogar in drei verschiedenen Varianten umgesetzt:
a) für jede der 3 AlarmStufen einen eigenen Ausgang (Q4 .. Q6)
b) einen BlinkAusgang (Q7), der je nach AlarmStufe unterschiedlich blinkt (benutzt die Dekodierung von a).
c) die Nummer der AlarmStufe wird gebildet (B016) und könnte numerisch (oder als Balken) angezeigt werden.

Übrigens werden die betriebsbereiten Motoren "gezählt", indem die drei Signale von I1 .. I3 auf die drei Eingänge eines "VollAddierers" geschaltet werden. Die beiden Ausgänge des VA stellen dann die Anzahl als BinärZahl dar.
Schliesslich wird noch die Anzahl der nicht betriebsbereiten aus der Zahl der betriebsbereiten gebildet
- durch Negation an den Eingängen der DekodierBlöcke (B020, B021 und B031) bzw.
- durch die "umgekehrte" Belegung der Parameter des MUX-Blocks (B016).

1von3-3.jpg
Nach dem Herunterladen der pdf-Datei im Explorer '.pdf' entfernen (per umbenennen)!
 

Anhänge

Zurück
Oben