Zuviel Werbung? - > Hier kostenlos beim SPS-Forum registrieren

Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 11

Thema: Lösung: 2 Structs miteinander vergleichen ohne vorher die Struktur zu kennen.

  1. #1
    Registriert seit
    04.03.2015
    Beiträge
    66
    Danke
    10
    Erhielt 31 Danke für 12 Beiträge

    Idee


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Hallo zusammen,
    ich habe eine Lösung gefunden um 2 Structs miteinander zu vergleichen. Es gab dabei mehrere Probleme vorallem mit Strings die ihre vorherigen Einträge nicht löschen wenn dieser mit einem Kürzerer String überschrieben wurde

    Ich benutze eine S7 1513-1 PN

    Es wird ein "nicht bausteinoptimierter" DB benötigt der 2 Arrays mit jeweils einem Array[0..300] of Byte enthält ( die 300 kann natürlich variieren)

    Code:
    IN:
    IN_1           : Variant
    IN_2           : Variant
    
    OUT :
    Unterschied_erkannt : Bool
    
    Temp:
    i               : int
    LEN_1        : dint
    LEN_2        : dint
    RET_VAL_1 : int
    RET_VAL_1 : int
    Unterschied : bool
    
    //Structs in Array of byte kopieren
    #RET_VAL_1 := Serialize(SRC_VARIABLE := #IN_A, DEST_ARRAY=>"GLB_HW_Vergleichs_DB".A , POS:= #LEN_1);
    #RET_VAL_2 := Serialize(SRC_VARIABLE := #IN_B, DEST_ARRAY=>"GLB_HW_Vergleichs_DB".B, POS:= #LEN_2);
    
    
    #Unterschied := false;
    
    // arrays bytweise vergleichen und Array anschließend auf 0 setzen !Wichtig!
    IF #LEN_1 = #LEN_2 THEN
        FOR #i := 0 TO #LEN_1 DO
            IF "GLB_HW_Vergleichs_DB".A[#i] <> "GLB_HW_Vergleichs_DB".B[#i] THEN
                #Unterschied := true;
            END_IF;
            "GLB_HW_Vergleichs_DB".A[#i] := 0;
            "GLB_HW_Vergleichs_DB".B[#i] := 0;
            If #Unterschied then
                 EXIT;
            END_IF;
        END_FOR;
    ELSE
    // wenn Längen unterschiedlich dann sind die Structs eh unterschiedlich
        #Unterschied := true;
    END_IF;
    
    Unterschied_erkannt := Unterschied;
    ich hoffe es nützt euch

    Balu

    *edit Anmerkungen von Harald eingebaut
    *edit Anmerkungen von Peter eingebaut
    Geändert von Balu_der_Bär (30.03.2017 um 10:20 Uhr)
    Zitieren Zitieren Lösung: 2 Structs miteinander vergleichen ohne vorher die Struktur zu kennen.  

  2. Folgende 3 Benutzer sagen Danke zu Balu_der_Bär für den nützlichen Beitrag:

    kafiphai (30.03.2017),Münchnerjunge (30.03.2017),vollmi (25.08.2016)

  3. #2
    Registriert seit
    22.06.2009
    Ort
    Sassnitz
    Beiträge
    10.785
    Danke
    884
    Erhielt 3.160 Danke für 2.560 Beiträge

    Standard

    Hallo Balu,

    zunächst mal Danke für die Veröffentlichung Deiner Idee. Unter TIA funktioniert ja vieles nicht mehr so einfach.
    Trotzdem ein paar Fragen und Kritiken.

    1) Warum vergleichst Du die Arrays erst ab dem zweiten Byte?
    2) Warum ist es wichtig, die Array-Bytes nach dem Vergleich auf 0 zu setzen?
    3) Sobald der erste Unterschied gefunden wurde kann man den Vergleich (Schleife) abbrechen.
    4) Es ist ungünstig, dem OUT "Unterschied" mehrmals Werte zuzuweisen. Besser eine interne Variable benutzen und am Ende die interne Variable auf den OUT kopieren.
    5) Wo/Wie ist das Problem mit dem STRING-Vergleich gelöst?

    Weil ich gerade kein TIA zur Verfügung habe:
    6) Wie geht "Serialize" mit vom TIA versteckten Struct-Membern und mit Padding-Bytes und Padding-Bits um?
    7) Wie ist die Repräsentation von Bools nach dem Serialize?

    PS: Du könntest noch erwähnen, für welche SPS der Code gedacht ist.

    Harald
    Es ist immer wieder überraschend, wie etwas plötzlich funktioniert, sobald man alles richtig macht.

    FAQ: Linkliste SIMATIC-Kommunikation über Ethernet

  4. Folgender Benutzer sagt Danke zu PN/DP für den nützlichen Beitrag:

    Balu_der_Bär (25.08.2016)

  5. #3
    Registriert seit
    04.03.2015
    Beiträge
    66
    Danke
    10
    Erhielt 31 Danke für 12 Beiträge

    Standard

    Hallo Harald,
    danke für deine Anmerkungen

    1) Warum vergleichst Du die Arrays erst ab dem zweiten Byte?

    Danke das war ein Fehler meinerseits.

    2) Warum ist es wichtig, die Array-Bytes nach dem Vergleich auf 0 zu setzen?

    Da muss ich ein wenig weiter ausholen auch in der Vermutung das ich viel bekanntes erzähle.

    Wenn ein Variable of String in eine andere Variable kopiert wird, wird nur der "sichtbare" Teil kopiert + die Maximale und die genutzte länge.

    Bsp:
    Variable A und B sind vom Typ String[10]
    A := 'test'
    B := '1234567890'

    Trotz der nur [10] Zeichen hat die Variable aber 12 Byte Länge, da vorweg noch die Maximale länge (10) und die tatsächlich genutzten Zeichen ( für A 4) stehen.

    Kopiert man nun A nach B steht dort zwar Symbolisch B ='test' , schaut man sich jedoch den String als Array an sieht man das dort 'test567890' steht und nur durch den nicht sichtbaren "genutzte Länge" Teil der Rest nicht berücksichtigt wird.

    Problematisch wird es wenn man einen Umweg über eine weitere Variable geht
    A := 'test'
    B := 'XXXXXX'
    C := '1234567890'
    D := ''
    E := ''

    Wenn wir nun folgende schritte abarbeiten:
    D := C
    D := B
    D := A
    E := C
    E := A

    Haben wir durch das mehrfache überschreiben zwar symbolisch in E und D 'test' stehen, aber wenn man sich das ganze Absolut anschaut steht in E 'test567890' und in D 'testXX7890'

    Da man Strukturen nicht miteinander vergleichen kann muss man diese Byte weise vergleichen und dann haben wir das eben gezeigte Problem das trotz der Symbolischen Gleichheit es einen Unterschied gibt.

    Man müsste also vor jedem Kopiervorgang die variable D und E initialisieren.

    Wenn man auf die absolute Adressierung verzichten will, fallen die normalen Move befehle
    ( ":=" , "Move_blk_variant") weg, da diese nur 2 gleichen Datentypen zum kopieren akzeptieren und ich nicht weiß wo sich der String befindet den ich löschen will.

    Daher nutze ich den "Serialize" Befehl, der die ganze Struktur in ein Array of Byte kopiert und überschreibe nach jedem vergleichen das Byte mit 0, damit beim nächsten kopieren die "Phantomzeichen" gelöscht sind.


    3) Sobald der erste Unterschied gefunden wurde kann man den Vergleich (Schleife) abbrechen.

    in meinem Fall überprüfe ich zyklisch ob sich die Eingabe im Editorfenster gegenüber dem gespeichertem im Array geändert hat. Dies wird in 99,9% der Fälle nicht der Fall sein , daher habe ich darauf verzichtet da es auf das eine Mal dann auch nicht mehr drauf an kommt. In anderen Bereichen kann das aber durchaus Sinn machen ja.


    4) Es ist ungünstig, dem OUT "Unterschied" mehrmals Werte zuzuweisen. Besser eine interne Variable benutzen und am Ende die interne Variable auf den OUT kopieren.
    Hast du recht, ändere ich ab.

    5)Wo/Wie ist das Problem mit dem STRING-Vergleich gelöst?

    siehe 2

    6) Wie geht "Serialize" mit vom TIA versteckten Struct-Membern und mit Padding-Bytes und Padding-Bits um?

    Ich denke das alle Informationen dort abgebildet werden.In meinem Beispiel hatte ein String der Länge[10] 22 Byte belegt.Da ich davon nur 12 Byte zuordnen kann muss da noch einiges verstecktes drin sein.
    Serialize ist dafür gemacht um ein Struct über einen Seriellen Bus auf eine andere SPS zu übertragen. Das Gegenstück nennt sich dann Deserialize. Um das Struct exakt kopieren zu können müssen ja alle Informationen vorhanden sein.
    Aber mehr kann ich dir dazu nicht sagen.

    7) Wie ist die Repräsentation von Bools nach dem Serialize?
    müsste ich ausprobieren, komme ich aber heute nicht mehr zu

  6. #4
    Registriert seit
    09.08.2013
    Beiträge
    23
    Danke
    10
    Erhielt 7 Danke für 6 Beiträge

    Standard

    Hallo Balu,
    ich habe mich heute mit deinem Script beschäftigt.
    Erstmal Besten Dank dafür!

    Es sind mir ein paar Unstimmigkeiten aufgefallen:
    3) Sobald der erste Unterschied gefunden wurde kann man den Vergleich (Schleife) abbrechen.
    Der Abbruch innerhalb der Fallentscheidung auf ungleich verhindert eine Initialisierung des ByteArray[i] mit 0.
    Nachdem ein Unterschied erkannt wurde hat dann die Auswertung nicht mehr richtig funktioniert.
    Beim Nachladen des Parametersatz blieben so scheinbar einige Byte beschrieben, ein Unterschied war geboren...


    Ich habe den Schleifenabbruch versetzt und so funkt. alles bisher:

    Code:
    IF #LEN_1 = #LEN_2 THEN
        FOR #i := 0 TO #LEN_1 BY +1 DO
            IF "VergleichDB".A[#i] <> "VergleichDB".B[#i] THEN
                "VergleichDB".Unterschied := true;
            END_IF;
            "VergleichDB".A[#i] := 0;
            "VergleichDB".B[#i] := 0;
            IF "VergleichDB".Unterschied THEN   EXIT;   END_IF;
        END_FOR;
    ELSE

    LG
    Peter

  7. #5
    Registriert seit
    04.03.2015
    Beiträge
    66
    Danke
    10
    Erhielt 31 Danke für 12 Beiträge

    Standard

    Hallo Peter,
    danke für die Information habs oben schon abgeändert.

    inzwischen wird man dieses Code jedoch kaum noch brauchen, da es mit V14 möglich ist den inhalt von 2 Datentypen direkt miteinander zu vergleichen

    Code:
    If datentyp1 =datentyp2 then
    ;
    end_if;
    leider ist dort noch ein Bug drin der es nicht zulässt in SCL datentypen eines arrays zu vergleichen. Hab Siemens das schon mitgeteilt und sie geloben Besserung

    bis dahin muss man für den vergleich zuerst die Datentypen in einen Temporären bereich kopieren und dann vergleichen.

    grüße

    Balu
    Geändert von Balu_der_Bär (30.03.2017 um 10:29 Uhr)

  8. #6
    Registriert seit
    22.06.2009
    Ort
    Sassnitz
    Beiträge
    10.785
    Danke
    884
    Erhielt 3.160 Danke für 2.560 Beiträge

    Standard

    Zitat Zitat von kafiphai Beitrag anzeigen
    Es sind mir ein paar Unstimmigkeiten aufgefallen:
    3) Sobald der erste Unterschied gefunden wurde kann man den Vergleich (Schleife) abbrechen.
    Der Abbruch innerhalb der Fallentscheidung auf ungleich verhindert eine Initialisierung des ByteArray[i] mit 0.
    Nachdem ein Unterschied erkannt wurde hat dann die Auswertung nicht mehr richtig funktioniert.
    Hähhh? Was hat das Ablöschen des unterschiedlichen Bytes in beiden Arrays nach dem Vergleich mit dem Vergleichsergebnis zu tun? Warum mußt Du die beiden Bytes ablöschen, was hat bei Dir nicht richtig funktioniert?

    PS: Übrigens bezeichnet das Wort Initial etwas, was man vorher macht und nicht nachher. "Initialisierung" ist der falsche Ausdruck für das was Du da meinst - kann es sein, daß Du vielleicht auch eine falsche Vorstellung hast von dem was der Code tut? Der Code von Balu funktioniert sowieso nur eingeschränkt und keinesfalls universell, weil er auch von den Daten nicht belegten Speicher (Padding) mit vergleicht - er kann nicht prüfen, ob die Strukturen überhaupt gleich aufgebaut sind oder ob die Datentypen gleich sind. Ein simples Kopieren des Codes für eigene abweichende Zwecke kann zu Fehl-Meldungen über Unterschiede führen.


    Zitat Zitat von Balu_der_Bär Beitrag anzeigen
    Hallo Peter,
    danke für die Information habs oben schon abgeändert.
    Hallo Balu,
    besser Du verbesserst nicht sofort angebliche Bugs in Deinem Beitrag #1, irgendwann sieht man nicht mehr das Konzept.

    Zitat Zitat von Balu_der_Bär Beitrag anzeigen
    inzwischen wird man dieses Code jedoch kaum noch brauchen, da es mit V14 möglich ist den inhalt von 2 Datentypen direkt miteinander zu vergleichen

    Code:
    If datentyp1 =datentyp2 then
    ;
    end_if;
    Hast Du eine Ahnung, was für eine Zykluszeit-Bombe Du Dir mit der einen unscheinbaren Zeile in Dein Programm holst, wenn das Programm den Vergleich nicht immer macht?

    Harald
    Es ist immer wieder überraschend, wie etwas plötzlich funktioniert, sobald man alles richtig macht.

    FAQ: Linkliste SIMATIC-Kommunikation über Ethernet

  9. #7
    Registriert seit
    27.05.2004
    Ort
    Thüringen/Berlin
    Beiträge
    12.140
    Danke
    524
    Erhielt 2.672 Danke für 1.929 Beiträge

    Standard

    Zitat Zitat von PN/DP Beitrag anzeigen
    Hast Du eine Ahnung, was für eine Zykluszeit-Bombe Du Dir mit der einen unscheinbaren Zeile in Dein Programm holst, wenn das Programm den Vergleich nicht immer macht?

    Harald
    Effektiver Code interessiert doch heute keinen mehr, schau mal ins Forum da wimmelt es von Schleifen und Strings
    Gruß
    Ralle

    ... there\'re 10 kinds of people ... those who understand binaries and those who don\'t …
    and the third kinds of people … those who love TIA-Portal

  10. #8
    Registriert seit
    09.08.2013
    Beiträge
    23
    Danke
    10
    Erhielt 7 Danke für 6 Beiträge

    Standard

    Umgebung:
    TIA V13 SP1 Upd9 mit PLCsim und nettoPLCsim mit WInCC Advanced Simulation am PC

    Hier eine Beschreibung:

    Befindet sich der EXIT innerhalb der IF Abfrage und ein Unterschied der serialisierten UDT's wird erkannt, wird dem Bit "VergleichDB".Unterschied "true" zugewiesen.
    Soweit, so gut.
    Werden nun neue, gleiche Daten in die UDT's geladen und kommen im nächsten Zyklus serialisiert (je 49 Byte) in den Schleifenvergleich, dann wird weiterhin ein Unterschied erkannt.

    Befindet sich der EXIT nach der Initialisierung innerhalb der Schleife, funktioniert alles!
    Initialisierung deshalb, da die Schleife alle Elemente auf einen definierten Zustand für den kommenden Schleifendurchlauf bringt.
    Also wird es ja gewissermaßen vorher gemacht...

    Letztlich sah ich die Ursache für das Verhalten in der enthaltenen String Variable:
    2) Warum ist es wichtig, die Array-Bytes nach dem Vergleich auf 0 zu setzen?

    Ich bedanke mich für eure Zeit und bin offen für andere Herangehensweisen.

    Peter

  11. #9
    Registriert seit
    22.06.2009
    Ort
    Sassnitz
    Beiträge
    10.785
    Danke
    884
    Erhielt 3.160 Danke für 2.560 Beiträge

    Standard

    Zitat Zitat von kafiphai Beitrag anzeigen
    Befindet sich der EXIT nach der Initialisierung innerhalb der Schleife, funktioniert alles!
    Initialisierung deshalb, da die Schleife alle Elemente auf einen definierten Zustand für den kommenden Schleifendurchlauf bringt.
    Also wird es ja gewissermaßen vorher gemacht...
    Nein, nicht vorher, denn Du "initialisierst" für einen nächsten Schleifendurchlauf - und wer "initialisiert" die Elemente VOR dem ersten Durchlauf? Nach Deiner Erklärung vergleichst Du beim ersten Durchlauf sozusagen nicht initialisierte Elemente und initialisierst erst nach dem Vergleich - Was soll der Sinn hinter einem solchen Vorgehen sein?

    Außerdem: selbst wenn Du nach dem Vergleich erst noch die beiden unterschiedlichen Bytes "initialisierst" und dann die Schleife verläßt - wie werden die Elemente hinter dem ersten Unterschied "initialisiert"? Da können ja auch noch Unterschiede sein, die beim nächsten mal noch nicht "initialisiert" wurden... Dein Vorgehen funktioniert nur scheinbar oder zufällig. Die Ursache für Dein Problem muß woanders liegen. Theoretisch sollte doch das Serialize() sämtliche Bytes des Ausgabe-Arrays definiert beschreiben - "initialisieren"! Hast Du das mal alleine getestet?
    Also wenn die Serialize-Funktion wirklich so scheixxe funktioniert, daß sie nicht initialisierte String-Restbytes oder Padding-Bytes in das Ausgabe-Array einstreut, dann taugt das ganze Vorgehen überhaupt nichts und das Ausgabe-Array muß VOR dem Serialize() komplett gelöscht/initialisiert werden.


    Zitat Zitat von kafiphai Beitrag anzeigen
    Werden nun neue, gleiche Daten in die UDT's geladen und kommen im nächsten Zyklus serialisiert (je 49 Byte) in den Schleifenvergleich, dann wird weiterhin ein Unterschied erkannt.
    Klingt ja unglaublich! Höchstens Deine UDT enthalten Strings, die nicht max-voll sind - doch auch dann dürfte Dein Beschreiben des Ausgabe-Arrays im Durchlauf vor dem erneuten Serialize() keinen Einfluß haben. Es sei denn, das Serialize() funktioniert nicht richtig.

    Kannst Du uns mal zeigen wie Deine 49 Byte langen UDT deklariert sind? Und wie das aus Serialize() resultierende Byte-Array aussieht (welche Werte in den einzelnen Bytes stehen)?


    PS: irgendwie scheint dieses Serialize() und Deserialize() so ziemlich die krankhafteste Lösung zu sein, aus "optimiertem" Speicher einen Speicherbereich mit kontrollierter Struktur zu machen. Wenn ich feststellen würde, daß ich Serialize() und Co brauche, dann wäre das ganz klar das Argument, daß der betreffende Speicherbereich "nicht-optimiert" gehört.

    Harald
    Es ist immer wieder überraschend, wie etwas plötzlich funktioniert, sobald man alles richtig macht.

    FAQ: Linkliste SIMATIC-Kommunikation über Ethernet

  12. #10
    Registriert seit
    09.08.2013
    Beiträge
    23
    Danke
    10
    Erhielt 7 Danke für 6 Beiträge

    Standard


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    So, ein paar Tests:
    Exit innerhalb der IF Abfrage

    1. Flanke: gespeicherte Datensätze[1] --> Projektierfelder.Datensatz : danach im Projektier Feld die Bezeichnung auf 'Test 11' erweitert. Unterschied erkannt!
    2. Flanke: gespeicherte Datensätze[2] --> Projektierfelder.Datensatz : es fehlen schon manche String Byte im Array des VergleichDB... INT und TIME sind korrekt.
    3. im FB die Zeilen mit der 0-Zuweisung und EXIT aus kommentiert --> die Byte im Array sind nun richtig aus "Projektierfelder.Datensatz" serialisiert worden!

    VergleichDB.A entspricht dem serialisierten Projektierfelder.Datensatz.
    Das Problem tritt nur auf, wenn der nachfolgende String kürzer ist.
    Was mit 'Test 2' gegenüber 'Test 11' der Fall war.

    War ja im ersten Beitrag auch schon so beschrieben:
    Es gab dabei mehrere Probleme vorallem mit Strings die ihre vorherigen Einträge nicht löschen wenn dieser mit einem Kürzerer String überschrieben wurde

    Ist das EXIT außerhalb der IF Abfrage innerhalb der Schleife funktioniert alles wie erwartet.

    LG
    Peter
    Angehängte Grafiken Angehängte Grafiken
    • Dateityp: jpg 1..JPG (476,3 KB, 19x aufgerufen)
    • Dateityp: jpg 2..JPG (480,8 KB, 15x aufgerufen)
    • Dateityp: jpg 3..JPG (470,1 KB, 12x aufgerufen)
    Zitieren Zitieren Tests  

Ähnliche Themen

  1. Antworten: 6
    Letzter Beitrag: 25.02.2016, 16:05
  2. 2 Datenbausteine miteinander vergleichen
    Von SPS-Fuchs im Forum Simatic
    Antworten: 18
    Letzter Beitrag: 10.12.2015, 08:44
  3. TIA Zeiten miteinander vergleichen
    Von kuti im Forum Simatic
    Antworten: 17
    Letzter Beitrag: 22.09.2013, 19:44
  4. UDTs miteinander vergleichen
    Von Freakazoid im Forum Simatic
    Antworten: 2
    Letzter Beitrag: 25.03.2011, 10:08
  5. 3 Char miteinander vergleichen
    Von MK_Auto im Forum Simatic
    Antworten: 17
    Letzter Beitrag: 13.11.2010, 09:42

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •