Supported platforms: CODESYS 2.3, CODESYS 3.5, CODESYS 3.5 SAFETY

 

Using J1939

J1939 is a CAN based protocol, that is used for communication with an engine, for example.

 

 

Required:

 

 

The code template depends on the used platform.

This guide shows an example of

  1. CODESYS 2.3 product

  2. CODESYS 3.5 6000 series / 5050

  3. CODESYS 3.5 S Series / E Series

 

In SDK3.8 or newer J1939 PGN message's (source and/or destination) address can be manual or use address claiming. See Using Address Claiming for more details on using PGNs with address claiming.

 

1. CODESYS 2.3

To start using J1939 (this example is configured using MultiTool 6.9):

 

1. In MultiTool, add a J1939 device (named "Engine" in this example) and make the needed configurations:

    For more detailed description, refer to Epec MultiTool Creator manual.

 

2. MultiTool generates the initializations for J1939 to the code template and generates the following structures.

This example receives EEC1, HOURS, DM1 and ET1 PGNs.

 

Code template structure exampleCode template structure example

 

Code template example

Description

VAR_GLOBAL

    J1939_CAN2: J1939_CAN2;

    J1939_FB_CAN2: J1939;

END_VAR

 

MultiTool generates J1939 global variable list to CODESYS IDE's Resources tab.

 

TYPE J1939_CAN2 :

STRUCT

    In: J1939_CAN2_IN;

    Out: J1939_CAN2_OUT;

END_STRUCT

END_TYPE

 

 

MultiTool generates a struct for J1939 messages:

  • In contains the received messages

  • Out contains the transmitted messages

 

TYPE J1939_CAN2_IN :

STRUCT

    Engine : J1939_CAN2_IN_Engine;

    PGNs: ARRAY [1..G_J1939_CAN2_RX_PGNS] OF J1939_pPGN;

END_STRUCT

END_TYPE

 

 

MultiTool Creator generates separate structs for received and transmitted messages. It also generates a table for PGN messages to be used by library. Engine contains the PGN variables that are configured in MultiTool Creator for the device in question.

 

 

TYPE J1939_CAN2_IN_Engine :

STRUCT

(*PGN: EEC1, F004*)

EEC1_EngTorqueMode: BYTE;

EEC1_ActualEnginePercentTorqueHiRes: BYTE;

EEC1_DriversDemandEngPercentTorque: BYTE;

EEC1_ActualEngPercentTorque: BYTE;

EEC1_EngSpeed: WORD;

EEC1_SrcAddrssOfCtrllngDvcForEngCtrl: BYTE;

EEC1_EngStarterMode: BYTE;

J1939_CAN2_EEC1_Dummy_RX_1: BYTE;

EEC1_EngDemandPercentTorque: BYTE;

PGN_EEC1_SPNs:ARRAY[1..9] OF J1939_SPN;

PGN_EEC1:J1939_PGN;

(*PGN: HOURS, FEE5*)

HOURS_EngTotalHoursOfOperation: DWORD;

HOURS_EngTotalRevolutions: DWORD;

PGN_HOURS_SPNs:ARRAY[1..2] OF J1939_SPN;

PGN_HOURS:J1939_PGN;

(*PGN: ET1, FEEE*)

ET1_EngCoolantTemp: BYTE;

ET1_EngFuelTemp: BYTE;

ET1_EngOilTemp1: WORD;

ET1_EngTurboOilTemp: WORD;

ET1_EngIntercoolerTemp: BYTE;

ET1_EngIntercoolerThermostatOpening: BYTE;

PGN_ET1_SPNs:ARRAY[1..6] OF J1939_SPN;

PGN_ET1:J1939_PGN;

(*PGN: DM1, FECA*)

DM1_ProtectLampStatus: BYTE;

DM1_AmberWarningLampStatus: BYTE;

DM1_RedStopLampState: BYTE;

DM1_MalfunctionIndicatorLampStatus: BYTE;

DM1_FlashProtectLamp: BYTE;

DM1_FlashAmberWarningLamp: BYTE;

DM1_FlashRedStopLamp: BYTE;

DM1_FlashMalfuncIndicatorLamp: BYTE;

