TIA Probleme bei Datenempfang von TRCV

Austria

Level-1
Beiträge
36
Reaktionspunkte
1
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen!
Ich habe so einen ähnlichen Beitrag schonmal gestellt, jedoch bin ich leider zu keiner Lösung gekommen, deshalb versuche ich es mit der Bitte um mögliche Lösungsvorschläge nochmals.

Version: Step 7 Professional V17
Gerät: CPU S7-1511-1PN

TRC Einstellungen: Adhoc = true / Len = 0 / optimierter Datenzugriff

Mein Problem besteht darin, dass ich mit meinem TRCV Baustein Daten eines RFID Readers empfangen möchte, was jedoch nicht richtig klappt. Einlesen möchte ich mit variabler Länge (Adhoc Modus) in ein Char oder Byte Array (egal welches).
Der zu erwartende String schaut folgendermaßen aus: 7767CE65$R$L -> also 10 Zeichen

Problem: es wird leider folgendermaßen eingelesen 767CE65$R$L -> also immer nur 9 Zeichen statt 10 Zeichen -> das 1te Zeichen wird nicht erkannt...

Folgendermaßen schaut es aus wenn ich am Reader etwas scanne:

so wie ich das verstehe werden 2 TCP Pakete empfangen:
1. Packet enthält -> 7
2. Packet enthält -> 767CE65$R$L

Jedoch ist es für mich nicht verständlich warum das 1.Paket nicht im Buffer[0] steht...!!!

1651662539783.png

Der beigefügte Code ist sicherlich noch ausbaufähig, jedoch geht es mir hauptsächlich um das korrekte Einlesen. Habe auch schon andere Ansätze für das Empfangen der Daten probiert, doch scheitere ich immer wieder an diesem Problem...

Ich füge hier mal meinen gesamten SCL Code ein:
Code:
REGION Initialize TCP/IP Blocks
 
  #TCON_Instance(REQ := #TCON_Instance.REQ,
                 ID := 1,
                 DONE => #TCON_Instance.DONE,
                 BUSY => #TCON_Instance.BUSY,
                 ERROR => #TCON_Instance.ERROR,
                 STATUS => #TCON_Instance.STATUS,
                 CONNECT := "PLC_Controller_Connection_DB");
 
 
  #TRCV_Instance(EN_R := #TRCV_Instance.EN_R,
                 ID := 1,
                 LEN := #TRCV_Instance.LEN,
                 ADHOC := #TRCV_Instance.ADHOC,
                 NDR => #TRCV_Instance.NDR,
                 BUSY => #TRCV_Instance.BUSY,
                 ERROR => #TRCV_Instance.ERROR,
                 STATUS => #TRCV_Instance.STATUS,
                 RCVD_LEN => #TRCV_Instance.RCVD_LEN,
                 DATA := #Input.Buffer);
 
 
END_REGION

REGION Enable Connection and Set Receive Mode
 
  //Enable Connection
  #TCON_Instance.REQ := "Clock_2Hz";
 
  //Check Connection
  IF #TCON_Instance.DONE = 1 AND #TCON_Instance.STATUS = 0
  THEN
    #ConnectionStatus.IsConnected := TRUE;
  END_IF;
 
  IF #ConnectionStatus.IsConnected
  THEN
    
    //Enable TRCV
    #TRCV_Instance.EN_R := TRUE;
    #ConnectionStatus.RecvRequested := TRUE;
  END_IF;
 
END_REGION

REGION Receive Data
 
  IF #ConnectionStatus.RecvRequested AND #TRCV_Instance.NDR
  THEN
    #ConnectionStatus.IsConnected := FALSE;
    #ConnectionStatus.RecvRequested := FALSE;
    
    //Received Length of Buffer
    #Input.RecvLength := #TRCV_Instance.RCVD_LEN;
    
  END_IF;
 
END_REGION
 
