Multiinstanzing aus einem OB

vollmi

Level-3
Beiträge
5.436
Reaktionspunkte
1.409
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen. Ich bau mir grad eine Kommunikation für ModbusTCP auf.
Von Siemens habe ich den treiber der wird so aufgerufen.

Code:
      CALL  "MODBUSPN" , DB1001
       ID              :=
       DB_PARAM        :=
       RECV_TIME       :="CONTROL_DAT".MOD1.RECV_TIME
       CONN_TIME       :="CONTROL_DAT".MOD1.CONN_TIME
       KEEP_ALIVE      :=
       ENQ_ENR         :="CONTROL_DAT".MOD1.ENQ_ENR
       DISCONNECT      :="CONTROL_DAT".MOD1.DISCONNECT
       REG_KEY         :="LICENSE_DB".REG_KEY
       LICENSED        :="CONTROL_DAT".MOD1.LICENSED
       BUSY            :="CONTROL_DAT".MOD1.BUSY
       CONN_ESTABLISHED:="CONTROL_DAT".MOD1.CONN_ESTABLISHED
       DONE_NDR        :="CONTROL_DAT".MOD1.DONE_NDR
       ERROR           :="CONTROL_DAT".MOD1.ERROR
       STATUS_MODBUS   :="CONTROL_DAT".MOD1.STATUS_MODBUS
       STATUS_CONN     :="CONTROL_DAT".MOD1.STATUS_CONN
       STATUS_FUNC     :="CONTROL_DAT".MOD1.STATUS_FUNC
       IDENT_CODE      :="CONTROL_DAT".MOD1.IDENT_CODE
       UNIT            :="CONTROL_DAT".MOD1.UNIT
       DATA_TYPE       :="CONTROL_DAT".MOD1.DATA_TYPE
       START_ADDRESS   :="CONTROL_DAT".MOD1.START_ADDRESS
       LENGTH          :="CONTROL_DAT".MOD1.LENGTH
       TI              :="CONTROL_DAT".MOD1.TI
       WRITE_READ      :="CONTROL_DAT".MOD1.WRITE_READ
Also einmal Zyklisch in einem FB mit einem Instanzdb
Und einmalig im OB100 beim aufstart mit demselben Instanzdb

Code:
       L     1
      T     "CONTROL_DAT".MOD1.ID

      CALL  "MODBUSPN" , DB1001
       ID              :="CONTROL_DAT".MOD1.ID
       DB_PARAM        :="MODBUS_PARAM"
       RECV_TIME       :=
       CONN_TIME       :=
       KEEP_ALIVE      :=
       ENQ_ENR         :=
       DISCONNECT      :=
       REG_KEY         :=
       LICENSED        :=
       BUSY            :="CONTROL_DAT".MOD1.BUSY
       CONN_ESTABLISHED:="CONTROL_DAT".MOD1.CONN_ESTABLISHED
       DONE_NDR        :="CONTROL_DAT".MOD1.DONE_NDR
       ERROR           :="CONTROL_DAT".MOD1.ERROR
       STATUS_MODBUS   :="CONTROL_DAT".MOD1.STATUS_MODBUS
       STATUS_CONN     :="CONTROL_DAT".MOD1.STATUS_CONN
       STATUS_FUNC     :="CONTROL_DAT".MOD1.STATUS_FUNC
       IDENT_CODE      :=
       UNIT            :=
       DATA_TYPE       :=
       START_ADDRESS   :=
       LENGTH          :=
       TI              :=
       WRITE_READ      :=
Jetzt würde ich den Baustein gerne als Multiinstanz im FB aufrufen. Kriege ich das irgendwie hin das ich ihn im OB100 so aufrufe das er in denselben Muliinstanzabschnitt eingreift wie der im FB?

Ich habe schon versucht den übergeordneten FB so zu bauen das ich ihn aus dem OB100 aufrufen kann und ihm dann
ID :="CONTROL_DAT".MOD2.ID
DB_PARAM :="MODBUS_PARAM"
einmalig übergebe. Allerdings läuft dann der Treiber nicht und sagt er müsse initialisiert werden. Irgendwie kriegt der das also mit das der FB nicht direkt im OB100 aufgerufen wurde sondern in einem FB der vom OB100 aufgerufen wird.

mfg René
 
Hi,

ich würde prinzipiell anders vorgehen.
Ich würde im OB100 den kompletten FB in dem die Instanz enthalten ist aufrufen und mit einem Kennbit, das ich beim Aufruf OB100 setzte/rücksetze nur an die Aufrufstelle Kommunikationsteils springen.

MfG
 
ich würde prinzipiell anders vorgehen.
Ich würde im OB100 den kompletten FB in dem die Instanz enthalten ist aufrufen und mit einem Kennbit, das ich beim Aufruf OB100 setzte/rücksetze nur an die Aufrufstelle Kommunikationsteils springen.

So ähnlich habe ich es versucht.
Also einen FB gemacht dort in der Schnittstelle IN ID und ID_Param definiert

dann im FB so aufgerufen:
Code:
CALL  #MOD1
       ID              :=#MOD1ID
       DB_PARAM        :=#MOD1PARAM
       RECV_TIME       :="CONTROL_DAT".MOD1.RECV_TIME
       CONN_TIME       :="CONTROL_DAT".MOD1.CONN_TIME
       KEEP_ALIVE      :=
       ENQ_ENR         :="CONTROL_DAT".MOD1.ENQ_ENR
       DISCONNECT      :="CONTROL_DAT".MOD1.DISCONNECT
       REG_KEY         :="LICENSE_DB".REG_KEY
       LICENSED        :="CONTROL_DAT".MOD1.LICENSED
       BUSY            :="CONTROL_DAT".MOD1.BUSY
       CONN_ESTABLISHED:="CONTROL_DAT".MOD1.CONN_ESTABLISHED
       DONE_NDR        :="CONTROL_DAT".MOD1.DONE_NDR
       ERROR           :="CONTROL_DAT".MOD1.ERROR
       STATUS_MODBUS   :="CONTROL_DAT".MOD1.STATUS_MODBUS
       STATUS_CONN     :="CONTROL_DAT".MOD1.STATUS_CONN
       STATUS_FUNC     :="CONTROL_DAT".MOD1.STATUS_FUNC
       IDENT_CODE      :="CONTROL_DAT".MOD1.IDENT_CODE
       UNIT            :="CONTROL_DAT".MOD1.UNIT
       DATA_TYPE       :="CONTROL_DAT".MOD1.DATA_TYPE
       START_ADDRESS   :="CONTROL_DAT".MOD1.START_ADDRESS
       LENGTH          :="CONTROL_DAT".MOD1.LENGTH
       TI              :="CONTROL_DAT".MOD1.TI
       WRITE_READ      :="CONTROL_DAT".MOD1.WRITE_READ
IM OB100 Dann den FB aufgerufen
und zwar so
Code:
      L     1
      T     "CONTROL_DAT".MOD1.ID


CALL FB1, DB1
       MOD1ID              :="CONTROL_DAT".MOD1.ID        
       MOD1PARAM        :="MODBUS_PARAM"
Dann habe ich aber im Status immer zurückbekommen das sich der ParameterDB geändert hätte und man dann die CPU neustarten müsse.

Er hat das also irgendwie nie gefressen.

Wenn ich jetzt natürlich für jeden Modbusteilnehmer einen InstanzDB generieren lasse (sind immerhin 40 Stück) dann funktionierts. sieht aber einfach im Programm äusserst bescheiden aus.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
@Vollmi:
Es gibt da einen Teil in deinen Ausführungen, der mir fehlt ...
Wie sieht denn jetzt der Aufruf des Wunsch-Master-FB's im OB100 aus und wie im OB1 ? Stell das doch bitte mal als Code dar ...

Gruß
Larry
 