DM1_DTC1: DWORD;

DM1_DTC2: DWORD;

DM1_DTC3: DWORD;

DM1_DTC4: DWORD;

DM1_DTC5: DWORD;

PGN_DM1_SPNs:ARRAY[1..13] OF J1939_SPN;

PGN_DM1:J1939_PGN;

END_STRUCT

END_TYPE

 

 

MultiTool generates a struct that contains the variables that are received from the device. These variables are raw values that you must scale if needed. MultiTool Creator generates PGN & SPN variables for received messages.

 

 

Application example of J1939 variable scalingApplication example of J1939 variable scaling

The following example describes how to access and scale the measurement values.

 

Application code example

Description

 

J1939_CAN2.In.Engine.EEC1_EngSpeed

 

 

Raw value for engine speed

 

EngineRpm:=J1939_CAN2.In.Engine.EEC1_EngSpeed/8;

 

 

An example for scaling the engine RPM

 

EngineHours:=DWORD_TO_WORD(J1939_CAN2.In.Engine.HOURS_EngTotalHoursOfOperation/20);

 

An example for scaling the engine hours

 

CoolantTemp:=BYTE_TO_SINT(J1939_CAN2.In.Engine.ET1_EngCoolantTemp)-40;

 

An example for scaling the engine coolant temperature to Celsius degrees

 

 

Application example of converting received DM1 log's DTCs to SPN-FMI valuesApplication example of converting received DM1 log's DTCs to SPN-FMI values

The following converts raw DTC signals to SPN-FMI error codes.

DM1 PGN message has 5 DTC variables by default but more DTCs can be added in MultiTool Creator.

 

Conversion method 4 is recommended but used method depends on J1939 device which sends the DM log.

 

Definitions:

 

DM1_SPNFMI: ARRAY [1..5] OF J1939_SPNFMI;

 

 

Code:

 

IF J1939_CAN2.In.Engine.PGN_DM1.NewData THEN

   J1939_SPNFMI_Convert(

      i_SPNFMIConversionMethod := 4,

      i_pDTC_Data := ADR(J1939_CAN2.In.Engine.DM1_DTC1),

      i_NumberOfDTC := 5,

      i_pSPNFMI_Data := ADR(DM1_SPNFMI)

   );

END_IF

 

 

2. CODESYS 3.5 6107 & 5050

To start using J1939 (this example is configured using MultiTool 6.9):

 

1. In MultiTool, add a J1939 device (named "Engine" in this example) and make the needed configurations:

    For more detailed description, refer to Epec MultiTool Creator manual.

 

2. MultiTool generates the initializations for J1939 to the code template and generates the following structures.

This example receives EEC1, HOURS, DM1 and ET1 PGNs.

 

Code template structure exampleCode template structure example

 

 

Code template example

Description

VAR_GLOBAL

    J1939_CAN2: J1939_CAN2;

    J1939_FB_CAN2: J1939;

END_VAR

 

J1939Globals global variable list generated by MultiTool Creator in

Device > Application > CodeTemplate > Globals

Contains main variable for J1939 all application data.

Contains function block instance for J1939.

 

TYPE J1939_CAN2 :

STRUCT

    In: J1939_CAN2_IN;

    Out: J1939_CAN2_OUT;

END_STRUCT

END_TYPE

 

 

MultiTool Creator generates a struct for J1939 messages:

  • In contains the received messages

  • Out contains the transmitted messages

 

TYPE J1939_CAN2_IN :

STRUCT

    Engine : J1939_CAN2_IN_Engine;

    PGNs: ARRAY [1..4] OF J1939_pPGN;

END_STRUCT

END_TYPE

 

 

MultiTool Creator generates separate structs for received and transmitted messages. It also generates a table for PGN messages to be used by library. Engine contains the PGN variables that are configured in MultiTool Creator for the device in question.

 

 

TYPE J1939_CAN2_IN_Engine :

STRUCT

EEC1_EngTorqueMode: BYTE;

EEC1_ActualEnginePercentTorqueHiRes: BYTE;

EEC1_DriversDemandEngPercentTorque: BYTE;

