Hallo,
ich sitze mal wieder an der SPS und habe ein Problem mit der EL6001 Klemme. Ich bin in der Lage Befehle mittels RS232 und einer COM Schnittstelle zu senden. Allerdings bleibt der Receive Buffer komplett leer. Ich sitze da jetzt schon laenger immer mal wieder dran und mir gehen die Loesungsansaetze aus. Da es meine erster Kommunikationsbaustein fuer RS232 ist liegt der Fehler bestimmt bei mir.
Das der Fehler im Code und nicht an nicht gesendeten daten liegt konnte ich unter anderem durch ein Oszilloskop bestaetigen auf dass ich die ASCI Antwort ablesen konnte.
Da das Gesamtsystem eine Zykluszeit von 10ms hat, wird die Kommunikation ueber einen zweiten schnelleren Task mit einer Zykluszeit von 1ms aufgerufen (BackgroundEL). BackgroundEL ist dabei komplett einem Beckhoff Beispiel entnommen.
Hier die drei relevanten aber teils gekürzte Codeteile die benutzt werden. Ziel ist es einen Befehl an den Kommunikationspartner zu schicken. Dieser sendet immer eine Antwort. Sobald die Antwort kommt ist der Sendeprozess erfolgreich abgeschlossen.
In der "normalen" Main Task geht die Kommunikation ueber den FB_SerialCom und soll jeweils dann abgeschlossen sein wenn eine Antwort des Kommunikationspartners kam.
Aufgeruffen wird die Instanz vom SerialCom baustein wie folgt:
Aktuell habe ich keine Ahnung wie ich das Problem weiter eingrenze kann. Wie würdet ihr vorgehen? Oder gibt es direkt einen sichtbaren Fehler meiner Herangehensweise?
ich sitze mal wieder an der SPS und habe ein Problem mit der EL6001 Klemme. Ich bin in der Lage Befehle mittels RS232 und einer COM Schnittstelle zu senden. Allerdings bleibt der Receive Buffer komplett leer. Ich sitze da jetzt schon laenger immer mal wieder dran und mir gehen die Loesungsansaetze aus. Da es meine erster Kommunikationsbaustein fuer RS232 ist liegt der Fehler bestimmt bei mir.
Das der Fehler im Code und nicht an nicht gesendeten daten liegt konnte ich unter anderem durch ein Oszilloskop bestaetigen auf dass ich die ASCI Antwort ablesen konnte.
Da das Gesamtsystem eine Zykluszeit von 10ms hat, wird die Kommunikation ueber einen zweiten schnelleren Task mit einer Zykluszeit von 1ms aufgerufen (BackgroundEL). BackgroundEL ist dabei komplett einem Beckhoff Beispiel entnommen.
Hier die drei relevanten aber teils gekürzte Codeteile die benutzt werden. Ziel ist es einen Befehl an den Kommunikationspartner zu schicken. Dieser sendet immer eine Antwort. Sobald die Antwort kommt ist der Sendeprozess erfolgreich abgeschlossen.
Code:
PROGRAM BackgroundEL
VAR
(* background communication with the EL6001 terminal *)
fbEL6001Ctrl : SerialLineControl;
bEL6001CtrlError : BOOL;
eEL6001CtrlErrorID : ComError_t;
(* I/O variables for a EL6001 terminal*)
stIn_EL6001 AT %I* : EL6inData22B; (* linked to the EL6001 in the TwinCAT System Manager *)
stOut_EL6001 AT %Q* : EL6outData22B;(* linked to the EL6001 in the TwinCAT System Manager *)
END_VAR
________________
(*
The SerialLineControl function block is supposed to be called in every PLC cycle.
It communicates with the serial line hardware device and transmits or receives data.
The SerialLineControl can be called in the standard task (e.g.for PcCOM port usage)
or in a separate fast task (e.g.for terminal usage) as well.
A fast separate task will be necessary at high baud rates or with KL6001 terminals
which have a small process image (3 or 5 data bytes only)
*)
(* background communication with the EL6001 terminal *)
fbEL6001Ctrl( Mode := SERIALLINEMODE_EL6_22B,
pComIn := ADR(stIn_EL6001),
pComOut := ADR(stOut_EL6001),
SizeComIn := SIZEOF(stIn_EL6001),
Error=> ,
ErrorID=> ,
TxBuffer := TxBufferEL,
RxBuffer := RxBufferEL );
IF fbEL6001Ctrl.Error THEN
bEL6001CtrlError := TRUE;
eEL6001CtrlErrorID := fbEL6001Ctrl.ErrorID;
END_IF
In der "normalen" Main Task geht die Kommunikation ueber den FB_SerialCom und soll jeweils dann abgeschlossen sein wenn eine Antwort des Kommunikationspartners kam.
Code:
FUNCTION_BLOCK FB_SerialCom
VAR_IN_OUT
TxBuffer : ComBuffer;
RxBuffer : ComBuffer;
END_VAR
VAR_OUTPUT
nfinished : UDINT;
sStatus : STRING;
END_VAR
VAR_INPUT
aSendBytes : ARRAY[0..MAX_STRING_LENGTH] OF BYTE;
nLength : UDINT;
END_VAR
VAR
....
END_VAR
// Method to data using the Serial Communication with EL6001
CASE nSwitchSend OF
0:
... ein par abfragen ob ein neuer Befehl gesendet werden darf
nSwitchSend := 10;
10:
fbReceive( Prefix := '',
Suffix := '',
Timeout := T#10S,
ReceivedString := sReceivedString,
RXbuffer := RxBufferEL,
StringReceived => bStringReceived,
Busy => bReceiveBusy,
Error => ,
RxTimeout => bReceiveTimeout );
IF fbReceive.Error <> COMERROR_NOERROR THEN
eReceiveErrorID := fbReceive.Error;
END_IF
IF bStringReceived THEN
nReceiveCounter := nReceiveCounter + 1;
sLastReceivedString := sReceivedString;
bStringReceived := 0;
END_IF
IF NOT bSent THEN
fbSendData( pSendData := ADR(aSendBytes),
Length := SIZEOF(aSendBytes),
Busy => bSendBusy,
Error => eSendErrorID,
TXbuffer := TxBuffer);
IF fbSendData.Error <> COMERROR_NOERROR THEN // if the error message is not "No Error" write error ID
eSendErrorID := fbSend.Error;
bError :=TRUE;
END_IF
IF NOT fbSendData.Busy THEN
bSent := TRUE;
nSendCounter := nSendCounter+1;
END_IF;
END_IF;
IF (bSent AND nSendCounter=nReceiveCounter AND nSendCounter>nLastSendCounter) THEN
nSwitchSend := 20;
END_IF
20: (*Reset sent function and prepare for next send command*)
nLastSendCounter:= nSendCounter;
bSent := FALSE;
nSwitchSend := 30
30:
bBusy := FALSE;
nfinished := 1;
nSwitchSend := 0;
END_CASE
Code:
....
nSwitchInitialise := 10;
10:
aSendBytes[0] := 16#01; //<PRE>
aSendBytes[1] := F_ToASC('1'); //<ADR> '1'
aSendBytes[2] := F_ToASC('R'); //<CODE1> 'R'
aSendBytes[3] := F_ToASC('Z'); //<CODE2> 'Z'
aSendBytes[4] := F_ToASC('3'); //<CODE2> '3'
aSendBytes[5] := F_ToASC('0'); //<CODE2> '0'
LRC:= 16#00;
FOR i:=1 TO 5 BY 1 DO
LRC:= LRC XOR aSendBytes[i];
END_FOR
LRC:= LRC OR 16#80;
aSendBytes[6]:= LRC; //<LRC>
aSendBytes[7]:= 16#0D; //<POST> 'CR'
fbCOMDispenser( aSendBytes := aSendBytes,
nLength := 8,
TxBuffer := TxBufferEL,
RxBuffer := RxBufferEL,
nfinished => nSent);
IF nSent=1 THEN
nSwitchInitialise:=999;
END_IF