Table of Contents

AxisStepperEL70xx

Note

This guide is targeted towards users of the Zeugwerk Framework Addon: Equipment Beckhoff.

Stepper axes offer a good cost to value ratio for not so time-critical and not very precise positioning tasks. In the maker scene there are several common applications for steppers, e.g for 3D-printers or laser cutters. However, in industrial-automation applications, which are usually fieldbus driven (i.e. Ethercat), this gets a bit more involved.

Beckhoff's EL7031 stepper terminal seems like a good fit, but if used with NC-Motion, licensing costs can sometimes not be neglected. For simple tasks most stepper terminals are able to work without any motion or soft motion controller and they can instead be preconfigured and then commanded by I/Os (first Input = position1, second input = position2, ...). This solution lacks flexibility though.

Beckhoff's EL70xx terminal series can actually be controlled over EtherCAT without any soft-motion-controller. While in principle the terminal's documentation is enough to implement the interface to control a stepper motor through the terminal, in practice, the actual implementation is a tedious task. This is were Zeugwerk's AxisStepperEL70xx implementation comes in handy as it is a tested implementation for Beckhoff's stepper-terminal interface. This tutorial guides you through the steps that you have to take to use this implementation in your application.

The tutorial is target towards users that only use the unmanaged variant of the implementation in a context that does not use the Zeugwerk Template (AxisStepperEL70xxUM), however, all points mentioned in the tutorial apply to the managed variant as well.

Prerequisites

This tutorial requires a working runtime. This could be a runtime on an IPC, an embedded PC or a local runtime on a development PC. If you want to drive the stepper axis for real, also a working Ethercat connection is required. For simulation purposes a usermode runtime is enough and can be started on every Windows driven machine. Take a look on this tutorial for working with the usermode runtime.

For demonstration purposes we utilize a stepper axis connected to a EL7031 terminal. And use a small stepper motor with 200 full steps. The motor is mounted to a horizontal belt drive. On the negative side of the linear belt drive there is a limit switch which also acts as homing switch. The diameter of the bevel powered by the motor is 6mm which means that 1 rotation on the stepper is about 38mm on the linear belt.

Create a solution

Start Twincat XaeShell and create a new solution. After that, integrate a Standard PLC to the solution and open the MAIN program. Then add the ZCore and ZEquipmentBeckhoff libraries as references to the PLC. Lets add a Step function block out of ZCore and create some steps inside a CASE branch.

Implementation and simulation

Place the cursor under the Step variable, press F2 and select Text search on the top of the new dialogue. Now enter Stepper and select an instance of the ZEquipmentBeckhoff.AxisStepperEL7031UM FB. Be sure to have Insert with arguments and Insert with namespace prefix checked.

When working without the Zeugwerk Template, Unmanaged objects have to be used, which involves calling their cyclic behaviour manually. Make sure to call the AxisStepperEL7031UM.Cyclic() method on the very top of the MAIN.PRG, after that

  • Add a variable of type BOOL, which is later used to issue a start command to the stepper
  • Initialize the stepper axis with the following settings
    • SetName : Name of your choice for the axis
    • SetSimulation: Switch on simulation or not
    • SetMotorFullsteps: Fullsteps of the Stepper motor
    • SetGearRatio: mechanical gear Ratio, if attached, also needed for converting from rotational to linear movement
    • SetHomingMethod: Set the desired homing method; currently OnCurrentPosition, OnPositive and NegativeLimitSwitch, and OnPositive or NegativeBlock
    • SetInput1Features: choose if the homing switches should evaluated in an inverted manner
    • SetInput2Features: if needed choose a featureset for input2 of stepper terminal
    • SetMotorSettings: Current, voltage and coil settings
    • SetPosSettings: Some limits for the trajectory calculation of the terminal
    • SetStmFeatures: Sets a Speed range and motor polarity
    • SetStmSettings: controller parameter, leave them in default for the first tests
  • Reboot the stepper instance after initializing it, so that the changed parameters are written to the drive.

Please note that if a initialization method is not called, default values are used which are described in the comments of the methods input parameter or in the API-documentation

