EPICS电机支持(asynMotor)

EPICS电机支持

1) 顶层对象是EPICS motor记录

已经对这个对象编写了很多代码:spec,IDL和Python类等

2)下一层是EPICS设备支持

了解motor记录,与驱动会话

3)最底层是EPICS驱动

对motor记录一无所知,与硬件会话

当前推荐的设备和驱动开发框架是asynMotor(模型3)

asynPortDriver用于扩展这个框架用于不被motorRecord支持的硬件特性。

asynMotor(模型3)

1)从2011年,在synApps motor模块中出现。

2)C++模型。

3)两个基类,asynMotorController和asynMotorAxis。

4)基类提供了大部分功能,只需要编写设备相关的实现。

5)易于支持控制器相关的特性。

6)在驱动API中对协同轮廓移动的直接支持。

基于synApps的motor驱动开发

1) synApps motor模块(需要ASYN,BUSY,IPAC和SNCSEQ)

        a) motorRecord($(MOTOR)/motorApp/MotorSrc)
        b) asynMotor设备支持(devMotorAsyn.c)
        c) asynMotor驱动基类
                i) asynMotorController.h, .cpp
                ii) asynMotorAxis.h, .cpp

2) Motor驱动代码要实现asynMotor基类的控制器相关方法

        a) <Name>MotorDriver.cpp
        b) <Name>MotorDriver.h
        c) <Name>MotorSupport.dbd

’控制器‘构造器做什么?

1) 创建一个实现了一个'真实'电机控制器的控制器对象(asynPortDriver)。

        电机控制器硬件必须初始化

2)为在'CreateController'参数中,为每个请求的电机通道调用轴数次'Axis'构造器。

3)启动Poller任务,将更新所有电机通道的状态。

4)实现非-motorRecord特性。

  • 用于其它控制器参数的asynPortDriver方法
  • 内建"轮廓移动"(协同多轴)方法

ACRController构造器

/* asynMotorController.h
 * 此文件是asynMotorController的基类。真实控制器是从这个类派生的。
 * 它派生自asynPortDriver
 */
#ifndef asynMotorController_H
#define asynMotorController_H

#include <epicsEvent.h>
#include <epicsTypes.h>
#include <shareLib.h>

#define MAX_CONTROLLER_STRING_SIZE 256
#define DEFAULT_CONTROLLER_TIMEOUT 2.0

/** Strings defining parameters for the driver. 为这个驱动定义参数的字符串。
  * 这些是被传递给drvUserCreate的值。
  * 当标志的asyn接口方法被调用时,
  * 此驱动将在pasynUser->reason中放入一个要被使用的整数。
  */
