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

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

Thema: Zeichenkette über Zeiger in DB speichern

  1. #1
    Registriert seit
    26.03.2016
    Beiträge
    16
    Danke
    7
    Erhielt 0 Danke für 0 Beiträge

    Standard


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Ich hoffe der Titel ist nicht zu unverständlich, mir ist leider nichts passendes eingefallen.

    Ich bin Automatiker im 4. Lehrjahr und erlerne zurzeit die Grundlagen in AWL. Ich habe nun die Möglichkeit einen Notebookmanager zu entwerfen. Dieser soll bewerkstelligen das wir einen Überblick haben, wer zurzeit welchen Laptop hat. Zu diesem Zweck haben wir ein HMI Panel über welchen man den Namen und die Laptop Nr. eintragen kann, diese Daten werden dann in einem DB gespeichert.

    Nun bin ich soweit das ich über des Eingabefeld eine Zeichenkette eintragen und sie in einem DB mit dem Datentyp String abspeichern kann. Jetzt will ich diese Eingabe in einen anderen DB Laden bei welchem der Offset über einen Pointer veränderbar ist. Ich habe mir das Programm so vorgestellt.


    // Bedingung neuen Benutzer einlesen
    A "Neuen Benutzer einlesen" => I0.0
    FP "Flankenmerker (Neuen Benutzer einlesen)" =>M4.4
    S "Hilfsmerker(Neuen Benutzer einlesen)" => M4.5
    JCN Exit
    R "Hilfsmerker(Neuen Benutzer einlesen)" => M4.5
    // Schleifenzähler auf 0
    L 0
    T "Schleifenzähler_Benutzer einlesen" => MW 5
    loop: NOP 0
    // Pointer
    L "Schleifenzähler_Benutzer einlesen" => MW 5
    L 254
    *I
    SLD 3
    LAR1
    // Freien Platz suchen
    OPN "Benutzernamen" => DB2
    L DBW [ AR1 , P#0.0 ]
    L ' '
    ==I
    JC Einlesen
    //Schleifenzähler + 1
    L "Schleifenzähler_Benutzer einlesen" => MW5
    L 1
    +I
    T "Schleifenzähler_Benutzer einlesen" => MW5
    // Maximale Anzahl an freien plätzen erreicht
    L 20
    L "Schleifenzähler_Benutzer einlesen" => MW 5
    ==I
    = "Keine freien plätze mehr" => M4.6
    JC Exit
    // von vorne beginnen
    JU loop

    Einlesen : NOP 0
    // Pointer Benutzer einlesen
    L "Schleifenzähler_Benutzer einlesen" => MW5
    L 254
    *I
    SLD 3
    LAR1
    // Benutzername Speichern
    L "HMI Eingabe"."Benutzernamen eingabe" => DB3
    OPN "Benutzernamen"
    L DBW [ AR1 , P#0.0 ] => DB2


    Allerdings kommt nun beim Laden des DB3 folgende Fehlermeldung: Der Operand String ist für diese Anweisung nicht zulässig.

    Leider versuche ich nun schon seit langem einen anderen Weg zu finden um diesen Fehler zu beheben aber mir ist bis jetzt noch nichts gelungen. Gibt es vielleicht irgendeine Möglichkeit über den Datentyp Char ?

    Ich hoffe das klar ist was ich meine.
    Zitieren Zitieren Zeichenkette über Zeiger in DB speichern  

  2. #2
    Registriert seit
    23.07.2009
    Ort
    Österreich
    Beiträge
    2.354
    Danke
    455
    Erhielt 694 Danke für 519 Beiträge

    Standard

    Du hast uns leider nicht verraten in welcher SPS du programmiert. S7-300/400 oder 1200/1500.
    Bei letzteren wäre es mit einem Array_of_String sehr einfach. Auch in 300/400 sofern man SCL einsetzt.

    In 300/400-AWL ist es ein wenig komplizierter.
    Zitat Zitat von PLU Beitrag anzeigen
    Allerdings kommt nun beim Laden des DB3 folgende Fehlermeldung: Der Operand String ist für diese Anweisung nicht zulässig.
    Der L(Lade)-Befehl lädt Werte in die AKKUs der CPU. Diese sind aber 32-Bit groß und somit auf Datentypen wie DWORD,DINT oder REAL begrenzt. Ein String-Wert kann so nicht geladen werden.

    Zum Kopieren von längeren Datenbereichen verwendet man die Funkion SFC20 BLKMOV und kommt damit in Berührung mit dem ANY-Pointer.
    Lies dazu bitte einmal erst das hervorragende FAQ von Volker.
    Any-Zeiger für Datentypen


    Bevor es komplizierter wird.
    Du könntest auch das variable "Pointer"-basierende programmieren auslassen und einfach einen SFC20-Aufruf für jeden Ziel-String programmieren und diesen via Index selektieren.

    Wenn es immer noch variabel sein soll, dann muss nun dieser ANY-Pointer (welcher die Information über Start-Adresse und Länge des zu kopieren Bereichs enthält) variabel zusammenbaut werden.

    Hier ein Beispiel:
    Datenbaustein mit 20 Strings mit der Länge 30 Zeichen beginnend ab Byte 100.
    Am Anfang des Datenbausteins speichere ich mir noch ein paar Variablen ab welche Information über die Beschaffenheit der Strings enthalten.
    Code:
    L    10
    T    DbStrings.DbNr        //Datenbausteinnummer
    L    20
    T    DbStrings.StringCnt    //Anzahl der Strings
    L    100
    T    DbStrings.StringN1Offset    //Offset des ersten Stings im DB
    L    32
    T    DbStrings.StringByteLEN    //Länge eines Strings (Zeichenanzahl in Byte + 2Byte für Längeninformation)
    Jetzt zum erstellen des ANY-Pointers und dem Kopieren
    Code:
    L    StringIndex        //Nummer des Strings auf den kopiert werden soll (1..20)
    L    1
    >=I
    U(
    L    StringIndex
     L    DbStrings.StringCnt    //Prüfen dass kein falscher Index angegeben wurde
    <=I
    )
    SPBN MErr
    
    
    //Schritt 1 - Berechnen der Startadresse des gewünschten Strings.
    L    StringIndex
    +    -1
    L    DbStrings.StringByteLEN
    *I
    L    DbStrings.StringN1Offset
    +I
    T    #tmpStringStartAddr    //Berechnete Startadresse des Strings (TEMP-Bereich)
    
    
    //Im TEMP-Bereich des Bausteins wurde auf Byte 0 eine Variable "tmpANY" vom Typ "ANY" (ANY-Pointer) angelegt.
    //Diesen wird, entsprechend dem FAQ, passend modifiziert
    
    L    B#16#10            //Kennung "S7" auf Byte 0 des ANY
    T    LB0
    L    B#16#02            //Datentyp Byte
    T    LB1
    L    DbStrings.StringByteLEN    //Anzahl der zu kopierenden Bytes
    T    LW2
    L    DbStrings.DbNr         //Datenbaustein-Nummer
    T    LW4
    L    #tmpStringStartAddr    //Startadresse                    
    SLD  3
    T    LD6
    L    B#16#84
    T    LB6                        //Speicherbereich - Datenbaustein
    
    
    //Jetzt hast du einen ANY-Pointer der z.B. bei Index 5 folgende Information enthalten würde.
    //   Speicherbereich Datenbaustein
    //   Datenbausteinnummer 10
    //   Startadresse 228
    //   Länge 32Byte
    
    //Nun zum Kopieren mit SFC20 BLKMOV
    
          CALL  "BLKMOV"
           SRCBLK :=DBString.StringAusEingabe    //String mit Länge 30 Zeichen aus der Eingabe
           RET_VAL:=#tmpRETVAL            //Rückgabewert der Funktion (bei Erfolg 0)
           DSTBLK :=#tmpANY                //Der ANY-Pointer (Kopier-Ziel)
    PS.: Wenn du hier Code postest, verwende entweder das "#"-Symbol im Menü oder füge manuell am Beginn ein
    [CODE] und am Ende ein [/CODE] ein.
    If at first you don't succeed, you're not Van Damme!
    ... or maybe using TIA!

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

    PLU (27.03.2016)

  4. #3
    PLU ist offline Neuer Benutzer
    Themenstarter
    Registriert seit
    26.03.2016
    Beiträge
    16
    Danke
    7
    Erhielt 0 Danke für 0 Beiträge

    Standard

    Ich Programmiere eine S7/1500 im TIA.

    Das FAQ Any-Zeiger für Datentypen habe ich durchgelesen und mehr oder weniger verstanden. Ich verstehe die Funktion des SFC 20 und auch ungefähr wie der Any-Pointer aufgebaut ist, aber ich denke das mir hier noch die Grundlagen im AWL programmieren fehlen. Ich habe dann ein Programm wie folgt aufgebaut, dies hat leider nicht wirklich funktioniert, was mir zeigt das das ich den Any-Zeiger doch nicht verstanden habe.

    Das Programm sah so aus.
    Code:
          L     B#16#10              // was ist mit :"10h für s7" gemeint ?
          T     %LB0
          L     B#16#13              //Typ String
          T     %LB1
          L     1                    // Keine Wiederholung 
          T     %LW2
          L     1                    //DB1 
          T     %LW4
          L     MW0    //Wird bei jeder Eingabe um 254 erhöht
          SLD   3                    //Pointer
          T     %LD6
          L     B#16#84
          T     %LB6
          CALL  BLKMOV
             SRCBLK  :="HMI Eingabe"."Eingabe über HMI"
             RET_VAL :="Fehlercode"
             DSTBLK  :=#MyZeiger
    Den Code welcher du als Beispiel geschrieben hast habe ich leider auch nur ungefähr verstanden, auch hier fehlt mir wahrscheinlich die Erfahrung.

    Zu beginn hast du noch von einem Array_of_String gesprochen, welcher bei einer S7/1500 funktionieren sollte.
    Was bedeutet das? und wie programmiert man das? Benötigt man auch hier den Any-Zeiger?

    Danke Vielmals für eine Hilfe!

  5. #4
    Registriert seit
    23.07.2009
    Ort
    Österreich
    Beiträge
    2.354
    Danke
    455
    Erhielt 694 Danke für 519 Beiträge

    Standard

    Zitat Zitat von PLU Beitrag anzeigen
    Ich Programmiere eine S7/1500 im TIA.
    Na, dann hätten wir uns den Aufwand gleich sparen sparen können.
    Gib das in Zukunft immer gleich an, TIA heist nicht automatisch 1500.

    Gelernt hast du aber trotzdem was...

    Besagter Code mit dem ANY und dem SFC20 hätte zwar auch auf der 1500 funktioniert, allerdings nur
    in "Nicht Optimierten"-Bausteinen. Denn nur dort gibt es Adressen.

    Zitat Zitat von PLU Beitrag anzeigen
    Ich habe dann ein Programm wie folgt aufgebaut, dies hat leider nicht wirklich funktioniert, was mir zeigt das das ich den Any-Zeiger doch nicht verstanden habe.
    Code:
    L     B#16#10    // was ist mit :"10h für s7" gemeint ?
            // Ist eine Konstante die für ANY-Pointer innerhalb einer S7
            // immer den Wert "B#16#10" haben muss. Warum... Keine Ahnung. :-)
    
    
    L     B#16#13    // Typ String
    L     1        // Keine Wiederholung
            // Hier ist der Fehler warum es nicht geklappt hat.
            // Der Any-Pointer beeinhaltet keine gültige Längeninformation
            // Wie lang ist eine Wiederholung vom Typ String?
             // Ein String kann 10,20,30 bis 254 Zeichen haben.
            // Ich würde hier aber trotzdem den Datentyp Byte nehmen.
            // Selbst wenn man einer Funktion sybolisch einen String an einen ANY-Eingang
            // übergibt bekommt man am inneren (wenn man den ANY zerlegt) trotzdem
            // den Datentyp B#16#2 (Byte) mit Wiederholungsfaktor "Anzahl der Zeichen + 2".
             // Warum gibt es den Datentyp "String" im ANY überhaupt? Weiß ich auch nicht.
    
    L     MW0    //Wird bei jeder Eingabe um 254 erhöht
            //Darf ich annehmen dass dein String als String[254] deklariert ist?
            //Dann wäre auch diese Angabe falsch da ein String immer zwei Zusatzbytes belegt.
            //Byte0 enthält die maximale Anzahl an Zeichen, bei String[30] eben 30.
            //Byte1 enthält die aktuelle Länge des enthalteten Strings. "Hallo" = 5.
            //Dann kommen erst die 30Byte Zeichen. Sind dann 32Byte im gesamten.
    Zitat Zitat von PLU Beitrag anzeigen
    Den Code welcher du als Beispiel geschrieben hast habe ich leider auch nur ungefähr verstanden, auch hier fehlt mir wahrscheinlich die Erfahrung.
    Du musst dann schon nennen was du konkret nicht verstanden hast....
    Zitat Zitat von PLU Beitrag anzeigen
    Zu beginn hast du noch von einem Array_of_String gesprochen, welcher bei einer S7/1500 funktionieren sollte. Was bedeutet das? und wie programmiert man das? Benötigt man auch hier den Any-Zeiger?
    Deswegen die Frage nach dem System auf dem du programmierst.
    Das mit dem Array ist wahrscheinlich die einfachste Variante, funktioniert in AWL aber nur auf der 1500.
    Auf der 300/400 ging das nur in SCL.

    Ein Array (google einfach mal danach) ist ein Feld aus Elementen gleichen Datentyps.
    Ein "ARRAY[1..10] of INT" ist ein Feld aus 10 Integern wobei z.B. das fünfte Element über Symbolname[5] angesprochen werden kann.

    Wenn du ein deinem Ziel-Datenbaustein also ein StringArray wie folgt deklarierst.
    Name "MeineZielStrings" und in der Spalte Datentyp "Array[1..20] of String[254]" dann bekommst du 20 Strings welche du wie folgt ansprechen kannst.

    "MeinDatenbaustein".MeineZielStrings[1]
    "MeinDatenbaustein".MeineZielStrings[2]
    "MeinDatenbaustein".MeineZielStrings[3]
    ...
    Die Nummer ist der sogenannte Array-Index und kann auch Variabel gestaltet werden.
    "MeinDatenbaustein".MeineZielStrings[#tmpIndexVariable]

    Im 1500er AWL kannst du dann die Funktion MOVE verwenden. (Ist das selbe wie die MOVE-Box in KOP/FUP)
    Code:
     //Sollte ungefähr so aussehen. Hab kein TIA hier für die genaue Syntax.
    //Schreib einfach "CALL MOVE", drück Enter. Den Rest findest du aus der F1-Hilfe.
    
    L     5
    T     #tmpIndexVariable        //TEMP-Bereich Typ-Integer
    
    //Vor dem Kopieren solltest du den Index (wo auch immer der herkommt) nochmal auf Gültigkeit prüfen.
    
    CALL  MOVE
    IN    :="HMI Eingabe"."Eingabe über HMI"
    OUT   :="MeinDatenbaustein".MeineZielStrings[#tmpIndexVariable]
    (Genau dieser variable Index geht unter 300/400 nur in SCL)

    Das schreibt deinen Eingabe-String auf das 5. Element deines String-Array.
    Da brauchst du keine Adressen berechnen und keine ANY-Pointer.
    Geändert von RONIN (27.03.2016 um 20:53 Uhr)
    If at first you don't succeed, you're not Van Damme!
    ... or maybe using TIA!

  6. Folgender Benutzer sagt Danke zu RONIN für den nützlichen Beitrag:

    PLU (27.03.2016)

  7. #5
    PLU ist offline Neuer Benutzer
    Themenstarter
    Registriert seit
    26.03.2016
    Beiträge
    16
    Danke
    7
    Erhielt 0 Danke für 0 Beiträge

    Standard

    Danke Vielmal für deine Zeit und Hilfe, funktioniert so wie ich es mir erhofft hatte

  8. #6
    Registriert seit
    23.07.2009
    Ort
    Österreich
    Beiträge
    2.354
    Danke
    455
    Erhielt 694 Danke für 519 Beiträge

    Standard

    Das kannst du anstelle von AWL auch genauso mit der MOVE-Box in FUP oder in SCL machen.
    Auf der 1200 gibt es zum Beispiel kein AWL mehr.
    If at first you don't succeed, you're not Van Damme!
    ... or maybe using TIA!

  9. #7
    PLU ist offline Neuer Benutzer
    Themenstarter
    Registriert seit
    26.03.2016
    Beiträge
    16
    Danke
    7
    Erhielt 0 Danke für 0 Beiträge

    Standard

    Habe bei der Simulation gerade bemerkt, das es doch nicht funktioniert. Beim "In" des MOVE Befehles wird angezeigt das hier nicht der Datentyp String verwendet werden darf.

  10. #8
    Registriert seit
    23.07.2009
    Ort
    Österreich
    Beiträge
    2.354
    Danke
    455
    Erhielt 694 Danke für 519 Beiträge

    Standard

    Zitat Zitat von PLU Beitrag anzeigen
    Habe bei der Simulation gerade bemerkt, das es doch nicht funktioniert. Beim "In" des MOVE Befehles wird angezeigt das hier nicht der Datentyp String verwendet werden darf.
    Hast du zwischen "CALL MOVE" und "IN" auch die Datentypen auf String / String gestellt?

    Sonst zeig mal nen Screenshot.
    If at first you don't succeed, you're not Van Damme!
    ... or maybe using TIA!

  11. #9
    PLU ist offline Neuer Benutzer
    Themenstarter
    Registriert seit
    26.03.2016
    Beiträge
    16
    Danke
    7
    Erhielt 0 Danke für 0 Beiträge

    Standard

    TIA_Ntzwerk 1.PNG

    Da CALL MOVE ein unbekannter Befehl war habe ich es mit dem Baustein programmiert. Unter dem Rot angezeigten Text steht folgende Meldung: Der Datentyp String des Aktualparameters passt nicht zum Datentyp Byte, Char usw.

  12. #10
    Registriert seit
    23.07.2009
    Ort
    Österreich
    Beiträge
    2.354
    Danke
    455
    Erhielt 694 Danke für 519 Beiträge

    Standard


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Zitat Zitat von PLU Beitrag anzeigen
    Unter dem Rot angezeigten Text steht folgende Meldung: Der Datentyp String des Aktualparameters passt nicht zum Datentyp Byte, Char usw.
    OK, am "IN" hast du einen String angegeben, an "OUT" allerdings einen CHAR. Damit ist die Meldung richtig so. Du hast "Datenbaustein_2"."HMI_Eingabe[MW0]" angegeben.

    Dieser Zugriff ist nicht das was ich mit "Verwendung von Arrays" gemeint habe.
    Du musst wissen dass der Datentyp String eigentlich selbst ein "Array_of_CHAR" ist.
    Wenn man auf einen String mit String[10] zugreift dann bekommt man das zehnte Zeichen und das hat den Datentyp CHAR.

    Ich hatte hatte aber ein Array_of_String gemeint. Ist verwirrend ich weiß...
    Daher kommen hier jetzt Bilder zum Einsatz.
    TIA_String_Array_Move_1.jpgTIA_String_Array_Move_2.jpg

    Musste allerdings selbst feststellen das Siemens es wiedereinmal nicht geschafft hat alle Datentypen mit dem Befehl MOVE zu kopieren.
    Mann kann Byte, Int, Real, Struct, UDT, DTL und Konsorten jetzt endlich mit dem selben Befehl kopieren, für String musste man aber wieder einen eigenen namens S_MOVE einfügen.
    Was soll das denn?

    Wenn du für deine Eingaben allerdings mehr als nur einen String speichern willst würde ich die Kombination aus Array und benutzerdefinierten Datentyp vorschlagen.
    TIA_String_Array_Move_3.jpgTIA_String_Array_Move_4.jpgTIA_String_Array_Move_5.jpg

    PS.: Der MOVE bzw. der S_MOVE gehen problemlos in AWL. Einfach "CALL MOVE" tippen und Enter.
    Geändert von RONIN (27.03.2016 um 23:18 Uhr)
    If at first you don't succeed, you're not Van Damme!
    ... or maybe using TIA!

  13. Folgender Benutzer sagt Danke zu RONIN für den nützlichen Beitrag:

    PLU (28.03.2016)

Ähnliche Themen

  1. TIA Fragen über Speichern
    Von rogpomlar im Forum Simatic
    Antworten: 2
    Letzter Beitrag: 20.05.2015, 08:30
  2. Antworten: 23
    Letzter Beitrag: 09.12.2014, 07:36
  3. Zeichenkette
    Von Waschtel im Forum Simatic
    Antworten: 3
    Letzter Beitrag: 08.12.2012, 19:44
  4. Datenbereich über ANY Zeiger aus DB holen
    Von Temotec im Forum Simatic
    Antworten: 2
    Letzter Beitrag: 21.06.2009, 21:42
  5. Antworten: 1
    Letzter Beitrag: 01.12.2008, 16:34

Lesezeichen

Berechtigungen

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