Möglichkeit eine Funktion nur einmal auszuführen ?

Pneumatik

Level-2
Beiträge
46
Reaktionspunkte
1
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich versuche(muss) mich gerade an einem Beispiel von Siemens an Simatic ranzutasten.
Mein Prof (arbeite als studentischer Mitarbieter) will, dass ich ein SMS Modul für eine Hochregallager programmiere. Dies soll Fehlermeldungen und Statusmeldungen per SMS senden.
Simatic ist vollkommen neu für mich .. und überfordert mich ehrlich gesagt.

Beim Start soll ja erstmal die Anmeldung im GSM Netz durchgeführt werden.
Das Ganze soll natürlich nur einmal durchgeführt werden.

Hardware:
CPU315-2 DP
CP341

Software:
Step7 5.3

Meine Überlegung (welche bisher nicht funktioniert ^^) ist folgende:

Zuerst habe ich mittels Infos aus dem Forum 2 Merker im OB100 definiert die jeweils immer 0 und 1 sind.
Code:
U „always_false“
R „always_false“

UN “always_true”
S”always_true”

Dann habe ich einen Merker für die Anmeldung im OB 100 auf 0 gesetzt.
Code:
U „always_false“
U “always_true“
=”Modem_anmeldung”

Im OB 1 wird nun folgendes aufgerufen:
Code:
U “Modem_anmeldung“ // Modem_anmeldung UND always_true =1 dann Jump
U “always_true“
SPB jump

Call „GSM_anmeldung“ // Funktion zum Anmdelden im GSM Netz

Jump: NOP 0
UC  „SEND“
UC  “RECV“

Wo ist mein Denkfehler ? Wie gesagt STEP7 und SPS ist vollkommen neu für mich und bis auf ein bisschen Erfahrungen mit C bin ich auch kein erfahrener Programmierer 

Schonmal Danke im vorraus :)

Fehler wie Groß- und Kleinschreibung oder Rechtschreibfehler im Code bitte nicht beachten ... der Rechner an dem ich programmiere hat kein Internet .. dementsprechend ist der Code nur abgetippt und stimmen im echten Code wahrscheinlich.
 
Zuletzt bearbeitet:
Code:
U „always_false“
R „always_false“
 
UN “always_true”
S”always_true”
Das ist OK
Dann habe ich einen Merker für die Anmeldung im OB 100 auf 0 gesetzt.
Code:
U „always_false“
U “always_true“
=”Modem_anmeldung”
Umsonst
Code:
Im OB 1 wird nun folgendes aufgerufen:
[CODE]
U “Modem_anmeldung“ // Modem_anmeldung UND always_true =1 dann Jump
U “always_true“
SPB jump
 
Call „GSM_anmeldung“ // Funktion zum Anmdelden im GSM Netz
 
Jump: NOP 0
UC  „SEND“
UC  “RECV“
OB 1 ändern in
Code:
     U ”always_true”
     SPBN Jump
     Call „GSM_anmeldung“ // Funktion zum Anmdelden im GSM Netz
Jump: U ”always_true”
     R ”always_true”
Falls Du "always_true" wirklich als immer "High" verwenden willst erzeuge im OB100 einen separten Merker für den Anlauf.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Eigentlich reicht es, wenn du im OB100 fpr das Setzen von ”Modem_anmeldung” schreibst:

Code:
U “always_true“
=”Modem_anmeldung”

U „always_false“

ist Unsinn, da das ja immer False ist, also wird dein Merker

=”Modem_anmeldung”

gar nicht gesetzt.

Du solltest aber auc die Möglichkeit zulassen, die Anmeldung z.Bsp. von einem HMI aus anzustoßen, denn der OB100 wird ja nur beim Anlauf der SPS 1 Mal bearbeitet. Was machst du, wenn zwischendurch das GSM-Modul mal ausgeschalten wird, dann müßtest du die SPS in Stop und wieder Run schalten. Also noch einen Merker, der dann über das Panel geschalten werden kann.
 
Danke für die schnelle Antwort.

Leider wird jetzt aber GSM Anmeldung übersprungen ..