#define motorMoveRelString              "MOTOR_MOVE_REL"      /*相对移动*/
#define motorMoveAbsString              "MOTOR_MOVE_ABS"      /*绝对移动*/
#define motorMoveVelString              "MOTOR_MOVE_VEL"      /*速度移动*/
#define motorHomeString                 "MOTOR_HOME"          /*寻home*/
#define motorStopString                 "MOTOR_STOP_AXIS"     /*停止轴*/
#define motorVelocityString             "MOTOR_VELOCITY"      /*设置速度*/
#define motorVelBaseString              "MOTOR_VEL_BASE"      /*设置基速度*/
#define motorAccelString                "MOTOR_ACCEL"         /*设置加速度*/
#define motorPositionString             "MOTOR_POSITION"      /*设置位置*/
#define motorEncoderPositionString      "MOTOR_ENCODER_POSITION"    /*设置编码器位置*/
#define motorDeferMovesString           "MOTOR_DEFER_MOVES"        
#define motorMoveToHomeString           "MOTOR_MOVE_HOME"
#define motorResolutionString           "MOTOR_RESOLUTION"
#define motorEncoderRatioString         "MOTOR_ENCODER_RATIO"
#define motorPGainString                "MOTOR_PGAIN"
#define motorIGainString                "MOTOR_IGAIN"
#define motorDGainString                "MOTOR_DGAIN"
#define motorHighLimitString            "MOTOR_HIGH_LIMIT"
#define motorLowLimitString             "MOTOR_LOW_LIMIT"
#define motorClosedLoopString           "MOTOR_CLOSED_LOOP"
#define motorPowerAutoOnOffString       "MOTOR_POWER_AUTO_ONOFF"
#define motorPowerOnDelayString         "MOTOR_POWER_ON_DELAY"
#define motorPowerOffDelayString        "MOTOR_POWER_OFF_DELAY"
#define motorPowerOffFractionString     "MOTOR_POWER_OFF_FRACTION"
#define motorPostMoveDelayString        "MOTOR_POST_MOVE_DELAY"
#define motorStatusString               "MOTOR_STATUS"
#define motorUpdateStatusString         "MOTOR_UPDATE_STATUS"
#define motorStatusDirectionString      "MOTOR_STATUS_DIRECTION"
#define motorStatusDoneString           "MOTOR_STATUS_DONE"
#define motorStatusHighLimitString      "MOTOR_STATUS_HIGH_LIMIT"
#define motorStatusAtHomeString         "MOTOR_STATUS_AT_HOME"
#define motorStatusSlipString           "MOTOR_STATUS_SLIP"
#define motorStatusPowerOnString        "MOTOR_STATUS_POWERED"
#define motorStatusFollowingErrorString "MOTOR_STATUS_FOLLOWING_ERROR"
#define motorStatusHomeString           "MOTOR_STATUS_HOME"
#define motorStatusHasEncoderString     "MOTOR_STATUS_HAS_ENCODER"
#define motorStatusProblemString        "MOTOR_STATUS_PROBLEM"
#define motorStatusMovingString         "MOTOR_STATUS_MOVING"
#define motorStatusGainSupportString    "MOTOR_STATUS_GAIN_SUPPORT"
#define motorStatusCommsErrorString     "MOTOR_STATUS_COMMS_ERROR"
#define motorStatusLowLimitString       "MOTOR_STATUS_LOW_LIMIT"
#define motorStatusHomedString          "MOTOR_STATUS_HOMED"

/* 
    这些是每个轴的参数,用于传递其它motor基类信息到驱动
*/
#define motorRecResolutionString        "MOTOR_REC_RESOLUTION"
#define motorRecDirectionString         "MOTOR_REC_DIRECTION"
#define motorRecOffsetString            "MOTOR_REC_OFFSET"

/* 这些是每个控制器参数,用于轮廓移动(协同移动) */
#define profileNumAxesString            "PROFILE_NUM_AXES"
#define profileNumPointsString          "PROFILE_NUM_POINTS"
#define profileCurrentPointString       "PROFILE_CURRENT_POINT"
#define profileNumPulsesString          "PROFILE_NUM_PULSES"
#define profileStartPulsesString        "PROFILE_START_PULSES"
#define profileEndPulsesString          "PROFILE_END_PULSES"
#define profileActualPulsesString       "PROFILE_ACTUAL_PULSES"
#define profileNumReadbacksString       "PROFILE_NUM_READBACKS"
#define profileTimeModeString           "PROFILE_TIME_MODE"
#define profileFixedTimeString          "PROFILE_FIXED_TIME"
#define profileTimeArrayString          "PROFILE_TIME_ARRAY"
#define profileAccelerationString       "PROFILE_ACCELERATION"
#define profileMoveModeString           "PROFILE_MOVE_MODE"
#define profileBuildString              "PROFILE_BUILD"
#define profileBuildStateString         "PROFILE_BUILD_STATE"
#define profileBuildStatusString        "PROFILE_BUILD_STATUS"
#define profileBuildMessageString       "PROFILE_BUILD_MESSAGE"
#define profileExecuteString            "PROFILE_EXECUTE"
#define profileExecuteStateString       "PROFILE_EXECUTE_STATE"
#define profileExecuteStatusString      "PROFILE_EXECUTE_STATUS"
#define profileExecuteMessageString     "PROFILE_EXECUTE_MESSAGE"
#define profileAbortString              "PROFILE_ABORT"
#define profileReadbackString           "PROFILE_READBACK"
#define profileReadbackStateString      "PROFILE_READBACK_STATE"
#define profileReadbackStatusString     "PROFILE_READBACK_STATUS"
#define profileReadbackMessageString    "PROFILE_READBACK_MESSAGE"

/* 这些是用于轮廓移动的每个轴参数*/
#define profileUseAxisString            "PROFILE_USE_AXIS"
#define profilePositionsString          "PROFILE_POSITIONS"
#define profileReadbacksString          "PROFILE_READBACKS"
#define profileFollowingErrorsString    "PROFILE_FOLLOWING_ERRORS"

/**  
    当状态变化时,这些结构体被传回devMotorAsyn。
*/
typedef struct MotorStatus {
  double position;           /**< 命令电机位置 */
  double encoderPosition;    /**< 实际编码器位置 */
  double velocity;           /**< 实际速度 */
  epicsUInt32 status;        /**< 包含状态位的字 (移动结束, 限位等.) */
} MotorStatus;

enum ProfileTimeMode{
  PROFILE_TIME_MODE_FIXED,
  PROFILE_TIME_MODE_ARRAY
};

enum ProfileMoveMode{
  PROFILE_MOVE_MODE_ABSOLUTE,
  PROFILE_MOVE_MODE_RELATIVE
};

/* 
 * 用于构建,读取和执行的状态代码。
 * 小心,这些必须匹配对应的MBBI记录,但没有检测这个的方式 
 */
enum ProfileBuildState{
  PROFILE_BUILD_DONE,
  PROFILE_BUILD_BUSY
};

enum ProfileExecuteState{
  PROFILE_EXECUTE_DONE,
  PROFILE_EXECUTE_MOVE_START,
  PROFILE_EXECUTE_EXECUTING,
  PROFILE_EXECUTE_FLYBACK
};

enum ProfileReadbackState{
  PROFILE_READBACK_DONE,
  PROFILE_READBACK_BUSY
};


/* 用于构建,执行和读取的状态代码 */
enum ProfileStatus {
  PROFILE_STATUS_UNDEFINED,
  PROFILE_STATUS_SUCCESS,
  PROFILE_STATUS_FAILURE,
  PROFILE_STATUS_ABORT,
  PROFILE_STATUS_TIMEOUT
};

#ifdef __cplusplus
#include <asynPortDriver.h>

class asynMotorAxis;

class epicsShareClass asynMotorController : public asynPortDriver {

  public:
  /* 这是这个类的构造器 */
  asynMotorController(const char *portName, int numAxes, int numParams,
                      int interfaceMask, int interruptMask,
                      int asynFlags, int autoConnect, int priority, int stackSize);

  virtual ~asynMotorController();