Der WunschMasterFB aufruf im OB1 sieht so aus

Code:
      L     1
      T     "CONTROL_DAT".MOD1.ID
      L     2
      T     "CONTROL_DAT".MOD2.ID


      CALL  "Modbus" , DB101
       MOD1ID   :="CONTROL_DAT".MOD1.ID
       MOD1PARAM:="MODBUS_PARAM"
       MOD2ID   :="CONTROL_DAT".MOD2.ID
       MOD2PARAM:="MODBUS_PARAM"

Und im OB1 sieht er so aus.

Code:
      CALL  "Modbus" , DB101
       MOD1ID   :=
       MOD1PARAM:=
       MOD2ID   :=
       MOD2PARAM:=

Und im FB101 (das ist der WunschMasterFB) Sieht der aufruf der einzelnen Multiinstanzen so aus:
Code:
      CALL  #MOD1
       ID              :=#MOD1ID
       DB_PARAM        :=#MOD1PARAM
       RECV_TIME       :="CONTROL_DAT".MOD1.RECV_TIME
       CONN_TIME       :="CONTROL_DAT".MOD1.CONN_TIME
       KEEP_ALIVE      :=
       ENQ_ENR         :="CONTROL_DAT".MOD1.ENQ_ENR
       DISCONNECT      :="CONTROL_DAT".MOD1.DISCONNECT
       REG_KEY         :="LICENSE_DB".REG_KEY
       LICENSED        :="CONTROL_DAT".MOD1.LICENSED
       BUSY            :="CONTROL_DAT".MOD1.BUSY
       CONN_ESTABLISHED:="CONTROL_DAT".MOD1.CONN_ESTABLISHED
       DONE_NDR        :="CONTROL_DAT".MOD1.DONE_NDR
       ERROR           :="CONTROL_DAT".MOD1.ERROR
       STATUS_MODBUS   :="CONTROL_DAT".MOD1.STATUS_MODBUS
       STATUS_CONN     :="CONTROL_DAT".MOD1.STATUS_CONN
       STATUS_FUNC     :="CONTROL_DAT".MOD1.STATUS_FUNC
       IDENT_CODE      :="CONTROL_DAT".MOD1.IDENT_CODE
       UNIT            :="CONTROL_DAT".MOD1.UNIT
       DATA_TYPE       :="CONTROL_DAT".MOD1.DATA_TYPE
       START_ADDRESS   :="CONTROL_DAT".MOD1.START_ADDRESS
       LENGTH          :="CONTROL_DAT".MOD1.LENGTH
       TI              :="CONTROL_DAT".MOD1.TI
       WRITE_READ      :="CONTROL_DAT".MOD1.WRITE_READ
 
... ich denke, dass dein Fehler ist, dass du in deinem WMF für deine 2 Modulo auch 2 Instanzen des ursprünglichen Modbus-FB's anlegen mußt und die dann entsprechend der Versorgung von Aussen aktivieren mußt. Du kannst ja nicht beide "Achsen" (?) im gleichen Datenbereich abspeichern. Es müßte also auch noch einen #MOD2 geben - dann geht es sicherlich ...

Du kommst also m.E. um diene Instanz-Datenbereiche nicht wirklich herum ...

Gruß
Larry
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich hab grad rausgefunden. Wenn ich im WunschmasterFB den Modbustreiber einmal aufrufe mit ID und Parameter verschaltet (mit InitMerker aus OB100) und einmal aufrufe mit ID und Parameter unbeschaltet (mit Initmerker zurückgesetzt am ende von OB100)

Dann funktionierts.

Der Nachteil ist einfach das dann im AufrufFB für jede Verbindung zweimal der Treiberaufruf vorhanden ist und bei der Initialisation nach 40 Treiberaufrufen aus dem Baustein ausgesprungen wird. Und nach der Initialisation die vorgängigen 40 Treiberaufrufe übersprungen werden.

