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

Ergebnis 1 bis 7 von 7

Thema: SCL Zuweisungen, indirekter Vergleich

  1. #1
    Registriert seit
    20.12.2012
    Beiträge
    4
    Danke
    3
    Erhielt 0 Danke für 0 Beiträge

    Standard


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Guten Tag,

    Ich habe zwei Fragen:

    die 1. ist schnell beantwortet:
    Ich möchte Variabel auf ein DB zugreifen z.B. Var1 := MyDB.DX[Var_Byte,VarBit]. Soweit so gut.
    Nun möchte ich aber die adresse vorher mathematisch berechnen. ich habe z.B 2 bytes (0.0 - 0.7 und 1.0 und 1.7) in dem DB hinterlegt.
    ich habe dann zum beispiel eine Formel: Var_Byte_And_Bit := 2*x .... für x = 6 hätte man ein Wert von 12. 12 entspricht normalerweise dem Bit 1.3. also hätte ich stehen:
    mit Variable: Var := MyDB.DX[Var_Byte_And_Bit] und mit zahlen ersetzt für x = 6 MyDB.DX[12]
    und jetzt meine eigentliche frage ist dieses DX[12] = DX[1.3] bzw für Var_Byte = 1 und Varbit = 3 ??? ist das das gleiche ?

    die zweite Frage:
    ich habe 2 Datenbausteine DB1 und DB2. Nun möchte ich ein Datenfeld von 10 Byte oder 80 bit vom DB1 mit dem Datenfeld aus DB2 vergleichen. wenn die gleich sind soll einfach ein Boolscher ausgang geschaltet werden.

    ich habs mal so versucht:

    Repeat
    If DB1.DX[Var_Byte_And_Bit] = DB2.DX[Var_Byte_And_Bit] Then
    Var_Byte_And_Bit := Var_Byte_And_Bit +1 ;
    End_IF;
    Until Var_Byte_And_Bit = 80;
    End_Repeat;

    If Var_Byte_And_Bit = 80 then
    Ergebnis := 1 ;
    End_if;

    oder

    For Var_Byte_And_Bit := 0 To 80 Do
    If DB1.DX[Var_Byte_And_Bit] = DB2.DX[Var_Byte_And_Bit] Then

    ja und jetzt weiss ich nicht weiter, weil ja nur jedes einzelne bit abgefragt wird. ich will aber dass alle 80 bits abgefragt werden und wenn die alle richtig sind soll das Ergebnis := 1 gesetzt werden


    Hoffe das war nicht zu umständlich erklärt. Die aufgabe im im allgemeinen lautet so:
    Man hat eine Variable Anzahl an Spannern. diese Spanner sollen für eine Variable Anzahl an Schritten je nach schritt in 2 Stellungen gefahren werden.
    Es soll z.b in Schritt 1: spanner 1 in Arbeitsstellung sein, Sp2 ind Grundstellung, Sp3 in AS, Sp4 in AS, Sp5 in GS usw.
    in Schritt 2: Sp1 in Gs, Sp2 in AS, Sp3 in AS, Sp4 in Gs usw.

    ich hab dazu mittels UDT's 2 DB's angelegt die mit max 20 Schritten und 100 Spannern vorbelegt sind. In dem DB1 sind die Sollwerte im DB2 die Istwerte.
    Dazu sollen die max 100 Spanner schritt für schritt verglichen werden. Und erst in den nächsten Schritt gehen wenn der erste Schritt erfüllt ist.


    Danke schonmal
    Zitieren Zitieren SCL Zuweisungen, indirekter Vergleich  

  2. #2
    Registriert seit
    18.04.2012
    Beiträge
    21
    Danke
    2
    Erhielt 1 Danke für 1 Beitrag

    Standard

    Zitat Zitat von lexxoe Beitrag anzeigen
    ich habs mal so versucht:

    Repeat
    If DB1.DX[Var_Byte_And_Bit] = DB2.DX[Var_Byte_And_Bit] Then
    Var_Byte_And_Bit := Var_Byte_And_Bit +1 ;
    End_IF;
    Until Var_Byte_And_Bit = 80;
    End_Repeat;

    If Var_Byte_And_Bit = 80 then
    Ergebnis := 1 ;
    End_if;

    oder

    For Var_Byte_And_Bit := 0 To 80 Do
    If DB1.DX[Var_Byte_And_Bit] = DB2.DX[Var_Byte_And_Bit] Then

    ja und jetzt weiss ich nicht weiter, weil ja nur jedes einzelne bit abgefragt wird. ich will aber dass alle 80 bits abgefragt werden und wenn die alle richtig sind soll das Ergebnis := 1 gesetzt werden


    Hoffe das war nicht zu umständlich erklärt. Die aufgabe im im allgemeinen lautet so:
    Man hat eine Variable Anzahl an Spannern. diese Spanner sollen für eine Variable Anzahl an Schritten je nach schritt in 2 Stellungen gefahren werden.
    Es soll z.b in Schritt 1: spanner 1 in Arbeitsstellung sein, Sp2 ind Grundstellung, Sp3 in AS, Sp4 in AS, Sp5 in GS usw.
    in Schritt 2: Sp1 in Gs, Sp2 in AS, Sp3 in AS, Sp4 in Gs usw.
    das erste ist böse, da es eine Endlosschleife wird wenn zwei Bits nicht gleich sind.

    die For-Schleife ist gut, ich würde es spontan so machen:

    tmpErgebnis := 1;
    For Var_Byte_And_Bit := 0 To 80 Do
    If DB1.DX[Var_Byte_And_Bit] != DB2.DX[Var_Byte_And_Bit] Then
    tmpErgebnis := 0;
    END_IF;
    END_FOR;
    Ergebnis := tmpErgebnis;
    != soll ungleich sein.

    Wenn nun ein Bit nicht stimmt wird dein Ergebnis falsch.

  3. Folgender Benutzer sagt Danke zu tommy0014 für den nützlichen Beitrag:

    lexxoe (18.02.2014)

  4. #3
    Registriert seit
    14.11.2008
    Beiträge
    66
    Danke
    3
    Erhielt 6 Danke für 6 Beiträge

    Standard

    zu Frage 1, ich vermute das ist an sich richtig, aber wie beschrieben off by one

    Bit 0.0 = Index 0
    Bit 0.7 = Index 7
    Bit 1.0 = Index 8
    Bit 1.3 = Index 11

    Das Beispiel mit 2*x erscheint mir aber völlig praxisfremd, weil alles 1 oder 8 oder 16 ... Bits hat und nicht 2. Also Zugriff auf Bit 4.5: 4*8+5. Zugriff auf Bit 4.5 des Elements an Index 7 eines Arrays [0..20] einer 12 Byte-Struktur, Startadresse des Arrays ist (Byte) 100: 100*8+7*12*8+4*8+5

    Zitat Zitat von lexxoe Beitrag anzeigen
    ja und jetzt weiss ich nicht weiter, weil ja nur jedes einzelne bit abgefragt wird. ich will aber dass alle 80 bits abgefragt werden
    Die Aussage klingt lustig. "jedes einzelne" impliziert doch "alle", selbst in Endlosschleifen (vollständige Induktion) Aber tommy0014's Lösung sieht schon richtig aus, aber die FOR Schleife muss von 0 bis anz_bits-1, also 79 gehen.

    Allerdings erscheint mir der ganze Lösungsansatz nicht ganz passend zur Aufgabe. Deine Lösung ist ein generischer Vergleicher, nur dass die Anfangsadressen und Länge festgelegt sind, so dass er gar nicht generisch nutzbar ist. Außerdem ist es assemblerähnlich oder eher noch ein Level tiefer (Umgang mit Adressen) und ineffizient (Vergleich bitweise).

    Mögliche Verbesserungen sehe ich also in 2 Richtungen: einen tatsächlich generischen Vergleicher "memcmp" in AWL, aber das führt zu ANY-Pointern ... "down that path lies madness" ... der hässliche Code existiert dann nur einmal. Oder einfach anwendungsspezifisch ein Array aus 100 Spanner-Bits oder als Erweiterung Spanner-UDTs anlegen und als solches benutzen, vergleichen etc. Das könnte flexibler sein, besonders wenn mal nicht ein 1:1-Vergleich gefordert ist.

  5. Folgender Benutzer sagt Danke zu Drutbluck für den nützlichen Beitrag:

    lexxoe (18.02.2014)

  6. #4
    Registriert seit
    27.06.2009
    Ort
    am Nordharz
    Beiträge
    3.716
    Danke
    443
    Erhielt 914 Danke für 739 Beiträge

    Standard

    Zitat Zitat von lexxoe Beitrag anzeigen
    und jetzt meine eigentliche frage ist dieses DX[12] = DX[1.3] bzw für Var_Byte = 1 und Varbit = 3 ??? ist das das gleiche ?
    Step7 erwartet m.W.n. DBx.DX[ Byte , Bit]. Deine Variante DBx.DX[ Var_Byte_And_Bit ] dürfte einen Fehler bei der Ausführung ergeben.
    Die Angabe des Index funktioniert m.W.n. nur beim symbolischen Zugriff auf ein Array.



    Bevor ich zur 2. Frage komme:
    Warum programmierst Du nicht symbolisch?
    Wie sind denn die ganzen boolschen Werte symbolisiert (wenn überhaupt)? Einzeln oder als Array oder als Struct?

    Zitat Zitat von lexxoe Beitrag anzeigen
    die zweite Frage:
    ich habe 2 Datenbausteine DB1 und DB2. Nun möchte ich ein Datenfeld von 10 Byte oder 80 bit vom DB1 mit dem Datenfeld aus DB2 vergleichen. wenn die gleich sind soll einfach ein Boolscher ausgang geschaltet werden.
    Hängt auch ein wenig davon ab, wie Du alles an den Baustein übergeben willst.


    Wenn's denn unbedingt unsymbolisch bzw. absolut sein soll, dann mal dies als Anregung:
    Code:
    FUNCTION "Bitvergleich" : BOOL
    
    VAR_INPUT
        DB_1: Block_DB;
        StartByte1: INT;
        StartBit1: INT;
        DB_2: Block_DB;
        StartByte2: INT;
        StartBit2: INT;
        Anzahl: INT;
    END_VAR
    
    VAR_TEMP
        i: INT;
    END_VAR
    
    
        "Bitvergleich" := true;
        FOR i:= 1 TO Anzahl BY 1 DO
            IF DB_1.DX[ StartByte1 + ( StartBit1 + i - 1 ) / 8 , ( StartBit1 + i - 1 ) MOD 8 ] <>
               DB_2.DX[ StartByte2 + ( StartBit2 + i - 1 ) / 8 , ( StartBit2 + i - 1 ) MOD 8 ] THEN
                "Bitvergleich":= false;
            END_IF;
        END_FOR;
        
    
    END_FUNCTION
    
    Ich würde aber eine Variante vorziehen, bei der die Bytes/Bits symbolisch übergeben werden.
    Geändert von hucki (17.02.2014 um 22:13 Uhr) Grund: "Mit beliebigen Bit beginnen" eingefügt

  7. Folgender Benutzer sagt Danke zu hucki für den nützlichen Beitrag:

    lexxoe (18.02.2014)

  8. #5
    Registriert seit
    01.10.2012
    Beiträge
    203
    Danke
    12
    Erhielt 56 Danke für 36 Beiträge

    Standard

    *dummfrag*
    Wenn die Datensätze nur auf Ungleicheit geprüft werden sollen, warum dann nicht byte- bzw. wortweise? Solange ich nicht das ungleiche Bit ermitteln will ist es doch Banane was da wo ungleich ist. Durchrennen bis bis was ungleich ist und dann raus aus der Schleife.
    */dummfrag*
    Nüchtern betrachtet war es besoffen besser.

  9. #6
    lexxoe ist offline Neuer Benutzer
    Themenstarter
    Registriert seit
    20.12.2012
    Beiträge
    4
    Danke
    3
    Erhielt 0 Danke für 0 Beiträge

    Standard

    Hallo zusammen,
    Danke schonmal für die antworten !

    Die Aufgabe ist noch etwas komplizierter... also die vorher beschriebenen Spanner bleiben. Genauso wie die einzelnen Schritte. Es sollen aber hinzu noch unterschiedliche Programme laufen. D.h Programme 0-128, Schritte 0-10, Spanner 0-100. Die jeweil verschachtelt sind. ich habe das mit UDt's gemacht

    z.B UDT1:
    Code:
      
    Sp1_GS    
    Sp1_AS    
    Sp2_GS   
    Sp2_AS
    
    bis 
    
    Sp100_AS
    im UDT2:
    Code:
    Schritt    ARRAY[1..10]   
        "Spanner"
    im DB1:
    Code:
    PRG    ARRAY[0..128]           
        "HMI_Sollwerte"
    Also steht im DB1 in der Datenansicht:
    Code:
    PRG[0].Schritt[1].Sp1_GS    
    PRG[0].Schritt[1].Sp1_AS  
    ...
    PRG[128].Schritt[10].Sp100_AS
    es Soll jetzt je nachdem welches Programm gerade läuft die Schritte mit den Spannern vom DB1 (Sollwerte) mit dem DB2 (Istwerte) verglichen werden?

    Zitat von Drutbluck

    Allerdings erscheint mir der ganze Lösungsansatz nicht ganz passend zur Aufgabe.
    wie hättest du es denn gemacht ?

  10. #7
    Registriert seit
    14.11.2008
    Beiträge
    66
    Danke
    3
    Erhielt 6 Danke für 6 Beiträge

    Standard


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Hallo,

    sorry ich bin nicht so oft im Forum und habe nicht so oft Zeit zu schreiben.

    Ein Vergleicher ist wahrscheinlich am besten eine separate Funktion, diese ist entweder vollkommen generisch oder typ(UDT)-spezifisch.

    Der UDT-spezifische Vergleicher ist am Anfang am einfachsten und vielleucht auch flexibler. Dazu einen FC erstellen, in SCL oder AWL oder ..., mit 2 INPUT-Parametern des UDT-Typs. Diese Parameter lassen sich sowohl einfach übergeben als auch einfach abfragen. Symbolisch, und mit beliebigen Instanzen des UDT.

    Arrayzugriffe sind ohnehin ineffizient, ich denke Zugriff via Parameter ist nur wenig ineffizienter.

    Ein generischer Vergleicher geht mit ANY-Pointern, dabei ist die Parameterübergabe einfach, den Vergleicher selbst zu schreiben ist nicht so einfach aber dafür geht es so effizient wie eben möglich.

    Dein Beispielcode zum Vergleichen könnte auch mit einem Präprozessor generiert werden, der so etwas ähnliches wie C-Makros in SCL implementiert. Das ist effizienter als ein Vergleicher-FC und hat noch andere Vorteile, aber die höchste Effizienz erfordert möglichst DINT-Vergleiche statt BOOL. Dann muss zunächst mal der Präprozessor entwickelt werden.

    Nur das direkte manuelle "absolute" "Programmieren" ohne rein symbolischen Quellcode würde ich möglichst vermeiden.

Ähnliche Themen

  1. Step 7 S7 SCL indirekter Adressierung Merker - Fehler abfangen
    Von trexer im Forum Simatic
    Antworten: 6
    Letzter Beitrag: 24.04.2013, 00:49
  2. Indirekter zugriff auf DB's (SCL)
    Von zloyduh im Forum Simatic
    Antworten: 5
    Letzter Beitrag: 03.05.2012, 09:45
  3. Vergleich AWl <--> SCL
    Von nobug im Forum Programmierstrategien
    Antworten: 6
    Letzter Beitrag: 11.03.2008, 20:11
  4. SCL - Indirekter Zugriff auf DB/AR1,2
    Von Floh im Forum Simatic
    Antworten: 5
    Letzter Beitrag: 07.06.2006, 10:32
  5. Indirekter Datenbausteinaufruf in SCL
    Von Anonymous im Forum Simatic
    Antworten: 5
    Letzter Beitrag: 13.09.2005, 14:47

Stichworte

Lesezeichen

Berechtigungen

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