  /*
       这些是从asynPortDriver重写的方法。
   */
  virtual asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value);
  virtual asynStatus writeFloat64(asynUser *pasynUser, epicsFloat64 value);
  virtual asynStatus writeFloat64Array(asynUser *pasynUser, epicsFloat64 *value, size_t nElements);
  virtual asynStatus readFloat64Array(asynUser *pasynUser, epicsFloat64 *value, size_t nElements, size_t *nRead);
  virtual asynStatus readGenericPointer(asynUser *pasynUser, void *pointer);
  virtual void report(FILE *fp, int details);

  /* 这些时这个类的新方法 */
  virtual asynMotorAxis* getAxis(asynUser *pasynUser);
  virtual asynMotorAxis* getAxis(int axisNo);
  virtual asynStatus startPoller(double movingPollPeriod, double idlePollPeriod, int forcedFastPolls);
  virtual asynStatus wakeupPoller();
  virtual asynStatus poll();
  virtual asynStatus setDeferredMoves(bool defer);
  void asynMotorPoller();  // 者应该是私有的,但从C函数被调用 

  /* 处理moveToHome的函数 */
  virtual asynStatus startMoveToHomeThread();
  void asynMotorMoveToHome();

  /* 这些是用于轮廓移动的函数 */
  virtual asynStatus initializeProfile(size_t maxPoints);
  virtual asynStatus buildProfile();
  virtual asynStatus executeProfile();
  virtual asynStatus abortProfile();
  virtual asynStatus readbackProfile();

  virtual asynStatus setMovingPollPeriod(double movingPollPeriod);
  virtual asynStatus setIdlePollPeriod(double idlePollPeriod);

  int shuttingDown_;   /**< 表明IOC正在关闭的标记。停止pollerF */

  protected:
  /**
   * 这些是参数库中参数的索引编号。它们是在调用中来自设备支持的pasynUser->reason值。 */
   //  这些是电机命令
  #define FIRST_MOTOR_PARAM motorMoveRel_
  int motorMoveRel_;
  int motorMoveAbs_;
  int motorMoveVel_;
  int motorHome_;
  int motorStop_;
  int motorVelocity_;
  int motorVelBase_;
  int motorAccel_;
  int motorPosition_;
  int motorEncoderPosition_;
  int motorDeferMoves_;
  int motorMoveToHome_;
  int motorResolution_;
  int motorEncoderRatio_;
  int motorPGain_;
  int motorIGain_;
  int motorDGain_;
  int motorHighLimit_;
  int motorLowLimit_;
  int motorClosedLoop_;
  int motorPowerAutoOnOff_;
  int motorPowerOnDelay_;
  int motorPowerOffDelay_;
  int motorPowerOffFraction_;
  int motorPostMoveDelay_;
  int motorStatus_;
  int motorUpdateStatus_;

  // 这些是状态位
  int motorStatusDirection_;
  int motorStatusDone_;
  int motorStatusHighLimit_;
  int motorStatusAtHome_;
  int motorStatusSlip_;
  int motorStatusPowerOn_;
  int motorStatusFollowingError_;
  int motorStatusHome_;
  int motorStatusHasEncoder_;
  int motorStatusProblem_;
  int motorStatusMoving_;
  int motorStatusGainSupport_;
  int motorStatusCommsError_;
  int motorStatusLowLimit_;
  int motorStatusHomed_;

  //  这些是每个轴的参数,用于传递其它电机记录信息给这个驱动。
  int motorRecResolution_;
  int motorRecDirection_;
  int motorRecOffset_;

  // 这些是每个控制器的参数,用于轮廓移动
  int profileNumAxes_;
  int profileNumPoints_;
  int profileCurrentPoint_;
  int profileNumPulses_;
  int profileStartPulses_;
  int profileEndPulses_;
  int profileActualPulses_;
  int profileNumReadbacks_;
  int profileTimeMode_;
  int profileFixedTime_;
  int profileTimeArray_;
  int profileAcceleration_;
  int profileMoveMode_;
  int profileBuild_;
  int profileBuildState_;
  int profileBuildStatus_;
  int profileBuildMessage_;
  int profileExecute_;
  int profileExecuteState_;
  int profileExecuteStatus_;
  int profileExecuteMessage_;
  int profileAbort_;
  int profileReadback_;
  int profileReadbackState_;
  int profileReadbackStatus_;
  int profileReadbackMessage_;

  // 这些是每个轴的参数,用于轮廓移动
  int profileUseAxis_;
  int profilePositions_;
  int profileReadbacks_;
  int profileFollowingErrors_;
  #define LAST_MOTOR_PARAM profileFollowingErrors_

  int numAxes_;                 /**< 这个控制器支持的轴数 */
  asynMotorAxis **pAxes_;       /**< 轴对象的指针数组  */
  epicsEventId pollEventId_;    /**< 唤醒poLler的事件ID */
  epicsEventId moveToHomeId_;    /**< 唤醒移动到home线程的事件ID */
  double idlePollPeriod_;       /**< 当没有轴在移动时,轮询之间的时间 */
  double movingPollPeriod_;     /**< 当有轴在移动时,轮询之间的时间 */
  int    forcedFastPolls_;      /**< 当poller唤醒时,强制快速轮询的数目 */

  size_t maxProfilePoints_;     /**< 轮廓点的最大数目 */
  double *profileTimes_;        /**< 每个轮廓点的次数的数组 */

  int moveToHomeAxis_;

  /* 这些是快捷函数,用于对硬件使用asynOctet接口的控制器 */
  asynStatus writeController();
  asynStatus writeController(const char *output, double timeout);
  asynStatus readController();
  asynStatus readController(char *response, size_t maxResponseLen, size_t *responseLen, double timeout);
  asynStatus writeReadController();
  asynStatus writeReadController(const char *output, char *response, size_t maxResponseLen, size_t *responseLen, double timeout);
  asynUser *pasynUserController_;
  char outString_[MAX_CONTROLLER_STRING_SIZE];
  char inString_[MAX_CONTROLLER_STRING_SIZE];

  friend class asynMotorAxis;
};
#define NUM_MOTOR_DRIVER_PARAMS (&LAST_MOTOR_PARAM - &FIRST_MOTOR_PARAM + 1)

#endif /* _cplusplus */
#endif /* asynMotorController_H */

在从st.cmd调用iocInit()前:asynMotor.cmd(BCDA标准IOC启动文件)

ACR示例:motor/iocWithAsyn/st.cmd.acr

# portName, asynPort, num of axes, active poll period(ms), idle poll period(ms)

ACRCreateController("ACR1", "ARIES", 1, 20, 1000)

extern "C" int ACRCreateController(const char * portName, const char * ACRPortName, 
        int numAxes,
        int movingPollPeriod,
        int idlePollPeriod)
{
    new ACRController(portName, ACRPortName, numAxes, movingPollPeriod/1000., idlePollPeriod/1000.)
}

创建一个新的ACRController对象。

参数:

  • [in] portName:将为这个驱动创建的asyn端口的名称。
  • [in] ACRPortName:先前创建的为连接ACR控制器的drvAsynIPPort的名称。
  • [in] numAxes:这个控制器支持的轴数。
  • [in] movingPollPeriod:当任何轴在移动时,轮询之间的时间。
  • [in] idlePollPeriod:当没有轴在移动时,轮询之间的时间。
ACRController::ACRController(const char * portName, 
const char * ACRPortName, int numAxes, double movingPollPeriod, double idlePollPeriod)
: asynMotorController(portName, numAxes, NUM_ACR_PARAMS, asynUInt32DigitalMask,
asynUInt32DigitalMask, ASYN_CANBLOCK | ASYN_MULTIDEVICE, 1, 0, 0)
asynMotorController:asynMotorController(const char * portName,
                                        int         numAxes,
                                        int         numParams,
                                        int         interfaceMask,
                                        int         interruptMask,
                                        int         asynFlags,
                                        int         autoConnect,
                                        int         priority,
                                        int         stackSize
)

 创建一个新的asynMotorController对象。所有参数只是被传递给了asynPortDriver基类的构造器。在调用这个基类构造器后,这个方法创建了在asynMotorDriver.h中定义的电机参数。

ACRController::ACRController(const char * portName, 
const char * ACRPortName, int numAxes, double movingPollPeriod, double idlePollPeriod)
: asynMotorController(portName, 
                      numAxes, 
                      NUM_ACR_PARAMS, 
                      asynUInt32DigitalMask,
                      asynUInt32DigitalMask, 
                      ASYN_CANBLOCK | ASYN_MULTIDEVICE, 
                      1,  // 自动连接
                      0, 0) // 默认优先级和栈尺寸
{
    ...
    // 创建控制器相关的参数
    createParam(ACRJerkString,            asynParamFloat64,    &ACRJerk_);
    createParam(ACRReadBinaryIOString,    asynParamInt32,      &ACRReadBinaryIO_);

    // 连接到ACR控制器
    status = pasynOctetSyncIO->connect(ACRPortName, 0, &pasynUserContorller_, NULL);

     // 关闭命令回送
    sprintf(outString_, "ECHO 4");
    writeController();

    // 创建轴对象
    for (axis = 0; axis < numAxes; axis++){
        new ACRAxis(this, axis);
    }

    startPoller(movingPollPeriod, idlePollPeriod, 2);
}
ACRAxis::ACRAxis(class ACRController * pc, int axisNo)

创建一个ACRAxis对象。

参数:

[in] pC:指向这个轴所属的ACRController的指针

[in]axisNo:这个轴的索引,范围从0到pc->numAxes_-1。

初始化寄存器数目等。

asynStatus asynMotorController::startPoller(double movingPollPeriod,
                                            double indlePollPeriod,
                                            int    forcedFastPolls)

启动这个电机的poller线程。派生类将在它们构造器接近末尾处调用这个方法。派生类一般可以使用这个poller线程的基类实现,但如果需要,可以自动重新实现。

参数:

  • [in] movingPollPeriod:当电机正在运动时,轮询之间的时间。
  • [in] idlePollPeriod:当没有轴运动时,轮询之间的时间。
  • [in] forcedFastPolls:在唤醒这个poller后,执行movingPollPeriod的次数。对于在告诉一个轴已经启动后,不立即报告那个轴正在移动的控制器,这需要非0。

asynMotorController方法ACRController自定义参数

asynStatus ACRController::writeFloat64(asynUser * pasynUser, epicsFloat64 value)
{
    int function = pasynUser->reason;
    asynStatus status = asynSuccess;

    ACRAxis * pAxis = getAxis(pasynUser);

    static const char * functionName = "writeFloat64";

    if (function == ACRJerk_){
        sprintf(outString_, "%s JOG JRK %f", pAxis->axisName_, value);
    }
    else{
        /* 调用基类方法 */
        status = asynMotorController::writeFloat64(pasynUser, value);
    }

    /* 进行回调, 因而更高层看到任何变化 */
    pAxis->callParamCallbacks();
}
asynStatus ACRController::writeFloat64(asynUser * pasynUser, epicsFloat64 value)

当客户端调用pasynFloat64->write()时,被调用。

从pasynUser中提取功能和轴编号。在参数库中设置这个值。如果功能时ACRJerk_,它设置控制器中的jerk值。对这个pasynUser->reason和地址,调用任何已注册的回调。对于所有其它功能,它调用asynMotorController::writeFloat64()。

参数:

[in] pasynUser:编码reasone和地址的asynUser结构体。

[in] value:要写的值。

对asynMotorController的重新实现。

asynMotorAxis构造器

/* asynMotorAxis.h
 * 此文件为asynMotorAxis定义了一个基类。真实电机轴是从它派生而来。
 */
#ifndef asynMotorAxis_H
#define asynMotorAxis_H

#include <epicsEvent.h>
#include <epicsTypes.h>
#include <shareLib.h>

#ifdef __cplusplus
#include <asynPortDriver.h>

#include "asynMotorController.h"

/** 电机轴从这个类派生而来 */
class epicsShareClass asynMotorAxis {

  public:
  /* 这是用于这个类的构造器 */
  asynMotorAxis(class asynMotorController *pController, int axisNumber);
  virtual ~asynMotorAxis();

  virtual asynStatus setIntegerParam(int index, int value);
  virtual asynStatus setDoubleParam(int index, double value);
  virtual asynStatus setStringParam(int index, const char *value);
  virtual void report(FILE *fp, int details);
  virtual asynStatus callParamCallbacks();

  virtual asynStatus move(double position, int relative, double minVelocity, double maxVelocity, double acceleration);
  virtual asynStatus moveVelocity(double minVelocity, double maxVelocity, double acceleration);
  virtual asynStatus home(double minVelocity, double maxVelocity, double acceleration, int forwards);
  virtual asynStatus stop(double acceleration);
  virtual asynStatus poll(bool *moving);
  virtual asynStatus setPosition(double position);
  virtual asynStatus setEncoderPosition(double position);
  virtual asynStatus setHighLimit(double highLimit);
  virtual asynStatus setLowLimit(double lowLimit);
  virtual asynStatus setPGain(double pGain);
  virtual asynStatus setIGain(double iGain);
  virtual asynStatus setDGain(double dGain);
  virtual asynStatus setClosedLoop(bool closedLoop);
  virtual asynStatus setEncoderRatio(double ratio);
  virtual asynStatus doMoveToHome();

  virtual asynStatus initializeProfile(size_t maxPoints);
  virtual asynStatus defineProfile(double *positions, size_t numPoints);
  virtual asynStatus buildProfile();
  virtual asynStatus executeProfile();
  virtual asynStatus abortProfile();
  virtual asynStatus readbackProfile();

  void setReferencingModeMove(int distance);
  int getReferencingModeMove();

  int getWasMovingFlag();
  void setWasMovingFlag(int wasMoving);
  int getDisableFlag();
  void setDisableFlag(int disableFlag);
  double getLastEndOfMoveTime();
  void setLastEndOfMoveTime(double time);

  protected:
  class asynMotorController *pC_;    /** 指向此轴所属的asynMotorController的指针
                                      *   缩写,因为它被非常频繁的使用   */
  int axisNo_;                       /** 这个轴的索引 (0 < pC_->numAxes_-1) */
  asynUser *pasynUser_;              /** 连接到这个轴为asynTrace调试的asynUser */
  double *profilePositions_;         /**< 用于轮廓移动的目标位置数组 */
  double *profileReadbacks_;         /**< 用于轮廓移动的回读位置数组 */
  double *profileFollowingErrors_;   /**< 用于轮廓移动的以下错误的素组*/
  int referencingMode_;

  MotorStatus status_;
  int statusChanged_;

  private:
  int referencingModeMove_;
  int wasMovingFlag_;
  int disableFlag_;
  double lastEndOfMoveTime_;

  friend class asynMotorController;
};

#endif /* _cplusplus */
#endif /* asynMotorAxis_H */

创建一个Axis对象,它自定义为一个特定的电机控制器。

1)在控制器硬件中的电机轴必须初始化。

2)根据motorRecord表征motorRecord:GrainSupport, HasEncoder

3)实现提供所有可用motorRecord功能的方法:move,moveVelocity, home, setPosition,...

实现'report'方法

ACRAxis

ACRAxis::ACRAxis(ACRController * pc, int axisNo) : asynMotorAxis(pC, axisNo), pC_(pC)

ACRAxis::ACRAxis(ACRController * pc, int axisNo) 

创建一个新的asynMotorAxis对象。

参数:

[in] pC:指向这个轴所属的asynMotorController的指针。

[in] axisNo:这个轴的索引号,范围从0到pC->numAxies_ - 1。

检查那个pC不是NULL,并且axisNo在有效范围内。在pC->pAxes[axisNo_]中设置一个指向自身的指针。连接pasynUser_为这个asyn端口和axisNo。

asynMotorAxis方法

ACRAxis Move

asynStatus ACRAxis::move(double position,
                         int    relative,
                         double minVelocity,
                         double maxVelocity,
                         double acceleration)

移动电机到一个绝对位置或者通过相对量。

参数:

[in] position:(如果relative=0)移动到绝对位置,或者(如果relative=1)要移动的相对位置。(单位steps)。

[in] relative:表明相对移动(1)或者绝对移动(0)的标记。

[in] minVelocity:初始速度,经常称为基速度。单位=steps/sec。

[in] maxVelocity:最大速度,经常称为回转速度。单位=steps/sec。

[in] acceleration:加速度值。单位=steps/sec/sec。

