Welcome to our new forum
All users of the legacy CODESYS Forums, please create a new account at account.codesys.com. But make sure to use the same E-Mail address as in the old Forum. Then your posts will be matched. Close

Problem mit String in Globaler Variable

Deutsch
mschierer
2013-11-22
2013-12-18
  • mschierer

    mschierer - 2013-11-22

    Hallo,

    ich bin in der SPS Programmierung noch ein Neuling, daher weiß ich nicht woran mein Problem liegt.
    Ich habe eine WAGO 750-880 mit einer Seriellen Schnittstelle an die ich eine Waage angeschlossen habe.
    Um etwas zu empfangen habe ich mir das Beispielprogramm für die Serielle Schnittstelle von Wago angepasst.

    PROGRAM Waage
    VAR
    (* Communicationparams for 750-65x/003-000 only*)
       wBaudRate      : WORD := 960;
       bDataBits      : BYTE := 8;
       bParity         : BYTE := 0;
       bFlowControl    : BYTE := 0;
       i             : INT;
    (* COM2  ********************************************)
       COM2          : SERIAL_INTERFACE;
       xOpenPort2      : BOOL := TRUE;
       xInitPort2      : BOOL;
       xSendActive2   : BOOL;
       SendString2      : STRING := 'Msg from COM2';
       ReceiveBuffer2   : typRing_Buffer;
       ReceiveBuffer2OldIndex   : INT;
       ReceiveString2    : STRING(255);
       pReceiveStr2     : POINTER TO ARRAY[0..255] OF BYTE;
       help2Idx       : INT;
       iTo2         : INT;
    END_VAR
    
    (* Send and Receive for COM2 *)
    COM2(   bCOM_PORT_NR    := 2,
          cbBAUDRATE       := wBaudRate,
          cbsBYTESIZE      := bDataBits,
          cpPARITY      := bParity,
          csSTOPBITS      := STOPBITS_1,
          cfFLOW_CONTROL   := bFlowControl,
          utRECEIVE_BUFFER := ReceiveBuffer2,
          ptSEND_BUFFER   := ADR(SendString2),
          xINIT         := xInitPort2,
            xOPEN_COM_PORT    := xOpenPort2,
          iBYTES_TO_SEND   := LEN(SendString2) +1,
          xSTART_SEND      := xSendActive2 );
    (* Display received data for COM2 *)
    IF ReceiveBuffer2OldIndex <> ReceiveBuffer2.Index THEN
       iTo2   := ReceiveBuffer2.Index - ReceiveBuffer2OldIndex -1;
       IF iTo2 < 0 THEN
          iTo2 := iTo2 + SIZEOF(ReceiveBuffer2.Data);
       END_IF;
       IF pReceiveStr2 = 0 THEN
          pReceiveStr2 := ADR( ReceiveString2 );
       END_IF;
          FOR i:=0 TO iTo2 DO
          help2Idx := (ReceiveBuffer2OldIndex + i) MOD (SIZEOF(ReceiveBuffer2.Data));
          pReceiveStr2^[i] :=  ReceiveBuffer2.Data[ help2Idx ];
          IF ReceiveBuffer2.Data[ help2Idx ] = 16#00 THEN
             ReceiveBuffer2OldIndex := ReceiveBuffer2.Index;
          END_IF;
       END_FOR;
    END_IF;
    

    Das Programm läuft nun stabil und ich bekomme über ReceiveString2 ein Ergebnis.
    Jetzt wollte ich den ausgegebenen String weiter verarbeiten und habe ihn als Globale Variable deklariert:

    VAR_GLOBAL
       ReceiveString2: STRING(255);
    END_VAR
    

    Wenn ich mich nun auf mein System einlogge bekomme ich nur in meinem Programm Waage den String ausgegeben und unter der Globalen Variable nur ein ReceiveString2: ".
    Was habe ich falsch gemacht? Kann mir da jemand helfen?

     
  • Anonymous - 2013-11-24

    Originally created by: mg

    Ich habs nur kurz überflogen. Evtl ist meine Antwort falsch:

    Ich glaube Du hast die Variable "ReceiveString2" doppelt deklariert.
    Du darfst diese Variable nur 1x deklarieren als "VAR" oder als "VAR_GLOBAL" niemals in beiden.

     
  • Erik Böhm

    Erik Böhm - 2013-11-25

    Moin

    Technisch gesehen darf man natürlich schon globale und lokale Variablen mit dem selben Namen erstellen.
    Aber dann kann eben genau das passieren was hier passierte: Verwechslung.
    Es gibt diverse Möglichkeiten diese zu vermeiden.
    Z.B. können globale Variablen generell mit g oder g_ anfangen.
    Dazu gibts NamingConventions. Siehe auch: http://en.wikipedia.org/wiki/Naming_conventions_(programming)

    Gruß Erik

     
  • Anonymous - 2013-11-25

    Originally created by: mg

    Erik Böhm hat geschrieben:
    Moin
    Technisch gesehen darf man natürlich schon globale und lokale Variablen mit dem selben Namen erstellen.
    Aber dann kann eben genau das passieren was hier passierte: Verwechslung.
    Es gibt diverse Möglichkeiten diese zu vermeiden.
    Z.B. können globale Variablen generell mit g oder g_ anfangen.
    Dazu gibts NamingConventions. Siehe auch: http://en.wikipedia.org/wiki/Naming_conventions_(programming)
    Gruß Erik

    Naja ... mir ist das auch schon öfter passiert. Das Progi greift dann aber immer auf die "lokale" zu. Wie das vom Codesys behandelt wird, weiß ich nicht. Lästig ist es allemal. Hab auch schon mal eine Weile Fehler gesucht.

    Danke

    Mario

     
  • Erik Böhm

    Erik Böhm - 2013-11-26

    Moin

    CoDeSys behandelt das wie alle anderen auch (zumindest alles was ich kenne).
    Lokal kommt vor Global.
    In der Hilfe steht:

    "Es ist möglich, eine lokale Variable mit gleichem Namen wie eine globale zu definieren. Innerhalb eines Bausteins hat stets die lokal definierte Variable Vorrang. "

    Gruß Erik

     
  • mschierer

    mschierer - 2013-11-26

    Danke für die Antwort!
    Das hätte ich mir auch denken können. Aber manchmal sieht man den Wald vor lauter Bäumen nicht!

    Jetzt habe ich aber folgendes Problem. Evtl. kann mir jemand helfen?
    Den String, den ich jetzt über die Globale Variable bekomme wird dauerhaft von einer Waage gesendet.
    Dieser String wiederholt sich permanent. Wenn ich nun versuche den String auf die Daten zu kürzen, die ich brauche, kommt immer ein anderer Wert. Ich kann das gerade nicht sehr gut erklären, daher habe ich Screenshots von dem laufenden System gemacht. Daran kann man es besser sehen.
    Um mein Problem zu lösen, müsste ich doch nach festen Buchstaben, die immer im String vorkommen suchen.
    z.B. 16.475 Kg $R$N
    Jetzt brauche ich aber nur das Gewicht vor dem festen Textblock. Wie kann man das realisieren???
    Ich habe schon ein paar Versuche unternommen, welche aber nicht geklappt haben.

    Ich hoffe mir kann jemand weiter Helfen.

    IMG: Screenshot_GlobaleVariable_der_Waage.jpg

    IMG: Screenshot_Eingangswerte.jpg

     
  • Anonymous - 2013-12-18

    Originally created by: blackenslaver666

    Hallo.
    Sollte das Problem noch akut sein hier meine Anmerkungen (wobei ich den Wago-FB/Code nicht kenne):
    1. Du hast sicherlich ein Problem durch das zyklische Senden. Deine Rohdaten werden im String immer hinten angehängt & leider ist der Empfangsstring auch kein ganzzahliges Vielfaches von 255. Im Bsp. ist der Rohdaten-String 14 (?) Zeichen lang inkl. Terminierungszeichen. Das geht nicht ganzzahlig in den 255er String, d.h. nach X Durchgängen hast du kein gültiges Gewicht mehr an der Überlaufstelle (Pos 0/255). Daher sehen die Daten auch so zerrupft aus. Bedenke zudem dass dein Gewicht auch variabel sein kann, denn 8.xxx kg hat eine Stelle weniger (Nutzdaten Telegrammlänge)!
    2. Aus dem 255er String kannst unmöglich das zZt aktuelle Gewicht extrahieren weil du die zuletzt geschriebene Position nicht kennst & daher die String-FUNs nicht korrekt parametrieren kannst.
    3. Die Lösung sähe daher so aus, in den Empfangsstring immer nur als aktuelle Gewicht zu übertragen. Dafür musst du aber mit jedem Datenempfang deinen Empfangspuffer leeren, d.h. der Bsp-Code von Wago muss modifiziert werden. Kann ich aber nix groß zu sagen weil ich nicht weiss wie der FB funktioniert & was die internen Var machen (Index etc.) . Evt. reicht es ja schon aus, den Ringpuffer (Empfangsstruktur) zu löschen! Dann bekommst du mit jedem Empfangstelegramm im String nur das zuletzt aktuelle Meßergebnis & darauf kannst die String-FUN loslassen. Wenn du dann noch die Terminierungszeichen killst kannst du mit STRING_TO_xxx-Konvertierung direkt dein Ergebnis abspeichern.

    Gruß A.

     

Log in to post a comment.