EEC1_ActualEngPercentTorque: BYTE;

EEC1_EngSpeed: WORD;

EEC1_SrcAddrssOfCtrllngDvcForEngCtrl: BYTE;

EEC1_EngStarterMode: BYTE;

J1939_CAN2_EEC1_Dummy_RX_1: BYTE;

EEC1_EngDemandPercentTorque: BYTE;

PGN_EEC1_SPNs: ARRAY[1..9] OF J1939_SPN;

PGN_EEC1: J1939_PGN;

HOURS_EngTotalHoursOfOperation: DWORD;

HOURS_EngTotalRevolutions: DWORD;

PGN_HOURS_SPNs: ARRAY[1..2] OF J1939_SPN;

PGN_HOURS: J1939_PGN;

ET1_EngCoolantTemp: BYTE;

ET1_EngFuelTemp: BYTE;

ET1_EngOilTemp1: WORD;

ET1_EngTurboOilTemp: WORD;

ET1_EngIntercoolerTemp: BYTE;

ET1_EngIntercoolerThermostatOpening: BYTE;

PGN_ET1_SPNs: ARRAY[1..6] OF J1939_SPN;

PGN_ET1: J1939_PGN;

DM1_ProtectLampStatus: BYTE;

DM1_AmberWarningLampStatus: BYTE;

DM1_RedStopLampState: BYTE;

DM1_MalfunctionIndicatorLampStatus: BYTE;

DM1_FlashProtectLamp: BYTE;

DM1_FlashAmberWarningLamp: BYTE;

DM1_FlashRedStopLamp: BYTE;

DM1_FlashMalfuncIndicatorLamp: BYTE;

DM1_DTC1: DWORD;

DM1_DTC2: DWORD;

DM1_DTC3: DWORD;

DM1_DTC4: DWORD;

DM1_DTC5: DWORD;

PGN_DM1_SPNs: ARRAY[1..13] OF J1939_SPN;

PGN_DM1: J1939_PGN;

END_STRUCT

END_TYPE

 

 

MultiTool Creator generates a struct that contains the variables that are received from the device. These variables are raw values that you must scale if needed. MultiTool Creator generates PGN & SPN variables for received messages.

 

 

Application example of J1939 variable scalingApplication example of J1939 variable scaling

The following example describes how to access and scale the measurement values.

 

Application code example

Description

 

J1939_CAN2.In.Engine.EEC1_EngSpeed

 

 

Raw value for engine speed

 

EngineRpm:=J1939_CAN2.In.Engine.EEC1_EngSpeed/8;

 

 

An example for scaling the engine RPM

 

EngineHours:=DWORD_TO_WORD(J1939_CAN2.In.Engine.HOURS_EngTotalHoursOfOperation/20);

 

An example for scaling the engine hours

 

CoolantTemp:=BYTE_TO_SINT(J1939_CAN2.In.Engine.ET1_EngCoolantTemp)-40;

 

An example for scaling the engine coolant temperature to Celsius degrees

 

 

Application example of converting received DM1 log's DTCs to SPN-FMI valuesApplication example of converting received DM1 log's DTCs to SPN-FMI values

The following converts raw DTC signals to SPN-FMI error codes.

DM1 PGN message has 5 DTC variables by default but more DTCs can be added in MultiTool Creator.

 

Conversion method 4 is recommended but used method depends on J1939 device which sends the DM log.

 

Definitions:

 

DM1_SPNFMI: ARRAY [1..5] OF EPEC_J1939.J1939_SPNFMI;

 

 

Code:

 

IF J1939_CAN2.In.Engine.PGN_DM1.NewData THEN

   EPEC_J1939.J1939_SPNFMI_Convert(

      i_SPNFMIConversionMethod := 4,

      i_pDTC_Data := ADR(J1939_CAN2.In.Engine.DM1_DTC1),

      i_NumberOfDTC := 5,

      i_pSPNFMI_Data := ADR(DM1_SPNFMI)

   );

END_IF

 

 

3. CODESYS 3.5 S Series / E Series

The code template differs compared to other control units.

 

J1939 structures and global variable lists have been modified because of safety platform specific restrictions (see Safety project guidelines and Known issues).