Du musst eben selber einen Puffer führen, in den du die Anzahl der empfangenen Bytes einfügst bis die entsprechende Endekennung vorkommt. Dann alles bis zur Endekennung auswerten, den Teil aus dem internen Puffer abtrennen weil es könnten ja schon weitere Daten von der nächsten Sequenz vorhanden sein.

Etwas einfacher und bei so kurzen Daten durchaus im Rahmen, wäre, beim TRCV immer nur ein einzelnes Byte zu lesen und dieses an deinen eigenen Puffer anzuhängen, bis du bei dir z.B. ein $R$N empfangen hast. Dann kopierst du dir den Pufferinhalt um, leerst diesen (Zeiger auf Anfang setzen) und dann wieder mit dem TRCV füllen lassen.

Wenn die Länge nicht fest ist kommst du nicht umhin da mehr oder weniger viel selber zu Fuß programmieren zu müssen.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Danke nochmals Thomas für die Antwort. Habe mir schon sowas in der Art gedacht, jedoch habe ich es noch nicht ganz hinbekommen.
Etwas einfacher und bei so kurzen Daten durchaus im Rahmen, wäre, beim TRCV immer nur ein einzelnes Byte zu lesen und dieses an deinen eigenen Puffer anzuhängen, bis du bei dir z.B. ein $R$N empfangen hast. Dann kopierst du dir den Pufferinhalt um, leerst diesen (Zeiger auf Anfang setzen) und dann wieder mit dem TRCV füllen lassen
Mein Problem ist, dass ich noch nicht ganz verstehe wie ich immer nur 1 Byte auslese. Wenn ich auf NDR prüfe lädt mir TRCV ja sofort alle Daten in den Puffer... Vlt. könntest du mir dabei noch auf die Sprünge helfen?
 
Code:
  #TCON_Instance(REQ := #TCON_Instance.REQ,
                 ID := 1,
                 DONE => #TCON_Instance.DONE,
                 BUSY => #TCON_Instance.BUSY,
                 ERROR => #TCON_Instance.ERROR,
                 STATUS => #TCON_Instance.STATUS,
                 CONNECT := "PLC_Controller_Connection_DB");

Was treibst Du da mit dem Zuweisen der Parameter zu sich selbst? Hat das einene tieferen Grund?

Zu der eigentlichen Frage:
Wie Thomas schon schreibt solltest Du die LEN beim RECV auf 1 stellen, und das in deinen Buffer kopieren, und wenn dann deine Endzeichen da sind, den gesamten Buffer bis zu dieser Stelle an die Stelle deiner Wahl kopieren.

Grüße

Marcel
 
NDR kommt ja nur einen Zyklus lang. In RCVD_LEN steht die Länge der Empfangenen Daten. Wenn du beim 1. Mal nur ein Byte bekommst. sollte da eine 1 drin stehen. Du holst dann dieses eine Byte von Pos 1 aus dem Buffer und schreibst es an Stelle 1 eines eigenen E-Buffers (Array). Beim nächsten NDR kommen die restlichen Byte + Länge. Nun holst du diese Byte von Pos 1-X aus dem Buffer und schreibst sie an Pos 2-(X+1) in dienen eigenen E-Buffer. Die Daten in deinem eigenen E-Buffer wertest du nach jedem Eintragen immer auf dei Endekennung aus. Wenn die da ist, kopierst du die Daten in einen endgültigen Ziel-Buffer oder auch in einen Ziel-String, ja nach Bedarf. Danach löscht du den E-Buffer und stellst den Zeiger für die Position, an welche die nächsten Empfangsdaten geschrieben werden wieder auf 1. Die Gesamtlänge des E-Buffer solltest du auch im Auge behalten, falls einmal die Endekennung nicht korrekt kommt.

PS: Noch ien Hinweis, wenn ein Error kommt, dann kommt kein NDR, also immer NDR OR ERROR auswerten und entsprechend reagieren.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Was treibst Du da mit dem Zuweisen der Parameter zu sich selbst? Hat das einene tieferen Grund?
hast recht, muss ich noch ändern. hat keinen spezifischen Grund

Wie Thomas schon schreibt solltest Du die LEN beim RECV auf 1 stellen, und das in deinen Buffer kopieren, und wenn dann deine Endzeichen da sind, den gesamten Buffer bis zu dieser Stelle an die Stelle deiner Wahl kopieren.
da ich ja den adhoc modus aktiviert habe und laut Hilfe bei einem optimierten Baustein Len = 0 verlangt wird. Soll ich dementsprechend keinen optimierten verwenden?

NDR kommt ja nur einen Zyklus lang. In RCVD_LEN steht die Länge der Empfangenen Daten. Wenn du beim 1. Mal nur ein Byte bekommst. sollte da eine 1 drin stehen. Du holst dann dieses eine Byte von Pos 1 aus dem Buffer und schreibst es an Stelle 1 eines eigenen E-Buffers (Array). Beim nächsten NDR kommen die restlichen Byte + Länge. Nun holst du diese Byte von Pos 1-X aus dem Buffer und schreibst sie an Pos 2-(X+1) in dienen eigenen E-Buffer. Die Daten in deinem eigenen E-Buffer wertest du nach jedem Eintragen immer auf dei Endekennung aus. Wenn die da ist, kopierst du die Daten in einen endgültigen Ziel-Buffer oder auch in einen Ziel-String, ja nach Bedarf. Danach löscht du den E-Buffer und stellst den Zeiger für die Position, an welche die nächsten Empfangsdaten geschrieben werden wieder auf 1. Die Gesamtlänge des E-Buffer solltest du auch im Auge behalten, falls einmal die Endekennung nicht korrekt kommt.
Danke für den Lösungsansatz, werd ich jetzt mal versuchen umzusetzen.
 
NDR kommt ja nur einen Zyklus lang. In RCVD_LEN steht die Länge der Empfangenen Daten. Wenn du beim 1. Mal nur ein Byte bekommst. sollte da eine 1 drin stehen. Du holst dann dieses eine Byte von Pos 1 aus dem Buffer und schreibst es an Stelle 1 eines eigenen E-Buffers (Array). Beim nächsten NDR kommen die restlichen Byte + Länge. Nun holst du diese Byte von Pos 1-X aus dem Buffer und schreibst sie an Pos 2-(X+1) in dienen eigenen E-Buffer. Die Daten in deinem eigenen E-Buffer wertest du nach jedem Eintragen immer auf dei Endekennung aus. Wenn die da ist, kopierst du die Daten in einen endgültigen Ziel-Buffer oder auch in einen Ziel-String, ja nach Bedarf. Danach löscht du den E-Buffer und stellst den Zeiger für die Position, an welche die nächsten Empfangsdaten geschrieben werden wieder auf 1. Die Gesamtlänge des E-Buffer solltest du auch im Auge behalten, falls einmal die Endekennung nicht korrekt kommt.
Könntest du mir evtl. mit etwas Pseudocode unter die Arme greifen...?
 
Hallo,

ich denke für dich die beste Lösung wäre wenn du den AdHoc-Modus deaktivierst und eine Empfangslänge von 10 eingibst.
Soweit ich das verstanden habe hast du ja keine dynamische Länge deswegen ist der AdHoc die falsche Methode.

Mit der fixen Länge kannst du den Baustein bereits auf den fertigen Empfang warten lassen und musst dir dann nicht alles selbst zusammenbuffern.

btw: Würde dir raten auf TRCV_C umzusteigen, dadurch wird das Programm schon deutlich schlanker.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,

ich denke für dich die beste Lösung wäre wenn du den AdHoc-Modus deaktivierst und eine Empfangslänge von 10 eingibst.
Soweit ich das verstanden habe hast du ja keine dynamische Länge deswegen ist der AdHoc die falsche Methode.
Naja, bei reinem TCP-Stream hat Adhoc immer den Vorteil, das es von selber wieder in Tritt kommt. Bei fester Länge wird ja auf das nächste Tele gewartert, bis die Solllänge erreicht wird. Einmal durcheinander wegen Problem>>Immer durcheinander.
... so ist bis her mein Wissen und Erfahrungsschatz.
 
