Problem bei mehrfach aufruf von FC

mzva

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

habe ein Problem bei einem mehrfach aufruf eines FC. Der FC wird/soll 4x aufgerufen werden. Der FC bildet einen Mittelwert (aus analog input PEW). Habe IN, OUT & TEMP darin verwendet (wie schon oft zuvor). Beim aufruf wird der FC mit verschiedenen DB Adressen belegt.
Was nun passiert ist folgendes: FC arbeitet wie er soll, leider aber werten alle FC's nur das ein und selbe PEW aus.

Fuer Rat jeder Art schon ein Danke im voraus.

mzva
 
hallöchen

ich trau mich fast nicht dies zu sagen

aber könnte es sein das du in deinen FC auf irgendwas direkt zugreifst und nicht über deine schnittstellen

wie sieht denn dein baustein aus
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Variablen im Temp-Bereich sind nur für einen Aufruf gültig,
da eine Mittelwertbildung ja Werte über mehrere Zyklen erfordert,
ist das mit Variablen im TEMP Bereich definitiv nicht zu machen.
Oder nur mit diversen Effekten.

Möglichkeit 1:
Du legst eine Variable vom Typ IN/OUT an, z.B. ein Array of INT mit der benötigten Anzahl an Werten

Möglichkeit 2:
Du verwendest einen FB, und schreibst alles was du jetzt im TEMP-Bereich hast,
in den STAT-Bereich.

Mfg
Manuel
 
Die Auswertung von PEWs sollte eigentlich kein Problem sein. Hier ein kurzes Beispiel:

Code:
FUNCTION FC 40 : VOID
TITLE =
VERSION : 0.1
 
VAR_INPUT
  EW : WORD ;   
END_VAR
VAR_OUTPUT
  MW : WORD ;   
END_VAR
BEGIN
NETWORK
TITLE =
      L     #EW; 
      T     #MW; 
      NOP   0; 
END_FUNCTION
ORGANIZATION_BLOCK OB 1
TITLE = Hauptprogramm
AUTHOR : KAI
FAMILY : SPSFORUM
NAME : SEGMENT
VERSION : 1.0
 
VAR_TEMP
  OB1_EV_CLASS : BYTE ; //Bits 0-3 = 1 (Coming event), Bits 4-7 = 1 (Event class 1)
  OB1_SCAN_1 : BYTE ;   //1 (Cold restart scan 1 of OB 1), 3 (Scan 2-n of OB 1)
  OB1_PRIORITY : BYTE ; //Priority of OB Execution
  OB1_OB_NUMBR : BYTE ; //1 (Organization block 1, OB1)
  OB1_RESERVED_1 : BYTE ;   //Reserved for system
  OB1_RESERVED_2 : BYTE ;   //Reserved for system
  OB1_PREV_CYCLE : INT ;    //Cycle time of previous OB1 scan (milliseconds)
  OB1_MIN_CYCLE : INT ; //Minimum cycle time of OB1 (milliseconds)
  OB1_MAX_CYCLE : INT ; //Maximum cycle time of OB1 (milliseconds)
  OB1_DATE_TIME : DATE_AND_TIME ;   //Date and time OB1 started
END_VAR
BEGIN
NETWORK
TITLE =
      CALL FC    40 (
           EW                       := PEW  752,
           MW                       := MW    10);
      NOP   0; 
NETWORK
TITLE =
      CALL FC    40 (
           EW                       := PEW  754,
           MW                       := MW    12);
      NOP   0; 
END_ORGANIZATION_BLOCK

Sonst stell doch mal Deinen FC (Programmcode) und die Aufrufe Deines FCs hier ins Forum.

Gruß Kai
 
Variablen im Temp-Bereich sind nur für einen Aufruf gültig,
da eine Mittelwertbildung ja Werte über mehrere Zyklen erfordert,
ist das mit Variablen im TEMP Bereich definitiv nicht zu machen.
Oder nur mit diversen Effekten.

Manuel schreibt aber, dass er bei seiner Mittelwertbildung mit DBs arbeitet. Das könnte also so in Ordnung sein.

Es bleibt aber alles nur Spekulation, solange wir den Programmcode von Manuel nicht haben.

Gruß Kai
 
danke fuer die Tips. Anbei mein Code.

Code:
NW1 
U     #start
SPBN  goon
 
