您的位置:首页 > 财经 > 产业 > asynMotorAxis类

asynMotorAxis类

2024/10/6 10:29:26 来源:https://blog.csdn.net/yuyuyuliang00/article/details/141817836  浏览:    关键词:asynMotorAxis类

轴对象的基类,具体的轴类是派生自这个类,控制器类是其友元类。

派生类根据需要实现以下方法:

asynMotorAxis.h 头文件:

/* asynMotorAxis.h 
** 这个文件为一个asynMotorAxis定义了一个基类。
** 真实电机从这个类派生
*/
#ifndef asynMotorAxis_H
#define asynMotorAxis_H#include <epicsEvent.h>
#include <epicsTypes.h>#ifdef __cplusplus
#include <asynPortDriver.h>#include "asynMotorController.h"class epicsShareFunc asynMotorAxis {public:
/*  这是这个类的构造器:控制器对象的指针以及这个轴编号 */
asynMotorAxis(class asynMotorController *pController, int axisNumber);// 根据索引设置参数库中的整数变量
virtual asynStatus setIntegerParam(int index, int value);
// 根据索引设置参数库中的双精度浮点变量
virtual asynStatus setDoubleParam(int index, double value);
virtual void report(FILE *fp, int details);
virtual asynStatus callParamCallbacks();// 移动:要移动的位置,相对或绝对,最低速度,最高速度,加速度
// 要移动的位置以step为单位
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);
//设置比例增益
00040   virtual asynStatus setPGain(double pGain);
//设置积分增益
virtual asynStatus setIGain(double iGain);
//设置微分增益
00042   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();protected:
class asynMotorController *pC_;    //所属控制器对象
int axisNo_;          //轴编号                           
asynUser *pasynUser_; //这个轴的使用者           
double *profilePositions_;         
double *profileReadbacks_;         
double *profileFollowingErrors_;   
int referencingMode_;private:
/*
*      typedef struct MotorStatus {
*          double position;           //命令电机位置
*          double encoderPosition;    //实际编码器位置
*          double velocity;           //实际速度
*          epicsUInt32 status;        //包含状态位(运动结束,限位等)的字
*        } MotorStatus;
*/
MotorStatus status_;   
int statusChanged_;
int referencingModeMove_;friend class asynMotorController;
};
#endif /* _cplusplus */
#endif /* asynMotorAxis_H */

asynMotorAxis.cpp 实现:

