TIA Name & Datentyp zur Laufzeit in globalen DB erzeugen

TimeOUT

Level-1
Beiträge
125
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo und ein frohes neues Jahr erstmal,

ich versuche derzeit im TIA Portal viele Antworttelegramme zu handlen und dem Benutzer strukturiert anzuzeigen.

Für ein empfangenes Antworttelegramm benutzte ich im Instanz-DB ein Array of Byte [0 ..63] (Name: "InData")
Da dieses Array allerdings bei jeder neuen Antwort überschrieben wird möchte ich die vorhgerige Antwort in einem globalen DB zwischenspeichern.

Wie kann ich zur Laufzeit in dem globalen DB das 64Byte Array zwischenspeichern, sodass es möglichst strukturiert aufgelistet ist?
Er soll mir dabei den Namen (Reply Message) mit zugehörigem Indice und Datentype erstellen und das Antworttelegramm "InData" dort reinkopieren.

Ich stelle mir das in etwa so vor:

Reply Message #1 - Array [ 0 ..63] of Byte
Reply Message #2 - Array [ 0 ..63] of Byte
.
.
usw..

Viele Grüße
timeout
 
Ich würde einen PLC-Datentyp erzeugen, in dem du ein Array[0..63] of Byte anlegst.
Den Datentyp nennt du Reply_Message, das Array ByteNo.
Dann legst du einen globalen Datenbaustein an, in dem definierst du ein Array[1..1000] of "Reply_Message".
Dann kannst du z.Bp. mit einem Blockmove oder in SCL mit einer direkten Zuweisung die Array umkopieren.

Zugriff aus AWL dann:

Code:
      CALL  BLKMOV
         Any
         SRCBLK  :="Messages".Reply_Message[1]
         RET_VAL :=#RetVal
         DSTBLK  :="Messages".Reply_Message[2]

Zugriff aus SCL, wobei MyMessage hier eine in Temp definierte Variable vom Typ "Reply_Message" ist.

Code:
"Messages".Reply_Message[1] := #MyMessage;

Du kannst dann für den Index auch eine Int-Variable einsetzen und über diesen Index steuern, wohin das Array denn dann geschrieben werden soll (im Bsp. 1000 Plätze).

Code:
"Messages".Reply_Message[My_Int] := #MyMessage;

PS. Prüfe mal, ob 1..1000 in den DB paßt, bei mir wurde das korrekt im TIA übersetzt, man kann ja auch 1…500 nehmen oder noch weniger, je nach Bedarf.
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Vielen Dank für die Antwort

Werde es mal so umsetzen.
Mehr als 50 Antworttelegramme erwarte ich nicht, also passt das von daher ;)

/edit: Sagen wir ich habe 20 ReplyMessages in meinem globalen DB definiert.
Ich will meine ReplyMessages über eine Int-Variable, die ich nach jedem Telegramm inkrementiere, ansprechen.
Gibt es in TIA eine Funktion, die mir die Gesamtgröße des DB's zurückgibt?
Um zu verhindern, dass er mir im Falle von bspw. 21 Antwortelegrammen, bei nur 20 festgelegten ReplyMessages, nicht in undefinierte Bereiche schreibt und abstürzt.
Sollte der letzte ReplyMessage-"Speicher" (also: ReplyMEssage[20]) gefüllt sein, wird das nächste Antworttelegramm ignoriert.
 
Zuletzt bearbeitet:
Dazu mußt du doch nur den Index überwachen, den du ja selbst inkrementierst. Der darf nicht größer als 20 werden, bzw. du nutzt die 21 als KO-Kriterium.
Also immer inkrementieren, und vor dem Schreiben abfragen ob die Variable kleiner/gleich 20 ist. Ist sie das nicht (21), dann umspringst du die Scheiboperation, bzw. in SCL machst du das in einer If…Then - Anweisung.
 