Then lets wait in the next step until the controller is parameterized, which is followed by homing the stepper on the negative limit switch. When done, the next step waits for some user input. We wait for a rising edge on the Start flag. To monitor what the Stepper is doing, we can use the properties ActualPosition and ActualVelocity, which we copied into two local variables.

The full declaration and implementation of the PRG is as follows.

PROGRAM MAIN
VAR
  Step : ZCore.Step(begin:=0, end:=100);
  
  Stepper : ZEquipmentBeckhoff.AxisStepperEL7031UM;
  Start : BOOL := FALSE;
  
  ActPosition, ActVelocity : LREAL;
END_VAR
Stepper.Cyclic();

ActPosition := Stepper.ActualPosition;
ActVelocity := Stepper.ActualVelocity;

CASE Step.CurrentIndex() OF
  (* ------------------------------------------------------------ *)
  0: // Idling
  (* ------------------------------------------------------------ *)
    IF Start THEN
      Start := FALSE;
      Step.SetNext(10);
    END_IF
    
  (* ------------------------------------------------------------ *)
  10: // initialize Stepper
  (* ------------------------------------------------------------ *)
    IF Step.OnEntry() THEN
      Stepper.SetName('Transport');
      Stepper.SetSimulation(FALSE);
      Stepper.Parameter.Booting.SetMotorFullsteps(LREAL_TO_UINT(360.0 / 1.8)); // 200 Full Steps
      Stepper.Parameter.Booting.SetGearRatio(ratioInput:=1, ratioOutput:=1);   
   
      Stepper.Parameter.Booting.SetInput1Features(invertInput1:=FALSE, 
                                                  input1Function:=ZEquipmentBeckhoff.AxisStepperEL70xxDigitalInputFunction.PlcCam);
      // Stepper.Parameter.Booting.SetInput2Features(invertInput2:= , input2Function); <- if used
      
      Stepper.Parameter.Drive.SetHomingMethod(homingMethod:=ZEquipmentBeckhoff.AxisStepperEL70xxHomingMethod.OnPositiveLimitSwitch,
                                              distance:=100,
                                              speedTowardsCam:=5, speedOffCam:=0.5,
                                              offset:=150, timeout:=60);
      Stepper.Parameter.Booting.SetMotorSettings(maximumCurrent:=600,
                                                 reducedCurrent:=300,
                                                 nominalVoltage:=24000,
                                                 motorCoilResistance:=64,
                                                 motorEMF:=0,
                                                 motorStartVelocity:=0,
                                                 driveOnDelayTime:=100,
                                                 driveOffDelayTime:=100);
      Stepper.Parameter.Booting.SetPosSettings(velocityMax:=10,
                                               accelerationMax:=200,
                                               decelerationMax:=200,
                                               decelerationEmergencyMax:=300,
                                               calibrationVelocityToward:=1,
                                               calibrationVelocityOff:=1,
                                               positionWindow:=10,
                                               monitoringWindow:=3);
      Stepper.Parameter.Booting.SetStmFeatures(operationMode:=ZEquipmentBeckhoff.AxisStepperEL70xxOperationMode.PositionControl,
                                               speedRange:=ZEquipmentBeckhoff.AxisStepperEL70xxSpeedRange.Steps2000,
                                               invertMotorPolarity:=TRUE);
      Stepper.Parameter.Booting.SetStmSettings(kp:=400,
                                               ki:=4,
                                               innerWindow:=0,
                                               outerWindow:=0,
                                               filterCutoffFrequency:=0,
                                               ka:=100,
                                               kd:=100);
      Stepper.RebootAsync(0);
    END_IF
    
    IF Stepper.Done THEN
      Step.SetNext(20);
    END_IF
    
  (* ------------------------------------------------------------ *)
  20: // Start Homing
  (* ------------------------------------------------------------ *)
    IF Step.OnEntry() THEN
      Stepper.HomingAsync(0);
    END_IF
    
    IF Stepper.Done THEN
      Step.SetNext(30);
    END_IF
  
  (* ------------------------------------------------------------ *)
  30: // Idling again, wait till movement should start
  (* ------------------------------------------------------------ *)
    IF Start THEN
      Start := FALSE;
      Step.SetNext(40);
    END_IF
  
  (* ------------------------------------------------------------ *)  
  40: // Start movement and wait till it ends
  (* ------------------------------------------------------------ *)
    IF Step.OnEntry() THEN
      Stepper.MoveAbsoluteAsync(0, SEL(IsNullLreal(Stepper.ActualPosition, 0.1), 0, 400), 100.0);
    END_IF

    IF Stepper.Error THEN
      Step.SetNext(99); // error occured
    ELSIF NOT Stepper.Busy THEN
      Step.SetNext(30); // wait till next rising edge of Start
    END_IF