Mächtig viel Code der einfach nur übersprungen wird. Aber so würds funktionieren.
 
Du kannst ja nicht beide "Achsen" (?) im gleichen Datenbereich abspeichern. Es müßte also auch noch einen #MOD2 geben - dann geht es sicherlich ...

Den #MOD2 gibts natürlich auch. Ich habe die Speicherbereiche also schon getrennt ich will sie nur im selben InstanzDB drinhaben.

Also für jeden Treiberaufruf gibts einen Abschnit im InstanzDB. Aber irgendwie scheint der Treiber das nicht zu mögen das ID und PARAM im Zyklischen Programm noch beschalten sind.
 
Naja ... für die Inistialisierung könntest du da ja einiges Vereinfachen ...
Dein WMF hat z.B. einen Eingang "Init" und wenn der =True ist, dnn spulst du intern den ganzen Kram der Reihe nach durch - also auch die ggf. geänderte Beschaltung. Vielleicht läßt sich da für den OB1-Aufruf auch noch etwas finden ...
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Naja ... für die Inistialisierung könntest du da ja einiges Vereinfachen ...
Dein WMF hat z.B. einen Eingang "Init" und wenn der =True ist, dnn spulst du intern den ganzen Kram der Reihe nach durch - also auch die ggf. geänderte Beschaltung. Vielleicht läßt sich da für den OB1-Aufruf auch noch etwas finden ...

Also wenn ich den MasterFB aus dem OB100 mit einem Initeingang auf true aufrufe und dann im FB nur die ID und Param Beschaltung durchlaufe ausspringe und dann zum OB1 wechsle. Gleicher Aufruf mit INIT := False und im MasterFB dann die aufrufe mit ID und Param überspringe funktioniert es.

Wenn ich allerdings den OB100 ganz weglasse. Den Init über

Code:
      L     #OB1_SCAN_1                 // Abfrage Erstdurchlauf OB1
      L     B#16#3
      <>I   
      =     "Init"

Im OB1 mache. Inklusive ID und Param beschaltung. Dann motzt der wieder vonwegen Baustein wurde nicht initialisiert obwohl ich mit einem Merker erkenne das der Init ausgeführt wurde (er hat die mit ID und Param beschaltenen Aufrufe durchlaufen im ersten Zyklus).

Der scheint das irgndwie zu erkennen ob die Initialisation durch OB100 gemacht wird oder durch OB1 Firstscan.
 
DEr MasterFB sieht jetzt so aus

Code:
VAR_INPUT
  Init : BOOL ;    
  MOD1ID : WORD ;    
  MOD1PARAM : BLOCK_DB ;    
  MOD2ID : WORD ;    
  MOD2PARAM : BLOCK_DB ;    
END_VAR
VAR
   MOD1 : "MODBUSPN";    
  MOD2 : "MODBUSPN";    