Mein Code lautet jetzt:

OB100:
Code:
      U     "always_false"
      R     "always_false"

      UN    "always_true"
      S     "always_true"

OB1:
Code:
//   U     "always_false"
//   R     "always_false"

//   UN    "always_true"
//   S     "always_true"

      U     "always_true"
      SPBN  jump
      CALL  "GSM_Anmeldung"
jump: U     "always_true"
      R     "always_true"
      UC    "SEND"                      //Call of FC for executing P_SND_RK -Jobs
      UC    "RECV"                      //Call of FC for executing RCV   -Jobs

Abgeshen davon, dass es noch nicht ganz funktioniert kann ich momentan auch noch nicht erkennen an welcher Stelle dafür gesorgt wird, dass "GSM_Anmeldung" nur einmal ausgeführt wird ?
Hab ich was falsch verstanden ?
 
Dein Programm hat den Fehler:

U "always_true" // Wenn hier VKE = 0 wird weggesprungen
SPBN jump
CALL "GSM_Anmeldung"
jump: U "always_true"
R "always_true"

Nach dem ersten Druchlauf wird der Merker auf Null gesetzt und dann wird immer weggesprungen.
Außerdem ist der Merker schlecht bezeichnet.
Allways true sollte immer 1 sein, als immer gesetzt aber nie zurück gesetzt werden.


bike
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Eigentlich reicht es, wenn du im OB100 fpr das Setzen von ”Modem_anmeldung” schreibst:

Code:
U “always_true“
=”Modem_anmeldung”

U „always_false“

ist Unsinn, da das ja immer False ist, also wird dein Merker

=”Modem_anmeldung”

gar nicht gesetzt.

Du solltest aber auc die Möglichkeit zulassen, die Anmeldung z.Bsp. von einem HMI aus anzustoßen, denn der OB100 wird ja nur beim Anlauf der SPS 1 Mal bearbeitet. Was machst du, wenn zwischendurch das GSM-Modul mal ausgeschalten wird, dann müßtest du die SPS in Stop und wieder Run schalten. Also noch einen Merker, der dann über das Panel geschalten werden kann.

Auch dir Ralle Danke ;-)

Aber wird durch:
Code:
U “always_true“
=”Modem_anmeldung”
nicht der Merker ”Modem_anmeldung” auf 1 gesetzt ? Das soll doch erst passieren, wenn die Funktion „GSM_anmeldung“ einmal durchgelaufen ist ?


Zum 2ten Punkt: Du hast vollkommen recht, später sollte das auf jedenfalls auch über ein Interface per Hand neuinitialisierbar sein.
Ich müsste aber doch dann eigentlich den "always_true" Merker recht einfach durch einen geschalteten Eingang ersetzen können oder ?
 
Dein Programm hat den Fehler:

U "always_true" // Wenn hier VKE = 0 wird weggesprungen
SPBN jump
CALL "GSM_Anmeldung"
jump: U "always_true"
R "always_true"

Nach dem ersten Druchlauf wird der Merker auf Null gesetzt und dann wird immer weggesprungen.
Außerdem ist der Merker schlecht bezeichnet.
Allways true sollte immer 1 sein, als immer gesetzt aber nie zurück gesetzt werden.


bike

Mans seit ihr schnell ...
und ja eigentllich sollte "always_true" immer 1 sein.. das war zumindest meine Intention am Anfang. Für die Idee von Paule wäre das aber nicht so und ich würde den Merker dementsprechend später umbennenen, falls ich mit der Variante zum Erfolg gelange ^^.

Zur Sache mit dem VKE .. ich habe mir jetzt 2 Bücher gekauft die ich nebenbei versuche durchzuarbeiten. Aber mir ist noch nicht so richtig klar was das Verknüpfungsergebniss ist.
 
Mans seit ihr schnell ...
und ja eigentllich sollte "always_true" immer 1 sein.. das war zumindest meine Intention am Anfang. Für die Idee von Paule wäre das aber nicht so und ich würde den Merker dementsprechend später umbennenen, falls ich mit der Variante zum Erfolg gelange ^^.