Basically, the PGN and SPN variables and PGNs arrays have been moved to new global variable lists.

Also, the J1939 function block and application data are in separate global variable lists

 

To start using J1939 (this example is configured using MultiTool 6.9):

 

1. In MultiTool, add a J1939 device (named "Engine" in this example) and make the needed configurations:

    For more detailed description, refer to Epec MultiTool Creator manual.

 

2. MultiTool generates the initializations for J1939 to the code template and generates the following structures.

This example adds:

 

Code template exampleCode template example

 

Code template example

Description

VAR_GLOBAL

CAN2: J1939_CAN2;

END_VAR

G_J1939 global variable list generated by MultiTool in

Device > Application > CodeTemplate > Globals > J1939

Contains main variable for J1939 all application data.

VAR_GLOBAL

CAN2: EPEC_J1939.J1939;

END_VAR

G_J1939_FB global variable list generated by MultiTool in

Device > Application > CodeTemplate > Globals > J1939

Contains function block instance for J1939.

VAR_GLOBAL

PGNs: ARRAY[1..G_J1939_CAN2_RX_PGNS] OF J1939_pPGN;

Engine_EEC1_SPNs: ARRAY[1..9] OF J1939_SPN;

Engine_EEC1: J1939_PGN;

Engine_HOURS_SPNs: ARRAY[1..2] OF J1939_SPN;

Engine_HOURS: J1939_PGN;

Engine_ET1_SPNs: ARRAY[1..6] OF J1939_SPN;

Engine_ET1: J1939_PGN;

Engine_DM1_SPNs: ARRAY[1..13] OF J1939_SPN;

Engine_DM1: J1939_PGN;

END_VAR

G_J1939_CAN2_RPGN global variable list generated by MultiTool in Device > Application > CodeTemplate > Globals > J1939

 

MultiTool generates PGN & SPN variables for received messages. It also generates a table for PGN messages to be used by library.

VAR_GLOBAL

PGNs: ARRAY[1..G_J1939_CAN2_TX_PGNS] OF J1939_pPGN;

Engine_TSC1_SPNs: ARRAY[1..9] OF J1939_SPN;

Engine_TSC1: J1939_PGN;

END_VAR

G_J1939_CAN2_TPGN global variable list generated by MultiTool in

Device > Application > CodeTemplate > Globals > J1939

 

MultiTool generates PGN & SPN variables for transmitted messages. It also generates a table for PGN messages to be used by library.

 

TYPE J1939_CAN2 :

STRUCT

In: J1939_CAN2_IN;

Out: J1939_CAN2_OUT;

END_STRUCT

END_TYPE

 

 

MultiTool generates a struct for J1939 message's application data:

  • In contains the received application variables

  • Out contains the transmitted application variables

 

TYPE J1939_CAN2_IN :

STRUCT

Engine: J1939_CAN2_IN_Engine;

END_STRUCT

END_TYPE

 

 

MultiTool generates struct for received data.

Engine contains the application variables that are configured in MultiTool Creator for the device in question.

 

TYPE J1939_CAN2_IN_Engine :

STRUCT

EEC1_EngTorqueMode: BYTE;

EEC1_ActualEnginePercentTorqueHiRes: BYTE;

EEC1_DriversDemandEngPercentTorque: BYTE;

EEC1_ActualEngPercentTorque: BYTE;

EEC1_EngSpeed: WORD;

EEC1_SrcAddrssOfCtrllngDvcForEngCtrl: BYTE;

EEC1_EngStarterMode: BYTE;

EEC1_Dummy_RX_1: BYTE;

EEC1_EngDemandPercentTorque: BYTE;

HOURS_EngTotalHoursOfOperation: DWORD;

HOURS_EngTotalRevolutions: DWORD;

ET1_EngCoolantTemp: BYTE;

ET1_EngFuelTemp: BYTE;

ET1_EngOilTemp1: WORD;

ET1_EngTurboOilTemp: WORD;

ET1_EngIntercoolerTemp: BYTE;

ET1_EngIntercoolerThermostatOpening: BYTE;

