Step 7 ANY-Pointer Indirekt Adressieren

Heini

Level-1
Beiträge
1
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Zusammen,

habe folgendes Anliegen:

in einem FB (FB100) verwende ich die SFB14 (PUT) und SFB15 (GET). Da ich mit mehreren Steuerungen kommunizieren muss, will ich den FB100 als Multi_FB mehrmals aufrufen.
Wie kann ich jetzt die Pointer für die PUT-/GET-Bausteine als Eingangsvariablen an FB100 anparametrieren?
Pointer
SRC:=>P#DB80.DBX14.0 BYTE 10
DST:=P#DB100.DBX0.0 BYTE 10
möchte ich durch lokale Variablen ersetzen, damit ich den FB100 unverändert mehrmals verwenden kann?

Bedanke mich im Voraus..
 
Benutze mal google mit der Suche "ANY an FB übergeben" - da findest Du viele komplett ausprogrammierte Beispiele

Kurzfassung:
übergib SRC und DST als IN-Parameter (Typ: ANY) an den FB100
im FB100 kopierst Du die IN-Parameter auf TEMP-ANY (mit Hilfe von AR1 und AR2)
die TEMP-ANY kannst Du dann an PUT/GET schreiben/übergeben

Harald
 
Hätte zu diesem Theme auch noch eine Frage. Ich habe den Any über die TEMPvariable auf die INvariable gelegt. Jeweils für Senden und Empfangen. Das funktioniert auch so.
Am IN des FB wird dann z.B der Wert P#DB100.DBX0.0 BYTE 100 für den Empfangsbereich und P#DB100.DBX100.0 BYTE 100 für den Sendebereich angegeben.

Jetzt möchte ich im FB in die ANY TEMPvariable ein INT am anfang reinschreiben also die ersten 2 Byte. Die restlichen Bytes werden durch den DB ja belegt.

Was ich machen will ist egal welchen DB und welche länge man am FB eingibt das immer die ersten zwei Bytes für den Watchdog vorbelegt sind. Somit muss der Anwender sich nicht mehr um die Überwachung kümmern.

Hab schon das Thema ANY Aufbau im Forum gefunden aber ich bekomme einfach keinen Anfang.
 
Hallo Larry,
hab den Baustein als Bild angehängt.
http://img18.myimg.de/VMwaree3b99.png

Wie du siehst führe ich meinen Watchdog (RemoteCounter & MyCounter) momentan noch nach außen an den FB und übergebe ihn dann an den DB.
Ich möchte mir aber diesen Schritt sparen.
Wenn jetzt der Anwender an dem IN "SendData" seinen DB100DBX.0.0 BYTE 100 angibt möchte ich einfach im FB auf die ersten zwei BYTE's den MyCounter draufschreiben. und mit dem RecvData das gleiche.

Somit muss sich der Anwender nicht mehr um die Beschaltung des Watchdog kümmern den er liegt immer auf den ersten zwei Bytes.

Hoffe man versteht es :p
 
Zuletzt bearbeitet:
... ich glaube ich habe es verstanden ...
Und nein ... das geht so nicht.
Der ANY-Pointer zeigt ja auf einen Datenbereich und ist nicht der Datenbereich selber. Was du also nur machen kannst ist, dir eine lokale Kopie deines Datenblocks anzulegen (also der echten Quelldaten), diese dann um die gewünschten weiteren Daten zu erweitern und die erweiterten Daten dann weiterzuschicken (also darauf dann einen neuen ANY zeigen lassen).

Gruß
Larry
 
Zuviel Werbung?
-> Hier kostenlos registrieren
@Petri:
Wenn ich es richtig verstanden habe, dann ist das, was Du vorhast, eine höchst unsaubere Programmierung.
Falls die PUT/GET-Speicherbereiche bei jeder FB-Instanz immer gleich groß sein sollten, dann könntest Du diese Speicherbereiche als STRUCT an den FB übergeben und so sauber auf Variablen in den Speicherbereichen zugreifen.