Das ist mir schon bewusst ;)
Ich suche nur eine elegante Möglichkeit nicht ständig den Quellcode ändern zu müssen, wenn ich die Anzahl der gespeicherten ReplyMessages ändere.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Prinzipiell gibt es bei der S7-300/400 (wovon ich jetzt einfach mal ausgehe), den SFC24 "Test_DB", wird wohl auch in TIA zu finden sein ...
Dieser gibt unter anderem die DB-Länge in Bytes aus.
 
Ja, Test_DB gibt es noch:

Anweisung in S7-300/400:
TEST_DB


Anweisung in S7-1500
ATTR_DB


Achtung
Asynchrone Bearbeitung
Die neuen Anweisungen arbeiten in S7-1500 asynchron, d. h. ihre Ausführung erstreckt sich über mehrere Programmzyklen.
Beschreibung zu ATTR_DB
Mit der Anweisung "ATTR_DB" erhalten Sie Informationen über einen im Arbeitsspeicher der CPU liegenden Datenbaustein (DB). Die Anweisung ermittelt für den ausgewählten DB die gesetzten Attribute am Parameter ATTRIB.
Für Datenbausteine mit optimiertem Zugriff kann die Länge nicht ausgelesen werden, der Parameter DB_LENGH enthält für DBs mit optimiertem Zugriff die Länge "0".
Datenbausteine für Motion Control können mit der Anweisung "ATTR_DB" nicht ausgelesen werden. Für diese wird der Fehlercode 80B2 ausgegeben.
 
Für Datenbausteine mit optimiertem Zugriff kann die Länge nicht ausgelesen werden, der Parameter DB_LENGH enthält für DBs mit optimiertem Zugriff die Länge "0".

Leider nutze ich nur optimierte DB's :(

Dann eben doch über die statische Abfrage.
Danke!
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Du kannst ja in dem DB eine Variable vorsehen, die angibt, wie viele Messages maximal möglich sind.
Erzeugst du einen längeren DB, dann legst du die Länge darin ab.
 
Ja, Test_DB gibt es noch:

Anweisung in S7-300/400:
TEST_DB


Anweisung in S7-1500
ATTR_DB ..

Kann mir jemand sagen, wie man bei einer S7-1200 vorgeht? Ich habe aus der Classic-Welt einen SCL-Baustein, dem ich u.a. zwei BLOCK_DB übergebe. Ich benötige für indirekte Zugriffe von beiden DBs die DB-Länge und die DB-Nummer.

Der Code aus Step7-Classic bzw. S7300/400
Code:
    // DB-Länge ermitteln
        #TEMP_INT:=TEST_DB(DB_NUMBER := BLOCK_DB_TO_WORD(#DB_IN),
           DB_LENGTH      => #TEMP_WORD,
           WRITE_PROT     => #TEMP);
           #DB_IN_LAENGE   := WORD_TO_INT(#TEMP_WORD);
    
    #TEMP_INT:=TEST_DB(DB_NUMBER := BLOCK_DB_TO_WORD(#DB_OUT),
           DB_LENGTH      => #TEMP_WORD,
           WRITE_PROT     => #TEMP);
           #DB_OUT_LAENGE  := WORD_TO_INT(#TEMP_WORD);
    
    // Parameter prüfen
    IF #DB_IN_LAENGE <> #DB_OUT_LAENGE
       OR #DB_IN_LAENGE MOD 4 <> 0
       THEN RETURN;
    END_IF;
    
    // Adresse berechnen
    #ADRESSE := 4 * #AUFRUF_NUMMER;
    IF #ADRESSE > #DB_IN_LAENGE-4
       THEN RETURN;
    END_IF;
    
    // Messwert "Aufrufnummer" bearbeiten
    #x := DWORD_TO_REAL(#DB_IN.DD(#ADRESSE));
    #y := DWORD_TO_REAL(#DB_OUT.DD(#ADRESSE));

//    usw.