Zur Sache mit dem VKE .. ich habe mir jetzt 2 Bücher gekauft die ich nebenbei versuche durchzuarbeiten. Aber mir ist noch nicht so richtig klar was das Verknüpfungsergebniss ist.

Das VKE ist das Ergebnis aller Verknüpfungen, die nach der letzten Zuweisung bis zur nächsten Verknüpfung programmiert sind. Das VKE ist NICHT abhängig von Netzwerk oder Bausteingrenze!
Bei U muss das Signal 1, bei UN muss das Signal 0 sein, damit das VKE 1 wird.


bike
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Mans seit ihr schnell ...
und ja eigentllich sollte "always_true" immer 1 sein.. das war zumindest meine Intention am Anfang. Für die Idee von Paule wäre das aber nicht so und ich würde den Merker dementsprechend später umbennenen, falls ich mit der Variante zum Erfolg gelange ^^.
Genau, das meinte ich ja mit einem separatem Merker für den Anlauf.
Abgeshen davon, dass es noch nicht ganz funktioniert kann ich momentan auch noch nicht erkennen an welcher Stelle dafür gesorgt wird, dass "GSM_Anmeldung" nur einmal ausgeführt wird ?
Hab ich was falsch verstanden ?
Ich erkenne jetzt da keinen Fehler.
Deshalb mal die "Wegbeschreibung" in Worten (wobei das oft verwirrender ist).
> Im OB100 wird ein Merker (in diesem [noch] Fall "always_true" auf High gesetzt wenn er den Zustand Low hatte.
> Im OB1 wird im ersten Zyklus der Sprung nicht ausgeführt da der Merker High ist (Springe nur bei Low), also wird "CALL GSM_Anmeldung" ausgeführt.
> anschließend wird der Merker auf Low gesetzt.
> im nächsten Zyklus ist der Merker immer noch Low (bis zum nächsten Neustart) und deshalb wird über die CALL Anweisung gesprungen.
 
Genau, das meinte ich ja mit einem separatem Merker für den Anlauf.
Umso besser :)

Ich erkenne jetzt da keinen Fehler.
Deshalb mal die "Wegbeschreibung" in Worten (wobei das oft verwirrender ist).
> Im OB100 wird ein Merker (in diesem [noch] Fall "always_true" auf High gesetzt wenn er den Zustand Low hatte.
> Im OB1 wird im ersten Zyklus der Sprung nicht ausgeführt da der Merker High ist (Springe nur bei Low), also wird "CALL GSM_Anmeldung" ausgeführt.
> anschließend wird der Merker auf Low gesetzt.
> im nächsten Zyklus ist der Merker immer noch Low (bis zum nächsten Neustart) und deshalb wird über die CALL Anweisung gesprungen.
Ich habe gerade rausgefunden, dass wenn ich das "UC RECV" auskommentiere alles so funktioniert wie es soll.
Momentan verstehe ich zwar noch nicht warum, aber das ist ein Problem für Donnerstag (nächtser Arbeitstag :)).

Ich bin mal gespannt wie das mit mir uns SPS endet ^^ ich schwanke immer zwischen Wohlwollen und Flüchen.

Naja auf jedenfalls erstmal vielen Dank! .. dank euch kann ich jetzt guten Gewissens Feierabend machen.
 
Richtimpuls Neustart-Wiederanlauf-Kaltstart

Hallo Allerseits,

mal einen ganz anderen Ansatz für dieses Problem.Bei jedem Start eines OB`s werden im Lokaldatenstack des OB`s 20 Byte Informationen bzgl.des Startereignis hinterlegt.Im OB1 gibt es eine Lokale Variable (OB1_Scan_1) die folgende Informationen haben kann.

Länge 1 Byte

B#16#01: Abschluss des Neustarts
B#16#02: Abschluß des Wiederanlaufs
B#16#03: Abschluß des freien Zyklus
B#16#04: Abschluß des Kaltstarts
B#16#05: Erster OB 1-Zyklus der neuen Master-CPU nach Master-Reserve-Umschaltung und STOP des bisherigen Masters.

