In this article, TURCK’s TBEN-L5-PLC-11 Codesys PLC and Codesys SoftMotion are used to control Delta’s ASDA-A3 Servo drive via EtherCAT.
Come on, let’s enjoy FA.
Reference Link
CODESYS SoftMotion
CODESYS SoftMotion is a motion control tool for controllers with PLCopen® functionality and CAM integrated into the IEC61131-3 programming system CODESYS.
With CODESYS SoftMotion, everything from single-axis to multi-axis motion to CAM can be developed directly with logic applications in the familiar IEC 61131-3 programming environment. Motion controllers with CODESYS SoftMotion can implement motion functions in the form of a toolkit integrated into the PLC development system.
The runtime system CODESYS Control SoftMotion must be implemented in the motion controller in order to program it with the CODESYS SoftMotion toolkit.
Platform requirements:
When using the CODESYS SoftMotion controller, users have a variety of options when it comes to implementing motion tasks. For example, they can use the provided PLCopen motion POU or take advantage of the full functionality of the IEC 61131-3 development system.
- Must be supported by CODESYS Control (minimum 32 bits recommended on FPU).
- Application requires sufficient performance to compute position, velocity, and acceleration data.
- Application requires hard real-time performance with low jitter values.
CODESYS SoftMotion contains…
CODESYS SoftMotion includes the following Packages…
- Certified PLCopen POU for single and multi-axis operation
- Certified PLCopen POUs for add-on functions such as diagnostics, stop and CAM controllers
- Additional POUs for various tasks such as dynamic data monitoring, error follow-up, CAM and CAM controller operation
- Visualization templates for quick and easy commissioning of POUs using CODESYS visualization
- Visualization elements for online modification of CAMs and CAM controllers
- Integrated graphical CAM editor with extensive configuration options
- Support of virtual and logical axes
- Integrated drivers for numerous CAN, CANopen® and EtherCAT® drives
- Configuration of drives as standard field devices
- Example of a CODESYS SoftMotion project
Servo ASDA-A3?
The Servo used in this project will be Delta’s ASDA-A3 series Servo.
Layout
EtherCAT Mode
The ASDA-A3 servo system can use EtherCAT mode, and the pin assignments of the two EtherCAT connectors (CN6) are identical.
Note that the IN connector can be connected to the controller (master) or the previous servo drive for receiving, and the OUT connector can only be connected to the next servo drive for output. Incorrect connection will result in loss of communication.
Connection Example
The figure below shows an example of connecting multiple ASDA-A3 servo systems on an EtherCAT network.
Specification
This is the EtherCAT version of the ASDA-A3 servo system.
Architecture
The EtherCAT architecture of the servo drive is as follows
- Communication profile: This protocol includes communication objects (PDO, SDO, SYNC, and emergency objects) and the associated communication object dictionary.
- DS402: Device profile for drive and motion control, defining the behavior of each motion mode and the object parameter settings required to execute it.
Synchronous mode
Delta servo drives support two synchronous modes: Free Mode and DC-Synchronous mode.
Free Run mode (Asynchronous)
In Free Run mode, the master and slave stations operate asynchronously. Each station has a separate clock that calculates time, and the master and slave clocks are not synchronized. The transmission of commands and feedback between master and slave is based on sequential order rather than precise time synchronization. For example, the master sends a PDO at time T1 and the slave receives the PDO at T2 after the SM2 event.
DC-Synchronous mode (SYNC0 synchronization)
There will be precise time synchronization between the master and slave stations so that the master will periodically run the control program and send PDO packets at fixed times according to the synchronization clock. The master sends commands to the slave and receives feedback from the slave, which in turn receives and updates the PDO data at regular intervals according to the synchronization clock.
PDO mapping configuration
PDO mapping objects are allocated in the object dictionary from index OD 1600 to OD 1603 for RxPDO and from index OD 1A00 to OD 1A03 for TxPDO.
Each group of RxPDO and TxPDO can support PDO data updates for up to 8 sets of 32-bit objects.
Default PDO mapping configuration
The table below shows the default PDO mapping settings of the EtherCAT servo drives for data exchange. This is also defined in the XML file of the EtherCAT slave and the PDO mapping settings can be changed on request.
In Delta ASDA-x3-E rev0.03.xml, the first through fourth groups of PDO configurations are as follows
ASDA-Software Tools
Download ASDA-Soft at the link below for commisioning with Delta’s Servo.
Start the installation EXE and proceed with Next>.
Set the installation location of the tool and proceed with Install.
Just a second..
The USB Driver installation screen will appear, and click Install to install the Driver that communicates with the Servo Drive.
Done!
Implementation
Delta Drive Side
Set P1.001 to 0x000C in the parameters. This is the setting for EtherCAT communication.
TURCK Side
Add EtherCAT Master
Right-click on Device>Add Device to add a communication Driver.
Add Fieldbus>EtherCAT>Master>EtherCAT Master.
Done!EtherCAT Master has been added.
Configure Adapter
Click on the EtherCAT Master that was just added and Tab to General and click Select.
Configure the Ethernet Adapter you want to use as EtherCAT Master in the actual application.
Done!
Scan For Devices
Right-click on the EtherCAT Master you just added>Scan for Devices to search for slaves in the EtherCAT network.
Done!Now that you have identified Delta’s Servo drive, click on “Copy All Devices to Project” to duplicate the network’s Slave to the project.
Done!
Configuration
The resolution of Delta’s Servo drive used in this article is 16777216=1 revolution, so open the Tab for Scaling/Mapping and enter 16777216 for Scaling.
Next, enter 1 in the Incremenets<==>units in application field. In other words, one rotation is now 1 mm.
Program
Next, we will create a program. This time, we will create a program while stepping through a few OOP concepts such as Interface, Function Block, and Extend.
Interface
The first step is to create an interface, which allows you to focus only on “what” the Function Block is supposed to do and not on “how” it is supposed to do it. program and the “how” to do it. Interface can also be used to create a more unified program, with multiple different Function Blocks sharing only the same interface.
ITF_SpeedAxis
This defines “what to do” when controlling Servo speed.
METH_Half
This Method can stop a JOB that Servo is executing.
METHOD METH_Half : INT VAR_INPUT iCmd:BOOL; END_VAR |
METH_JogFWBW
The Method here is Servo’s JOG operation.
METHOD METH_JogFWBW : INT VAR_INPUT iFw,iBw:BOOL; iVelSetpoint:LREAL; iVelAcc,iVelDec:LREAL; END_VAR |
METH_PowerON
The Method here is Servo ON operation.
METHOD METH_PowerON : INT VAR_INPUT iCmd:BOOL; END_VAR |
METH_Reset
This Method is a Servo reset operation.
METHOD METH_Reset : INT VAR_INPUT iCmd:BOOL; END_VAR |
METH_VelocityCmd
こちらのMethodはServoの定速運転操作になります。
METHOD METH_VelocityCmd : INT VAR_INPUT iCmd:BOOL; iVelSetpoint:LREAL; iVelAcc,iVelDec:LREAL; END_VAR |
PROPERTY Prop_CommunicationOK : BOOL
You can get Servo’s communication status from PROPERTY here.
PROPERTY Prop_Error : Bool
You can get Servo’s error status from PROPERTY here.
PROPERTY Prop_Ready : Bool
You can get Servo’s ready signal from PROPERTY here.
PROPERTY Prop_Running : Bool
You can get Servo’s on-the-move signal from PROPERTY here.
PROPERTY Prop_Stopped : Bool
You can get Servo’s stop signal from PROPERTY here.
ITF_PositionAxis EXTENDS ITF_SpeedAxis
Let’s define a new Interface and extend it from INTERFACE ITF_SpeedAxis.
METH_Home
This Method can be Home Servo.
METHOD METH_Home : INT VAR_INPUT iCmd:BOOL; END_VAR |
METH_MoveRelative
This Method implements a relative positioning operation on Servo.
METHOD METH_MoveRelative : INT VAR_INPUT iCmd:BOOL; iVelSetpoint:LREAL; iVelAcc,iVelDec:LREAL; iDistance:LREAL; END_VAR |
METH_MoveAbs
This Method implements an absolute positioning operation on Servo.
METHOD METH_MoveAbs : INT VAR_INPUT iCmd:BOOL; iVelSetpoint:LREAL; iVelAcc,iVelDec:LREAL; iPosition:LREAL; END_VAR |
DUT
The next step is to define the structure.
eAxisBasicReturnValue
This is the return value of Method from this enumeration.
{attribute ‘qualified_only’} {attribute ‘strict’} TYPE eAxisBasicReturnValue : ( init ,ERROR ,Done ,Busy ,nop ,InVelocity ); END_TYPE |
Function Block
FB_Delta_ASDA_A3_SpeedAxis
This Function Block implements the ITF_SpeedAxis Interface defined earlier.
FUNCTION_BLOCK FB_Delta_ASDA_A3_SpeedAxis IMPLEMENTS ITF_SpeedAxis VAR_INPUT ioAxis :REFERENCE TO AXIS_REF_ETC_Delta_ASDA_A3; END_VAR VAR_OUTPUT END_VAR VAR_IN_OUT END_VAR VAR _MC_Power:MC_Power; _MC_Reset:MC_Reset; _MC_Half:MC_Halt; _MC_Jog:MC_Jog; _MC_MoveVelocity:MC_MoveVelocity; END_VAR |
METH_Half
This is the implementation of a Method to stop a running JOB.
METHOD METH_Half : INT VAR_INPUT iCmd:BOOL; END_VAR VAR_INST R_TRIG:R_TRIG; END_VAR |
MC_Half is used to execute the job that the Servo axis is executing, and returns the appropriate return value according to the execution status and result of the Function Block.
R_TRIG(CLK:=iCmd); _MC_Half( Axis:=ioAxis ,Execute:=iCmd ,Deceleration:=100.0 ); IF R_TRIG.Q THEN METH_Half:=eAxisBasicReturnValue.nop; END_IF; IF _MC_Half.Error THEN METH_Half:=eAxisBasicReturnValue.ERROR; ELSIF _MC_Half.Busy THEN METH_Half:=eAxisBasicReturnValue.Busy; ELSIF _MC_Half.Done THEN METH_Half:=eAxisBasicReturnValue.Done; END_IF |
METH_JogFWBW
This is an implementation of Method to operate SERVO’s JOB.
METHOD METH_JogFWBW : INT VAR_INPUT iFw,iBw:BOOL; iVelSetpoint:LREAL; iVelAcc,iVelDec:LREAL; END_VAR VAR_INST R_TRIG:R_TRIG; END_VAR VAR fw,bw:BOOL; END_VAR |
MC_Jog is used to execute Servo axis JOG operations and return appropriate return values according to the execution status and results of the Function Block.
fw:=iFw AND NOT iBw; bw:=iBw AND NOT iFw; R_TRIG( CLK:=(iFw AND NOT iBw) OR (iBw AND NOT iFw) ); _MC_Jog( Axis:=ioAxis ,JogForward:=fw ,JogBackward:=bw ,Velocity:=iVelSetpoint ,Acceleration:=iVelAcc ,Deceleration:=iVelDec ); IF R_TRIG.Q THEN METH_JogFWBW:=eAxisBasicReturnValue.nop; END_IF; IF _MC_Jog.Error THEN METH_JogFWBW:=eAxisBasicReturnValue.ERROR; ELSIF _MC_Jog.Busy THEN METH_JogFWBW:=eAxisBasicReturnValue.Busy; END_IF |
METH_PowerON
This is the implementation of the SERVO ON operation.
METHOD METH_PowerON : INT VAR_INPUT iCmd:BOOL; END_VAR VAR_INST R_TRIG:R_TRIG; END_VAR |
MC_Power is used to execute Servo ON/OFF of Servo axis and returns appropriate return value according to the execution status and result of Function Block.
R_TRIG(CLK:=iCmd); _MC_Power( Axis:=ioAxis ,Enable:=iCmd ,bRegulatorOn:=iCmd ,bDriveStart:=iCmd ); IF R_TRIG.Q THEN METH_PowerON:=eAxisBasicReturnValue.nop; END_IF; IF _MC_Power.Error THEN METH_PowerON:=eAxisBasicReturnValue.ERROR; ELSIF _MC_Power.Busy THEN METH_PowerON:=eAxisBasicReturnValue.Busy; ELSIF _MC_Power.Enable THEN METH_PowerON:=eAxisBasicReturnValue.Done; END_IF |
METH_Reset
This is the implementation of the SERVO reset operation.
METHOD METH_Reset : INT VAR_INPUT iCmd:BOOL; END_VAR VAR_INST R_TRIG:R_TRIG; END_VAR |
MC_Reset is used to execute Servo ON/OFF of Servo axis and returns appropriate return value according to the execution status and result of Function Block.
R_TRIG(CLK:=iCmd); _MC_Reset( Axis:=ioAxis ,Execute:=iCmd ); IF R_TRIG.Q THEN METH_Reset:=eAxisBasicReturnValue.nop; END_IF; IF _MC_Reset.Error THEN METH_Reset:=eAxisBasicReturnValue.ERROR; ELSIF _MC_Reset.Busy THEN METH_Reset:=eAxisBasicReturnValue.Busy; ELSIF _MC_Reset.Done THEN METH_Reset:=eAxisBasicReturnValue.Done; END_IF |
METH_VelocityCmd
This is an implementation of SERVO’s constant speed operation.
METHOD METH_VelocityCmd : INT VAR_INPUT iCmd:BOOL; iVelSetpoint:LREAL; iVelAcc,iVelDec:LREAL; END_VAR VAR_INST R_TRIG:R_TRIG; END_VAR |
MC_MoveVelocity is used to execute Servo ON/OFF of Servo axis and returns appropriate return value according to the execution status and result of Function Block.
R_TRIG(CLK:=iCmd); _MC_MoveVelocity( Axis:=ioAxis ,Execute:=iCmd ,Velocity:=iVelSetpoint ,Acceleration:=iVelAcc ,Deceleration:=iVelDec ); IF R_TRIG.Q THEN METH_VelocityCmd:=eAxisBasicReturnValue.nop; END_IF; IF _MC_MoveVelocity.Error THEN METH_VelocityCmd:=eAxisBasicReturnValue.ERROR; ELSIF _MC_MoveVelocity.Busy THEN METH_VelocityCmd:=eAxisBasicReturnValue.Busy; ELSIF _MC_MoveVelocity.InVelocity THEN METH_VelocityCmd:=eAxisBasicReturnValue.InVelocity; END_IF |
PROPERTY Prop_CommunicationOK : BOOL
This property determines whether communication is OK from the IodataInvalid variable.
Prop_CommunicationOK:=ioAxis.bCommunication; |
PROPERTY Prop_Error : BOOL
This property determines if communication is OK from the Error variable.
Prop_Error:=ioAxis.bError; |
PROPERTY Prop_Ready : BOOL
This property determines Servo’s ready status from the Ready variable.
Prop_Ready:=ioAxis.bDriveStartRealState; |
PROPERTY Prop_Running : BOOL
This property determines whether Servo is moving from the Ready variable.
Prop_Running:= ioAxis.bAccelerating OR ioAxis.bDecelerating OR ioAxis.fActVelocity>1.0 OR ioAxis.fActVelocity<-1.0 ; |
PROPERTY Prop_Stopped : BOOL
This property determines whether Servo is stopped from the Ready variable.
Prop_Stopped:= NOT ioAxis.bAccelerating AND NOT ioAxis.bDecelerating AND NOT (ioAxis.fActVelocity >1.0) AND NOT (ioAxis.fActVelocity <-1.0) ; |
FB_Delta_ASDA_A3_PositionAxis
Next, let’s create a FB for positioning. This FB extends the FB_Delta_ASDA_A3_SpeedAxis created earlier and implements ITF_PositionAxis.
FUNCTION_BLOCK FB_Delta_ASDA_A3_PositionAxis EXTENDS FB_Delta_ASDA_A3_SpeedAxis IMPLEMENTS ITF_SpeedAxis, ITF_PositionAxis VAR_INPUT END_VAR VAR_OUTPUT END_VAR VAR _MC_MoveAbsolute:MC_MoveAbsolute; _MC_MoveRelative:MC_MoveRelative; _MC_Home:MC_Home; END_VAR |
METH_Home
This is an implementation of Method to operate SERVO’s HOME.
METHOD METH_Home : INT VAR_INPUT iCmd : BOOL; END_VAR VAR_INST R_TRIG:R_TRIG; END_VAR |
MC_Home is used to execute the Servo axis Home operation and return the appropriate return value according to the execution status and result of the Function Block.
R_TRIG(CLK:=iCmd); _MC_Home( Axis:=ioAxis ,Execute:=iCmd ,Position:=0.0 ); IF R_TRIG.Q THEN METH_Home:=eAxisBasicReturnValue.nop; END_IF; IF _MC_Home.Error THEN METH_Home:=eAxisBasicReturnValue.ERROR; ELSIF _MC_Home.Busy THEN METH_Home:=eAxisBasicReturnValue.Busy; ELSIF _MC_Home.Done THEN METH_Home:=eAxisBasicReturnValue.Done; END_IF |
METH_MoveAbs
MC_MoveAbsolute is used to perform absolute positioning of the Servo axis and returns the appropriate return value according to the execution status and result of the Function Block.
METHOD METH_MoveAbs : INT VAR_INPUT iCmd:BOOL; iVelSetpoint:LREAL; iVelAcc,iVelDec:LREAL; iPosition:LREAL; END_VAR VAR_INST R_TRIG:R_TRIG; END_VAR |
R_TRIG(CLK:=iCmd); _MC_MoveAbsolute( Axis:=ioAxis ,Execute:=iCmd ,Position:=iPosition ,Velocity:=iVelSetpoint ,Acceleration:=iVelAcc ,Deceleration:=iVelDec ); IF R_TRIG.Q THEN METH_MoveAbs:=eAxisBasicReturnValue.nop; END_IF; IF _MC_MoveAbsolute.Error THEN METH_MoveAbs:=eAxisBasicReturnValue.ERROR; ELSIF _MC_MoveAbsolute.Busy THEN METH_MoveAbs:=eAxisBasicReturnValue.Busy; ELSIF _MC_MoveAbsolute.Done THEN METH_MoveAbs:=eAxisBasicReturnValue.Done; END_IF |
METH_MoveRelative
MC_MoveRelative is used to execute relative positioning of the Servo axis and return the appropriate return value according to the execution status and result of the Function Block.
METHOD METH_MoveRelative : INT VAR_INPUT iCmd:BOOL; iVelSetpoint:LREAL; iVelAcc,iVelDec:LREAL; iDistance:LREAL; END_VAR VAR_INST R_TRIG:R_TRIG; END_VAR |
R_TRIG(CLK:=iCmd); _MC_MoveRelative( Axis:=ioAxis ,Execute:=iCmd ,Distance:=iDistance ,Velocity:=iVelSetpoint ,Acceleration:=iVelAcc ,Deceleration:=iVelDec ); IF R_TRIG.Q THEN METH_MoveRelative:=eAxisBasicReturnValue.nop; END_IF; IF _MC_MoveRelative.Error THEN METH_MoveRelative:=eAxisBasicReturnValue.ERROR; ELSIF _MC_MoveRelative.Busy THEN METH_MoveRelative:=eAxisBasicReturnValue.Busy; ELSIF _MC_MoveRelative.Done THEN METH_MoveRelative:=eAxisBasicReturnValue.Done; END_IF |
pServo
This is the main program, which calls the Function Block created earlier and repeats absolute and relative positioning using CASE statements.
PROGRAM pServo VAR Axis1:FB_Delta_ASDA_A3_PositionAxis; bError:BOOL; bRunning:BOOL; bStopped:BOOL; bPowerON:BOOL; bReset:BOOL; RetValue:INT; bReady:BOOL; bRun:BOOL; bStop:BOOL; fSetValue:REAL; bFw,bBw:BOOL; bHome:BOOL; bMoveAbs,bMoveRelative:BOOL; f32AbsPos,f32AbsVel,f32AbsAcc,f32AbsDec:REAL; f32RelativePos,f32RelativeVel,f32RelativeAcc,f32RelativeDec:REAL; bCommunicationOK:BOOL; iStep:INT; iCount:INT; start:BOOL; R_TRIG:R_TRIG; END_VAR |
//Axis of Delta Servo Axis1(ioAxis:=SM_Drive_ETC_Delta_ASDA_A3); // RetValue:= Axis1.METH_PowerON( iCmd:=bPowerON ); // bReady:=Axis1.Prop_Ready; bRunning:=Axis1.Prop_Running; bError:=Axis1.Prop_Error; bStopped:=Axis1.Prop_Stopped; bCommunicationOK:=Axis1.Prop_CommunicationOK; // // RetValue:=Axis1.METH_Reset( iCmd:=bReset ); // RetValue:=Axis1.METH_Half( iCmd:=bStop ); // RetValue:=Axis1.METH_Home( iCmd:=bHome ); IF RetValue = eAxisBasicReturnValue.Done THEN bHome:=FALSE; END_IF // RetValue:=Axis1.METH_VelocityCmd( iCmd:=bRun ,iVelSetpoint:=fSetValue ,iVelAcc:=100.0 ,iVelDec:=100.0 ); RetValue:=Axis1.METH_JogFWBW( iFw:=bFw AND NOT bBw ,iBw:=bBw AND NOT bFw ,iVelSetpoint:=fSetValue ,iVelAcc:=100.0 ,iVelDec:=100.0 ); RetValue:=Axis1.METH_MoveAbs( iCmd:=bMoveAbs ,iVelSetpoint:=f32AbsVel ,iVelAcc:=f32AbsAcc ,iVelDec:=f32AbsDec ,iPosition:=f32AbsPos ); RetValue:=Axis1.METH_MoveRelative( iCmd:=bMoveRelative ,iVelSetpoint:=f32RelativeVel ,iVelAcc:=f32RelativeAcc ,iVelDec:=f32RelativeDec ,iDistance:=f32RelativePos ); R_TRIG(CLK:=start); IF R_TRIG.Q THEN iStep:=10; END_IF CASE iStep OF 10: f32RelativePos:=10.0; bMoveRelative:=TRUE; iCount:=iCount+1; IF bRunning THEN iStep:=15; END_IF; 15: IF bStopped THEN iStep:=20; END_IF 20: bMoveRelative:=FALSE; IF iCount>=10 THEN iCount:=0; iStep:=30; ELSE iStep:=10; END_IF; 30: f32RelativePos:=-10.0; bMoveRelative:=TRUE; iCount:=iCount+1; IF bRunning THEN iStep:=35; END_IF; 35: IF bStopped THEN iStep:=40; END_IF 40: bMoveRelative:=FALSE; IF iCount>=10 THEN iCount:=0; iStep:=10; ELSE iStep:=30; END_IF; END_CASE |
Download
Finally, download the project to Runtime.
Result
Here is a video of controlling Delta’s Servo drive from TURCK PLC via EtherCAT.
Download Project
You can download the project for this article from this link.
https://github.com/soup01Threes/Codesys/blob/main/TURCK-EtherCAT-DeltaServo.projectarchive