END_VAR
BEGIN
NETWORK
TITLE =

      U     #Init; 
      SPBN  INIT; 

      CALL #MOD1 (
           ID                       := #MOD1ID,
           DB_PARAM                 := #MOD1PARAM,
           BUSY                     := "CONTROL_DAT".MOD1.BUSY,
           CONN_ESTABLISHED         := "CONTROL_DAT".MOD1.CONN_ESTABLISHED,
           DONE_NDR                 := "CONTROL_DAT".MOD1.DONE_NDR,
           ERROR                    := "CONTROL_DAT".MOD1.ERROR,
           STATUS_MODBUS            := "CONTROL_DAT".MOD1.STATUS_MODBUS,
           STATUS_CONN              := "CONTROL_DAT".MOD1.STATUS_CONN,
           STATUS_FUNC              := "CONTROL_DAT".MOD1.STATUS_FUNC);

      L     500; 
      T     "CONTROL_DAT".MOD1.RECV_TIME; 

      L     T#5S; 
      T     "CONTROL_DAT".MOD1.CONN_TIME; 

      L     "CONTROL_DAT".MOD1.STATUS_CONN; 
      T     "CONTROL_DAT".MOD1.Save_STATUS_CONN; //for static display in VAT

      L     "CONTROL_DAT".MOD1.STATUS_MODBUS; 
      T     "CONTROL_DAT".MOD1.Save_STATUS_MODBUS; //for static display in VAT

      L     2; 
      T     "CONTROL_DAT".MOD2.ID; 

      CALL #MOD2 (
           ID                       := #MOD2ID,
           DB_PARAM                 := #MOD2PARAM,
           BUSY                     := "CONTROL_DAT".MOD2.BUSY,
           CONN_ESTABLISHED         := "CONTROL_DAT".MOD2.CONN_ESTABLISHED,
           DONE_NDR                 := "CONTROL_DAT".MOD2.DONE_NDR,
           ERROR                    := "CONTROL_DAT".MOD2.ERROR,
           STATUS_MODBUS            := "CONTROL_DAT".MOD2.STATUS_MODBUS,
           STATUS_CONN              := "CONTROL_DAT".MOD2.STATUS_CONN,
           STATUS_FUNC              := "CONTROL_DAT".MOD2.STATUS_FUNC);

      L     500; 
      T     "CONTROL_DAT".MOD2.RECV_TIME; 

      L     T#5S; 
      T     "CONTROL_DAT".MOD2.CONN_TIME; 

      L     "CONTROL_DAT".MOD2.STATUS_CONN; 
      T     "CONTROL_DAT".MOD2.Save_STATUS_CONN; //for static display in VAT

      L     "CONTROL_DAT".MOD2.STATUS_MODBUS; 
      T     "CONTROL_DAT".MOD2.Save_STATUS_MODBUS; //for static display in VAT



INIT: NOP   0; 
NETWORK
TITLE =



      CALL #MOD1 (
           RECV_TIME                := "CONTROL_DAT".MOD1.RECV_TIME,
           CONN_TIME                := "CONTROL_DAT".MOD1.CONN_TIME,
           ENQ_ENR                  := "CONTROL_DAT".MOD1.ENQ_ENR,
           DISCONNECT               := "CONTROL_DAT".MOD1.DISCONNECT,
           REG_KEY                  := "LICENSE_DB".REG_KEY,
           LICENSED                 := "CONTROL_DAT".MOD1.LICENSED,
           BUSY                     := "CONTROL_DAT".MOD1.BUSY,
           CONN_ESTABLISHED         := "CONTROL_DAT".MOD1.CONN_ESTABLISHED,
           DONE_NDR                 := "CONTROL_DAT".MOD1.DONE_NDR,
           ERROR                    := "CONTROL_DAT".MOD1.ERROR,
           STATUS_MODBUS            := "CONTROL_DAT".MOD1.STATUS_MODBUS,
           STATUS_CONN              := "CONTROL_DAT".MOD1.STATUS_CONN,
           STATUS_FUNC              := "CONTROL_DAT".MOD1.STATUS_FUNC,
           IDENT_CODE               := "CONTROL_DAT".MOD1.IDENT_CODE,
           UNIT                     := "CONTROL_DAT".MOD1.UNIT,
           DATA_TYPE                := "CONTROL_DAT".MOD1.DATA_TYPE,
           START_ADDRESS            := "CONTROL_DAT".MOD1.START_ADDRESS,
           LENGTH                   := "CONTROL_DAT".MOD1.LENGTH,
           TI                       := "CONTROL_DAT".MOD1.TI,
           WRITE_READ               := "CONTROL_DAT".MOD1.WRITE_READ);



