Below is code that will allow you to set a bit when communications is lost with a J1939 device. (Assuming a single Source Address is generating the message, this will not work if two devices are generating the same PGN with different source addresses.)


VAR
recSwData:J1939_2_RECEIVE;
END_VAR

**CODE**

recSwData(
ENABLE:= TRUE,
CONFIG:= INIT,
PG:= 0,
PF:=SW_DATA_PF,
PS:=SW_DATA_PS,
DST:= ADR(swData),
RPT:=HEARTBEAT_TIME,
LIFE:= LIFE,
RESULT=> ,
DEVICE=> ,
LEN=> );


COMM_ERROR:=(recSwData.RESULT=3 OR COMM_ERROR) AND NOT (recSwData.RESULT=1);

If you have 2 or more devices using the same PGN with different source addresses. Below is an example using 2 joysticks with the same PGN and different source addresses.
I send the SA result to a data area based on the value, I then have a timer that looks for that result to be 0 (or an unused source address). Then I reset the SA value back to zero and when the next message is received that has the matching SA the timer is reset. If the timer times out, an error is generated.

VAR
recBJM:J1939_RECEIVE;
dataBJM:ARRAY [1..8] OF BYTE;

PF:BYTE:=16#FD;
PS:BYTE:=16#D6;
SA:BYTE;
tmrJS1Comms:TON;
tmrJS2Comms:TON;
JS1_SA: BYTE;
JS2_SA: BYTE;

i: INT;
loop: INT:=1000;
testbit: BOOL;
tmError:TIME:=t#150ms;

dataJS1:ARRAY [1..8] OF BYTE;
JS1_COMM_ERROR: BOOL;
dataJS2:ARRAY [1..8] OF BYTE;
JS2_COMM_ERROR: BOOL;
END_VAR

**CODE**

(*Receive data from joystick*)
recBJM(
ENABLE:= TRUE,
CONFIG:= INIT_1,
PG:= 0,
PF:= PF,
PS:= PS,
DST:= ADR(dataBJM),
RPT:= t#100ms,
LIFE:= 3,
RESULT=> ,
DEVICE=> SA,
LEN=> );

(*filter data according to source address*)
IF SA=JOYSTICK_1_ADDRESS THEN
JS1_SA:=SA;
dataJS1:=dataBJM;
ELSIF SA=JOYSTICK_2_ADDRESS THEN
JS2_SA:=SA;
dataJS2:=dataBJM;
END_IF

(*check for message received on SA and reset that value back to zero and monitor with a timer*)
tmrJS1Comms(IN:=JS1_SA<>JOYSTICK_1_ADDRESS, PT:=tmError);
JS1_SA:=0;
JS1_COMM_ERROR:=tmrJS1Comms.Q;

tmrJS2Comms(IN:=JS2_SA<>JOYSTICK_2_ADDRESS, PT:=tmError);
JS2_SA:=0;
JS2_COMM_ERROR:=tmrJS2Comms.Q;