Supported platforms: CODESYS 3.5 SAFETY, CODESYS 3.5

 

Sending J1939 Message with Fixed Interval

This section describes how to define J1939 messages to be sent with a fixed interval.

CAN message sending is independent of the application cycle (see limitations below).

 

This example uses MultiTool Creator generated PGNs, but it is also possible to define PGNs manually.

 

Some engines require a certain message interval for TSC1 messages. In some cases the software cycle time is affected so that the TSC1 message is not sent within the correct time frame. In this case, the engine may not respond to the RPM (rounds per minute) request. In this case, use the interrupt functionality described in this section. The interrupt functionality sends the TSC1 message in the correct time frame regardless of the software cycle time.

 

 

Required:

 

Limitations:

  • Maximum number of the send messages is 10

  • Accuracy of the time is +-2 ms

  • Minimum time interval for sending is 1 ms, but it is recommended to use intervals > 10 ms.

  • Used CAN channel must be initialized before initializing the time triggered messages (done automatically with MultiTool Creator code template)

  • Function block instance must be called at least every 100 ms, otherwise message sending is stopped

 

The following example uses MultiTool Creator and code template so the CAN channel is automatically initialized.

 

Creating an S Series / E Series project with PGN

1. Open MultiTool, create e.g. SC52 control unit and add Transmit PGN. This example uses TSC1, which is sent to the engine in address 0.

 

   

 

2. Create a CODESYS 3.5 project

 

Changing J1939 sending to use time triggered CAN sending

This example uses SC52 code template with MultiTool 5.7.

Time triggered message code is added to a non-safe PRG.

 

Definitions:

 

bInit:BOOL:=TRUE;

tsc1CanApiHandler:EPEC_HWD.CanApiTimeTriggeredMsg;

usedCobId:DWORD;

 

 

Code:

 

IF bInit THEN

bInit := FALSE;

(* Set TSC1 PGN *)

(* Time triggered CAN message supports only data length <= 8 *)

IF G_J1939_CAN2_TPGN.Engine_TSC1.DataLength <= 8 THEN

(* Set cycle time to 0ms to prevent message sending by J1939 server *)

G_J1939_CAN2_TPGN.Engine_TSC1.CycleTime := 0;

(* Set data length *)

tsc1CanApiHandler.i_Dlc := WORD_TO_BYTE(G_J1939_CAN2_TPGN.Engine_TSC1.DataLength);

 

(* Set init data for message *)

EPEC_J1939.J1939_BuildPGN(

i_pBasePGN := ADR(G_J1939_CAN2_TPGN.Engine_TSC1),

i_pDataBuffer := ADR(tsc1CanApiHandler.i_Data)

);

tsc1CanApiHandler.UpdateData();

 

(* Init cobid for time triggered message *)

(* build used cobid from PGN *)

usedCobId:=BYTE_TO_DWORD(G_J1939_CAN2_TPGN.Engine_TSC1.Priority);

usedCobId:=SHL(usedCobId,1) OR 0;

usedCobId:=SHL(usedCobId,1) OR BYTE_TO_DWORD(G_J1939_CAN2_TPGN.Engine_TSC1.DataPage);

usedCobId:=SHL(usedCobId,8) OR WORD_TO_DWORD(SHR(G_J1939_CAN2_TPGN.Engine_TSC1.PGN_Number,8) AND 16#FF);

 

IF 16#F000 > G_J1939_CAN2_TPGN.Engine_TSC1.PGN_Number THEN

usedCobId:=SHL(usedCobId,8) OR BYTE_TO_DWORD(G_J1939_CAN2_TPGN.Engine_TSC1.Destination);

ELSE

usedCobId:=SHL(usedCobId,8) OR WORD_TO_DWORD(G_J1939_CAN2_TPGN.Engine_TSC1.PGN_Number AND 16#FF);

END_IF

 

usedCobId := SHL(usedCobId,8) OR BYTE_TO_DWORD(G_J1939_CAN2_TPGN.Engine_TSC1.SourceAddress);

usedCobId := usedCobId OR EPEC_CANVXD.MASK_29BIT; (* Set bit on which defines message as 29bit *)

 

(* Init time triggered message *)

tsc1CanApiHandler.InitCobId(

i_CanChannel := 1, (*CAN2*)

i_CobId := usedCobId,

i_TimeInterval := T#10MS

);

 

tsc1CanApiHandler.i_Enable := TRUE;

END_IF

ELSE

(* J1939 variables are accessed normally through J1939 structure*)

G_J1939.CAN2.Out.Engine.TSC1_EngRqedSpeed_SpeedLimit := WORD#1000 * 8; (*1000 rpm to raw value*)

 

(* Update PGN data to Api handler input*)

EPEC_J1939.J1939_BuildPGN(

i_pBasePGN := ADR(G_J1939_CAN2_TPGN.Engine_TSC1),

i_pDataBuffer := ADR(tsc1CanApiHandler.i_Data)

);

 

(* Update Api handler data*)

tsc1CanApiHandler.UpdateData();

 

(* Function block instance must be called at least with 100ms interval *)

tsc1CanApiHandler();

END_IF

 

 

See also

 

 

Source file topic100359.htm

Last updated 13-Jun-2024