NETWORK
TITLE =Modbus 2

      CALL #MOD2 (
           RECV_TIME                := "CONTROL_DAT".MOD2.RECV_TIME,
           CONN_TIME                := "CONTROL_DAT".MOD2.CONN_TIME,
           ENQ_ENR                  := "CONTROL_DAT".MOD2.ENQ_ENR,
           DISCONNECT               := "CONTROL_DAT".MOD2.DISCONNECT,
           REG_KEY                  := "LICENSE_DB".REG_KEY,
           LICENSED                 := "CONTROL_DAT".MOD2.LICENSED,
           BUSY                     := "CONTROL_DAT".MOD2.BUSY,
           CONN_ESTABLISHED         := "CONTROL_DAT".MOD2.CONN_ESTABLISHED,
           DONE_NDR                 := "CONTROL_DAT".MOD2.DONE_NDR,
           ERROR                    := "CONTROL_DAT".MOD2.ERROR,
           STATUS_MODBUS            := "CONTROL_DAT".MOD2.STATUS_MODBUS,
           STATUS_CONN              := "CONTROL_DAT".MOD2.STATUS_CONN,
           STATUS_FUNC              := "CONTROL_DAT".MOD2.STATUS_FUNC,
           IDENT_CODE               := "CONTROL_DAT".MOD2.IDENT_CODE,
           UNIT                     := "CONTROL_DAT".MOD2.UNIT,
           DATA_TYPE                := "CONTROL_DAT".MOD2.DATA_TYPE,
           START_ADDRESS            := "CONTROL_DAT".MOD2.START_ADDRESS,
           LENGTH                   := "CONTROL_DAT".MOD2.LENGTH,
           TI                       := "CONTROL_DAT".MOD2.TI,
           WRITE_READ               := "CONTROL_DAT".MOD2.WRITE_READ);


END_FUNCTION_BLOCK
Im OB1 rufe ich ihn auf mit einem FALSE auf Init

Im OB100 rufe ich ihn auf mit einem TRUE auf init sowie die ID und PARAM beschalten.

Das funktioniert so.

Interessant wäre es natürlich wenn ich den FB direkt aus dem OB1 aufrufen könnte mit dem INIT abhängig vom Erstdurchlauf.

Und ID und PARAM beschalten.

Code:
      L     #OB1_SCAN_1                 // Abfrage Erstdurchlauf OB1
      L     B#16#3
      <>I   
      =     #INIT



      L     1
      T     "CONTROL_DAT".MOD1.ID
      L     2
      T     "CONTROL_DAT".MOD2.ID


      CALL  "Modbus" , DB101
       Init     :=#INIT
       MOD1ID   :="CONTROL_DAT".MOD1.ID
       MOD1PARAM:="MODBUS_PARAM"
       MOD2ID   :="CONTROL_DAT".MOD2.ID
       MOD2PARAM:="MODBUS_PARAM"

So funktioniert es aber nicht. Dann wird die Initialisation nicht sauber durchgeführt. Keine Ahnung wieso.

IM OB1 der Aufruf mit INIT= FALSE und im OB100 derselbe Aufruf mit INIT gleich TRUE dann funktioniert die Initialisation.

Und noch schöner wärs wenn ich die Treiber im Masterfb nicht zweimal eintragen müsste nur um sie abhängig vom Init zu überspringen.
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Der Unterschied zwischen der einen und der anderen Variante sind (mit OB100) 2 verschiedene Zyklen bzw. (nur mit OB1) ein und der gleiche Zyklus.
Mach doch mal ein "BEA" vor deine Sprungmarke "INIT: NOP0". Dann sollte es auch, wie du es haben willst, funktionieren ...

Gruß
Larry
 
Der Unterschied zwischen der einen und der anderen Variante sind (mit OB100) 2 verschiedene Zyklen bzw. (nur mit OB1) ein und der gleiche Zyklus.
Mach doch mal ein "BEA" vor deine Sprungmarke "INIT: NOP0". Dann sollte es auch, wie du es haben willst, funktionieren ...

Habe ich mir auch schon gedacht hat aber leider auch keine Verbesserung gebracht.

Vor allem ohne BEA wird ja beim Aufruf aus OB100 auch gleich die Communikation nach der Initialisation im gleichen Zyklus angestossen. Und da funktionierts ja auch.

*grml*
 
Zurück
Oben