asynStatus ACRAxis::move(double position, int relative, double minVelocity,
                         double maxVelocity, double acceleration)
{
    sprintf(pc_->outString_, "%s JOG ACC %f", axisName_, acceleration/pulsesPerUnit_);
    status = pC_->writeController();

    sprintf(pc_->outString_, "%s JOG VEL %f",  axisName_, maxVelocity/pulsePerUnit_);
    status = pc_->writeCOntroller();

    if (relative){
        sprintf(pC_->outString_, "%c:%s JOG INC %f", CtlY, axisName_, position/pulsePerUnit_);
        status = pC_->writeController();
    }
    else{
        sprintf(pC_->outString_, "%c:%s JOG ABS %f", CtlY, axisName_, position/pulsesPerUnit_);
        status = pC_->writeController();
    }
}

ACRAxis MoveVelocity

asynStatus ACRAxis::moveVelocity(double minVelocity, double maxVelocity, double acceration)

以固定速度移动电机,直到告诉电机停止。

参数:

[in] minVelocity:初始速度,经常被称为基速度。单位=steps/sec。

[in] maxVelocity:最大速度,经常称为回转速度。单位=steps/sec。

[in] acceration:加速度值。单位=steps/sec/sec。

对来自asynMotorAxis的重新实现。

ACRAxis Poll

asynStatus ACRAxis::poll(bool * moving)

查询这个轴。这个函数读取控制器位置,编码器位置,限位状态,移动状态和驱动上电状态。它为它轮询的每项调用setIntegerParam()和setDoubleParam(),并且接着在末尾调用callParamCallbacks()。

参数:

[out] moving:一个标记,设置它来表明这个轴是移动(1)或者结束(0)。

asynStatus ACRAxis::poll(bool * moving)
{
    // 读取当前编码器位置
    sprintf(pC_->outString, "?P%d", encoderPostionReg_);
    comStatus = pC_->writeReadController();
    if (comStatus) goto skip;
    encoderPosition_ = atof(pC_->inString);
    setDoubleParam(pC_->motorEncoderPosition_, encoderPostion);

    // 读取当前标记
    sprintf(pC_->outString_, "?P%d", flagReg_);
    comStatus = pC_->writeReadController();
    if (comStatus) goto skip;
    currentFlag_ = atoi(pC_->inString_);
    done = (currentFlags & 0x1000000) ? 0: 1;
    setIntegerParam(pC_->motorStatusDone_, done);
    * moving = done ? false : true;
        

    // 读取当前状态
    sprintf(pC_->outString, "?P%d", limitsReg_);
    comStatus = pC_->writeReadController();

    if (comStatus) goto skip;

    currentLimits_ = atoi(pC->inString_);
    limit = (currentLimts_ & 0x1) ? 1:0;
    setIntegerParam(pC_->motorStatusHighLimit_, limit);
    limit = (currentLimits_ & 0x2)?1:0;
    setIntegerParam(pC_->motorStatusAtHome_, limit);
    
skip:
    setIntegerParam(pC_->motorStatusProblem_, comStatus ? 1: 0);
    callParamCallbacks();
    return comStatus ? asynError : asynSuccess;
}

ACRAxis Home

asynStatus ACRAxis::home(double minVelocity, double maxVelocity, double acceleration, int forwards)

移动电机到home位置。

参数:

[in] minVelocity:初始速度,经常称为基速度。单位=steps/sec。

[in] maxVelocity:最大速度,经常称为回转速度。单位=steps/sec。

[in] acceraltion:加速度值。单位=steps/sec/sec。

[in] forwards:表明正(1)反(0)方向移动电机的标记。某些控制器需要被告知方向,另一些直到用哪种方式移动到home。

ACRAxis Report

void ACRAxis::report(FILE *fp, int level)

报告驱动的状态。

参数:

[in] fp:文件指针,报告信息将写入这个文件。

[in] level:详细程度。

如果detail>0,则输出每个轴的信息。在打印控制器相关信息后,调用asynMotorController::report()。

ACRAxis setPosition

asynStatus ACRAxis::setPosition(double position)

设置电机的当前值。

参数:

[in] position:新的绝对电机位置应该被设置到硬件中。Units=Steps。

ACRAxis Stop

asynStatus ACRAxis::stop(double acceleration)

停止电机。

参数:

[in] acceleration:绝对值。单位=steps/sec/sec。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值