ELSE
  ; 
END_CASE

Scope view

Now open a new measurement project and lets see how the stepper axis is moving. Start a new Twincat XaeShell and click on New Measurement project. Select YT Scope project and give it a proper name. On the left side in the solution explorer look for YT Chart and find the first axis, rename it to Position and create another one by Right clicking on YT Chart and then click on New Axis. Name the second axis Velocity. Now right click on YT Chart and select Properties. Look for a property entry called Stacked Axis and set this property to True. With these settings we have a better overview on the graph. Now lets add the actual velocity and actual position to the graph. Right click on the Position axis and select Target Browser. Highlight the variables ActPosition and ActVelocity, right click on it and select Add. Last but not least move the ActVelocity variable to the second axis and then press on the Start Record button in the toolbar of the scope.

Be sure that the PLC is running in the background otherwise the Target browser will not show any variables.

Finally start the movement of the simulated stepper axis again and see how the trajectory gets calculated and simulated. With this axis a normal sequence can now be written and checked if it is working without any hardware.

Commissioning with actual hardware

To test with the real world hardware scan in the ethercat fieldbus with the EL7031 terminal. Now double click on the terminal, select the Process Data dialog and at the bottom of the dialog click on the drop down menu. Then select Positioning interface. Twincat now adapts the PDO settings for you that they are compatible with the Zeugwerk Framework implementation of the stepper terminal.

Now we have to link this terminal to the PLC. To have a better overview, start from the terminal view and expand the STM Status node. Now right click on STM Status -> Status and select Change Link Select the _implPhysical._drive._input.StmStatus variable on the stepper PLC-instance side. Do the same with

  • POS Status -> Status link to _implPhysical._drive._input.PosStatus
  • POS Status -> Actual Velocity link to _implPhysical._drive._input.ActualVelocity
  • POS Status -> Actual Position link to _implPhysical._drive._input.ActualPosition
  • STM Control -> Control link to _implPhysical._drive._output.StmControl
  • POS Control -> Control link to _implPhysical._drive._output.PosControl
  • POS Control -> Target Position link to _implPhysical._drive._output.TargetPosition
  • POS Control -> Velocity link to _implPhysical._drive._output.Velocity
  • POS Control -> Start type link to _implPhysical._drive._output.StartType
  • POS Control -> Acceleration link to _implPhysical._drive._output.Acceleration
  • POS Control -> Deceleration link to _implPhysical._drive._output.Deceleration

Last but not least we link the ethercat slave fieldbus variables of the stepper implementation to the actual ESC links of the terminal. This is needed to be able to parameterize the stepper terminal and observe the actual ethercat status of the hardware.

We have to link:

  • WcState -> WcState link to _ethercatSlave._impl._input.WcState
  • WcState -> InputToggle link to _ethercatSlave._impl._input.InputToggle
  • InfoData -> State link to _ethercatSlave._impl._input.State
  • InfoData -> AdsAddr link to _ethercatSlave._impl._input.AdsAddr

Finally we have to switch off simulation by setting the Simulation:=FALSE. Activate the solution and login. To test the movement of the stepper now online set the Start BOOL variable. In the first place the stepper makes an initialization and then starts the homing sequence. After that it waits again for a rising edge on the Start boolean.