Die BDs sind ausschließlich mit REAL-Werten gefüllt. Ich lese aus dem einen DB ein DW nach dem anderen aus, bearbeite es und schreibe das Ergebnis in den anderen DB. Hat jemand eine Idee, wie man so etwas mit einer S7-1200 eleganter löst? Priorität liegt darauf, flexible DB-Längen als BLOCK_DB zu übergeben. Mit ANY-Pointern würde es sicherlich auch zu machen sein, möchte ich aus einem bestimmten Grund hier aber nicht machen.

Gruß, Onkel
 
Ich würde dafür Datentypen, Struct oder Array, gegebenfalls eine Kombination aus diesen nutzen.
Die Länge könnte man über Konstanten in der Symbolliste vorgeben, zumindest habe ich das in der 1500-er schon für statische Array in FB gemacht. Array[0..MaxWert] ...
Dann kann man beim Programmieren bestimmen, wie lang die Array werden sollen.

Diesse Daten dann über IN, INOUT an eineen FB/FC übergeben,der ebenfalls diese Konstante nutzt, darüber bekommt man dann auch die Länge, bzw. den Max Index.

Problem: Man kann die DB zur Lauffzeit nicht beliebig wechseln, davon uß man sich bei den 1200/1500-er SPS wohl eher verabschieden.

Für die 1500-er habe ich enen AWL-Baustein, der Any entsprechend verbiegt, aber die 1200-er kann ja kein AWL.
Bliebe die Lösung, das in SCL mit AT-Ansichten umzusetzen, dann aber mit nicht optimierten Bausteinen.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Danke Ralle, aber ich möchte nach Möglichkeit beim Parametertyp BLOCK_DB bleiben. Die DB-Größe wird sich auch nicht zur Laufzeit ändern. Mit "flexibler DB-Länge" meinte ich, von Projekt zu Projekt verschieden, jedoch nicht zur Laufzeit variabel. Ich bin gerade dabei, meine erhabenen Ergüsse der letzten zwanzig Jahre in die TIA-Welt zu retten. Ich hätte je wenigstens gedacht dass die Funktionen der S7300 auf allen neueren Generationen zu verwenden sind. In Classic war das alles überhaupt kein Akt. Ich muss nur irgendwie die DB-Länge und die DB-Nummer ermitteln können. Was kann man ohne diese Infos zu den DBs mit dem Parametertyp BLOCK_DB überhaupt anfangen?

Ich habe gerade erkannt dass das Titelthema garnicht zu meinem Problem passt, sorry. Ich hatte nach "TEST_DB" und nach "TIA" gesucht und bin halt hier gelandet, naja.
 
Mit der Konstanten geht es ja auch nciht zur Laufzeit, sondern beim Projektieren.
Ich habe inzwischen auch schon gemerkt, dass man sich von ein paar alten Zöpfen trennen muß, hilft nichts! Mach dich besser mit dem Gedanken vertraut. ;-)
 
Meine kleinen Probleme habe ich lösen können. "BLOCK_DB" habe ich durch "DB_ANY" ersetzt und meine indirekten Adressierungen durch "PEEK" & "POKE". "TEST_DB" und die damit verbundenen Parameterprüfungen habe ich einfach wegrationalisiert. Wenn ich ins Leere peeke oder poke, dann erkenne ich es am ENO, das genügt mir in diesem Fall. Wenn man tatsächlich mal die DB-Länge benötigt, dann müsste das ebenso mit peeken und Auswertung des ENO möglich sein. Nicht optimierte DBs haben in S7300/400 wie auch in S7-1200/1500 eine maximale Datenlänge von 64k. In einer Schleife sollte das mit max. 16 Durchläufen zu machen sein. Ich habe noch ein paar komplexere Standardbausteine. Bin jetzt mal optimistisch dass ich diese auch umgesetzt bekomme. Vor allem bin ich gespannt, was aus so einer preiswerten S7-1200 heraus zu holen ist ;-) .
 
Zurück
Oben