TIA One shot Funktionalität

Fabster

Level-2
Beiträge
35
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Moin Zusammen,
Ich habe wieder mal ein keines Problem beim Programmieren.

Erst mal mein Setting:
- CPU 1514SP-2 PN
- IM 155-6 PN ST (verbunden zur CPU über Profinet)

Mein Problem:
Ich habe drei LMQTT Clients in meinem Programm, diese haben einen valid Ausgang welcher sobald der Client verbunden ist auf TRUE schaltet.
Nun möchte ich sobald alle drei Clients verbunden sind (also alle drei Ausgänge valid auf TRUE sind) eine Nachricht senden. Jedoch soll die nachricht nur einmal gesendet weden (praktisch als Initialsierung). Die Nachricht kann erst wieder gesendet werden sobald einer (oder alle im Normalfall) der valid-Ausgänge an den Clients auf FALSE sind.

Aktuell ist es so (allerdings wird hier in jedem Zyklus geschickt, was natürlich nicht sein soll):
Latch_Set ist die Abfrage ob alle der drei Ausgänge valid sind
Output schaltet den Ausgang (ist eine InIOut variable)
latch_global war ein Test mit einer Variable die den Zustand speichern soll

Code:
#Output := FALSE;

#LatchSet := (#PUB_valid AND
#SUB_valid AND
#PUB_MISC_valid);

IF #LatchSet AND NOT #Latch_global THEN
    #Output := TRUE;
    #Latch_global := TRUE;
END_IF;

IF NOT #PUB_valid OR NOT #SUB_valid OR NOT #PUB_MISC_valid THEN
    #Output := FALSE;
    #Latch_global := FALSE;
END_IF;

Vielen Dank schon mal!
Fabi
 
Du könntest dir merken, dass die Nachricht bereits gesendet wurde, und die Merkvariable zurücksetzen, sobald nicht alle 3 Ausgänge True sind.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich hätte mal versucht, das Output-Signal nicht in der IF-Abfrage zu setzen.

Code:
#LatchSet := (#PUB_valid AND
#SUB_valid AND
#PUB_MISC_valid);

#Output := #LatchSet AND (NOT #Latch_global);

#Latch_Global := #LatchSet;

Dann brauchst du Output auch nicht als InOut deklarieren, sondern kannst einen einfachen Output daraus machen. Einzig Latch_global müsste irgendwie gespeichert sein (InOut, Static, DB).
 
Hey,
vielen Dank schon mal für eure Tipps!
Ich habe es jetzt mit Output als reiner Out und mit Latch_global als InOut getestet und noch weiter rumprobiert weil es noch nicht funktioniert.
Habe es jetzt so:

Code:
#Output := FALSE;

#LatchSet := (#PUB_valid AND
#SUB_valid AND
#PUB_MISC_valid);

IF NOT "Latch_global" AND #LatchSet THEN
    "Latch_global" := TRUE;
    #Output := TRUE;
ELSIF #LatchSet AND "Latch_global" THEN
    #Output := FALSE;
END_IF;

IF NOT #LatchSet THEN
    "Latch_global" := FALSE;
END_IF;

Ich weiß nicht ob latch_global geändert wird, habe es nun auch mit einem Merker als Latch_global probiert, wird aber auch jeden Zyklus gesendet.


1721019941664.png
 
Also Output soll das Senden der Nachricht anstoßen. Ich bringe aktuell einfach diese One Shot Sache nicht hin, so dass nur ein mal die Nachricht versendet wird.
 
Aber das ist doch genau das, wofür Latch_global da ist?

Ich dachte, in Latch_global soll gespeichert werden, dass die Nachricht gesendet wurde. Daher auch mein Programmbeispiel in Beitrag #3.

Ich habe als dritte Abfrage AND NOT #Output
Da der "Trigger" ja noch nicht gesetzt sein darf zu dem Zeitpunkt
Da du zu Anfang deines Bausteins #Output jedes Mal auf False setzt, kannst du dir die Abfrage aber sparen...
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Aber das ist doch genau das, wofür Latch_global da ist?