Durch Abfrage der Variable mittels eines Vergleichers läßt sich nun ein ein Impuls generieren



Code:
// Netzwerk Richtimpuls Neustart im OB1

l #OB1_Scan_1    //Lokale Variable LB2
l b#16#1            // Vergleichswert Neustart     
==I                   //Abfrage auf Gleichheit
= `Neustart`      // Richtimpuls Neustart, 1= erster OB1 Zyklus


// Netzwerk Richtimpuls Wiederanlauf im OB1

l #OB1_Scan_1    //Lokale Variable LB2
l b#16#2            // Vergleichswert Wiederanlauf
==I                   //Abfrage auf Gleichheit
= `Wiederanlauf`// Richtimpuls Wiederanlauf, 1= erster OB1 Zyklus


// Netzwerk Richtimpuls Kaltstart im OB1
 
 l #OB1_Scan_1    //Lokale Variable LB2
 l b#16#4            // Vergleichswert Kaltstart  
 ==I                   //Abfrage auf Gleichheit
 = `Kaltstart`      // Richtimpuls Kaltstart, 1= erster OB1 Zyklus
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich habe gerade rausgefunden, dass wenn ich das "UC RECV" auskommentiere alles so funktioniert wie es soll.

Warum verwendest du UC?
Kann es sein, dass der Aufruf nicht zyklisch sein darf?
Dass auf ein Result gewartet werden muss?
Ist dies ein Baustein aus der Bibliothek von BigS?


bike
 
@Bernard:
danke für den Vorschlag, habs aber noch nicht getestet und kann somit nicht sagen ob es funtkioniert. Ehrlich gesagt verwirrt mich dieses direkter adressieren von Bits und Bytes auch etwas.

@bike
ja das ist ein Teil des Siemens Beispielprogramms.
In diesem wurde "Send" und "Recv" glaube ich auch zyklisch mit "UC" aufgerufen.
Das werde ich aber nochmal morgen nachgucken. Soweit ich mich erinnere müsste das alles 1 zu 1 aus einem Beispielprogramm sein, somit sollten auch keine weiteren Wartezeiten nötig sein.
Genaueres kann ich morgen nochmal sagen.

Dann habe ich noch eine Frage:
Am Donnerstag habe ich noch eine Variante mit positiver Flankenauswertung ausprobiert.

Hier habe ich in "E0.02" einen Schalter eingebaut.
Sobald dieser betätigt wird, werden die AT Befehle fürs Modem gesendet.
Das funktioniert auch, aber leider nur einmal.
Müsste das nicht bei jedem aktivieren des Schalters einmal die AT Befehle senden? (Also "GSM_Anmeldung" aufrufen)

Code:
      U     E      0.2
      FP    "FO1"		//außer auf einen Merker "verlinken" muss ich ja hier nichts machen oder?
      =     "Modem_anmeldung"


      U     "Modem_anmeldung"
      SPBN  xxx
      CALL  "GSM_Anmeldung"

xxx:  NOP   0


      U     "Modem_anmeldung"  //Nur zum testen, damit ich sehe das Modem_anmeldung nur einmal kurz auf 1 gesetzt wird
      =     A      0.2
 
Zuletzt bearbeitet:
Hallo Pneumatik,

ich vermute die Ursache Deiner Probleme in Deinem Baustein "GSM_Anmeldung" oder in der grundsätzlichen Einbindung des Bausteins in das Restprogramm. Der Baustein passt wohl nicht zur Arbeitsweise des "SEND"-Bausteins des Siemens-Beispielprogramms. Er wird offensichtlich völlig unkoordiniert und nur 1 Zyklus lang aufgerufen.

Was macht der Baustein "GSM_Anmeldung"?
Setzt er nur ein Bit für einen Sendeauftrag, das später im Baustein "SEND" ausgewertet wird oder ist da womöglich ein Aufruf des "P_SND_RK"? In Deinem letzten Programmcode wird der Baustein "GSM_Anmeldung" nur 1 Zyklus lang aufgerufen. "P_SND_RK" braucht eine positive Flanke am Eingang REQ als Auftragsanstoß, d.h. zwischen 2 Aufträgen muß "P_SND_RK" auch einmal mit REQ=0 aufgerufen werden. Das scheint bei Dir nicht immer gegeben zu sein.