Naja, bei reinem TCP-Stream hat Adhoc immer den Vorteil, das es von selber wieder in Tritt kommt. Bei fester Länge wird ja auf das nächste Tele gewartert, bis die Solllänge erreicht wird. Einmal durcheinander wegen Problem>>Immer durcheinander.
... so ist bis her mein Wissen und Erfahrungsschatz.
ja genau das ist das Problem! Wird beispielsweise eine Karte gescannt, die eine Größere Länge als in Len definiert, kommt es zu Problemen...
 
Also, bei Start der Verbindung setzt du

die Int: nPos := 1
Das Array aEBuffer[1...20] löscht du, indem du in jedes Element 0 reinschreibst

Beim ersten NDR:
auslesen von LEN
kopieren der Zeichen von 1 bis LEN vom Empfangsbuffer in aEBuffer (Schleife)
nPos = nPos + LEN
Durchsuchen des aEBuffer nach der Endekennung. (Schleife)
Dazu suchst du in einer Schleife nach dem ersten Zeichen der Endekennung. Findest du keine, nichts tun, findest du eine, dann 2. Zeichen ebenfalls prüfen. Wenn Endekennung komplett, dann kopieren von aEBuffer 1 bis nPos-1 in deinen FertigBuffer.

Beim 2. NDR:
auslesen von LEN
kopieren der Zeichen von 1 bis LEN vom Empfangsbuffer in aEBuffer von nPos bis nPos + LEN (Schleife)
nPos = nPos + LEN
Durchsuchen des aEBuffer nach der Endekennung. (Schleife)
Dazu suchst du in einer Schleife nach dem ersten Zeichen der Endekennung. Findest du keine, nichts tun (oder Fehler generieren, wenn nach dem 2. NDR eine Endekennung dasein müßte!!!), findest du eine, dann 2. Zeichen ebenfalls prüfen. Wenn Endekennung komplett, dann kopieren von aEBuffer 1 bis nPos-1 in deinen FertigBuffer.

Am Ende, wenn alles ok war (Ebdekennung gefunden) oder bei Fehler:
nPos := 1
aEBuffer[1...20] löscht du in dem du in jedes Element 0 reinschreibst

PS: Du mußt immer auch abprüfen, ober statt NDR Error kam, dann Fehlerreaktion.
Weiterhin nach der Berechnung von nPos prüfen, ob die Arraylänge von aEBuffer nicht überschritten wird, gleiches in der Schleife vor dem kopieren der Empfangsdaten in aEBuffer, damit du nicht über die Länge des Array kommst.

PS2: Komisch finde ich übferhaupt, dass du 2 Tegrammschnipsel bekommst, das kenne ich bei so kurzen Daten eher nicht, das sollte eigentlich vom Scanner in einem Rutsch kommen.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Komisch finde ich überhaupt, dass du 2 Telegrammschnipsel bekommst, das kenne ich bei so kurzen Daten eher nicht, das sollte eigentlich vom Scanner in einem Rutsch kommen.
Das kommt möglicherweise daher, dass der Receive sehr schnell hintereinander aufgerufen wird. Ich würde hier mit einem Zeitintervall drangehen - also z.B. nur alle 500 ms abfragen (oder so). Ggf. würde dann schon mit dem ersten Einlesen alles passend im Puffer stehen.
Besser ist allerdings sicherlich, die empfangenen Daten immer gegenzuprüfen. Wenn allerdings 10 Zeichen erwartet werden und 10 Zeichen empfangen wurden sollte es ja passen ...
 
PS2: Komisch finde ich übferhaupt, dass du 2 Tegrammschnipsel bekommst, das kenne ich bei so kurzen Daten eher nicht, das sollte eigentlich vom Scanner in einem Rutsch kommen.
Ja verstehe ich leider auch nicht... Zur Info der Reader ist per USB an einen Ethernet Konverter angeschlossen, über diesen empfange ich meine Daten. Hänge ich den Reader über USB an den PC und lese als Tastatur Emulation ein bekomme ich problemlos den richtigen string -> 7767CE65

