Supported platforms: CODESYS 3.5, CODESYS 3.5 SAFETY

 

How to control proportional valves  

This section describes how to control proportional valves.

 

This example uses the following libraries:

SafeProportionalValveControl library

 

, or alternatively non-safe library

SensorsAndActuators library

 

 

Depending on hardware, output group control needs to be activated before controlling outputs. See How to use S series and E series HW diagnostics for more information.

 

 

Currently, the S Series and E Series control unit's code template S_Outputs / Outputs programs provide interface for all output related variables defined in Epec MultiTool Creator. All output related function blocks are implemented by the application.

 

External voltage detection in output pins is provided by safety control unit's switch startup test. The startup test execution depends on used product:

After startup test the external voltage is monitored by application diagnostics.

 

Application level detection is required if external voltage needs to be monitored while operational (application functionality specific). External voltage can be monitored using DOS status of the output when PWM control is not active.

 

Positive and negative attenuation signal statuses are probably non-validated DI signals, i.e. simple S_ADCToVoltageOrCurrent and S_VoltageToDI conversions.

 

 

 

Example code

In the following example, the output pin external voltage error is not monitored when control is inactive. See the How to control DO & DO ECO example for more information.

 

When the following example is used with non-safety I/O, the I/O variables are generated in Inputs and Outputs programs instead of S_Inputs and S_Outputs.

 

The following I/O is defined in MultiTool Creator:

 

This example covers only proportional valve output control. The joystick control request variable S_JoystickControl is defined but not implemented.

 

Safe PRG declarations:

VAR

S_BoomCurrentReqUp: EPEC_SPVC.S_CurrentRequest;

S_BoomCurrentReqDown: EPEC_SPVC.S_CurrentRequest;

S_BoomControlRamp: EPEC_SPVC.S_LinearRamp;

S_BoomEndAttenuation: EPEC_SPVC.S_EndAttenuation;

S_BoomUpValve: EPEC_SPVC.S_AdaptiveController;

S_BoomDownValve: EPEC_SPVC.S_AdaptiveController;

 

initDone: BOOL;

S_JoystickControl: SAFEINT; (*Control signal from joystick, not implemented in this example*)

enableControl: SAFEBOOL; (*Control enable conditions*)

 

(*ec_controlUp can be replaced with Joystick's event code if it exists in same control unit*)

ec_controlUp: EPEC_DITF.EventCode;

ec_controlDown: EPEC_DITF.EventCode;

 

(*Current controller parameters *)

ccParams:ARRAY [1..S_CURRENT_CONTROLLER_PAR_COUNT] OF UINT :=

[1359,1307,1231,1172,1137,1113,1103,1093,1088,1076,1075,1075,1075,1078,1076,1075,1034,1014,1014,1014];

ccParamsImpUp: ARRAY [1..S_CURRENT_CONTROLLER_PAR_COUNT] OF UINT :=

[ 1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,950,950,950,950,950,1000,1000,1000,1000,1000  ];

ccParamsImpDown:ARRAY [1..S_CURRENT_CONTROLLER_PAR_COUNT] OF UINT:=

[ 1200,1200,1100,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000];

END_VAR

VAR CONSTANT

S_CURRENT_CONTROLLER_PAR_COUNT : SAFEBYTE := BYTE#20;

S_CURRENT_CONTROLLER_PAR_STEP: SAFEBYTE := BYTE#50;

BOOM_VALVE_FREQ: DWORD := 200;

END_VAR

 

 

Init method:

IF NOT initDone THEN

initDone:=TRUE;

 

(*Application specific parameters*)

 

(*ec_controlUp can be replaced with Joystick's event code if it exists in same control unit*)

S_BoomEndAttenuation.Init(

S_i_PosDirAttenuationLimit := UINT#90,

S_i_NegDirAttenuationLimit := UINT#90,

i_pEventCode := ADR(ec_controlUp),

i_pEventCodePosDirAtt := ADR(S_Inputs.o_EventCode_PosDirAttOn),

i_pEventCodeNegDirAtt := ADR(S_Inputs.o_EventCode_NegDirAttOn)

);

 

S_BoomControlRamp.Init(

S_i_PosDirAscendRampTime := UINT#1000,

S_i_PosDirDescendRampTime := UINT#1000,

S_i_NegDirAscendRampTime := UINT#1000,

S_i_NegDirDescendRampTime := UINT#1000,

S_i_EnableCounterControl := FALSE,

i_pEventCode := ADR(ec_controlUp)

);

 

S_BoomCurrentReqUp.Init(

S_i_MinimumCurrent := UINT#150,

S_i_MaximumCurrent := UINT#600,

S_i_PositiveControlDir := TRUE,

i_pEventCode := ADR(ec_controlUp)

);

 

S_BoomUpValve.Init(

S_i_CoilResistance := UDINT#22000,

S_i_OverCurrentLimit := UINT#1100,

S_i_WireBrokenLimit := UINT#50,

S_i_DiagnosticDelay := UINT#100,

i_pCorrectionParameters := ADR(ccParams),

i_pImpulseUpParameters := ADR(ccParamsImpUp),

i_pImpulseDownParameters := ADR(ccParamsImpDown),

S_i_ParameterCount := S_CURRENT_CONTROLLER_PAR_COUNT,

S_i_ParStep := S_CURRENT_CONTROLLER_PAR_STEP,

i_pEventCode := ADR(ec_controlUp)

);

 

S_BoomCurrentReqDown.Init(

S_i_MinimumCurrent := UINT#150,

S_i_MaximumCurrent := UINT#600,

S_i_PositiveControlDir := FALSE,

i_pEventCode := ADR(ec_controlDown)

);

 

S_BoomDownValve.Init(

S_i_CoilResistance := UDINT#22000,

S_i_OverCurrentLimit := UINT#1100,

S_i_WireBrokenLimit := UINT#50,

S_i_DiagnosticDelay := UINT#100,

i_pCorrectionParameters := ADR(ccParams),

i_pImpulseUpParameters := ADR(ccParamsImpUp),

i_pImpulseDownParameters := ADR(ccParamsImpDown),

S_i_ParameterCount := S_CURRENT_CONTROLLER_PAR_COUNT,

S_i_ParStep := S_CURRENT_CONTROLLER_PAR_STEP,

i_pEventCode := ADR(ec_controlDown)

);

 

END_IF

 

 

The following code is common for both control directions.

 

Code at safe PRG:

 

 

The following code controls boom up direction.

 

Code at safe PRG:

 

 

The following code controls boom down direction.

 

Code at safe PRG:

 

 

 

The following code controls non-safe boom with alternative non-safe wrapper POU.

 

Code at non-safe PRG:

 

 

See also

 

 

Source file topic100380.htm

Last updated 21-Feb-2025