Ich dachte, in Latch_global soll gespeichert werden, dass die Nachricht gesendet wurde. Daher auch mein Programmbeispiel in Beitrag #3.


Da du zu Anfang deines Bausteins #Output jedes Mal auf False setzt, kannst du dir die Abfrage aber sparen...
Danke, jetzt hat es funktioniert, sorry für die Verwirrung! ich hatte das Output := FALSE noch drin. Tut mir Leid. Danke für eure Hilfe!
 
Hier noch dran denken.. da gibts im Systemmerkerbyte die Variable "FirstScan".. so als Hinweis!
Alternativ, wenn du aus irgendwelchen Gründen keine (System-)Merker verwenden möchtest, kannst du im OB100 ein Bit setzen (Anlauf), das dann am Ende von OB1 wieder rückgesetzt wird.

So würde mein Code dann mit Restart-Info aussehen.

Code:
#LatchSet := (#PUB_valid AND
#SUB_valid AND
#PUB_MISC_valid);

#Output := #LatchSet AND (NOT #Latch_global);

#Latch_Global := #LatchSet AND (NOT #Restart);

Kurze Erklärung: #LatchSet bleibt wie zuvor, ebenso #Output. Die Änderung bei #Latch_global sorgt dafür, dass bei Neustart und sofortiger Validität der Eingänge trotzdem ein Zyklus lang #Output auf True geht, nämlich im zweiten Zyklus nach Neustart. Voraussetzung dafür ist aber, dass #Latch_global remanent ausgeführt ist, sonst hast du potenziell zwei Zyklen lang einen Schreibbefehl. (Nämlich wenn bei SPS-Neustart sofort die Validität der Eingänge vorhanden ist, aber #Latch_global wegen fehlender Remanenz noch false ist.
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Also ich muss das Thema leider nochmal aufmachen.
Das Problem ist folgendes, wenn ich die CPU in Stop und anschließend wieder in start wird der output kurz ausgelöst, was richtig ist.
Jetzt geht es jedoch weiter und ich möchte eine MQTT Nachricht versenden über diesen Output, aber das Senden funktioniert nicht.
 
Ist es ein Problem mit deinem Senden oder mit der "One-Shot"-Funktion? In meinem Beitrag #14 hatte ich ein paar Sachen zum Thema Restart geschrieben, hattest du dir das noch angeschaut?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Sorry.
Also ich verwende TIA Portal V18 und die LMQTT Bausteine von Siemens.
Ich sende einen JSON Bytestream.

Die One shot funktionalität funktioniert wunderbar, soweit ich das sehen kann.

Das Probelm (reine Vermutung) wenn ich in die LMQTT Blocks beobachte dann sind die valid-Augänge auf TRUE und ändern sich auch nicht, das heißt, auch wenn der LMQTT Block noch nicht verbunden ist (zum Broker) wird der oneShot ausgeführt, weshalb auch keine Nachricht ankommt (logischerweise).

Neitrag #14 habe ich implementiert ja, aber das Problem jetzt ist ein anderes glaube ich.

Die LMQTT Blocks senden Daten bei Veränderung der I/Os welche ich in anderen Blocks überwache. Heißt ich triggere den JSON_Serializer und anschließend LMQTT aus anderen Blocks heraus.
 
Schau mal das du die neueste Version verwendest:

Valid hat erst mal nicht viel zu heißen.. das ist nur eine Rückmeldung dass zumindest die Parameter etc in Ordnung scheinen.
Im Statuswort hast du eine genauere Info.. undzwar 16#7004 = Client ist verbunden
 
So werte ich bei mir aus, ob der Client verbunden ist:
Code:
#tempReady := #constBOOL;

IF (NOT #ioInterface.Out.Error) AND (#ioInterface.Out.Status = "MQTT_STATUS_CONNECTED") THEN
    #tempReady := 1;
ELSE
    #tempReady := 0;
END_IF;
Screenshot 2024-07-17 093716.png
 
Zurück
Oben