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

Ergebnis 1 bis 6 von 6

Thema: SCL - Auswertung von Daten eines aufgerufenen FC's

  1. #1
    Registriert seit
    27.11.2005
    Ort
    im Osten
    Beiträge
    1.183
    Danke
    141
    Erhielt 271 Danke für 248 Beiträge

    Frage


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Jetzt habe ich auch mal wieder ein kleines Problem mit einem für mich(kein SCL-Freak) unerklärlichen Verhalten beim Aufruf des FC50 (AG_LRECV).

    Ich rufe in einem FC den FC50 auf und will dort immer nur ein Byte aus dem Empfangspuffer des CP's lesen und in anschliesssend in einen String einfügen.

    Code:
    VAR_INPUT
     ID : INT;      //Verbindungs-ID
     LADDR : WORD;  // Log. Adresse des CP 
    END_VAR
    
    VAR_IN_OUT
     NEW_DAT : BOOL ;       // alte Nachricht löschen    
     PUFFER : STRING[11] ;  // Zwischenspeicher der Nachricht
     REC_LEN : INT ;        // Länge der Empfangenen Nachricht
    END_VAR
    
    VAR_TEMP
    tmp_byte: BYTE;    
    tmp_ndr: BOOL;
    tmp_error: BOOL;
    tmp_status: WORD;
    tmp_len: INT;
    tmp_str : STRING[11];  
    END_VAR    
    
    
    BEGIN
    // Temp Initialisieren
    tmp_byte:= 63;
    tmp_ndr := FALSE;
    tmp_error := FALSE;
    tmp_status := W#16#0;
    tmp_len := 0;
    tmp_str := PUFFER;
    
    IF NEW_DAT  THEN    // Alte Daten löschen wenn neues Telegramm erwartet wird
        NEW_DAT := FALSE;
        tmp_str := '';
        REC_LEN := 0;
    END_IF;
    
    // Daten empfangen
    AG_LRECV (ID:= ID,
              LADDR:= LADDR,
              RECV:= tmp_byte,
              NDR:= tmp_ndr,
              ERROR:= tmp_error,
              STATUS:= tmp_status,
              LEN:= tmp_len);
    
    // Empfangenes Zeichen in String einfügen
    IF tmp_ndr AND (REC_LEN < 11) THEN
        tmp_str := CONCAT (IN1:= tmp_str,                                
                           IN2:= BYTE_TO_CHAR(tmp_byte)); 
        REC_LEN := REC_LEN + 1;                   
    END_IF;
    
    // String sichern
    PUFFER:= tmp_str;
    Jetzt zum Problem:
    Die gewünschten Daten(7Bytes) werden vom CP empfangen und der AG_LRECV liest sie auch aus, sichtbar wird dies am hochzählen des "REC_LEN".
    Im "PUFFER" kommen dabei nur 7 Fragezeichen(CHAR-Wert = 63) an, also der Wert mit dem "tmp_byte" initialisiert wurde, das wirklich empfangene Zeichen, das nach dem Aufruf des AG_LRECV in "tmp_byte" stehen müsste, wird einfach ignoriert.

    Jetzt habe ich mir das mal in AWL angesehen, da kommt auszugsweise folgendes raus:
    Code:
     L     #ID
          T     LW    20
          L     #LADDR
          T     LW    22
          L     DW#16#10020001
          T     LD    24
          L     W#16#0
          T     LW    28
          L     DW#16#87000000      // 87 = Vorgänger Lokaldaten - Adresse 0
          T     LD    30
          UC    "AG_LRECV"
                P#L 20.0
                P#L 22.0
                P#L 24.0
                P#L 1.0
                P#L 1.1
                P#L 2.0
                P#L 4.0
          L     #tmp_byte
          UD    DW#16#FF
          L     W#16#100
          T     LW    20
          TAK   
          SLW   8
          L     LD    20
          UD    DW#16#FF0000FF
          OD    DW#16#10000
          OD    
          T     LD    20                 // Das müsste jetzt das empfangene Byte sein - landet in den aktuellen Lokaldaten Adresse 20
          L     W#16#0
          T     LW    24
          L     DW#16#87000030
          T     LD    26
          L     W#16#0
          T     LW    30
          L     DW#16#870000A0 // 87 = Vorgänger Lokaldaten - Adresse 20
          T     LD    32
          L     W#16#0
          T     LW    36
          L     DW#16#87000030
          T     LD    38
          UC    "CONCAT"
                P#L 24.0
                P#L 30.0
                P#L 36.0
    Wieso arbeitet der SCL-Compiler beim Aufruf des CONCAT da mit den Vorgängerlokaldaten, wenn doch das konvertierte empfangene Byte in den aktuellen Lokaldaten abgelegt wurde?

    Da ich mir das jetzt nicht erklären konnte, habe ich das "tmp_byte" aus dem oberen Beispiel mal in den INOUT Bereich verschoben, das Initialisieren mit der Zahl 63 weggelassen und die Variable "tmp_byte" von aussen mit einem Byte aus dem STAT-Bereich des aufrufenden FB's belegt. Jetzt landet im "Puffer" immer der Wert den die STAT-Variable "tmp_byte" besitzt, also auch nur Mist.

    Wenn ich jetzt allerdings an diese INOUT-Variable ein Byte im Merkerbereich eingebe, funktioniert die ganze Sache auf einmal.

    Ich könnte das ganz ja so lassen, sieht aber doof aus ich will jetzt auch wissen woran das liegt bzw. wie ich den Baustein ändern muss damit es auch mit der temp-Variable funktioniert.
    Geändert von MW (29.05.2016 um 01:03 Uhr)
    Es ist nicht schwierig, mit noch nicht erreichten Zielen zu Leben; schwierig ist, ohne Ziele zu Leben !
    (Günther Kraftschik)
    Zitieren Zitieren SCL - Auswertung von Daten eines aufgerufenen FC's  

  2. #2
    Registriert seit
    22.03.2007
    Ort
    Detmold (im Lipperland)
    Beiträge
    11.794
    Danke
    398
    Erhielt 2.417 Danke für 2.013 Beiträge

    Standard

    Hallo MW,

    ich habe nun gerade kein Step7 zur Hand und kann es deshalb nicht genau gegenchecken - aber :
    erwartet der AG_LRecV am Eingang RecV nicht einen ANY-Pointer, der auf einen Speicherbereich (also z.B. ein Array of Byte) zeigt in dem seine Daten abgelegt werden sollen ?
    Vielleicht erzeugst du dir mal dieses Array_of_Byte in ausreichender Größe und läßt da die Daten reinschreiben. Wenn dich dann nur der Inhalt des Byte 7 interessiert so kannst du ja dann auch nur auf den Index zugreifen.
    Zum Debuggen von so etwas ist es m.E. auch immer ganz hilfreich, einen Empfangspuffer zunächst in einen statischen Bereich zu legen damit man sehen (und kontrollieren) kann, was ankommt.

    Gruß
    Larry

  3. #3
    Registriert seit
    29.03.2004
    Beiträge
    5.797
    Danke
    144
    Erhielt 1.707 Danke für 1.239 Beiträge

    Standard

    Also die Bausteindokumentation des AG_LRECV sagt:
    Der für die Datenübernahme angegebene Datenbereich kann ein PA-Bereich, ein Merkerbereich oder ein Datenbausteinbereich sein.
    Es steht aber dort nichts von Lokaldaten. Allerdings hätte ich in dem Fall eine Fehlermeldung der Funktion erwartet, denn unter den Fehlercodes gibt es zumindest die Fehlermeldung des ungültigen Speicherbereichs. Evtl. mal die Bausteinversion prüfen, ob es da eine aktuellere gibt?
    Die Genialität einer Konstruktion liegt in ihrer Einfachheit – Kompliziert bauen kann jeder.

    (Sergei Pawlowitsch Koroljow, sowjetischer Konstrukteur von Raketen und Weltraumpionier)

  4. #4
    Registriert seit
    27.05.2004
    Ort
    Thüringen/Berlin
    Beiträge
    12.263
    Danke
    537
    Erhielt 2.708 Danke für 1.957 Beiträge

    Standard

    Ich würde mich Larry anschließen.
    Hatte gerade bei einer 1500-er ein ähnlich gelagertes Problem.
    Kannst du denn sicherstellen, dass immer nur eine Byte geschickt wird? Wenn der Empfangs-Bereich nicht paßt, wird nichts reingeschrieben, das hatte ich auch gerade, mit einem String (was man nicht machen sollte, wenn man nicht sicherstellen kann, dass auch ein "echter" S7-String vom Sender geschickt wird!) als Empfänger für Recv. Nur wenn dort in den ersten beiden Byte eine Ziffer stand (das ist ja Länge und Max.Länge des Strings), kam der String in RECV an. Waren dort irgendwelche anderen "ungültigen" Zeichen angekommen ($ z.B.), dann sah man die empfangen Zeichen an der Recive-Funktion , aber sie waren nicht im angelegten statischen String. (Fehlermeldung --> Nope, keine).
    Lösung: "Array of Char", das war ja dann immer gültig und anschließend Wandlung in einen String.
    Ähnliches würde ich mal mit deiner Funktion ebenfalls versuchen.
    Geändert von Ralle (29.05.2016 um 16:00 Uhr)
    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

  5. #5
    Avatar von MW
    MW ist offline Erfahrener Benutzer
    Themenstarter
    Registriert seit
    27.11.2005
    Ort
    im Osten
    Beiträge
    1.183
    Danke
    141
    Erhielt 271 Danke für 248 Beiträge

    Standard

    Danke für eure Tipps.

    Der Grund warum ich immernur ein Byte aus dem Puffer des CP's lesen will, ist das ich derzeit ein Telegramm mit einer Länge von 7 Byte erwarte, die Gegenstelle kann mir aber später auch Telegramme mit anderer Länge über diese Verbindung(reines TCP) schicken. Deshalb will ich mit dem AG_LRECV jeden Zyklus nur ein Byte aus dem Puffer lesen und in einen String einfügen, wenn ich da eine feste Empfangslänge von mehr als einem Byte eintragen würde, könnte es bei der TCP-Verbindung zu Datenversatz kommen, falls zwischendurch mal ein Telegramm mit unerwarter Länge kommen würde.
    In dem so empfangenen String sind auch Zeichen enthalten die ich nicht brauche (Nachrichtanfangs-, Nachrichtend-kennung usw.), aber ich kann ja den zusammengesetzten String einfach nach meinem erwarteten Code durchsuchen und wenn der gefunden wurde, gebe ich das als Meldung an den aufrufenden Baustein zurück.

    @Larry: deine Vermutung ist korrekt, der AG_LRECV erwartet einen Any am Eingang.
    In dem Any könnte man ja auch auf die aktuellen Lokaldaten verweisen wenn man es "zu Fuß" programmieren würde, aber der SCL-Compiler macht das aus einem mir bisher unerklärlichen Grund nicht und baut da die Vorgängerlokaldaten ein.

    Der Hinweis von Thomas ist auch nicht schlecht, daran hatte ich jetzt garnicht gedacht, dass der FC eventuell garkeinen Verweis auf die Lokaldaten in dem Any zulässt. Aber wie du schon geschrieben hast, hätte ich da auch mal eine Fehlermeldung erwartet. Aber nö, er setzt das "NDR" Bit und meine Variable "REC_LEN" zählt dadurch schön bis 7 hoch, signalisiert mir so das die 7 Bytes empfangen wurden und das alles in Ordnung ist. Die 7 Bytes werden also gelesen, landen nur nicht da wo ich sie haben will.

    Da ich das ganze bisher in einen FC geschrieben habe, kann ich die Empfangsdaten leider nicht in den Statischen Bereich legen, im Grunde interessiert mich das einzelne Byte ja auch nicht, da ich es ja sowieso in einen CHAR konvertiere und in einen String einfüge wo ich es dann beobachten kann.
    Ich hatte ich es ja auch schon probiert dieses Empfangsbyte über die INOUT Schnittstelle an den FC zu übergeben und dann in den statischen Bereich des aufrufenden FB's zu speichern, wie im ersten Post erwähnt leider ohne Erfolg. Interessanterweise ging es aber wenn ich an dieses INOUT ein Merkerbyte von aussen übergab.

    Im schlimmsten Fall belasse ich es bei der Verwendung dieses Merkerbytes, aber dank eurer Vorschläge/Hinweise kann ich morgen noch etwas weiter testen, vorrausgesetzt ich finde dafür Zeit.
    Es ist nicht schwierig, mit noch nicht erreichten Zielen zu Leben; schwierig ist, ohne Ziele zu Leben !
    (Günther Kraftschik)

  6. #6
    Registriert seit
    22.06.2009
    Ort
    Sassnitz
    Beiträge
    11.314
    Danke
    932
    Erhielt 3.329 Danke für 2.688 Beiträge

    Standard


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Ich vermute ebenfalls, daß der AG_LRECV nicht mit RECV-Puffer in TEMP klarkommt. Der ANY-Pointer auf tmp_byte wird vom Compiler jedenfalls korrekt als "P#V0.0 BYTE 1" erstellt.
    (1) Wenn Du sowieso nur 1 Byte empfangen willst, dann versuche mal den FC6 AG_RECV (Familie: CP_400) anstatt FC60 AG_LRECV. Vielleicht geht es mit dem.

    Das mit den "Vorgänger Lokaldaten" ist schon richtig so, wie man auch beim funktionierenden CONCAT-Aufruf sehen kann. Für den aufgerufenen FC liegen die übergebenen Variablen in den Vorgänger-Lokaldaten.

    (2) Alternativ zum Merkerbyte sollte auch ein Byte aus einem DB/IDB funktionieren, allerdings müsste das DB/STAT-Byte als ANY an den FC übergeben werden, im FC auf eine TEMP-ANY-Variable umkopiert werden und diese Kopie an den AG_RECV übergeben werden - weil ein DB-Aktualparameter vom aufrufenden Baustein als Pointer auf eine TEMP-Kopie an den FC übergeben wird, wodurch ein Vorgänger-Vorgänger-Lokaldaten-Konflikt entsteht. Vielleicht löst der SCL-Compiler den Konflikt durch Umkopieren auf lokalen TEMP - das führt dann aber zur selben Situation wie die Übergabe des tmp_byte an AG_RECV. Dies würde das Scheitern der Übergabe des STAT-Bytes erklären.

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

    FAQ: Linkliste SIMATIC-Kommunikation über Ethernet

Ähnliche Themen

  1. TIA SCL Daten von FB in beliebigen DB schreiben
    Von ChrissT im Forum Simatic
    Antworten: 17
    Letzter Beitrag: 03.09.2013, 17:01
  2. Step 7 Auswertung eines Bits für 2 funktionen
    Von Der Dreschi im Forum Simatic
    Antworten: 28
    Letzter Beitrag: 16.07.2013, 22:42
  3. Speichern von Daten in SCL
    Von Karlson im Forum Simatic
    Antworten: 36
    Letzter Beitrag: 31.07.2012, 12:56
  4. Auswertung eines Zählwerts
    Von 4nD1 im Forum Simatic
    Antworten: 25
    Letzter Beitrag: 25.03.2011, 06:43
  5. Auswertung eines analogen Signals
    Von Rübezahl im Forum Simatic
    Antworten: 14
    Letzter Beitrag: 26.09.2008, 22:46

Lesezeichen

Berechtigungen

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