Zu einem CP341 darf immer nur 1 Auftrag "P_SND_RK" und 1 Auftrag "P_RCV_RK" gleichzeitig aktiv sein. Der nächste P_SND/P_RCV-Auftrag darf erst angestoßen werden, wenn der vorherige Auftrag beendet ist. Ein P_SND/P_RCV-Auftrag benötigt in aller Regel mehr als 1 OB1-Zyklus zur Abarbeitung. Wenn mehr als 32 Zeichen gesendet oder empfangen werden sollen, dann müssen "P_SND_RK"/"P_RCV_RK" zwingend in jedem OB1-Zyklus einmal aufgerufen werden solange ein Job aktiv ist. In "SEND" und "RECV" ist sicher irgendeine Job-Verriegelung, d.h. besondere Erzeugung der REQ-Signale. Passend dazu muß Deine "GSM_Anmeldung" eingebunden und koordiniert werden.

Ein Problem ist wahrscheinlich auch noch, daß Dein Modem auf das Senden der AT-Befehle mit Zeichen antwortet, mit denen Dein restliches Programm nicht rechnet.

Für genauere Aussagen müßte man den Code Deiner Bausteine "GSM_Anmeldung", "SEND", "RECV" sowie der darin aufgerufenen Bausteine kennen.
Aus welchem Siemens-Beispiel hast Du Dein Programmgerüst?
Ist der CP341 auf ASCII-Modus eingestellt oder auf ein bestimmtes Protokoll? Wie sieht die restliche Parametrierung aus?
Oder besser: kannst Du Dein Step7-Projekt hier mal hochladen? (ggf. auf die relevanten Bausteine gekürzt)

Wenn man Dir nur alle paar Tage weitere Details aus der Nase ziehen kann, dann dauert die Lösung Deines Problems womöglich noch Wochen ...

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wenn man Dir nur alle paar Tage weitere Details aus der Nase ziehen kann, dann dauert die Lösung Deines Problems womöglich noch Wochen ...
Ich werd mich bessern :) (müssen)

Ein Problem ist wahrscheinlich auch noch, daß Dein Modem auf das Senden der AT-Befehle mit Zeichen antwortet, mit denen Dein restliches Programm nicht rechnet.
Das Modem scheint keine Antwort zu senden. Zumindest leuchtet die RXD LED nicht auf. Und auch beim direkten Test über Hyperterm kommt keine Antwort vom Modem.

Ich konnte das Problem jetzt noch etwas eingrenzen:
Die Befehle werden doch mehrmals gesendet. AbER nicht jedesmal beim betätigen des Schalters. Sondern mal beim 4ten, 5ten oder 6ten drücken des Schalters.
Dabei wird "modem_anmeldung" aber immer beim betätigen des Schalters auf 1 gesetzt. (das erkenne ich, da ich ein LED am ausgang gleich modem_anmeldung gesetzt habe).

Somit muss das Hauptproblem ja in der Funktion GSM_Anmeldung liegen.

Der Code von GSM_Anmeldung lautet wie folgt:

Code:
      L     256                         //LADDR
      T     "SEND WORK DB".P_SND_RK_WORK_LADDR

      L     10                          //DB_NR
      T     "SEND WORK DB".P_SND_RK_WORK_DB_NO
      T     "SEND SRC DB".P_SND_RK_DB_NO

      L     0                           //DBB_NO
      T     "SEND WORK DB".P_SND_RK_WORK_DBB_NO
      T     "SEND SRC DB".P_SND_RK_DBB_NO

      L     28
      T     "SEND WORK DB".P_SND_RK_WORK_LEN    //LEN
      T     "SEND SRC DB".P_SND_RK_LEN  //LEN