Bin aktuell an der Umsetzung von Ralle dran und bin auch sehr froh für den Hinweis, jedoch habe ich da noch als SCL Neuling größere Schwierigkeiten...

Das kommt möglicherweise daher, dass der Receive sehr schnell hintereinander aufgerufen wird. Ich würde hier mit einem Zeitintervall drangehen - also z.B. nur alle 500 ms abfragen (oder so). Ggf. würde dann schon mit dem ersten Einlesen alles passend im Puffer stehen.
Besser ist allerdings sicherlich, die empfangenen Daten immer gegenzuprüfen. Wenn allerdings 10 Zeichen erwartet werden und 10 Zeichen empfangen wurden sollte es ja passen ...
Wäre schon sehr froh, wenn der Ansatz über ein Zeitintervall klappen würde, da ich mir dann das Umständliche Gegenprüfen ersparen kann.

Ich habe jetzt nochmals meinen Code überarbeitet, noch ohne der Lösung von Ralle, da bin ich noch dran:
An welcher Stelle in meinem Code müsste ich das Zeitintervall vor dem Receive einbauen? Verstehe ich es richtig, dass du damit einen Timer meinst?

Code:
//Establish Connection
#TCON_Instance.REQ := #ConnReset.Q;

//Save TCON Error
IF #Internal.TCON.ConnError
THEN
  #Internal.TCON.StatusSave := #Internal.TCON.ConnStatus;
END_IF;

//Initialize TCON Block
#TCON_Instance(//REQ := #Internal.TCON.ConnReq,
               ID := 1,
               DONE => #Internal.TCON.ConnDone,
               BUSY => #Internal.TCON.ConnBusy,
               ERROR => #Internal.TCON.ConnError,
               STATUS => #Internal.TCON.ConnStatus,
               CONNECT := "PLC_Controller_Connection");

//Starts Connection Diagnose
#T_DIAG_Instance.REQ := NOT #T_DIAG_Instance.BUSY;

//Initialize T_DIAG Block
#T_DIAG_Instance(//REQ := #Internal.TDIAG.Req,
                 ID := 1,
                 //BUSY => #Internal.TDIAG.Busy,
                 RESULT := #Internal.TDIAG.Result);

#ConnReset.I := #Internal.TDIAG.Result.State <> 16#04 AND NOT #ConnReset.Q;

//If there is no active connection, every 30s a new connection will be established
#ResetTimer(IN := #ConnReset.I,
            PT := t#30s,
            Q => #ConnReset.Q);

//Initialize TRCV Block
#TRCV_Instance(EN_R := TRUE,
               ID := 1,
               LEN := 0,
               ADHOC := TRUE,
               NDR => #Internal.TRCV.Ndr,
               BUSY => #Internal.TRCV.Busy,
               ERROR => #Internal.TRCV.Error,
               STATUS => #Internal.TRCV.Status,
               RCVD_LEN => #Internal.TRCV.RcvdLen,
               DATA := #Data.Buffer);

//Detect New Data Received and set Receive Trigger
#NdrPosEdge(CLK := #Internal.TRCV.Ndr,
            Q => #Internal.RcvReq);

IF #Internal.RcvReq
THEN
  #Data.RcvLen := #Internal.TRCV.RcvdLen;
END_IF;

//Save TRCV Error
IF #Internal.TRCV.Error
THEN
  #Internal.TRCV.StatusSave := #Internal.TRCV.Status;
END_IF;

//Save Global Error
#Error := #Internal.TCON.ConnError OR #Internal.TRCV.Error;
 
Wie bereits erwähnt ist es doch merkwürdig warum du anscheinend zwei Telegramme bekommst.

Ich hätte da noch zwei Ideen mit der du das abfangen bzw. prüfen könntest.