PS: Dein Baustein-Bild kann leider nicht geöffnet werden - Zugriff verboten.
Hänge das Bild einfach an den Beitrag an - das Klammersymbol im erweiterten Beitragseditor oder da der Button "Anhänge verwalten".

Harald
 
Guten morgen,
hab nochmals das Bild des Bausteins angehangen. KOP_AWL_FUP  - [OB1 -- _CYCL_EXC_ -- CP343-1 COM_Projekt1_SIMATIC 300(1)_CPU 315-000003.png KOP_AWL_FUP  - [FB680 -- _FB_AG_SEND_AG_RECV_ -- CP343-1 COM_Projekt1_SIMATIC 30-000005.jpg KOP_AWL_FUP  - [FB680 -- _FB_AG_SEND_AG_RECV_ -- CP343-1 COM_Projekt1_SIMATIC 30-000004.jpg



Ich benutze die AG_SEND & AG_RECV Bausteine und leite die Send und Recv Daten an den IN/OUT des Bausteins. Dies mach ich mit dem unteren Code.
Damit ich jetzt nicht immer die Watchdog Daten aus dem Baustein an den DB übergeben muss, dachte ich mir das ich dies einfach direkt im Baustein machen könnte. Da der DB Bereich sowieso am IN/OUT des Bausteins als ANY angegeben ist.




Code:
ANY-Parameter von IN/IN_OUT in TEMP umkopieren in Multiinstanz-FB:
 

Code:
//AR2 Adressregister sichern
      TAR2  #tmp_DW_AR2_Save

//*** SendData kopieren *************************
//Pointer auf IN_OUT-Parameter SendData erstellen
      LAR1  P##SendData                 // relative Adresse #SendData in dieser Instanz (DI)
      TAR2                              // Offset dieser Multiinstanz (DB)
      +AR1                              // AR1: absolute Adresse #SendData im IDB (DI)

//Pointer auf TEMP-Variable tmp_Any_SendData erstellen
      LAR2  P##tmp_Any_SendData         // AR2: Adresse des TEMP-ANY

//ANY IN_OUT.SendData nach TEMP.tmp_Any_SendData kopieren
      L     D [AR1,P#0.0]               // (S7-ID + Datentyp + Wiederholfaktor)
      T     D [AR2,P#0.0]
      L     W [AR1,P#4.0]               // (DB_Nr)
      T     W [AR2,P#4.0]
      L     D [AR1,P#6.0]               // (Bereichsadresse)
      T     D [AR2,P#6.0]



//*** RecvData kopieren *************************
//Pointer auf IN_OUT-Parameter RecvData erstellen
      LAR1  P##RecvData                 // relative Adresse #RecvData in dieser Instanz (DI)
      L     #tmp_DW_AR2_Save            // Offset dieser Multiinstanz (DB)
      +AR1                              // AR1: absolute Adresse #RecvData im IDB (DI)

//Pointer auf TEMP-Variable tmp_Any_RecvData erstellen
      LAR2  P##tmp_Any_RecvData         // AR2: Adresse des TEMP-ANY

//ANY IN_OUT.RecvData nach TEMP.tmp_Any_RecvData kopieren
//ALTERNATIVE Codevariante für besser verstehbar
      L     DID [AR1,P#0.0]             // (S7-ID + Datentyp + Wiederholfaktor)
      T     LD [AR2,P#0.0]
      L     DIW [AR1,P#4.0]             // (DB_Nr)
      T     LW [AR2,P#4.0]
      L     DID [AR1,P#6.0]             // (Bereichsadresse)
      T     LD [AR2,P#6.0]

//*** Ende Parameter vorbereiten ********************
//VOR Zugriffen auf Instanzobjekte das AR2 unbedingt wiederherstellen!
      LAR2  #tmp_DW_AR2_Save            //AR2 Adressregister wiederherstellen

Gruß
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Gute Frage Larry, da ich mich mit ANY - Poniter überhaupt nicht auskenne und schon froh bin das der Code zum durchreichen des ANY's von IN zu TEMP so funktioniert hat, dachte ich das Ihr noch eine Lösung habt.

Dein Vorschlag hörte sich ja gut an nur hab ich keine Ahnung wie man dies umsetzt. :confused:
 
Naja ... so wie beschrieben :
du bildest dir einen "eigenen" Speicherbereich in den du via BlockMove (SFC20) die eigentlichen Empfangsdaten hineinkopierst, der aber auch schon von vorn herein Platz für deine Zusatzinfo (hier jetzt am Ende) hätte. Auf diesen Speicherbereich in siener erweiterten Form bildest du dir wieder einen eigenen ANY den du dann weitergibst.
An welcher Stelle hast du ein Verständnisproblem ?

Gruß
Larry
 
Ich hätte ja auch noch eine andere Idee wie man es machen könnte, aber eben nur Theoretisch:

Wenn ich an den IN des Bausteins meinen DB anschreibe z.B P#DB100.dbx0.0 BYTE 100 wird er ja momentan im Baustein auf die TEMP Variable (tmp_Any_SendData) geschrieben, so dass ich ihn an den AG_SEND übergeben kann.

Somit steht in der TEMP Variable (tmp_Any_SendData) irgendwo ja schon die DB Nummer drin.
Wenn ich diese DB Nummer mir nehmen könnte und éine Variable (ka. welcher Datentyp man nimmt) erzeuge, mit dem inhalt z.B DBNummerDBW.0.0 währe mir weitergeholfen.
So könnte ich einen Wert in die Variable reinschreiben und diese wird dem DB übergeben.

Oder ist das alles einfach zu kompliziert für ein Anfänger.



.KOP_AWL_FUP  - [FB680 -- _FB_AG_SEND_AG_RECV_ -- CP343-1 COM_Projekt1_SIMATIC 30-000004.jpg
KOP_AWL_FUP  - [FB680 -- _FB_AG_SEND_AG_RECV_ -- CP343-1 COM_Projekt1_SIMATIC 30-000005.jpg
KOP_AWL_FUP  - [OB1 -- _CYCL_EXC_ -- CP343-1 COM_Projekt1_SIMATIC 300(1)_CPU 315-000003.png
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Wenn Du Dir das ANY-Format in der Step7-Hilfe oder hier in der Forum-FAQ anschaust, dann wirst Du sehen, daß Dein Vorhaben relativ leicht realisierbar ist - doch wie ich schon schrieb: das ist höchst unsaubere Programmierung, welche später wahrscheinlich nur noch von Profis nachvollziehbar ist.

Da Du immer auf den Anfang des per ANY übergebenen Speicherbereichs zugreifen willst, braucht eigentlich nur die Längenangabe in dem ANY geändert werden und schon hat man einen ANY-Pointer auf z.B. das erste Word in dem Speicherbereich. Oder man lädt die Adressangabe aus dem ANY in das DB-Register und AR1 und kann so indirekt auf das erste Word zugreifen (L W [AR1, P#0.0]).

Harald
 
Naja unsauber is es doch nur dann wenn es nicht funktioniert. Der Baustein sollte so aufgebaut sein das er einfach zu bedienen ist und eben alles abdeckt was ich zur S7 - S7 Komunikation mit CP343 brauche.

Wie würdes du den so ein Baustein aufbauen.

Danke
 
"Unsauber" ist das Programm schon dann, wenn die Variablenzugriffe nicht mehr in den Referenzdaten auftauchen (und auch nicht per Quelle rekonstruierbar sind) und man als (Fremd-)Programmierer dadurch fast keine Chance mehr hat, das Programm zu verstehen und zu warten.

Übrigens wirst auch Du früher oder später vergessen haben wie der so programmierte Programmteil funktioniert. Bei Deinen momentanen Programmierkenntnissen rechne ich damit eher früher. Also bitte: laß es sein.

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Gut dann wäre dieser Code in meinem Baustein auch schon unsauber, da man den Variablenzugriff nicht mehr in den Referenzdaten nachvollziehen kann?

Code:
//AR2 Adressregister sichern
      TAR2  #tmp_DW_AR2_Save

//*** SendData kopieren *************************
//Pointer auf IN_OUT-Parameter SendData erstellen
      LAR1  P##SendData                 // relative Adresse #SendData in dieser Instanz (DI)
      TAR2                              // Offset dieser Multiinstanz (DB)
      +AR1                              // AR1: absolute Adresse #SendData im IDB (DI)

//Pointer auf TEMP-Variable tmp_Any_SendData erstellen
      LAR2  P##tmp_Any_SendData         // AR2: Adresse des TEMP-ANY

//ANY IN_OUT.SendData nach TEMP.tmp_Any_SendData kopieren
      L     D [AR1,P#0.0]               // (S7-ID + Datentyp + Wiederholfaktor)
      T     D [AR2,P#0.0]
      L     W [AR1,P#4.0]               // (DB_Nr)
      T     W [AR2,P#4.0]
      L     D [AR1,P#6.0]               // (Bereichsadresse)
      T     D [AR2,P#6.0]



//*** RecvData kopieren *************************
//Pointer auf IN_OUT-Parameter RecvData erstellen
      LAR1  P##RecvData                 // relative Adresse #RecvData in dieser Instanz (DI)
      L     #tmp_DW_AR2_Save            // Offset dieser Multiinstanz (DB)
      +AR1                              // AR1: absolute Adresse #RecvData im IDB (DI)

//Pointer auf TEMP-Variable tmp_Any_RecvData erstellen
      LAR2  P##tmp_Any_RecvData         // AR2: Adresse des TEMP-ANY

//ANY IN_OUT.RecvData nach TEMP.tmp_Any_RecvData kopieren
//ALTERNATIVE Codevariante für besser verstehbar
      L     DID [AR1,P#0.0]             // (S7-ID + Datentyp + Wiederholfaktor)
      T     LD [AR2,P#0.0]
      L     DIW [AR1,P#4.0]             // (DB_Nr)
      T     LW [AR2,P#4.0]
      L     DID [AR1,P#6.0]             // (Bereichsadresse)
      T     LD [AR2,P#6.0]

//*** Ende Parameter vorbereiten ********************
//VOR Zugriffen auf Instanzobjekte das AR2 unbedingt wiederherstellen!
      LAR2  #tmp_DW_AR2_Save            //AR2 Adressregister wiederherstellen

Aber irgendwie muss ich den ANY - Pointer an den IN des Baustein schalten. Oder hast du da eine saubere Lösung.
 
Unsauber

Beispiel:

Du hast einen Speicherbereich DB100.DBB0..DBB99
Den übergibst Du als P#DB100.DBX0.0 BYTE 100 an Deinen FB an IN_OUT.SendData
Dies erscheint in den Referenzdaten (deshalb ist mein Kopiercode INOUT->TEMP in #18 auch nicht unsauber)

In dem Speicherbereich hast Du ein Lebensbit DB100.DBX0.7 und ein Counterbyte DB100.DBB1
Im FB ermittelst Du aus dem ANY von IN_OUT.SendData die Adresse des Lebensbits (IN_OUT.SendData + P#0.7) und des Counterbytes (IN_OUT.SendData + P#1.0) und beschreibst diese indirekt.
Diese Zugriffe erscheinen nicht in den Referenzdaten, noch nicht einmal unqualifiziert als DBX0.7 oder DBB1
--> "nirgends werden DB100.DBX0.7 und DB100.DBB1 beschrieben und doch ändern sie sich!"

Harald
 
Ok super jetzt hab ich es verstanden. Gibt es aber eine andere Lösung. Oder wie würdest du es umsetzen.

Das Problem was ich hab ist das der AG_SEND und AG_RECV den CPU Ausfall nicht erkennen nur wenn die CP343 ausfällt oder eben bei Kabelbruch.
Auserdem ist die Überwachung per Watchdog sicherer.

Wie programmiere ich sonst einen Baustein der SEND u. RECV beinhaltet sowie eine Verbindungsüberwachung.
Den wir haben eine Haupt S7-300 mit 2x CP343 und 20x S7-300 mit 1x CP343-Lean und benötigen hierfür einen Baustein.
Daher dachte ich mir ich schreibe einmal einen Baustein pro Verbindungsaufbau und rufe diesen 20X auf.
 
Zurück
Oben