// ------------------------
// SEND with Instance-DB
// ------------------------
      CALL  "P_SND_RK" , "SEND IDB"
       SF      :='S'
       REQ     :="SEND WORK DB".P_SND_RK_REQ
       R       :="SEND WORK DB".P_SND_RK_R
       LADDR   :="SEND WORK DB".P_SND_RK_WORK_LADDR
       DB_NO   :="SEND WORK DB".P_SND_RK_WORK_DB_NO
       DBB_NO  :="SEND WORK DB".P_SND_RK_WORK_DBB_NO
       LEN     :="SEND WORK DB".P_SND_RK_WORK_LEN
       R_CPU_NO:=
       R_TYP   :=
       R_NO    :=
       R_OFFSET:=
       R_CF_BYT:=
       R_CF_BIT:=
       DONE    :="SEND WORK DB".P_SND_RK_DONE
       ERROR   :="SEND WORK DB".P_SND_RK_ERROR
       STATUS  :="SEND WORK DB".P_SND_RK_WORK_STATUS

// ------------------------
// Generate edge P_SND_RK_REQ
// ------------------------
      UN    "SEND WORK DB".P_SND_RK_REQ //P_SND_RK_REQ
      S     "SEND WORK DB".P_SND_RK_REQ //set P_SND_RK_REQ

      O     "SEND WORK DB".P_SND_RK_DONE    //P_SND_RK_DONE
      O     "SEND WORK DB".P_SND_RK_ERROR    //P_SND_RK_ERROR
      R     "SEND WORK DB".P_SND_RK_REQ //P_SND_RK_REQ
// -------------------------------
// Check "Complete without error"
// -------------------------------
      UN    "SEND WORK DB".P_SND_RK_DONE    //check P_SND_RK_DONE
      SPB   CHER                        //if P_SND_RK_DONE equals 0, jump to CHER
//and check P_SND_RK_ERROR

// -------------------------------
// "Complete without error"
//  P_SND_RK_DONE = 1
// -------------------------------
      L     "SEND SRC DB".P_SND_RK_COUNTER_OK    //"Complete without Error"
      +     1                           //increment counter
      T     "SEND SRC DB".P_SND_RK_COUNTER_OK

      NOP   0
      NOP   0                           //further user functions
      NOP   0

      BE    

// -------------------------------
// Check "Complete with error"
// P_SND_RK_ERROR = 1
// -------------------------------
CHER: UN    "SEND WORK DB".P_SND_RK_ERROR    //check P_SND_RK_ERROR
      BEB                               //if no error occured, jump to end

// -------------------------------
// "Complete with error"
// -------------------------------
      L     "SEND SRC DB".P_SND_RK_COUNTER_ERR    //"Complete with error"
      +     1                           //increment counter
      T     "SEND SRC DB".P_SND_RK_COUNTER_ERR

      L     "SEND WORK DB".P_SND_RK_WORK_STATUS
      T     "SEND WORK DB".P_SND_RK_WORK_STATUS_SAV    //save STATUS

      NOP   0
      NOP   0                           //Error-Handling
      NOP   0
Das zugrundeliegende Beispiel heißt:
CP PtP Param V5.1 + Servicepack 7
(Auf der Webseite habe ich gerade gesehenn, dass es eine neuere Version gibt .. ich installiere diese gerade.)



Im Fall, dass noch mehr Informationen nötig sind habe ich das ganze Projekt angehängt. Die Versuche mit der Flankensteueruung sind in SIMATIC 300 Station (1).
 

Anhänge

  • FLO_M20n.rar
    232,6 KB · Aufrufe: 1
Zuletzt bearbeitet:
So, da das eigentliche Problem gelöst (eigentlich sogar mehrfach :))
möchte ich mich nochmal bei allen beteiligten bedanken.

Anhand der Verschaltungen mit Ausgängen konnte ich sehen, das alle Versionen am Ende funktioniert haben. Von Berhand bis Ralle und mein Versuch :).

Es hängt noch irgendwo in der Siemensbausteienen, da diese nicht so reagieren wie gehoft.... die Funktionen werden aber wie gewollt nur einmal ausgeführt.

Danke und Gruß aus Berlin

--Closed--
 
Zurück
Oben