# EPICS Motor Record Device and Driver Support

## March 11, 2012

## Mark Rivers

## University of Chicago

## Table of Contents

- Introduction
- Model 1 device and driver support
- Model 2 (asyn, C) device and driver support
- Model 3 (asyn, C++) device and driver support
  - Overview
  - asynMotorController
  - asynMotorAxis
  - Example drivers
    - ACS MCB-4B
    - Parker ACR
    - Newport XPS
- Coordinated motion

## Introduction

This document describes the device and driver support for the EPICS motors. It briefly describes the older APIs for such support (referred to as Model 1 and Model 2), but focuses mainly on the newer Model 3 API, which is the API which should be used for new motor drivers.

The APIs described here are mainly intended to be used with the EPICS motor record. However the Model 2 and Model 3 drivers are actually independent of the motor record. They implement standard EPICS asyn interfaces, and can in principle be used with any EPICS records, and do not require the motor record. However, the motor record currently provides the only "state machine" logic that keeps track of backlash, enforcing soft limits, etc. Model 2 and 3 drivers to permit access to controller-specific features that the motor record does not support, and this is typicaly implemented using standard EPICS records (ao, ai, bo, bi, etc.)

## Model 1 device and driver support

Model 1 is the API that was used for all motor drivers prior to 2006, when Model 2 was introduced. Model 1 drivers have the following characteristics:

- Each controller type requires both device-dependent device support and device-dependent driver support.
- The communication channel between device support and driver is custom for the motor record, and is very limited.
- The communication between device support and the driver is assumed to be via device-dependent strings. Thus, it not suited to register-based controllers, or controllers where the driver calls a vendor-library, rather than just sending strings to the controller.
- Cannot use other records to with the driver, only the motor record. Cannot take advantage of controller-specific features not supported by the motor record.
- There is no provision for multi-axis coordination.
- There is only a single thread per controller type. This means that if a system has, for example, many controllers of a given type then there is only one polling thread for all of these controllers. This is because the poller must wait for each response before sending the next query. This can lead to significantly poorer performance compared to the Model 2 and Model 3 drivers, which have a separate thread per controller.

Because this API was the only one supported prior to 2006, the majority of existing motor drivers are written using this Model 1 API.

## Model 2 device and driver support

Because of the recognized deficiencies in the Model 1 API, in 2006 Diamond Light Source and APS collaborated in developing a new API, now called Model 2. The Model 2 API has the following characteristics:

- Uses standard asyn interfaces to communicate between device support and driver.
- There is only a single device-independent device support file (devMotorAsyn.c).
- There is a single device-independent driver support file for asyn interfaces (drvMotorAsyn.).
- There is a device-dependent driver file below the asyn one. This driver must implement a set of functions that the device-independent driver file calls.
- Can use other records to talk to driver via asyn interfaces. This allows support for controller-specific features.
  - However, this is not as easy as it should be, because the drivers do not directly expose asyn interfaces.
  - One must write an asyn interposeInterface driver to support controller-specific parameters.
- There is no provision for multi-axis coordination.
- There is one polling thread per controller, which is more efficient than Model 1.

There are Model 2 drivers in the motor module for the simulation motor, Newport MM4000, Newport XPS, Pro-Dex MAXnet, Attocube ANC150, and Aerotech Ensemble.

## Model 3 device and driver support

In 2011 the Model 3 API was introduced. This API is based in part on the ideas and infrastructure that were developed for the areaDetector module. The Model 3 API has the following characteristics:

- Uses the asynPortDriver C++ class from asyn.
- Uses the same single device-independent device support file (devMotorAsyn.c) as Model 2 API.
- Model 3 drivers are written in C++ by implementing the methods from the new asynMotorController and asynMotorAxis base classes.
- The base classes take care of much of the work that one needed to write in the device-dependent driver in Model 2.
- Can use other records with the driver via asyn interfaces. This allows support for controller-specific features. This is now very easy to do, compared to the Model 2 driver.
- The API includes support for multi-axis coordination.
- There is one polling thread per controller, which is more efficient than Model 1.

The Model 3 C++ API is based on the concept of two types of objects: a motor controller and one or motor motor axes. The controller object supports the functions that apply to the entire controller. The controller supports one or more axes. The axis objects support the functions for a specific axis. These objects are implemented in the device-dependent driver. There is a base class for each of these objects, asynMotorControlller and asynMotorAxis.

The asynMotorController base class has methods that handle much of the work in writing a driver, including implementing the asyn interfaces and calling the appropriate methods in the axis classes. A basic motor driver derived class will often only need to implement only the constructor for the controller class, and can just use the base class implementation of all other methods in the asynMotorController class.

The asynMotorAxis base class on the other hand mainly provides dummy methods (asynMotorAxis::move(), asynMotorAxis::stop(), etc.). The main work in writing a Model 3 driver consists of implementing these methods in the derived class.

There are Model 3 drivers in the motor module for the simulation motor, Hytec XXXX, Newport XPS, Parker ACR series controllers (e.g. Aires), and the ACS MCB-4B.

The ACS MCB-4B is the simplest Model 3 driver, consisting of only 336 lines of well-commented C++ code (ACSSrc/MCB4BDriver.h and MCB4BDriver.cpp). It does not implement any controller-specific features, it only implements support for standard motor record features. It is a very good starting point for writing a new driver with basic motor record support.

### asynMotorController base class

The asynMotorController base class defines the following methods:

- `asynMotorController(const char *portName, int numAxes, int numParams, int interfaceMask, int interruptMask, int asynFlags, int autoConnect, int priority, int stackSize)`
  This is the constructor for the class. The parameters correspond to the parameters in the constructor for the asynPortDriver base class. The parameters are:
  - `portName`
    The name of the asynPort for this controller. This port name is used to identify the controller in EPICS record links.
  - `numAxes`
    The number of axes on this controller.
  - `numParams`
    The number of controller-specific parameters for this controller. If the driver only implements the standard motor record parameters then this is set to 0.
  - `interfaceMask`
    A bit mask for extra asyn interfaces supported by this controller. It is not necessary to specify the interfaces that the base class implements, which includes asynOctet, asynInt32, asynFloat64, asynFloat64Array, asynDrvUser, and asynGenericPointer. Normally set to 0.
  - `interruptMask`
    A bit mask for extra asyn interfaces supported by this controller that will do callbacks to device support. It is not necessary to specify the interfaces that the base class implements, which includes asynOctet, asynInt32, asynFloat64, asynFloat64Array, and asynGenericPointer. Normally set to 0.
  - `asynFlags`
    asyn flags to use when creating the asyn port. This is normally (ASYN_CANBLOCK | ASYN_MULTIDEVICE). ASYN_CANBLOCK means that the driver is "slow" and asynchonous device support must be used. ASYN_MULTIDEVICE means that the device supports more than one asyn address, i.e. more than one motor axis.
  - `autoConnect`
    This is normally set to 1, which means that asynManager will automatically call the connect() method in the driver if the controller is not connected.
  - `priority`
    This is normally set to 0, which means that asynManager will use a default priority for the port thread.
  - `stackSize`
    This is normally set to 0, which means that asynManager will use a default stack size for the port thread.

### asynMotorAxis base class

The asynMotorAxis base class defines the following methods:

NOTE: This documentation file is incomplete. It needs to be completed.