DM1_ProtectLampStatus: BYTE;

DM1_AmberWarningLampStatus: BYTE;

DM1_RedStopLampState: BYTE;

DM1_MalfunctionIndicatorLampStatus: BYTE;

DM1_FlashProtectLamp: BYTE;

DM1_FlashAmberWarningLamp: BYTE;

DM1_FlashRedStopLamp: BYTE;

DM1_FlashMalfuncIndicatorLamp: BYTE;

DM1_DTC1: DWORD;

DM1_DTC2: DWORD;

DM1_DTC3: DWORD;

DM1_DTC4: DWORD;

DM1_DTC5: DWORD;

END_STRUCT

END_TYPE

 

MultiTool generates a struct that contains the application variables that are received from the device. These variables are raw values that you must scale if needed.

TYPE J1939_CAN2_OUT :

STRUCT

Engine: J1939_CAN2_OUT_Engine;

END_STRUCT

END_TYPE

 

MultiTool generates struct for transmitted data.

Engine contains the application variables that are configured in MultiTool for the device in question.

TYPE J1939_CAN2_OUT_Engine :

STRUCT

TSC1_EngOverrideCtrlMode: BYTE;

TSC1_EngRqedSpeedCtrlConditions: BYTE;

TSC1_OverrideCtrlModePriority: BYTE;

TSC1_Dummy_TX_1: BYTE;

TSC1_EngRqedSpeed_SpeedLimit: WORD;

TSC1_EngRqedTorque_TorqueLimit: BYTE;

TSC1_TransmissionRate: BYTE;

TSC1_ControlPurpose: BYTE;

TSC1_EngineRequestedTorqueHiRes: BYTE;

END_STRUCT

END_TYPE

 

MultiTool generates a struct that contains the application variables that are transmitted to the device. These variables are raw values that you must scale if needed.

 

 

Application example of J1939 variable scalingApplication example of J1939 variable scaling

 

Application code example

Description

 

G_J1939.CAN2.In.Engine.EEC1_EngSpeed

 

 

Raw value for engine speed

 

EngineRpm := G_J1939.CAN2.In.Engine.EEC1_EngSpeed/WORD#8;

 

An example for scaling the engine RPM

 

EngineHours := DWORD_TO_WORD(G_J1939.CAN2.In.Engine.HOURS_EngTotalHoursOfOperation/DWORD#20);

 

An example for scaling the engine hours

 

CoolantTemp := BYTE_TO_SINT(G_J1939.CAN2.In.Engine.ET1_EngCoolantTemp)-SINT#40;

 

An example for scaling the engine coolant temperature to Celsius degrees

 

G_J1939.CAN2.Out.Engine.TSC1_EngRqedSpeed_SpeedLimit := RequiredRpm * WORD#8;

 

An example of setting engine's requested rpm to transmit message.

 

IF G_J1939_CAN2_RPGN.Engine_EEC1.Status = EPEC_J1939.J1939_PGNStatus.J1939_PGN_Timeout THEN

;(*do something*)

END_IF

 

An example of accessing the PGN variable to check message's status

 

 

Application example of converting received DM1 log's DTCs to SPN-FMI valuesApplication example of converting received DM1 log's DTCs to SPN-FMI values

The following converts raw DTC signals to SPN-FMI error codes.

DM1 PGN message has 5 DTC variables by default but more DTCs can be added in MultiTool Creator.

 

Conversion method 4 is recommended but used method depends on J1939 device which sends the DM log.

 

Definitions:

 

DM1_SPNFMI: ARRAY [1..5] OF EPEC_J1939.J1939_SPNFMI;

 

 

Code:

 

IF G_J1939_CAN2_RPGN.Engine_DM1.NewData THEN

   EPEC_J1939.J1939_SPNFMI_Convert(

      i_SPNFMIConversionMethod := 4,

      i_pDTC_Data := ADR(G_J1939.CAN2.In.Engine.DM1_DTC1),

      i_NumberOfDTC := 5,

      i_pSPNFMI_Data := ADR(DM1_SPNFMI)

   );

END_IF

 

 

See also

 

 

Source file topic100326.htm

Last updated 13-Jun-2024