Supported platforms: CODESYS 3.5 SAFETY
This section describes how to review generated code related to I/O.
A MultiTool Creator project defines variable names for all user defined I/O.
In a safety control unit, user shall also define which I/O is safety related. This is done in MultiTool Creator using I/O > Safety related setting.
Safety related setting affects the context I/O is mapped to.
Mapped I/O variables depend on the used pin type and the used mode. See hardware specific I/O Programming sections.
For example, Programming > Programming SC52 Safety Control Unit > I/O Programming.
IO_interface is a component generated in CODESYS, directly under the device.
Check each used I/O pin. The IO_interface > IO_interface I/O mapping tab has a folder for each I/O pin.
Verify that all I/O pins which are selected to be used in MultiTool Creator have mapped variables
Verify that the mapped variable name matches with name given in MultiTool Creator (see the example image in step 2)
Verify that all relevant variables are mapped for the selected I/O mode (See hardware specific I/O programming)
Check the pin context. The variable is mapped to a different code template program depending on MultiTool Creator's Safety related setting
Verify that all safety related inputs are mapped to the S_Inputs program
Verify that all safety related outputs are mapped to the S_Outputs program
Verify that all non-safety related inputs are mapped to the Inputs program
Verify that all non-safety related outputs are mapped to the Outputs program
The following image highlights the program name in red and the variable name in green, defined in MultiTool Creator.
Check internal diagnostic mapping. Verify that all I/O variables under the Internal folder are mapped to the S_Inputs program. These are used by hardware diagnostics.
All I/O initialization code (safety & non-safety related) is added to the S_Init_IO program.
Verify that the program is executed from S_PLC_PRG.
S_PLC_PRG Code: |
IF NOT o_InitDone AND PLC_PRG.o_InitDone THEN (* Code template safe FB initializations *) IF NOT S_Init_IO.o_Ready THEN S_Init_IO(); |
Verify initialization code generated to S_Init_IO program.
I/O initialization code does not depend on Safety related selection in MultiTool Creator
I/O initialization does depend on the used pin type, mode and configurations (selected in MultiTool Creator)
See hardware specific I/O programming sections for required initializations in each pin type/mode
|
Pin and connector numbers are added to I/O initialization for diagnostic purposes when using MultiTool 6.4 (SDK3.6) or later, or MultiTool Creator. |
The following variable definitions are added to the S_Init_IO program.
S_Init_IO Definitions |
PROGRAM S_Init_IO VAR_INPUT END_VAR VAR_OUTPUT o_Ready: SAFEBOOL := FALSE; o_Error: BOOL := FALSE; o_ErrorInConnector: DWORD := DWORD#0; o_ErrorInPin: DWORD := DWORD#0; o_FWErrorCode: EPEC_SYSTEM.SYSTEM_ERROR_CODES; END_VAR VAR result: EPEC_SYSTEM.SYSTEM_ERROR_CODES;
pin: DWORD := DWORD#0; connector: DWORD := DWORD#0; info1: DWORD := DWORD#0; // MSW connector, LSW pin info2: DWORD := DWORD#0; // error specific END_VAR |
I/O initialization code always begins by setting the I/O driver to IODRV_STATE_CONFIGURATION:
S_Init_IO Code |
IF result = EPEC_SYSTEM.SYSTEM_ERROR_CODES.FW_ERR_OK THEN result := EPEC_IODRV.IoDrvSetState(EPEC_IODRV.IoDrvStates.IODRV_STATE_CONFIGURATION); END_IF |
After I/O driver is set to configuration mode the following is generated:
All I/O pin related initializations
Internal diagnostic initializations
Firmware error is checked at each initialization function.
|
When I/O init's output o_Error is TRUE following diagnostic can be used by application:
|
|
Error code is added to application log only when device description includes SafeErrorLog library. In SC52 device description 3.5.10.6 or later is required. See also How to use application error log. |
I/O initialization code always ends with error checking and setting the I/O driver to IODRV_STATE_RUN:
S_Init_IO Code |
IF result = EPEC_SYSTEM.SYSTEM_ERROR_CODES.FW_ERR_OK THEN result := EPEC_IODRV.IoDrvSetState(EPEC_IODRV.IoDrvStates.IODRV_STATE_RUN); o_FWErrorCode := result; END_IF IF result <> EPEC_SYSTEM.SYSTEM_ERROR_CODES.FW_ERR_OK THEN o_Error:=TRUE; o_ErrorInConnector := connector; o_ErrorInPin := pin; o_FWErrorCode := result;
info1 := SHL(connector, 16) OR pin; EPEC_SERRLOG.S_AddError_DWORD( i_ErrorCode := ApplicationErrors.IO_INIT, i_LibraryErrorCode := result, i_Info1 := info1, // MSW connector, LSW pin i_Info2 := info2 // error specific ); END_IF
o_Ready:=TRUE; |
Verify that the S_Inputs program is called from S_PLC_PRG.
Initialization phase:
S_PLC_PRG Code: |
ELSIF NOT S_Inputs.o_InitReady THEN S_Inputs(i_Initialize:=TRUE); |
Run phase:
S_PLC_PRG Code: |
ELSIF PLC_PRG.o_Initdone THEN (* Safe actions to execute before safe main program *) S_Inputs(i_Initialize:=FALSE); (* ... *) S_Main(); |
If the project has non-safety related inputs, verify that the Inputs program is called from PLC_PRG.
Initialization phase:
PLC_PRG Code: |
|
ELSIF NOT Inputs.o_InitReady THEN Inputs(i_Initialize:=TRUE); |
Run phase:
PLC_PRG Code: |
|
ELSIF S_PLC_PRG.o_InitDone THEN (* ... *) Inputs(i_Initialize:=FALSE); (* ... *) Main(); |
Verify the generated code for safety related inputs
Same variables are generated regardless of Safety related selection in MultiTool Creator.
AI / DI measurement variables in S_Inputs are generated using SAFEDINT / SAFEBOOL type instead of DINT and BOOL.
|
There are no function blocks generated for pulse inputs.
|
|
SafeConversion library version 1.0.1.2
SafeConversion library version 1.1.0.0 or later
|
The following table lists the function blocks and functions which are generated for inputs depending on the mode:
Name |
Input mode |
Description |
S_ADCToVoltageOrCurrent |
AI V |
Raw ADC to SI value conversion - With Cat. 2 mode there is two AD conversions for main and redundant channel. - With AI V mode there is also pull-up voltage measurement on pins that have pull-up functionality - In DI mode only for AI/DI pin types which have voltage measurement |
S_VoltageToDI |
DI |
Voltage to DI conversion (with debounce filtering, SafeConversion 1.0.1.2) |
S_DebounceDI (SafeConversion 1.1.0.0 or later) |
DI |
DI debounce filtering |
S_AIOverCurrentProtection |
AI mA |
Over current monitoring for mA measurements |
S_AddError_BYTE |
AI V |
Adds input errors to application log. Generated only when using device description with SafeErrorLog available. |
MultiTool 6.6 or older code template uses constant limits for AI measurements.
S_ADCToVoltageOrCurrentS_ADCToVoltageOrCurrent
Verify that the function block instance is generated for each relevant pin
Cat. 2 mode has a second instance for redundant measurement
Type 096 pin (or other type with pull-up) has an instance for pull-up measurement
Verify that the Init method is executed for each instance
Output maximum: According to hardware specific enumeration for each pin type
Output high limit (AI V or AI mA mode): Hardware specific constants according to measurement range (e.g. 5V high voltage, 10V high voltage or high current)
Output high limit (DI mode): Same as output maximum
Cat2MonitoringCh input is FALSE in all other cases except in Cat. 2 redundant channel's AD conversion
Diagnostic delay: Hardware specific constant
Verify that the function block is executed for each instance
ADC raw value mapped to I/O interface is set in i_ADCValue
Corresponding output variable is updated with S_o_Output
The following is an initialization example of type 091 pin Joystick_Y_B in AI V mode using 10V range
Initialization: |
o_InitReady := o_InitReady AND FBScaleToSIUnits_Joystick_Y_B.Init( S_i_OutputMaximum := EPEC_HW.VALUE_AT_AD_MAXIMUM.U_TYPE091_10V, S_i_OutputHighLimit := EPEC_HW.Constants.G_AI_10V_HIGH_VOLTAGE , S_i_OutputLowLimit := EPEC_HW.Constants.G_AI_LOW_VOLTAGE, S_i_Cat2MonitoringCh := FALSE, S_i_DiagnosticDelay := EPEC_HW.Constants.G_VOLTAGE_INPUT_DIAGNOSTIC_DELAY, i_pEventCode := ADR(o_EventCode_Joystick_Y_B)); |
The following is an initialization example of type 093 pin Joystick_X_PosSwitch in DI mode
Initialization: |
o_InitReady := o_InitReady AND FBScaleToSIUnits_Joystick_X_PosSwitch.Init( S_i_OutputMaximum := EPEC_HW.VALUE_AT_AD_MAXIMUM.U_TYPE093_10V, S_i_OutputHighLimit := EPEC_HW.VALUE_AT_AD_MAXIMUM.U_TYPE093_10V , S_i_OutputLowLimit := DINT#0, S_i_Cat2MonitoringCh := FALSE, S_i_DiagnosticDelay := EPEC_HW.Constants.G_VOLTAGE_INPUT_DIAGNOSTIC_DELAY, i_pEventCode := ADR(o_EventCode_Joystick_X_PosSwitch)); |
The following is an initialization example of type 093 pin Position in Cat. 2 mode. If AI mA mode is used, then redundant channel is not used.
Initialization: |
o_InitReady := o_InitReady AND FBScaleToSIUnits_Position.Init( S_i_OutputMaximum := EPEC_HW.VALUE_AT_AD_MAXIMUM.I_TYPE093_20mA, S_i_OutputHighLimit := EPEC_HW.Constants.G_AI_HIGH_CURRENT , S_i_OutputLowLimit := EPEC_HW.Constants.G_AI_LOW_CURRENT, S_i_Cat2MonitoringCh := FALSE, S_i_DiagnosticDelay := EPEC_HW.Constants.G_CURRENT_INPUT_DIAGNOSTIC_DELAY, i_pEventCode := ADR(o_EventCode_Position));
o_InitReady := o_InitReady AND FBScaleToSIUnitsCat2Redundant_Position.Init( S_i_OutputMaximum := EPEC_HW.VALUE_AT_AD_MAXIMUM.I_TYPE093_20mA, S_i_OutputHighLimit := EPEC_HW.Constants.G_AI_HIGH_CURRENT , S_i_OutputLowLimit := EPEC_HW.Constants.G_AI_LOW_CURRENT, S_i_Cat2MonitoringCh := TRUE, S_i_DiagnosticDelay := EPEC_HW.Constants.G_CURRENT_INPUT_DIAGNOSTIC_DELAY, i_pEventCode := ADR(o_EventCode_Position)); |
The following is a run phase code example of AD conversion. The same principle applies to AI V, AI mA, Cat. 2 and DI. Variable prefixes may differ depending on measurement.
Code: |
FBScaleToSIUnits_Joystick_Y_B ( i_Enable := i_Enable, i_ADCValue := AI_RAW_MAIN_Joystick_Y_B, (*Variable mapped to I/O interface*) o_Status => o_AiScaleStatus_Joystick_Y_B, S_o_Output => o_AI_MAIN_Joystick_Y_B); (*Variable used by application*) |
MultiTool 6.7 or newer code template uses user defined limits for AI measurements.
S_ADCToVoltageOrCurrentS_ADCToVoltageOrCurrent
Verify that the function block instance is generated for each relevant pin
Cat. 2 mode has a second instance for redundant measurement
Type 096 pin (or other type with pull-up) has an instance for pull-up measurement
Verify that the Init method is executed for each instance
Output maximum: According to hardware specific enumeration for each pin type
Output low and high limit (AI V or AI mA mode): User defined limit from MultiTool
Output high limit (DI mode): Same as output maximum
Cat2MonitoringCh input is FALSE in all other cases except in Cat. 2 redundant channel's AD conversion
Diagnostic delay: Hardware specific constant
Verify that the function block is executed for each instance
Check that i_ADCValue input is assigned
AI V and DI modes: ADC raw value mapped to I/O interface is set in i_ADCValue
AI mA and Cat. 2 modes:
SafeSSeriesHardware up to version 1.3.2.7:
ADC raw value mapped to I/O interface is set in i_ADCValue
SafeSSeriesHardware version 1.4.0.0 and newer:
ADC value from overcurrent protection block's output is used for AI main channel
ADC raw value mapped to I/O interface is used for Cat. 2 redundant channel
Corresponding output variable is updated with S_o_Output
The following is an initialization example of type 091 pin Joystick_Y_B in AI V mode using 10V range
Initialization: |
o_InitReady := o_InitReady AND FBScaleToSIUnits_Joystick_Y_B.Init( S_i_OutputMaximum := EPEC_HW.VALUE_AT_AD_MAXIMUM.U_TYPE091_10V, S_i_OutputHighLimit := 10000, S_i_OutputLowLimit := 0, S_i_Cat2MonitoringCh := FALSE, S_i_DiagnosticDelay := EPEC_HW.Constants.G_VOLTAGE_INPUT_DIAGNOSTIC_DELAY, i_pEventCode := ADR(o_EventCode_Joystick_Y_B)); |
The following is an initialization example of type 093 pin Joystick_X_PosSwitch in DI mode
Initialization: |
o_InitReady := o_InitReady AND FBScaleToSIUnits_Joystick_X_PosSwitch.Init( S_i_OutputMaximum := EPEC_HW.VALUE_AT_AD_MAXIMUM.U_TYPE093_10V, S_i_OutputHighLimit := EPEC_HW.VALUE_AT_AD_MAXIMUM.U_TYPE093_10V , S_i_OutputLowLimit := DINT#0, S_i_Cat2MonitoringCh := FALSE, S_i_DiagnosticDelay := EPEC_HW.Constants.G_VOLTAGE_INPUT_DIAGNOSTIC_DELAY, i_pEventCode := ADR(o_EventCode_Joystick_X_PosSwitch)); |
The following is an initialization example of type 093 pin Position in Cat. 2 mode.
If AI mA mode is used, then redundant channel is not used.
Initialization: |
o_InitReady := o_InitReady AND FBScaleToSIUnits_Position.Init( S_i_OutputMaximum := EPEC_HW.VALUE_AT_AD_MAXIMUM.I_TYPE093_20mA, S_i_OutputHighLimit := 21900 , S_i_OutputLowLimit := 0, S_i_Cat2MonitoringCh := FALSE, S_i_DiagnosticDelay := EPEC_HW.Constants.G_CURRENT_INPUT_DIAGNOSTIC_DELAY, i_pEventCode := ADR(o_EventCode_Position));
o_InitReady := o_InitReady AND FBScaleToSIUnitsCat2Redundant_Position.Init( S_i_OutputMaximum := EPEC_HW.VALUE_AT_AD_MAXIMUM.I_TYPE093_20mA, S_i_OutputHighLimit := 21900 , S_i_OutputLowLimit := 0, S_i_Cat2MonitoringCh := TRUE, S_i_DiagnosticDelay := EPEC_HW.Constants.G_CURRENT_INPUT_DIAGNOSTIC_DELAY, i_pEventCode := ADR(o_EventCode_Position)); |
The following is a run phase code example of AD conversion.
Variable prefixes may differ depending on measurement.
Example applies to:
AI V mode
DI mode
AI mA with SafeSSeriesHardware up to version 1.3.2.7
Cat. 2 mode with SafeSSeriesHardware up to version 1.3.2.7 (note that Cat. 2 mode has main and redundant measurements)
|
AI mA & Cat. 2 modes: Runtime code is executed before S_AIOverCurrentProtection. |
Code: |
FBScaleToSIUnits_Joystick_Y_B ( i_Enable := i_Enable, i_ADCValue := AI_RAW_MAIN_Joystick_Y_B, (*Variable mapped to I/O interface*) o_Status => o_AiScaleStatus_Joystick_Y_B, S_o_Output => o_AI_MAIN_Joystick_Y_B); (*Variable used by application*) |
The following is a run phase code example of AD conversion for AI mA mode with SafeSSeriesHardware version 1.4.0.0 or newer.
|
Runtime code is executed after S_AIOverCurrentProtection. |
Code: |
FBScaleToSIUnits_Position ( i_Enable := o_AiOverCurrentStatus_Position.OutputValid, i_ADCValue := FbOvercurrent_Position.o_ADCValue, o_Status => o_AiScaleStatus_Position, S_o_Output => o_AI_MAIN_Position); |
The following is a run phase code example of AD conversion for Cat. 2 mode with SafeSSeriesHardware version 1.4.0.0 or newer.
|
Runtime code is executed after S_AIOverCurrentProtection. |
Code: |
FBScaleToSIUnits_Position ( i_Enable := o_AiOverCurrentStatus_Position.OutputValid, i_ADCValue := FbOvercurrent_Position.o_ADCValue, o_Status => o_AiScaleStatus_Position, S_o_Output => o_AI_MAIN_Position);
FBScaleToSIUnitsCat2Redundant_Position ( i_Enable := o_AiOverCurrentStatus_Position.OutputValid, i_ADCValue := AI_RAW_MAIN_REDUNANT_Position, o_Status => o_AiScaleStatusRedundant_Position, S_o_Output => o_AI_REDUNDANT_Position); |
The following example applies with SafeConversion version 1.0.1.2:
Verify that function block instance is generated for each DI
Verify that Init method is executed for each instance
Threshold high & low are set according to values set in MultiTool
Debounce delay is set according to value set in MultiTool
Verify that function block is executed for each instance
AD conversion's output valid flag is used as enable condition
S_i_Voltage input to DI filtering is set according to AD conversion's S_o_Output.
Corresponding DI state is updated with S_o_DigitalState
The following is an initialization example of DI filtering for Joystick_X_PosSwitch
Initialization: |
o_InitReady := o_InitReady AND FBVoltagetoDi_Joystick_X_PosSwitch.Init( S_i_ThresholdHigh := 4500, (*Value from MultiTool*) S_i_ThresholdLow := 3500, (*Value from MultiTool*) S_i_DebounceDelay := 30, (*Value from MultiTool*) i_pEventCode := ADR(o_EventCode_Joystick_X_PosSwitch)); |
The following is a run phase code example of DI filtering for Joystick_X_PosSwitch
Code: |
FBVoltagetoDi_Joystick_X_PosSwitch( i_Enable := FBScaleToSIUnits_Joystick_X_PosSwitch.o_Status.OutputValid, S_i_Voltage := FBScaleToSIUnits_Joystick_X_PosSwitch.S_o_Output, o_Status => o_DiConversionStatus_Joystick_X_PosSwitch, S_o_DigitalState => o_DI_Joystick_X_PosSwitch); |
The following examples apply with SafeConversion version 1.1.0.0 or later:
DI filtering for AI/DI pin types
S_VoltageToDI & S_DebounceDIS_VoltageToDI & S_DebounceDI
Verify that function block instances are generated for each DI
Verify that Init method is executed for each S_VoltageToDI instance
Threshold high & low are set according to values set in MultiTool
Verify that Init method is executed for each S_DebounceDI instance
Debounce delay is set according to value set in MultiTool
Debounce type is set according to type set in MultiTool
Verify that function block is executed for each instance
AD conversion's output valid flag is used as enable condition
S_i_Voltage input to S_VoltageToDI is set according to AD conversion's S_o_Output.
S_i_DigitalState input to S_DebounceDI is set according to S_VoltageToDI's S_o_DigitalState
Corresponding DI state is updated with DI debounce's S_o_DigitalState
The following is an initialization example of DI filtering for Joystick_X_PosSwitch
Initialization: |
o_InitReady := o_InitReady AND FBVoltagetoDi_Joystick_X_PosSwitch.Init( S_i_ThresholdHigh := 4500, (*Value from MultiTool*) S_i_ThresholdLow := 3500, (*Value from MultiTool*) i_pEventCode := ADR(o_EventCode_Joystick_X_PosSwitch));
o_InitReady := o_InitReady AND FBDebounceDi_Joystick_X_PosSwitch.Init( S_i_DebounceDelay := 30, (*Value from MultiTool*) i_FilterType := EPEC_SC.DebounceFilterType.Debounce_Fast, (*Debounce type from MultiTool*) i_pEventCode := ADR(o_EventCode_Joystick_X_PosSwitch)); |
The following is a run phase code example of DI filtering for Joystick_X_PosSwitch
Code: |
FBVoltagetoDi_Joystick_X_PosSwitch( i_Enable := FBScaleToSIUnits_Joystick_X_PosSwitch.o_Status.OutputValid, S_i_Voltage := FBScaleToSIUnits_Joystick_X_PosSwitch.S_o_Output, o_Status => o_DiConversionStatus_Joystick_X_PosSwitch, S_o_DigitalState => );
FBDebounceDi_Joystick_X_PosSwitch( i_Enable := FBVoltagetoDi_Joystick_X_PosSwitch.o_Status.OutputValid, S_i_DigitalState := FBVoltagetoDi_Joystick_X_PosSwitch.S_o_DigitalState, o_Status => o_DiDebounceStatus_Joystick_X_PosSwitch, S_o_DigitalState => o_DI_Joystick_X_PosSwitch);
|
DI filtering for pin type without AI voltage measurement
Verify that function block instances are generated for each DI
Verify that Init method is executed for each S_DebounceDI instance
Debounce delay is set according to value set in MultiTool
Debounce type is set according to type set in MultiTool
Verify that function block is executed for each instance
S_i_DigitalState input is set according to pin's digital status
Corresponding DI state is updated with DI debounce's S_o_DigitalState
The following is an initialization example of DI filtering for Joystick_X_PosSwitch
Initialization: |
o_InitReady := o_InitReady AND FBDebounceDi_Joystick_X_PosSwitch.Init( S_i_DebounceDelay := 30, (*Value from MultiTool*) i_FilterType := EPEC_SC.DebounceFilterType.Debounce_Fast, (*Debounce type from MultiTool*) i_pEventCode := ADR(o_EventCode_Joystick_X_PosSwitch)); |
The following is a run phase code example of DI filtering for Joystick_X_PosSwitch
Code: |
FBDebounceDi_Joystick_X_PosSwitch( i_Enable := i_Enable, S_i_DigitalState := ST_Joystick_X_PosSwitch, o_Status => o_DiDebounceStatus_Joystick_X_PosSwitch, S_o_DigitalState => o_DI_Joystick_X_PosSwitch);
|
S_AIOverCurrentProtection
Verify that the Init method is executed for each relevant pin
Verify that the function block is executed for each relevant pin
SafeSSeriesHardware up to version 1.3.2.7:
Measured current is set from AD conversion instance to S_i_Current input
SafeSSeriesHardware version 1.4.0.0 and newer:
ADC raw value mapped to I/O interface is set in i_ADCValue
In Cat. 2 mode, overcurrent protection is generated only for the main channel
The following is an initialization example of AI over current protection for Position
Initialization: |
o_InitReady := o_InitReady AND FbOvercurrent_Position.init(i_pEventCode := ADR(o_EventCode_Position)); |
The following is a run phase code example of AI over current protection for Position
The following examples apply with SafeSSeriesHardware versions up to 1.3.2.7:
|
Runtime code is executed after S_ADCToVoltageOrCurrent. |
SC52 Safety Control UnitSC52 Safety Control Unit
Code: |
FbOvercurrent_Position( i_Enable := o_AiScaleStatus_Position.OutputValid AND o_AiScaleStatusRedundant_Position.OutputValid, S_i_Current:=o_AI_MAIN_Position, o_Status => o_AiOverCurrentStatus_Position);
IF NOT o_AiOverCurrentStatus_Position.OutputValid AND i_Enable = TRUE THEN (* Over current error set pin to voltage mode *) EPEC_IODRV.IoDrvDOSetConfig (EPEC_HW.IO_Channels.PIN_1_02_DO_TYPE_V_mA, FALSE); END_IF |
SL84 Safety Control UnitSL84 Safety Control Unit
Code: |
FbOvercurrent_Position( i_Enable := o_AiScaleStatus_Position.OutputValid, S_i_Current:=o_AI_MAIN_Position, o_Status => o_AiOverCurrentStatus_Position);
IF ((NOT o_AiOverCurrentStatus_Position.OutputValid) OR FBScaleToSIUnits_Position.o_Status.OutputHigh) AND i_Enable = TRUE THEN (* Over current error set pin to voltage mode *) EPEC_IODRV.IoDrvDOSetConfig (EPEC_HW.IO_Channels.PIN_1_1_DO_TYPE_V_mA, FALSE); END_IF |
The following example applies to SafeSSeriesHardware version 1.4.0.0 or later:
|
Runtime code is executed before S_ADCToVoltageOrCurrent. |
Code: |
FbOvercurrent_Position( i_Enable := i_Enable, i_ADCValue := AI_RAW_MAIN_Position, o_Status => o_AiOverCurrentStatus_Position o_ADCValue => );
IF NOT o_AiOverCurrentStatus_Position.OutputValid AND i_Enable = TRUE THEN (* Over current error set pin to voltage mode *) EPEC_IODRV.IoDrvDOSetConfig (EPEC_HW.IO_Channels.PIN_1_02_DO_TYPE_V_mA, FALSE); END_IF |
S_AddError_BYTE
Verify that the function is executed for each relevant input pin
|
Error code is added to application log only when device description includes SafeErrorLog library. In SC52 device description 3.5.10.6 or later is required. See also How to use application error log. |
The following is a run phase code example of adding pin X1_02 input error to application log
Code: |
EPEC_SERRLOG.S_AddError_BYTE( i_ErrorCode := ApplicationErrors.INPUTS, i_LibraryErrorCode := o_EventCode_X1_02.EventID, i_Info1 := o_EventCode_X1_02.FunctionID, i_Info2 := o_EventCode_X1_02.DeviceID, i_Info3 := o_EventCode_X1_02.ChannelID, i_Info4 := 1, // connector i_Info5 := 2, // pin i_Info6 := 0, i_Info7 := 0, i_Info8 := 0); |
If the project has safety related outputs, verify that the S_Outputs program is called from S_PLC_PRG.
Initialization phase:
S_PLC_PRG Code: |
ELSIF NOT S_Outputs.o_InitReady THEN S_Outputs(i_Initialize:=TRUE); |
Run phase:
S_PLC_PRG Code: |
(* User safe main program *) S_Main(); (* Safe actions to execute after safe main program *) S_Outputs(i_Initialize:=FALSE); |
If the project has non-safety related outputs, verify that the Outputs program is called from PLC_PRG.
Initialization phase:
PLC_PRG Code: |
|
ELSIF NOT Outputs.o_InitReady THEN Outputs(i_Initialize:=TRUE); |
Run phase:
PLC_PRG Code: |
|
(* User non-safe main program *) Main(); (* Non-safe actions to execute after non-safe main program *) Outputs(i_Initialize:=FALSE); |
Verify generated code for safety related outputs
Currently there are no function blocks implemented in the S_Outputs / Outputs program. I/O interface mapped variables are controlled by program interface.
Example of DO output control
Code: |
DO_Boom_Y_ONOFF := i_DO_Boom_Y_ONOFF; o_CM_Boom_Y_ONOFF := CM_Boom_Y_ONOFF; o_DOS_Boom_Y_ONOFF := DOS_Boom_Y_ONOFF; (* Resolve status bits *) o_ST_Boom_Y_ONOFF.InitOk := DWORD_TO_BOOL(ST_Boom_Y_ONOFF AND 1); o_ST_Boom_Y_ONOFF.ParameterError := DWORD_TO_BOOL(ST_Boom_Y_ONOFF AND 2); o_ST_Boom_Y_ONOFF.OverCurrent := DWORD_TO_BOOL(ST_Boom_Y_ONOFF AND 4); |
Example of PWM output control
Code: |
o_CM_BoomCurUpRatio := CM_BoomCurUpRatio; PWFM_RATIO_BoomCurUpRatio := i_PWFM_RATIO_BoomCurUpRatio; PWFM_FREQ_BoomCurUpRatio := i_PWFM_FREQ_BoomCurUpRatio; o_PI_PULSE_WIDTH_BoomCurUpRatio := PI_PULSE_WIDTH_BoomCurUpRatio; o_DOS_BoomCurUpRatio := DOS_BoomCurUpRatio; (* Resolve status bits *) o_ST_BoomCurUpRatio.InitOk := DWORD_TO_BOOL(ST_BoomCurUpRatio AND 1); o_ST_BoomCurUpRatio.ParameterError := DWORD_TO_BOOL(ST_BoomCurUpRatio AND 2); o_ST_BoomCurUpRatio.OverCurrent := DWORD_TO_BOOL(ST_BoomCurUpRatio AND 4); |
|
Error code is added to application log only when device description includes SafeErrorLog library. In SC52 device description 3.5.10.6 or later is required. See also How to use application error log. |
Example of adding output's firmware error to application log.
Code: |
connector := 1; pin := 25; info1 := SHL(connector, 16) OR pin; // MSW connector, LSW pin info2 := DWORD#0; // reserved errorCode := DWORD_TO_DINT(ST_BoomCurUpRatio AND 16#FFFFFFE); // filter out InitOk bit EPEC_SERRLOG.S_AddError_DWORD(i_ErrorCode := ApplicationErrors.OUTPUTS_FW, i_LibraryErrorCode := errorCode, i_Info1:=info1, i_Info2:=info2); |
Source file topic100551.htm
Last updated 21-Feb-2025