NW2
//put PEW in pointer format
L     #PEW
SLD   3
T     #pPEW
 
NW3
L     PEW [#pPEW]
T     #PEW_int
 
NW4
// PEW to real
L     #PEW_int
ITD   
DTR   
 T     #PEW_value_real
// increase quantity
L     #quantity
L     1
+I    
T     #quantity
// integer to real for calc
L     #quantity
ITD   
 DTR   
T     #quantity_real
 
NW5
// value-last average
L     #PEW_value_real
L     #last_average_real
-R    
// divide by quantity
L     #quantity_real
 /R    
// result + last average
L     #last_average_real
+R    
 T     #average
// result to last average
L     #average
T     #last_average_real
 
NW6
goon: NOP 0

mzva
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Nun der FC aufruf.

Code:
      CALL  "average_value"
       start    :="measure_02_in_op"
       init     :="init_calc_values"
       PEW      :=280
       average  :="data_log".current_ST29
       quantity :="data_log".quantity_values_ST29
       min_value:="data_log".min_current_ST29
       max_value:="data_log".max_current_ST29

mzva
 
Kannst Du den FC mal als STEP7-Quelle posten, damit man den Schnittstellenbereich des FC sehen kann? :confused:

Ansonsten ist mir folgendes aufgefallen: :shock:

Code:
NW1 
U     #start
SPBN  goon
 
NW2
//put PEW in pointer format
L     #PEW
SLD   3
T     #pPEW
 
NW3
L     PEW [#pPEW]
T     #PEW_int
 
NW4
// PEW to real
L     #PEW_int
ITD   
DTR   
 T     #PEW_value_real
// increase quantity
L     #quantity
L     1
+I    
T     #quantity
// integer to real for calc
L     #quantity
ITD   
 DTR   
T     #quantity_real
 
NW5
// value-last average
L     #PEW_value_real
[COLOR=red]L     #last_average_real[/COLOR]
-R    
// divide by quantity
L     #quantity_real
 /R    
// result + last average
[COLOR=red]L     #last_average_real[/COLOR]
+R    
 T     #average
// result to last average
L     #average
[COLOR=red]T     #last_average_real[/COLOR]
 
NW6
goon: NOP 0

Wenn es sich bei der Variable #last_average_real um eine TEMP-Variable handelt, dann kann der Code so nicht funktionieren.

TEMP-Variablen sind nur innerhalb eines FB oder FC gültig. Nach Beendigung des FB oder FC geht der Inhalt der TEMP-Variablen verloren.

Wenn Du Dir den Inhalt der Variablen #last_average_real bis zum nächsten Aufruf des FC merken willst, dann mußt Du die Variable als INOUT-Parameter deklarieren oder statt des FC einen FB verwenden und dort die Variable als STAT-Parameter deklarieren.

Gruß Kai
 
Anbei die Quelle:

Code:
FUNCTION "average_value" : VOID
TITLE =
//average=last average+((value-last average)/quantity)
AUTHOR : mz
VERSION : 0.1
 
VAR_INPUT
  start : BOOL ; 
  init : BOOL ; 
  PEW : INT ; 
END_VAR
VAR_OUTPUT
  average : REAL ; 
  quantity : INT ; 
  min_value : REAL ; 
  max_value : REAL ; 
END_VAR
VAR_TEMP
  pPEW : DINT ; 
  PEW_int : INT ; 
  PEW_value_real : REAL ; 
  last_average_real : REAL ; 
  quantity_real : REAL ; 
END_VAR
BEGIN
NETWORK
TITLE =
      U     #start; 
      SPBN  goon; 
NETWORK
TITLE =
//change PEW with 2x 2x 2x (=8) to pointer format
//load PEW, 32bit, real
//put PEW in pointer format
      L     #PEW; 
      SLD   3; 
      T     #pPEW; 
NETWORK
TITLE =
      L     PEW [#pPEW]; 
      T     #PEW_int; 
NETWORK
TITLE =
//values to real format
// PEW to real
      L     #PEW_int; 
      ITD   ; 
      DTR   ; 
      T     #PEW_value_real; 
// increase quantity
      L     #quantity; 
      L     1; 
      +I    ; 
      T     #quantity; 
//
// integer to real for calc
      L     #quantity; 
      ITD   ; 
      DTR   ; 
      T     #quantity_real; 
NETWORK
TITLE =
//average=last average+((PEW_value-last average)/quantity)
// value-last average
      L     #PEW_value_real; 
      L     #last_average_real; 
      -R    ; 
// divide by quantity
      L     #quantity_real; 
      /R    ; 
// result + last average
      L     #last_average_real; 
      +R    ; 
      T     #average; 
// result to last average
      L     #average; 
      T     #last_average_real; 
NETWORK
TITLE =
//check min value
      L     #PEW_value_real; 
      L     #min_value; 
      <R    ; 
      SPB   min; 
      SPA   jp; 
NETWORK
TITLE =
//adjust min value
min:  L     #PEW_value_real; 
      T     #min_value; 
NETWORK
TITLE =
//check max value
jp:   L     #PEW_value_real; 
      L     #max_value; 
      >R    ; 
      SPB   max; 
      SPA   nojp; 
NETWORK
TITLE =
//adjust max value
max:  L     #PEW_value_real; 
      T     #max_value; 
NETWORK
TITLE =
nojp: NOP   0; 
      SPA   goon; 
NETWORK
TITLE =
goon: U     #init; 
      SPB   init; 
      SPA   done; 
NETWORK
TITLE =
//reset values
init: L     0; 
//  T     #PEW_value_real
//      T     #last_average_real
//      T     #quantity_real
//      T     #average
      T     #quantity; 
      L     3.402823e+038; 
      T     #min_value; 
      L     -3.402823e+038; 
      T     #max_value; 
NETWORK
TITLE =
done: NOP   0; 
END_FUNCTION

Danke an alle, Kai hast recht mit last average, werd ich wohl dann als In/Out anlegen.

Dies erklaert aber noch nicht mein eigentliches Problem. Der FC nimmt nur ein und denselben PEW wert zum rechnen.

mzva
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallöchen

----
er nimmt doch eh das richtige PEW nur deine ausgabe stimmt im mittelwert nicht ( siehe unten )
----
Ich will jetzt nicht Lehrer haft sein

aber weist du was eine TEMP variabel ist

eine TEMP variabel darf nur zu einen Zyklus verwendet werden
Soll heisen am anfang beschreiben und dann später im selber zyklus im selben fc wieder lesen


im nächsten zyklus kann noch das selbe drinnen stehen muss aber nicht !!!!!

deshalb gehts bei einen aufruf und beim 2 gehts auf einmal nicht mehr

Ich hab zwar nur einen kurzen blick reingeworfen aber bei deiner TEMP Variabel "last_average_real" greifst du gleich lesend drauf zu und da steht natrürlich der müll vom letzten aufruf drinnen

ich hoffe ich hab dir geholfen
 
Danke an alle, Kai hast recht mit last average, werd ich wohl dann als In/Out anlegen.

Dies erklaert aber noch nicht mein eigentliches Problem. Der FC nimmt nur ein und denselben PEW wert zum rechnen.

mzva

Wie kpeter bereits geschrieben hat, sieht Dein PEW-Aufruf im Programm richtig aus.

Du solltest also erst einmal Deine Variable #last_average_real als INOUT-Variable anlegen und dann den FC noch einmal testen.

Gruß Kai
 
Hallo mzva,

die Ausgänge einer Funktion müssen bei jedem Aufruf der Funktion beschrieben werden! Du überspringst die Zuweisungen bedingt. Bei einem FB ginge das, bei einer FC nicht!


Gruß, Onkel
 
Zuviel Werbung?
-> Hier kostenlos registrieren
die Ausgänge einer Funktion müssen bei jedem Aufruf der Funktion beschrieben werden! Du überspringst die Zuweisungen bedingt. Bei einem FB ginge das, bei einer FC nicht!

Also bei meinem FC funktioniert das Überspringen der Ausgangszuweisung ohne Probleme.

E0.0=1 -> MW10 = PEW572
E0.0=0 -> MW10 = letzter Wert, wird nicht aktualisiert

E0.1=1 -> MW12 = PEW574
E0.1=0 -> MW12 = letzter Wert, wird nicht aktualisiert

Code:
FUNCTION FC 40 : VOID
TITLE =
VERSION : 0.1
 
VAR_INPUT
  PEW : INT ;   
  START : BOOL ;    
END_VAR
VAR_OUTPUT
  MW : WORD ;   
END_VAR
VAR_TEMP
  pPEW : DINT ; 
END_VAR
BEGIN
NETWORK
TITLE =
      U     #START; 
      SPBN  GOON; 
      L     #PEW; 
      SLW   3; 
      T     #pPEW; 
      L     PEW [#pPEW]; 
      T     #MW;
GOON: NOP   0; 
 
END_FUNCTION
 
ORGANIZATION_BLOCK OB 1
TITLE = Hauptprogramm
AUTHOR : KAI
FAMILY : SPSFORUM
NAME : SEGMENT
VERSION : 1.0
 
VAR_TEMP
  OB1_EV_CLASS : BYTE ; //Bits 0-3 = 1 (Coming event), Bits 4-7 = 1 (Event class 1)
  OB1_SCAN_1 : BYTE ;   //1 (Cold restart scan 1 of OB 1), 3 (Scan 2-n of OB 1)
  OB1_PRIORITY : BYTE ; //Priority of OB Execution
  OB1_OB_NUMBR : BYTE ; //1 (Organization block 1, OB1)
  OB1_RESERVED_1 : BYTE ;   //Reserved for system
  OB1_RESERVED_2 : BYTE ;   //Reserved for system
  OB1_PREV_CYCLE : INT ;    //Cycle time of previous OB1 scan (milliseconds)
  OB1_MIN_CYCLE : INT ; //Minimum cycle time of OB1 (milliseconds)
  OB1_MAX_CYCLE : INT ; //Maximum cycle time of OB1 (milliseconds)
  OB1_DATE_TIME : DATE_AND_TIME ;   //Date and time OB1 started
END_VAR
BEGIN
NETWORK
TITLE =
      CALL FC    40 (
           PEW                      := 752,
           START                    := E      0.0,
           MW                       := MW    10);
NETWORK
TITLE =
      CALL FC    40 (
           PEW                      := 754,
           START                    := E      0.1,
           MW                       := MW    12);
 
END_ORGANIZATION_BLOCK

Gruß Kai
 
Code:
FUNCTION "average_value" : VOID
TITLE =
//average=last average+((value-last average)/quantity)
AUTHOR : mz
VERSION : 0.1
 
VAR_INPUT
  start : BOOL ; 
  init : BOOL ; 
  PEW : INT ; 
END_VAR
[COLOR=red]VAR_OUTPUT[/COLOR]
  average : REAL ; 
  [COLOR=red]quantity : INT[/COLOR] ; 
  min_value : REAL ; 
  max_value : REAL ; 
END_VAR
VAR_TEMP
  pPEW : DINT ; 
  PEW_int : INT ; 
  PEW_value_real : REAL ; 
  last_average_real : REAL ; 
  quantity_real : REAL ; 
END_VAR
BEGIN
NETWORK
TITLE =
      U     #start; 
      SPBN  goon; 
NETWORK
TITLE =
//change PEW with 2x 2x 2x (=8) to pointer format
//load PEW, 32bit, real
//put PEW in pointer format
      L     #PEW; 
      SLD   3; 
      T     #pPEW; 
NETWORK
TITLE =
      L     PEW [#pPEW]; 
      T     #PEW_int; 
NETWORK
TITLE =
//values to real format
// PEW to real
      L     #PEW_int; 
      ITD   ; 
      DTR   ; 
      T     #PEW_value_real; 
// increase quantity
      [COLOR=red]L     #quantity[/COLOR]; 
      L     1; 
      +I    ; 
      [COLOR=red]T     #quantity;[/COLOR] 
//
// integer to real for calc
     [COLOR=red]L     #quantity[/COLOR]; 
      ITD   ; 
      DTR   ; 
      T     #quantity_real; 
NETWORK
TITLE =
//average=last average+((PEW_value-last average)/quantity)
// value-last average
      L     #PEW_value_real; 
      L     #last_average_real; 
      -R    ; 
// divide by quantity
      L     #quantity_real; 
      /R    ; 
// result + last average
      L     #last_average_real; 
      +R    ; 
      T     #average; 
// result to last average
      L     #average; 
      T     #last_average_real; 
NETWORK
TITLE =
//check min value
      L     #PEW_value_real; 
      L     #min_value; 
      <R    ; 
      SPB   min; 
      SPA   jp; 
NETWORK
TITLE =
//adjust min value
min:  L     #PEW_value_real; 
      T     #min_value; 
NETWORK
TITLE =
//check max value
jp:   L     #PEW_value_real; 
      L     #max_value; 
      >R    ; 
      SPB   max; 
      SPA   nojp; 
NETWORK
TITLE =
//adjust max value
max:  L     #PEW_value_real; 
      T     #max_value; 
NETWORK
TITLE =
nojp: NOP   0; 
      SPA   goon; 
NETWORK
TITLE =
goon: U     #init; 
      SPB   init; 
      SPA   done; 
NETWORK
TITLE =
//reset values
init: L     0; 
//  T     #PEW_value_real
//      T     #last_average_real
//      T     #quantity_real
//      T     #average
      [COLOR=red]T     #quantity[/COLOR]; 
      L     3.402823e+038; 
      T     #min_value; 
      L     -3.402823e+038; 
      T     #max_value; 
NETWORK
TITLE =
done: NOP   0; 
END_FUNCTION

Mit der Variablen #quantity stimmt auch etwas nicht. Sie ist als OUT-Variable deklariert, wird aber zuerst abgefragt und dann erst zugewiesen. Die Variable #quantity sollte daher auch als INOUT-Variable deklariert werden.

Du solltest wirklich noch einmal ALLE Variablen überprüfen, ob sie im Schnittstellenbereich des FC richtig deklariert sind.

Gruß Kai
 
Also bei meinem FC funktioniert das Überspringen der Ausgangszuweisung ohne Probleme.

E0.0=1 -> MW10 = PEW572
E0.0=0 -> MW10 = letzter Wert, wird nicht aktualisiert

E0.1=1 -> MW12 = PEW574
E0.1=0 -> MW12 = letzter Wert, wird nicht aktualisiert

Ich muss kai rechtgeben solange außerhalb des FC nicht auf das Ausgangsword geschrieben wird ist es egal ob bedingt aufgerufen oder nicht oder ob als out oder in/out deklariert ist.

desweiteren frag ich mich schon die ganze zeit was du mit deinen fc machen willst

wie oft wird der denn zurück gesetzt das dein mittelwert nicht überläuft
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Erstmal Danke fuer die Hilfe. Lehrehaft ist ok, sehe mich als Lernender an.
Der FC soll ca. 500 werte aufnehmen. Die Werte kommen von einer Motorkarte (AO) und werden von der S7 als AI eingelesen. Die Werte schwanken zwischen 500 und 1500 incremente. Diese nehme ich und bilde mir einen Mittelwert (Formel), Anzahl der aufgenommenen Werte, min & max Wert.

Dachte mir dies ist einfacher als 500 Werte irgendwo hinzuschreiben und danach einen Mittelwert zu bilden.

"Ueberlaufen" sollte nicht (real).

Habe die IN/OUT modifiziert, was auch Sinn macht, mein Fehler, sorry.

Werde mir das ganze nochmal zu "Gemuete" fuehren muessen.

Also besten Dank fuer die Hilfe. Melde mich wenn ich weiss woran es lag.

mzva
 
"Ueberlaufen" sollte nicht (real).

real kann genau so überlaufen du hast nur eine sechsstellige genauigkeit wenn die abläuft macht es schwups und dein wert steht.

sechstellig heist nicht nach dem komma sondern insgesamt 6 stellen dann beginnt die ungenauigkeit und irgendwann zählt er nicht mehr richtig

ich bin selber schon mal darüber gestolbert.

nur bin ich mir von deiner formel nicht sicher ob dieser mittelwert so auch stimmt

du zählst ja permanent alles zusammen und dividiertst durch die anzahl nach einiger zeit wird sich dein mittelwert festfressen wenn du in nicht wieder zurücksetzt.
 
Hallo Kai,

Also bei meinem FC funktioniert das Überspringen der Ausgangszuweisung ohne Probleme...
Ok, unter Umständen, wie auch in deinem Beispiel, wird es funktionieren.

Hier ein Siemens-Beitrag dazu:
http://support.automation.siemens.com/WW/view/de/189227

oder auch in der Step7-Hilfe nachzulesen unter "Vermeiden von Fehlern beim Aufruf von Bausteinen".

Wenn man mit bedingten Sprüngen arbeitet ist es am einfachsten, entsprechende Parameter am Anfang der Funktion zu initialisieren.


Gruß, Onkel
 
Zurück
Oben