/* asynMotorAxis.cpp
** 这个文件为asynMotorAxis定义了基类。真实电机轴从这个类派生
**
*/
#include <stdlib.h>
#include <string.h>#include <epicsThread.h>#include <asynPortDriver.h>
#define epicsExportSharedSymbols
#include <shareLib.h>
#include "asynMotorAxis.h"
#include "asynMotorController.h"static const char *driverName = "asynMotorAxis";/** 创建一个asynMotorAxis对象.* 参数[in] pC :指向这个轴所属的asynMotorController的指针。* 参数[in] axisNo:这个轴的编号,范围从0到pC->numAxes_-1.* * 检查pC不为空,并且axisNo在有效范围内。* 在pC->pAxes[axisNo_]中设置一个指针指向自身* 连接pasynUser_到这个asyn端口和asynNo*/
asynMotorAxis::asynMotorAxis(class asynMotorController *pC, int axisNo): pC_(pC), axisNo_(axisNo), statusChanged_(1)
{static const char *functionName = "asynMotorAxis";if (!pC) {// 检查传入pC不为空printf("%s:%s: Error, controller is NULL\n",driverName, functionName);return;}// 检查axisNo在有效范围内if ((axisNo < 0) || (axisNo >= pC->numAxes_)) {printf("%s:%s: Error, axis=%d is not in range 0 to %d\n",driverName, functionName, axisNo, pC->numAxes_-1);return;}//pC->pAxes_的第axisNo索引指向自身pC->pAxes_[axisNo] = this;//初始状态置位0status_.status = 0;profilePositions_       = NULL;profileReadbacks_       = NULL;profileFollowingErrors_ = NULL;/* 用于在驱动程序中跟踪参考模式 */referencingMode_ = 0;/* 用于启用/禁用移动到零位,并且告诉驱动程序要移动多远 */referencingModeMove_ = 0;wasMovingFlag_ = 0;disableFlag_ = 0;lastEndOfMoveTime_ = 0;// 创建一个asynUser, 连接到这个轴/* 创建一个asynUser. 调用者指定两个回调process和timeout。这些回调仅由queueRequest的结果被调用。timeout是可选的。位errorMesage分配errorMessageSize个字符。存储量不能被更改。如果这个方法不能分配存储区,它不返回。*/pasynUser_ = pasynManager->createAsynUser(NULL, NULL);
/* 连接这个asynUser结构体到由portName,addr指定的一个设备。
这个端口号与在registerPort中指定的端口名相同。如果这个asynUser已经连接了一个设备,
这个调用将出错。如果端口不支持多设备,则忽略addr。connectDevice仅位portName,addr连接这个asynUser到端口驱动。端口驱动可能连接了实际设备,也可能没有连接。因而,connectDevice和
asynCommon:connect完全不同。
*/pasynManager->connectDevice(pasynUser_, pC->portName, axisNo);
}asynMotorAxis::~asynMotorAxis()
{
}/** 移动单机到一个绝对位置或者一个相对量。* 参数[in] position:如果relavtive=0,移动到绝对位置,relavtive=1移动一个相对距离  Units=steps.* 参数[in] relative:指明相对移动(1)或者绝对移动(0)的标记* 参数[in] minVelocity:初始速度,通常称为基速度,Units=steps/sec.* 参数[in] maxVelocity:最大速度,通常称为回转速度Units=steps/sec.* 参数[in] acceleration 加速度值. Units=steps/sec/sec. 
*/
asynStatus asynMotorAxis::move(double position, int relative, double minVelocity, double maxVelocity, double acceleration)
{return asynSuccess;
}/** 在告诉停止前,以固定速度移动电机。* 参数[in] minVelocity:初始速度,通常称为基速度,Units=steps/sec.Units=steps/sec.* 参数[in] maxVelocity: 最大速度,通常称为回转速度Units=steps/sec.* 参数[in] acceleration: 加速度值. Units=steps/sec/sec.*/
asynStatus asynMotorAxis::moveVelocity(double minVelocity, double maxVelocity, double acceleration)
{return asynSuccess;
}/** 移动电机到归零位置。* 参数[in]  minVelocity :初始速度,通常称为基速度,Units=steps/sec.* 参数[in]  maxVelocity :最大速度,通常称为回转速度Units=steps/sec.* 参数[in]  acceleration: 加速度值. Units=steps/sec/sec.* 参数[in]  forwards : 指明电机在正向(1)或反向(0)移动电机的标志* 某些电机需要告诉方向,另外知道哪个方向上归零。
*/
asynStatus asynMotorAxis::home(double minVelocity, double maxVelocity, double acceleration, int forwards)
{return asynSuccess;
}/** 停止电机*参数[in] acceleration :加速度值. Units=steps/sec/sec. */
asynStatus asynMotorAxis::stop(double acceleration)
{return asynSuccess;
}/** Poll the axis.查询这个轴。 这个函数应该读取控制器位置,编码器位置和硬件支持一样多的*motorStatus标记。它应该位它查询的每个项调用setIntegerParam() 和 setDoubleParam(),并且
*最后调用callParamCallbacks()。
* 参数[out] moving:函数必须设定这个标记,表明轴是移动(1)或者结束(0)。
*/
asynStatus asynMotorAxis::poll(bool *moving)
{return asynSuccess;
}/** 设置电机的当前位置。
* 参数[in] position:应该设置到硬件中的新绝对电机位置。  Units=steps.
*/
asynStatus asynMotorAxis::setPosition(double position)
{return asynSuccess;
}/** 设置电机的当前编码器位置
* 参数[in] position:应该设置到硬件中的新绝对编码器位置  Units=steps.
*/
asynStatus asynMotorAxis::setEncoderPosition(double position)
{return asynSuccess;
}/** 设置电机的上限位位置
* 参数in] highLimit:应该设定到硬件中新的上限位置.Units=steps.
*/
asynStatus asynMotorAxis::setHighLimit(double highLimit)
{return asynSuccess;
}/** 设置电机的下限位位置
* 参数[in] lowLimit:应该设定到硬件中新的下限位置.Units=steps.
*/
asynStatus asynMotorAxis::setLowLimit(double lowLimit)
{return asynSuccess;
}/** 设置电机比例增益*参数[in] pGain :新的比例增益*/
asynStatus asynMotorAxis::setPGain(double pGain)
{return asynSuccess;
}/** 设置电机积分增益* 参数[in] iGain 新的积分增益.*/
asynStatus asynMotorAxis::setIGain(double iGain)
{return asynSuccess;
}/** 设置电机微分增益* 参数[in] dGain 新的微分增益
*/
asynStatus asynMotorAxis::setDGain(double dGain)
{return asynSuccess;
}/** 设置电机闭环状态*  参数[in]  closedLoop true = 闭环, false = 开环 */
asynStatus asynMotorAxis::setClosedLoop(bool closedLoop)
{return asynSuccess;
}/** 设置电机编码器比率* 参数[in] ratio 新的编码器比率 */
asynStatus asynMotorAxis::setEncoderRatio(double ratio)
{return asynSuccess;
}void asynMotorAxis::report(FILE *fp, int details)
{
}/*** doMoveToHome的默认实现,派生类需要实现这个函数实际执行这个轴移动到归零位置*/
asynStatus asynMotorAxis::doMoveToHome()
{static const char *functionName="doMoveToHome";asynPrint(pasynUser_, ASYN_TRACE_ERROR,"%s:%s: Axis=%d no implementation\n",driverName, functionName, pC_->moveToHomeAxis_);return asynSuccess;
}/*** referencingModeMove_的设置方法*/
void  asynMotorAxis::setReferencingModeMove(int distance)
{referencingModeMove_ = distance;
}/*** referencingModeMove_的获取方法*/
int  asynMotorAxis::getReferencingModeMove()
{return referencingModeMove_;
}//我们实现setIntegerParam, setDoubleParam, 和 callParamCallbacks,因此我们可以构造
//聚合状态结构体并且对其进行回调。
/*
在参数库中为这个轴的一个整数设置值。
如果这个参数是motorStatus参数 (motorStatusDirection_, motorStatusHomed_等)之一,这个函数采取特殊操作。在这种情况中,它置位或清零其私有MotorStatus.status结构体中相应的位,并且当导演callParamCallbacks()时,如果状态发生变化,设置一个标记对devMotorAsyn进行回调。
参数[in] function :功能(参数)编号
参数[in] value:要设定的值
*/
asynStatus asynMotorAxis::setIntegerParam(int function, int value)
{int mask;epicsUInt32 status=0;// 这假设以上定义的参数与电机基类预计的位相同顺序/*这些是状态位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_;*/if (function >= pC_->motorStatusDirection_ &&function <= pC_->motorStatusHomed_) {status = status_.status; // 获取状态mask = 1 << (function - pC_->motorStatusDirection_);if (value) status |= mask;else       status &= ~mask;if (status != status_.status) {//状态发生了变化status_.status = status;statusChanged_ = 1;}}// 设置新的状态pC_->setIntegerParam(axisNo_, pC_->motorStatus_, status);return pC_->setIntegerParam(axisNo_, function, value);
}/** 在参数库中位这个轴的一个double设置值.* 如果这个参数是motorPosition_ 或 motorEncoderPosition_采取特殊操作。* 在这种情况下,它设置私有MotorStatus结构体中这个值,并且如果这个值发生变化,则* 设置置位一个在callParamCallbacks()被调用时对devMotorAsyn进行回调的标记* 参数[in] function :功能(参数)编号* 参数[in] value : 要设置的值
*/
asynStatus asynMotorAxis::setDoubleParam(int function, double value)
{if (function == pC_->motorPosition_) {if (value != status_.position) {// 传入的电机位置不能与状态结构体中的电机位置statusChanged_ = 1;status_.position = value;}} else if (function == pC_->motorEncoderPosition_) {if (value != status_.encoderPosition) {statusChanged_ = 1;status_.encoderPosition = value;}}// 调用控制类对象,存储这个功能编号对应的值return pC_->setDoubleParam(axisNo_, function, value);
}/*** 位参数库中这个轴的一个字符串设置值* 参数[in] function: 功能(参数)编号* 参数[in] value: 要设定的值
*/
asynStatus asynMotorAxis::setStringParam(int function, const char *value)
{// 调用控制类对象的setStringParamreturn pC_->setStringParam(axisNo_, function, value);
}/** 为在参数库中对应这个轴已经发生变化的任何参数,调用回调函数。
*如果聚合结构体已经发生变化,这个参数采取特殊操作。
*在这种情况,它对asynGenericPointer进行回调,尤其对devMotorAsyn
*/
asynStatus asynMotorAxis::callParamCallbacks()
{if (statusChanged_) {statusChanged_ = 0;pC_->doCallbacksGenericPointer((void *)&status_, pC_->motorStatus_, axisNo_);}return pC_->callParamCallbacks(axisNo_);
}/*  这些函数用于轮廓移动 */
asynStatus asynMotorAxis::initializeProfile(size_t maxProfilePoints)
{//轮廓移动的目标位置数组if (profilePositions_)       free(profilePositions_);profilePositions_ =         (double *)calloc(maxProfilePoints, sizeof(double));//轮廓移动的回读位置数组if (profileReadbacks_)    free(profileReadbacks_);profileReadbacks_ =         (double *)calloc(maxProfilePoints, sizeof(double));//  以下轮廓移动的误差的数组if (profileFollowingErrors_) free(profileFollowingErrors_);profileFollowingErrors_ =   (double *)calloc(maxProfilePoints, sizeof(double));return asynSuccess;
}/**  为一个轮廓移动定义电机位置的函数*  这个基类函数使用profileMotorOffset_, profileMotorDirection_和profileMotorResolution参数从用户单位转换位置为控制器单位,* 参数[in] positions :这个轴以用户单位的轮廓位置的数组A* 参数[in] numPoints :数组中位置数目*/
asynStatus asynMotorAxis::defineProfile(double *positions, size_t numPoints)
{size_t i;double resolution;double offset;int direction;double scale;int status=0;static const char *functionName = "defineProfile";asynPrint(pasynUser_, ASYN_TRACE_FLOW,"%s:%s: axis=%d, numPoints=%d, positions[0]=%f\n",driverName, functionName, axisNo_, (int)numPoints, positions[0]);if (numPoints > pC_->maxProfilePoints_) return asynError;status |= pC_->getDoubleParam(axisNo_, pC_->motorRecResolution_, &resolution);status |= pC_->getDoubleParam(axisNo_, pC_->motorRecOffset_, &offset);status |= pC_->getIntegerParam(axisNo_, pC_->motorRecDirection_, &direction);asynPrint(pasynUser_, ASYN_TRACE_FLOW,"%s:%s: axis=%d, status=%d, offset=%f direction=%d, resolution=%f\n",driverName, functionName, axisNo_, status, offset, direction, resolution);if (status) return asynError;if (resolution == 0.0) return asynError;// 转换成控制器单位scale = 1.0/resolution;if (direction != 0) scale = -scale;for (i=0; i<numPoints; i++) {profilePositions_[i] = (positions[i] - offset)*scale;}asynPrint(pasynUser_, ASYN_TRACE_FLOW,"%s:%s: axis=%d, scale=%f, offset=%f positions[0]=%f, profilePositions_[0]=%f\n",driverName, functionName, axisNo_, scale, offset, positions[0], profilePositions_[0]);return asynSuccess;
}/** 构建一个多轴联动移动的函数*/
asynStatus asynMotorAxis::buildProfile()
{// static const char *functionName = "buildProfile";return asynSuccess;
}/** 执行一个多轴联动移动的函数. */
asynStatus asynMotorAxis::executeProfile()
{// static const char *functionName = "executeProfile";return asynSuccess;
}/** 终止一个轮廓的函数 */
asynStatus asynMotorAxis::abortProfile()
{// static const char *functionName = "abortProfile";return asynSuccess;
}/** 从多轴联动移动回读实际电机位置的函数。这个基类函数转从控制器单位换这些回读和以下误差为用户单位,并且对这些数组进行回调。
注意:这个函数原地修改这些回读,因此它必须每个回读操作仅调用一次。*/
asynStatus asynMotorAxis::readbackProfile()
{int i;double resolution;double offset;int direction;int numReadbacks;int status=0;//static const char *functionName = "readbackProfile";status |= pC_->getDoubleParam(axisNo_, pC_->motorRecResolution_, &resolution);status |= pC_->getDoubleParam(axisNo_, pC_->motorRecOffset_, &offset);status |= pC_->getIntegerParam(axisNo_, pC_->motorRecDirection_, &direction);status |= pC_->getIntegerParam(0, pC_->profileNumReadbacks_, &numReadbacks);if (status) return asynError;// 转换成用户单位if (direction != 0) resolution = -resolution;for (i=0; i<numReadbacks; i++) {profileReadbacks_[i] = profileReadbacks_[i] * resolution + offset;profileFollowingErrors_[i] = profileFollowingErrors_[i] * resolution;}status  = pC_->doCallbacksFloat64Array(profileReadbacks_,       numReadbacks, pC_->profileReadbacks_, axisNo_);status |= pC_->doCallbacksFloat64Array(profileFollowingErrors_, numReadbacks, pC_->profileFollowingErrors_, axisNo_);return asynSuccess;
}/****************************************************************************/
/* 以下函数是由自动化驱动电源控制在asynMotorControler中基类poller中使用。
*//**
* 读取指示上次poll是否正在运行的标记
*/
int asynMotorAxis::getWasMovingFlag(void)
{return wasMovingFlag_;
}/**
* 如果之前查询表明移动状态,设置为1*/
void asynMotorAxis::setWasMovingFlag(int wasMovingFlag)
{wasMovingFlag_ = wasMovingFlag;
}/*** 表明驱动是否应该自定被禁用的标记*/
int asynMotorAxis::getDisableFlag(void)
{return disableFlag_;
}/*** 如果驱动应该自动被禁用,设置此为1*/
void asynMotorAxis::setDisableFlag(int disableFlag)
{disableFlag_ = disableFlag;
}/*** 读取上次移动结束的时间(以秒为单位)*/
double asynMotorAxis::getLastEndOfMoveTime(void)
{return lastEndOfMoveTime_;
}/*** Set this to the current time at the end of a move.* 将这个设置到移动结束时的当前时间*/
void asynMotorAxis::setLastEndOfMoveTime(double time)
{lastEndOfMoveTime_ = time;
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com