1. Die 1500er Steuerungen sind sehr schnell, ich finde es da persönlich wichtig dass du eine Mindestzykluszeit verwendest.
Ich hatte bei einem konvertierten Programm (ohne IEC-Timer, noch selbst an Zykluszeit angelehnte Timer) einmal den merkwürdigen Fall
dass kein einziger Timer mehr abgelaufen ist, da keine Mindestzykluszeit angegeben war und die CPU so sogar unter 1ms gekommen ist.
Eventuell kommt dadurch der zu häufige Aufruf zusammen, ich würde dir empfehlen dass zu prüfen und ev. 10ms zu verwenden.

Ansonsten kannst du auch in einem anderen OB3x mal die T_RCV aufrufen und den einfach alle 10-30ms durchlaufen lassen.

2. Mit Wireshark könntest du noch prüfen ob du wirklich zwei Telegramme von dem Gerät bekommst oder ob das Telegramm segmentiert wird.
Wenn du dort siehst dass es in einem Telegramm enthalten ist dann weißt du, dass es definitiv an der SPS-Seite scheitert.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
An welcher Stelle in meinem Code müsste ich das Zeitintervall vor dem Receive einbauen? Verstehe ich es richtig, dass du damit einen Timer meinst?
Ja ... ich meinte einen Timer mit dem genannten Intervall - also den Receive nur jeweils dann aufrufen wenn der Timer durchgelaufen ist. Dann den Timer wieder abwerfen.
Ich würde den Timer.Q vor/an den Baustein-Enable setzen ... also nicht den Baustein permanent aufrufen ...
 
Ja ... ich meinte einen Timer mit dem genannten Intervall - also den Receive nur jeweils dann aufrufen wenn der Timer durchgelaufen ist. Dann den Timer wieder abwerfen.
Ich würde den Timer.Q vor/an den Baustein-Enable setzen ... also nicht den Baustein permanent aufrufen ...
habs mal mit dem Timer versucht, jedoch werden trotzdem wieder nur 9 Zeichen eingelesen
1651759208747.png

Code:
//Establish Connection
#TCON_Instance.REQ := #ConnReset.Q;

//Save TCON Error
IF #Internal.TCON.ConnError
THEN
  #Internal.TCON.StatusSave := #Internal.TCON.ConnStatus;
END_IF;

//Initialize TCON Block
#TCON_Instance(ID := 1,
               DONE => #Internal.TCON.ConnDone,
               BUSY => #Internal.TCON.ConnBusy,
               ERROR => #Internal.TCON.ConnError,
               STATUS => #Internal.TCON.ConnStatus,
               CONNECT := "PLC_Controller_Connection");

//Starts Connection Diagnose
#T_DIAG_Instance.REQ := NOT #T_DIAG_Instance.BUSY;

//Initialize T_DIAG Block
#T_DIAG_Instance(ID := 1,
                 RESULT := #Internal.TDIAG.Result);

#ConnReset.I := #Internal.TDIAG.Result.State <> 16#04 AND NOT #ConnReset.Q;

//If there is no active connection, every 30s a new connection will be established
#ResetTimer(IN := #ConnReset.I,
            PT := t#30s,
            Q => #ConnReset.Q);

//Initialize TRCV Block
#TRCV_Instance(EN_R := #Internal.TRCV.Enable,
               ID := 1,
               LEN := 0,
               ADHOC := TRUE,
               NDR => #Internal.TRCV.Ndr,
               BUSY => #Internal.TRCV.Busy,
               ERROR => #Internal.TRCV.Error,
               STATUS => #Internal.TRCV.Status,
               RCVD_LEN => #Internal.TRCV.RcvdLen,
               DATA := #Data.Buffer);

#Processing.Start := 1;

IF #Processing.Start AND NOT #Internal.TCON.ConnError
THEN
  #WaitTimer(IN := #Processing.Start,
             PT := t#1s,
             Q => #Processing.SetTrcvEnable);
  IF #Processing.SetTrcvEnable
  THEN
    #Internal.TRCV.Enable := TRUE;
  END_IF;
 
END_IF;

//Detect New Data Received and set Receive Trigger
#NdrPosEdge(CLK := #Internal.TRCV.Ndr,
            Q => #Internal.RcvReq);

//Receive Trigger for new data
IF #Internal.RcvReq
THEN
  #Data.RcvLen := #Internal.TRCV.RcvdLen;
END_IF;

//Save TRCV Error
IF #Internal.TRCV.Error
THEN
  #Internal.TRCV.StatusSave := #Internal.TRCV.Status;
END_IF;

//Save Global Error
#Error := #Internal.TCON.ConnError OR #Internal.TRCV.Error;
 
Wie fängt dein Programm denn den Fall ab, wenn TRCV von den gesendeten 10 Bytes im ersten Aufruf 1 Byte, und dann im zweiten restlichen 9 ausgibt? Bei deinen Screenshots siehst du ja immer nur eine Momentaufnahme am Ende. Zähl mal die Flanken von NDR mit und summiere mit den Flanken die empfangenen Längen auf. Solange das nicht grundsätzlich richtig programmiert ist, brauchst du auch nicht mit irgendwelchen Timern probieren, der verschleiert womöglich das eigentliche Problem.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
... und Timer bedingt aufrufen (also in einer IF-Kondition einbetten) ist auch nicht der Bringer ... und dein #Internal.TRCV.Enable ist nach dem ersten Timer-Lauf immer TRUE (du setzt es ja nirgends zurück - habe ich jedenfalöls nicht gesehen).
 
Wie fängt dein Programm denn den Fall ab, wenn TRCV von den gesendeten 10 Bytes im ersten Aufruf 1 Byte, und dann im zweiten restlichen 9 ausgibt? Bei deinen Screenshots siehst du ja immer nur eine Momentaufnahme am Ende. Zähl mal die Flanken von NDR mit und summiere mit den Flanken die empfangenen Längen auf. Solange das nicht grundsätzlich richtig programmiert ist, brauchst du auch nicht mit irgendwelchen Timern probieren, der verschleiert womöglich das eigentliche Problem.
Telegramm 1 enthält 1tes Zeichen. Telegramm 2 enthält Zeichen 2-9. Da ich den Adhoc Modus verwende werden die Telegramm Daten sofort in den Buffer kopiert, was in meinem Fall bedeutet Telegramm2 überschreibt Telegramm1 und deshalb stehen nur 9 statt 10 Zeichen im Buffer. Deshalb wird kein Weg an dem Ansatz von Ralle in Beitrag 5 + 11 vorbeiführen.

So wie ich die Logik verstanden habe: es gibt Buffer1 welcher am Param Data von TRCV hängt und einen zusätzlichen Buffer2. Dann brauche ich eine For Schleife von 1 - RcvLen in der die Empfangen Werte von Buffer1 in Buffer2 kopiert werden. Das wird solange gemacht bis Steuerzeichen gefunden wurden.
 
Vielleicht noch einmal zu meinem Beitrag von gestern :
#Processing.Start := 1;

IF #Processing.Start AND NOT #Internal.TCON.ConnError
THEN
#WaitTimer(IN := #Processing.Start,
PT := t#1s,
Q => #Processing.SetTrcvEnable);
IF #Processing.SetTrcvEnable
THEN
#Internal.TRCV.Enable := TRUE;
END_IF;

END_IF;
den Code-Block halte ich für fragwürdig und würde es so in etwa machen :
#WaitTimer(IN := #Processing.Start and #Daten_verarbeitet,
PT := t#1s,
Q => #Internal.TRCV.Enable );
mich stört allerdings in jedem Fall deine Anweisung :
#Processing.Start := 1;
so macht das doch auch keinen Sinn ...

In jedem Fall (wie schon von mir geschrieben) hat der eingebaute Timer derzeit keine Auswirkung - also auch keine Änderung ...
Vielleicht überdenkst du dein Konstrukt noch einmal ...
 
Zurück
Oben