Merge branch 'initializer_for_EL734Axis' into 'master'
Girder axis and initializer EL734Axis See merge request sinqdev/sinqepicsapp!3
This commit is contained in:
@ -15,7 +15,7 @@ REQUIRED+=asynMotor
|
|||||||
# using a test version
|
# using a test version
|
||||||
#scaler_VERSION=2024
|
#scaler_VERSION=2024
|
||||||
|
|
||||||
LIBVERSION=2024
|
LIBVERSION=2024-dev
|
||||||
|
|
||||||
TEMPLATES += sinqEPICSApp/Db/dimetix.db
|
TEMPLATES += sinqEPICSApp/Db/dimetix.db
|
||||||
TEMPLATES += sinqEPICSApp/Db/slsvme.db
|
TEMPLATES += sinqEPICSApp/Db/slsvme.db
|
||||||
@ -35,6 +35,5 @@ SOURCES += sinqEPICSApp/src/EuroMoveDriver.cpp
|
|||||||
SOURCES += sinqEPICSApp/src/pmacAsynIPPort.c
|
SOURCES += sinqEPICSApp/src/pmacAsynIPPort.c
|
||||||
SOURCES += sinqEPICSApp/src/pmacAxis.cpp
|
SOURCES += sinqEPICSApp/src/pmacAxis.cpp
|
||||||
SOURCES += sinqEPICSApp/src/pmacController.cpp
|
SOURCES += sinqEPICSApp/src/pmacController.cpp
|
||||||
SOURCES += sinqEPICSApp/src/drvAsynMasterMACSPort.c
|
|
||||||
SOURCES += sinqEPICSApp/src/MasterMACSDriver.cpp
|
SOURCES += sinqEPICSApp/src/MasterMACSDriver.cpp
|
||||||
# MISCS would be the place to keep the stream device template files
|
# MISCS would be the place to keep the stream device template files
|
||||||
|
@ -11,7 +11,6 @@ Mark Koennecke, May, August 2017
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -30,84 +29,82 @@ Mark Koennecke, May, August 2017
|
|||||||
|
|
||||||
#define IDLEPOLL 60
|
#define IDLEPOLL 60
|
||||||
|
|
||||||
|
|
||||||
/** Creates a new EL734Controller object.
|
/** Creates a new EL734Controller object.
|
||||||
* \param[in] portName The name of the asyn port that will be created for this driver
|
* \param[in] portName The name of the asyn port that will be created for this driver
|
||||||
* \param[in] EL734PortName The name of the drvAsynSerialPort that was created previously to connect to the EL734 controller
|
* \param[in] EL734PortName The name of the drvAsynSerialPort that was created previously to connect to the EL734 controller
|
||||||
* \param[in] numAxes The number of axes that this controller supports
|
* \param[in] numAxes The number of axes that this controller supports
|
||||||
*/
|
*/
|
||||||
EL734Controller::EL734Controller(const char *portName, const char *EL734PortName, int numAxes)
|
EL734Controller::EL734Controller(const char *portName, const char *EL734PortName, int numAxes)
|
||||||
: SINQController(portName, EL734PortName, numAxes)
|
: SINQController(portName, EL734PortName, numAxes)
|
||||||
{
|
{
|
||||||
int axis;
|
int axis;
|
||||||
asynStatus status;
|
asynStatus status;
|
||||||
static const char *functionName = "EL734Controller::EL734Controller";
|
static const char *functionName = "EL734Controller::EL734Controller";
|
||||||
|
|
||||||
|
|
||||||
/* Connect to EL734 controller */
|
/* Connect to EL734 controller */
|
||||||
status = pasynOctetSyncIO->connect(EL734PortName, 0, &pasynUserController_, NULL);
|
status = pasynOctetSyncIO->connect(EL734PortName, 0, &pasynUserController_, NULL);
|
||||||
if (status) {
|
if (status)
|
||||||
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
|
{
|
||||||
"%s: cannot connect to EL734 controller\n",
|
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
|
||||||
functionName);
|
"%s: cannot connect to EL734 controller\n",
|
||||||
|
functionName);
|
||||||
}
|
}
|
||||||
pasynOctetSyncIO->setOutputEos(pasynUserController_,"\r",strlen("\r"));
|
pasynOctetSyncIO->setOutputEos(pasynUserController_, "\r", strlen("\r"));
|
||||||
pasynOctetSyncIO->setInputEos(pasynUserController_,"\r",strlen("\r"));
|
pasynOctetSyncIO->setInputEos(pasynUserController_, "\r", strlen("\r"));
|
||||||
|
|
||||||
switchRemote();
|
switchRemote();
|
||||||
|
|
||||||
for (axis=0; axis<numAxes; axis++) {
|
for (axis = 0; axis < numAxes; axis++)
|
||||||
new EL734Axis(this, axis+1);
|
{
|
||||||
|
new EL734Axis(this, axis + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
startPoller(1000./1000., IDLEPOLL, 2);
|
startPoller(1000. / 1000., IDLEPOLL, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Creates a new EL734Controller object.
|
/** Creates a new EL734Controller object.
|
||||||
* Configuration command, called directly or from iocsh
|
* Configuration command, called directly or from iocsh
|
||||||
* \param[in] portName The name of the asyn port that will be created for this driver
|
* \param[in] portName The name of the asyn port that will be created for this driver
|
||||||
* \param[in] EL734PortName The name of the drvAsynIPPPort that was created previously to connect to the EL734 controller
|
* \param[in] EL734PortName The name of the drvAsynIPPPort that was created previously to connect to the EL734 controller
|
||||||
* \param[in] numAxes The number of axes that this controller supports
|
* \param[in] numAxes The number of axes that this controller supports
|
||||||
*/
|
*/
|
||||||
extern "C" int EL734CreateController(const char *portName, const char *EL734PortName, int numAxes)
|
extern "C" int EL734CreateController(const char *portName, const char *EL734PortName, int numAxes)
|
||||||
{
|
{
|
||||||
EL734Controller *pEL734Controller
|
EL734Controller *pEL734Controller = new EL734Controller(portName, EL734PortName, numAxes);
|
||||||
= new EL734Controller(portName, EL734PortName, numAxes);
|
|
||||||
pEL734Controller = NULL;
|
pEL734Controller = NULL;
|
||||||
return(asynSuccess);
|
return (asynSuccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Reports on status of the driver
|
/** Reports on status of the driver
|
||||||
* \param[in] fp The file pointer on which report information will be written
|
* \param[in] fp The file pointer on which report information will be written
|
||||||
* \param[in] level The level of report detail desired
|
* \param[in] level The level of report detail desired
|
||||||
*
|
*
|
||||||
* If details > 0 then information is printed about each axis.
|
* If details > 0 then information is printed about each axis.
|
||||||
* After printing controller-specific information it calls asynMotorController::report()
|
* After printing controller-specific information it calls asynMotorController::report()
|
||||||
*/
|
*/
|
||||||
void EL734Controller::report(FILE *fp, int level)
|
void EL734Controller::report(FILE *fp, int level)
|
||||||
{
|
{
|
||||||
fprintf(fp, "EL734 motor driver %s, numAxes=%d\n",
|
fprintf(fp, "EL734 motor driver %s, numAxes=%d\n",
|
||||||
this->portName, numAxes_);
|
this->portName, numAxes_);
|
||||||
|
|
||||||
// Call the base class method
|
// Call the base class method
|
||||||
asynMotorController::report(fp, level);
|
asynMotorController::report(fp, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns a pointer to an EL734Axis object.
|
/** Returns a pointer to an EL734Axis object.
|
||||||
* Returns NULL if the axis number encoded in pasynUser is invalid.
|
* Returns NULL if the axis number encoded in pasynUser is invalid.
|
||||||
* \param[in] pasynUser asynUser structure that encodes the axis index number. */
|
* \param[in] pasynUser asynUser structure that encodes the axis index number. */
|
||||||
EL734Axis* EL734Controller::getAxis(asynUser *pasynUser)
|
EL734Axis *EL734Controller::getAxis(asynUser *pasynUser)
|
||||||
{
|
{
|
||||||
return static_cast<EL734Axis*>(asynMotorController::getAxis(pasynUser));
|
return static_cast<EL734Axis *>(asynMotorController::getAxis(pasynUser));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns a pointer to an EL734Axis object.
|
/** Returns a pointer to an EL734Axis object.
|
||||||
* Returns NULL if the axis number encoded in pasynUser is invalid.
|
* Returns NULL if the axis number encoded in pasynUser is invalid.
|
||||||
* \param[in] axisNo Axis index number. */
|
* \param[in] axisNo Axis index number. */
|
||||||
EL734Axis* EL734Controller::getAxis(int axisNo)
|
EL734Axis *EL734Controller::getAxis(int axisNo)
|
||||||
{
|
{
|
||||||
return static_cast<EL734Axis*>(asynMotorController::getAxis(axisNo));
|
return static_cast<EL734Axis *>(asynMotorController::getAxis(axisNo));
|
||||||
}
|
}
|
||||||
|
|
||||||
void EL734Controller::switchRemote()
|
void EL734Controller::switchRemote()
|
||||||
@ -116,27 +113,27 @@ void EL734Controller::switchRemote()
|
|||||||
size_t in, out;
|
size_t in, out;
|
||||||
int reason;
|
int reason;
|
||||||
|
|
||||||
strcpy(command,"RMT 1");
|
strcpy(command, "RMT 1");
|
||||||
pasynOctetSyncIO->writeRead(pasynUserController_, command, strlen(command),
|
pasynOctetSyncIO->writeRead(pasynUserController_, command, strlen(command),
|
||||||
reply,COMLEN, 1.,&out,&in,&reason);
|
reply, COMLEN, 1., &out, &in, &reason);
|
||||||
strcpy(command,"ECHO 0");
|
strcpy(command, "ECHO 0");
|
||||||
pasynOctetSyncIO->writeRead(pasynUserController_, command, strlen(command),
|
pasynOctetSyncIO->writeRead(pasynUserController_, command, strlen(command),
|
||||||
reply,COMLEN, 1.,&out,&in,&reason);
|
reply, COMLEN, 1., &out, &in, &reason);
|
||||||
strcpy(command,"RMT 1");
|
strcpy(command, "RMT 1");
|
||||||
pasynOctetSyncIO->writeRead(pasynUserController_, command, strlen(command),
|
pasynOctetSyncIO->writeRead(pasynUserController_, command, strlen(command),
|
||||||
reply,COMLEN, 1.,&out,&in,&reason);
|
reply, COMLEN, 1., &out, &in, &reason);
|
||||||
strcpy(command,"ECHO 0");
|
strcpy(command, "ECHO 0");
|
||||||
pasynOctetSyncIO->writeRead(pasynUserController_, command, strlen(command),
|
pasynOctetSyncIO->writeRead(pasynUserController_, command, strlen(command),
|
||||||
reply,COMLEN, 1.,&out,&in,&reason);
|
reply, COMLEN, 1., &out, &in, &reason);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* send a command to the EL734 and read the reply. Do some error and controller
|
* send a command to the EL734 and read the reply. Do some error and controller
|
||||||
* issue fixing on the way
|
* issue fixing on the way
|
||||||
* \param[in] command The command to send
|
* \param[in] command The command to send
|
||||||
* \param[out] reply The controllers reply
|
* \param[out] reply The controllers reply
|
||||||
*/
|
*/
|
||||||
|
|
||||||
asynStatus EL734Controller::transactController(int axisNo,char command[COMLEN], char reply[COMLEN])
|
asynStatus EL734Controller::transactController(int axisNo, char command[COMLEN], char reply[COMLEN])
|
||||||
{
|
{
|
||||||
asynStatus status;
|
asynStatus status;
|
||||||
size_t in, out, i;
|
size_t in, out, i;
|
||||||
@ -145,58 +142,71 @@ asynStatus EL734Controller::transactController(int axisNo,char command[COMLEN],
|
|||||||
SINQAxis *axis = getAxis(axisNo);
|
SINQAxis *axis = getAxis(axisNo);
|
||||||
|
|
||||||
pasynOctetSyncIO->flush(pasynUserController_);
|
pasynOctetSyncIO->flush(pasynUserController_);
|
||||||
|
|
||||||
status = pasynOctetSyncIO->writeRead(pasynUserController_, command, strlen(command),
|
status = pasynOctetSyncIO->writeRead(pasynUserController_, command, strlen(command),
|
||||||
reply,COMLEN, 2.,&out,&in,&reason);
|
reply, COMLEN, 2., &out, &in, &reason);
|
||||||
if(status != asynSuccess){
|
if (status != asynSuccess)
|
||||||
if(axis!= NULL){
|
{
|
||||||
|
if (axis != NULL)
|
||||||
|
{
|
||||||
axis->updateMsgTxtFromDriver("Lost connection to motor controller");
|
axis->updateMsgTxtFromDriver("Lost connection to motor controller");
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
check for the offline reply
|
check for the offline reply
|
||||||
*/
|
*/
|
||||||
if(strstr(reply,"?LOC") != NULL){
|
if (strstr(reply, "?LOC") != NULL)
|
||||||
|
{
|
||||||
switchRemote();
|
switchRemote();
|
||||||
return pasynOctetSyncIO->writeRead(pasynUserController_, command, strlen(command),
|
return pasynOctetSyncIO->writeRead(pasynUserController_, command, strlen(command),
|
||||||
reply,COMLEN, 1.,&out,&in,&reason);
|
reply, COMLEN, 1., &out, &in, &reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
check for echos. This means that the thing is offline.
|
check for echos. This means that the thing is offline.
|
||||||
*/
|
*/
|
||||||
if(strstr(reply,"p ") != NULL || strstr(reply,"u ") != NULL || strstr(reply,"msr ") != NULL){
|
if (strstr(reply, "p ") != NULL || strstr(reply, "u ") != NULL || strstr(reply, "msr ") != NULL)
|
||||||
|
{
|
||||||
switchRemote();
|
switchRemote();
|
||||||
return pasynOctetSyncIO->writeRead(pasynUserController_, command, strlen(command),
|
return pasynOctetSyncIO->writeRead(pasynUserController_, command, strlen(command),
|
||||||
reply,COMLEN, 1.,&out,&in,&reason);
|
reply, COMLEN, 1., &out, &in, &reason);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
check for EL734 errors
|
check for EL734 errors
|
||||||
*/
|
*/
|
||||||
strcpy(myReply, reply);
|
strcpy(myReply, reply);
|
||||||
for(i = 0; i < strlen(reply); i++){
|
for (i = 0; i < strlen(reply); i++)
|
||||||
|
{
|
||||||
myReply[i] = (char)tolower((int)reply[i]);
|
myReply[i] = (char)tolower((int)reply[i]);
|
||||||
}
|
}
|
||||||
if(strstr(myReply,"?cmd") != NULL){
|
if (strstr(myReply, "?cmd") != NULL)
|
||||||
snprintf(errTxt,sizeof(errTxt), "Bad command %s at axis %d", command, axisNo);
|
{
|
||||||
|
snprintf(errTxt, sizeof(errTxt), "Bad command %s at axis %d", command, axisNo);
|
||||||
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, errTxt);
|
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, errTxt);
|
||||||
if(axis!= NULL){
|
if (axis != NULL)
|
||||||
|
{
|
||||||
axis->updateMsgTxtFromDriver(errTxt);
|
axis->updateMsgTxtFromDriver(errTxt);
|
||||||
}
|
}
|
||||||
return asynError;
|
return asynError;
|
||||||
} else if(strstr(myReply,"?par") != NULL){
|
}
|
||||||
snprintf(errTxt,sizeof(errTxt), "Bad parameter in command %s", command);
|
else if (strstr(myReply, "?par") != NULL)
|
||||||
|
{
|
||||||
|
snprintf(errTxt, sizeof(errTxt), "Bad parameter in command %s", command);
|
||||||
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, errTxt);
|
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, errTxt);
|
||||||
if(axis!= NULL){
|
if (axis != NULL)
|
||||||
|
{
|
||||||
axis->updateMsgTxtFromDriver(errTxt);
|
axis->updateMsgTxtFromDriver(errTxt);
|
||||||
}
|
}
|
||||||
return asynError;
|
return asynError;
|
||||||
} else if(strstr(myReply,"?rng") != NULL){
|
}
|
||||||
snprintf(errTxt,sizeof(errTxt), "Parameter out of range in command %s", command);
|
else if (strstr(myReply, "?rng") != NULL)
|
||||||
|
{
|
||||||
|
snprintf(errTxt, sizeof(errTxt), "Parameter out of range in command %s", command);
|
||||||
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, errTxt);
|
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, errTxt);
|
||||||
if(axis!= NULL){
|
if (axis != NULL)
|
||||||
|
{
|
||||||
axis->updateMsgTxtFromDriver(errTxt);
|
axis->updateMsgTxtFromDriver(errTxt);
|
||||||
}
|
}
|
||||||
return asynError;
|
return asynError;
|
||||||
@ -208,14 +218,14 @@ asynStatus EL734Controller::transactController(int axisNo,char command[COMLEN],
|
|||||||
// These are the EL734Axis methods
|
// These are the EL734Axis methods
|
||||||
|
|
||||||
/** Creates a new EL734Axis object.
|
/** Creates a new EL734Axis object.
|
||||||
* \param[in] pC Pointer to the EL734Controller to which this axis belongs.
|
* \param[in] pC Pointer to the EL734Controller to which this axis belongs.
|
||||||
* \param[in] axisNo Index number of this axis, range 0 to pC->numAxes_-1.
|
* \param[in] axisNo Index number of this axis, range 0 to pC->numAxes_-1.
|
||||||
*
|
*
|
||||||
* Initializes register numbers, etc.
|
* Initializes register numbers, etc.
|
||||||
*/
|
*/
|
||||||
EL734Axis::EL734Axis(EL734Controller *pC, int axisNo)
|
EL734Axis::EL734Axis(EL734Controller *pC, int axisNo)
|
||||||
: SINQAxis(pC, axisNo), pC_(pC)
|
: SINQAxis(pC, axisNo), pC_(pC)
|
||||||
{
|
{
|
||||||
char command[COMLEN], reply[COMLEN];
|
char command[COMLEN], reply[COMLEN];
|
||||||
asynStatus status;
|
asynStatus status;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
@ -224,53 +234,63 @@ EL734Axis::EL734Axis(EL734Controller *pC, int axisNo)
|
|||||||
/*
|
/*
|
||||||
get the hardware limits from the controller
|
get the hardware limits from the controller
|
||||||
*/
|
*/
|
||||||
sprintf(command,"H %d",axisNo_);
|
sprintf(command, "H %d", axisNo_);
|
||||||
status = pC_->transactController(axisNo_,command,reply);
|
status = pC_->transactController(axisNo_, command, reply);
|
||||||
if(status == asynSuccess){
|
if (status == asynSuccess)
|
||||||
count = sscanf(reply,"%f %f",&low, &high);
|
{
|
||||||
if(count >= 2){
|
count = sscanf(reply, "%f %f", &low, &high);
|
||||||
pC_->setDoubleParam(axisNo_,pC_->motorLowLimit_,low);
|
if (count >= 2)
|
||||||
pC_->setDoubleParam(axisNo_,pC_->motorHighLimit_,high);
|
{
|
||||||
callParamCallbacks();
|
pC_->setDoubleParam(axisNo_, pC_->motorLowLimit_, low);
|
||||||
} else {
|
pC_->setDoubleParam(axisNo_, pC_->motorHighLimit_, high);
|
||||||
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
|
callParamCallbacks();
|
||||||
"Bad response - %s - requesting limits at axis %d", reply, axisNo_);
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
|
||||||
|
"Bad response - %s - requesting limits at axis %d", reply, axisNo_);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
|
|
||||||
"Failed to read limits at axis %d", axisNo_);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
|
||||||
|
"Failed to read limits at axis %d", axisNo_);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
oredMSR contains the axis status from the previous poll. The initial value
|
||||||
|
1 means that the axis is not moving and has no errors.
|
||||||
|
*/
|
||||||
|
oredMSR = 1;
|
||||||
next_poll = -1;
|
next_poll = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** Reports on status of the axis
|
/** Reports on status of the axis
|
||||||
* \param[in] fp The file pointer on which report information will be written
|
* \param[in] fp The file pointer on which report information will be written
|
||||||
* \param[in] level The level of report detail desired
|
* \param[in] level The level of report detail desired
|
||||||
*
|
*
|
||||||
* After printing device-specific information calls asynMotorAxis::report()
|
* After printing device-specific information calls asynMotorAxis::report()
|
||||||
*/
|
*/
|
||||||
void EL734Axis::report(FILE *fp, int level)
|
void EL734Axis::report(FILE *fp, int level)
|
||||||
{
|
{
|
||||||
if (level > 0) {
|
if (level > 0)
|
||||||
|
{
|
||||||
fprintf(fp, " axis %d\n",
|
fprintf(fp, " axis %d\n",
|
||||||
axisNo_);
|
axisNo_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call the base class method
|
// Call the base class method
|
||||||
//asynMotorAxis::report(fp, level);
|
// asynMotorAxis::report(fp, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
asynStatus EL734Axis::move(double position, int relative, double minVelocity, double maxVelocity, double acceleration)
|
asynStatus EL734Axis::move(double position, int relative, double minVelocity, double maxVelocity, double acceleration)
|
||||||
{
|
{
|
||||||
asynStatus status;
|
asynStatus status;
|
||||||
//static const char *functionName = "EL734Axis::move";
|
// static const char *functionName = "EL734Axis::move";
|
||||||
char command[COMLEN], reply[COMLEN];
|
char command[COMLEN], reply[COMLEN];
|
||||||
|
|
||||||
// status = sendAccelAndVelocity(acceleration, maxVelocity);
|
// status = sendAccelAndVelocity(acceleration, maxVelocity);
|
||||||
|
|
||||||
errlogPrintf("minVelocity = %f, maxVelocity = %f\n", minVelocity, maxVelocity);
|
errlogPrintf("minVelocity = %f, maxVelocity = %f\n", minVelocity, maxVelocity);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -279,16 +299,16 @@ asynStatus EL734Axis::move(double position, int relative, double minVelocity, do
|
|||||||
sprintf(command, "J %d %d", axisNo_, (int)maxVelocity);
|
sprintf(command, "J %d %d", axisNo_, (int)maxVelocity);
|
||||||
status = pC_->transactController(axisNo_, command, reply);
|
status = pC_->transactController(axisNo_, command, reply);
|
||||||
|
|
||||||
if (relative) {
|
if (relative)
|
||||||
|
{
|
||||||
position += this->position;
|
position += this->position;
|
||||||
}
|
}
|
||||||
oredMSR = 0;
|
|
||||||
homing = 0;
|
homing = 0;
|
||||||
errorReported = 0;
|
errorReported = 0;
|
||||||
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
|
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
|
||||||
"Starting axis %d with destination %f", axisNo_,position/1000);
|
"Starting axis %d with destination %f", axisNo_, position / 1000);
|
||||||
sprintf(command, "p %d %.3f", axisNo_, position/1000.);
|
sprintf(command, "p %d %.3f", axisNo_, position / 1000.);
|
||||||
status = pC_->transactController(axisNo_,command,reply);
|
status = pC_->transactController(axisNo_, command, reply);
|
||||||
setIntegerParam(pC_->motorStatusProblem_, false);
|
setIntegerParam(pC_->motorStatusProblem_, false);
|
||||||
updateMsgTxtFromDriver("");
|
updateMsgTxtFromDriver("");
|
||||||
next_poll = -1;
|
next_poll = -1;
|
||||||
@ -298,7 +318,7 @@ asynStatus EL734Axis::move(double position, int relative, double minVelocity, do
|
|||||||
asynStatus EL734Axis::home(double minVelocity, double maxVelocity, double acceleration, int forwards)
|
asynStatus EL734Axis::home(double minVelocity, double maxVelocity, double acceleration, int forwards)
|
||||||
{
|
{
|
||||||
asynStatus status;
|
asynStatus status;
|
||||||
//static const char *functionName = "EL734Axis::home";
|
// static const char *functionName = "EL734Axis::home";
|
||||||
char command[COMLEN], reply[COMLEN];
|
char command[COMLEN], reply[COMLEN];
|
||||||
|
|
||||||
// status = sendAccelAndVelocity(acceleration, maxVelocity);
|
// status = sendAccelAndVelocity(acceleration, maxVelocity);
|
||||||
@ -309,52 +329,55 @@ asynStatus EL734Axis::home(double minVelocity, double maxVelocity, double accele
|
|||||||
|
|
||||||
sprintf(command, "R %d", axisNo_);
|
sprintf(command, "R %d", axisNo_);
|
||||||
homing = 1;
|
homing = 1;
|
||||||
next_poll= -1;
|
next_poll = -1;
|
||||||
status = pC_->transactController(axisNo_,command,reply);
|
status = pC_->transactController(axisNo_, command, reply);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
asynStatus EL734Axis::moveVelocity(double minVelocity, double maxVelocity, double acceleration)
|
asynStatus EL734Axis::moveVelocity(double minVelocity, double maxVelocity, double acceleration)
|
||||||
{
|
{
|
||||||
asynStatus status;
|
asynStatus status;
|
||||||
//static const char *functionName = "EL734Axis::moveVelocity";
|
// static const char *functionName = "EL734Axis::moveVelocity";
|
||||||
char command[COMLEN], reply[COMLEN];
|
char command[COMLEN], reply[COMLEN];
|
||||||
|
|
||||||
// asynPrint(pasynUser_, ASYN_TRACE_FLOW,
|
// asynPrint(pasynUser_, ASYN_TRACE_FLOW,
|
||||||
// "%s: minVelocity=%f, maxVelocity=%f, acceleration=%f\n",
|
// "%s: minVelocity=%f, maxVelocity=%f, acceleration=%f\n",
|
||||||
// functionName, minVelocity, maxVelocity, acceleration);
|
// functionName, minVelocity, maxVelocity, acceleration);
|
||||||
|
|
||||||
|
|
||||||
errorReported = 0;
|
errorReported = 0;
|
||||||
if (maxVelocity > 0.) {
|
if (maxVelocity > 0.)
|
||||||
|
{
|
||||||
/* This is a positive move */
|
/* This is a positive move */
|
||||||
sprintf(command, "FF %d", axisNo_);
|
sprintf(command, "FF %d", axisNo_);
|
||||||
} else {
|
|
||||||
/* This is a negative move */
|
|
||||||
sprintf(command, "FB %d", axisNo_);
|
|
||||||
}
|
}
|
||||||
status = pC_->transactController(axisNo_,command,reply);
|
else
|
||||||
|
{
|
||||||
|
/* This is a negative move */
|
||||||
|
sprintf(command, "FB %d", axisNo_);
|
||||||
|
}
|
||||||
|
status = pC_->transactController(axisNo_, command, reply);
|
||||||
setIntegerParam(pC_->motorStatusProblem_, false);
|
setIntegerParam(pC_->motorStatusProblem_, false);
|
||||||
updateMsgTxtFromDriver("");
|
updateMsgTxtFromDriver("");
|
||||||
next_poll = -1;
|
next_poll = -1;
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
asynStatus EL734Axis::stop(double acceleration )
|
asynStatus EL734Axis::stop(double acceleration)
|
||||||
{
|
{
|
||||||
asynStatus status = asynSuccess;
|
asynStatus status = asynSuccess;
|
||||||
//static const char *functionName = "EL734Axis::stop";
|
// static const char *functionName = "EL734Axis::stop";
|
||||||
char command[COMLEN], reply[COMLEN];
|
char command[COMLEN], reply[COMLEN];
|
||||||
bool moving = false;
|
bool moving = false;
|
||||||
|
|
||||||
this->poll(&moving);
|
this->poll(&moving);
|
||||||
if(moving && errorReported == 0){
|
if (moving && errorReported == 0)
|
||||||
sprintf(command, "S %d", axisNo_);
|
{
|
||||||
status = pC_->transactController(axisNo_,command,reply);
|
sprintf(command, "S %d", axisNo_);
|
||||||
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR, "Sent STOP on Axis %d\n", axisNo_);
|
status = pC_->transactController(axisNo_, command, reply);
|
||||||
updateMsgTxtFromDriver("Axis interrupted");
|
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR, "Sent STOP on Axis %d\n", axisNo_);
|
||||||
errorReported = 1;
|
updateMsgTxtFromDriver("Axis interrupted");
|
||||||
}
|
errorReported = 1;
|
||||||
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@ -362,11 +385,11 @@ asynStatus EL734Axis::stop(double acceleration )
|
|||||||
asynStatus EL734Axis::setPosition(double position)
|
asynStatus EL734Axis::setPosition(double position)
|
||||||
{
|
{
|
||||||
asynStatus status;
|
asynStatus status;
|
||||||
//static const char *functionName = "EL734Axis::setPosition";
|
// static const char *functionName = "EL734Axis::setPosition";
|
||||||
char command[COMLEN], reply[COMLEN];
|
char command[COMLEN], reply[COMLEN];
|
||||||
|
|
||||||
sprintf(command, "U %d %f", axisNo_, position/1000.);
|
sprintf(command, "U %d %f", axisNo_, position / 1000.);
|
||||||
status = pC_->transactController(axisNo_,command,reply);
|
status = pC_->transactController(axisNo_, command, reply);
|
||||||
next_poll = -1;
|
next_poll = -1;
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
@ -374,8 +397,8 @@ asynStatus EL734Axis::setPosition(double position)
|
|||||||
|
|
||||||
asynStatus EL734Axis::setClosedLoop(bool closedLoop)
|
asynStatus EL734Axis::setClosedLoop(bool closedLoop)
|
||||||
{
|
{
|
||||||
//static const char *functionName = "EL734Axis::setClosedLoop";
|
// static const char *functionName = "EL734Axis::setClosedLoop";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This belongs into the Kingdom of Electronics.
|
This belongs into the Kingdom of Electronics.
|
||||||
We do not do this.
|
We do not do this.
|
||||||
@ -385,45 +408,50 @@ asynStatus EL734Axis::setClosedLoop(bool closedLoop)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Polls the axis.
|
/** Polls the axis.
|
||||||
* This function reads the motor position, the limit status, the home status, the moving status,
|
* This function reads the motor position, the limit status, the home status, the moving status,
|
||||||
* and the drive power-on status.
|
* and the drive power-on status.
|
||||||
* It calls setIntegerParam() and setDoubleParam() for each item that it polls,
|
* It calls setIntegerParam() and setDoubleParam() for each item that it polls,
|
||||||
* and then calls callParamCallbacks() at the end.
|
* and then calls callParamCallbacks() at the end.
|
||||||
* \param[out] moving A flag that is set indicating that the axis is moving (true) or done (false). */
|
* \param[out] moving A flag that is set indicating that the axis is moving (true) or done (false). */
|
||||||
asynStatus EL734Axis::poll(bool *moving)
|
asynStatus EL734Axis::poll(bool *moving)
|
||||||
{
|
{
|
||||||
int msr, count;
|
int msr, count;
|
||||||
float low, high;
|
float low, high;
|
||||||
asynStatus comStatus = asynSuccess;
|
asynStatus comStatus = asynSuccess;
|
||||||
char command[COMLEN], reply[COMLEN], errTxt[256];
|
char command[COMLEN], reply[COMLEN], errTxt[256];
|
||||||
|
|
||||||
// protect against excessive polling
|
// protect against excessive polling
|
||||||
if(time(NULL) < next_poll){
|
if (time(NULL) < next_poll)
|
||||||
|
{
|
||||||
*moving = false;
|
*moving = false;
|
||||||
return asynSuccess;
|
return asynSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
// read hardware limits
|
// read hardware limits
|
||||||
sprintf(command,"H %d",axisNo_);
|
sprintf(command, "H %d", axisNo_);
|
||||||
comStatus = pC_->transactController(axisNo_,command,reply);
|
comStatus = pC_->transactController(axisNo_, command, reply);
|
||||||
if(comStatus == asynSuccess){
|
if (comStatus == asynSuccess)
|
||||||
count = sscanf(reply,"%f %f",&low, &high);
|
{
|
||||||
if(count >= 2){
|
count = sscanf(reply, "%f %f", &low, &high);
|
||||||
pC_->setDoubleParam(axisNo_,pC_->motorLowLimit_,low);
|
if (count >= 2)
|
||||||
pC_->setDoubleParam(axisNo_,pC_->motorHighLimit_,high);
|
{
|
||||||
callParamCallbacks();
|
pC_->setDoubleParam(axisNo_, pC_->motorLowLimit_, low);
|
||||||
|
pC_->setDoubleParam(axisNo_, pC_->motorHighLimit_, high);
|
||||||
|
callParamCallbacks();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the current motor position
|
// Read the current motor position
|
||||||
setIntegerParam(pC_->motorStatusProblem_,false);
|
setIntegerParam(pC_->motorStatusProblem_, false);
|
||||||
sprintf(command,"u %d", axisNo_);
|
sprintf(command, "u %d", axisNo_);
|
||||||
comStatus = pC_->transactController(axisNo_,command,reply);
|
comStatus = pC_->transactController(axisNo_, command, reply);
|
||||||
if(comStatus == asynError){
|
if (comStatus == asynError)
|
||||||
setIntegerParam(pC_->motorStatusProblem_,true);
|
{
|
||||||
|
setIntegerParam(pC_->motorStatusProblem_, true);
|
||||||
goto skip;
|
goto skip;
|
||||||
}
|
}
|
||||||
if(strstr(reply,"*ES") != NULL){
|
if (strstr(reply, "*ES") != NULL)
|
||||||
|
{
|
||||||
*moving = false;
|
*moving = false;
|
||||||
setIntegerParam(pC_->motorStatusDone_, true);
|
setIntegerParam(pC_->motorStatusDone_, true);
|
||||||
setIntegerParam(pC_->motorStatusProblem_, true);
|
setIntegerParam(pC_->motorStatusProblem_, true);
|
||||||
@ -431,70 +459,86 @@ asynStatus EL734Axis::poll(bool *moving)
|
|||||||
updateMsgTxtFromDriver("Emergency Stop Engaged");
|
updateMsgTxtFromDriver("Emergency Stop Engaged");
|
||||||
comStatus = asynError;
|
comStatus = asynError;
|
||||||
goto skip;
|
goto skip;
|
||||||
} else if(strstr(reply,"?BSY") != NULL){
|
}
|
||||||
|
else if (strstr(reply, "?BSY") != NULL)
|
||||||
|
{
|
||||||
*moving = true;
|
*moving = true;
|
||||||
setIntegerParam(pC_->motorStatusDone_, false);
|
setIntegerParam(pC_->motorStatusDone_, false);
|
||||||
goto skip;
|
goto skip;
|
||||||
}
|
}
|
||||||
count = sscanf(reply,"%lf", &position);
|
count = sscanf(reply, "%lf", &position);
|
||||||
if(count != 1) {
|
if (count != 1)
|
||||||
if(!homing) {
|
{
|
||||||
snprintf(errTxt,sizeof(errTxt),"Bad reply %s when reading position for %d", reply, axisNo_);
|
if (!homing)
|
||||||
|
{
|
||||||
|
snprintf(errTxt, sizeof(errTxt), "Bad reply %s when reading position for %d", reply, axisNo_);
|
||||||
setIntegerParam(pC_->motorStatusProblem_, true);
|
setIntegerParam(pC_->motorStatusProblem_, true);
|
||||||
errorReported = 1;
|
errorReported = 1;
|
||||||
updateMsgTxtFromDriver(errTxt);
|
updateMsgTxtFromDriver(errTxt);
|
||||||
comStatus = asynError;
|
comStatus = asynError;
|
||||||
goto skip;
|
goto skip;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
|
else
|
||||||
"Axis %d, reply %s, position %lf\n", axisNo_, reply, position);
|
{
|
||||||
setDoubleParam(pC_->motorPosition_, position*1000);
|
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
|
||||||
//setDoubleParam(pC_->motorEncoderPosition_, position);
|
"Axis %d, reply %s, position %lf\n", axisNo_, reply, position);
|
||||||
|
setDoubleParam(pC_->motorPosition_, position * 1000);
|
||||||
|
// setDoubleParam(pC_->motorEncoderPosition_, position);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the moving status of this motor
|
// Read the moving status of this motor
|
||||||
sprintf(command,"msr %d",axisNo_);
|
sprintf(command, "msr %d", axisNo_);
|
||||||
comStatus = pC_->transactController(axisNo_,command,reply);
|
comStatus = pC_->transactController(axisNo_, command, reply);
|
||||||
if(comStatus == asynError){
|
if (comStatus == asynError)
|
||||||
setIntegerParam(pC_->motorStatusProblem_,true);
|
{
|
||||||
|
setIntegerParam(pC_->motorStatusProblem_, true);
|
||||||
goto skip;
|
goto skip;
|
||||||
}
|
}
|
||||||
sscanf(reply,"%x",&msr);
|
sscanf(reply, "%x", &msr);
|
||||||
|
|
||||||
//errlogPrintf("Axis %d, reply %s, msr %d, oredmsr = %d, position = %lf\n",
|
// errlogPrintf("Axis %d, reply %s, msr %d, oredmsr = %d, position = %lf\n",
|
||||||
// axisNo_, reply, msr, oredMSR, position);
|
// axisNo_, reply, msr, oredMSR, position);
|
||||||
|
|
||||||
oredMSR |= msr;
|
oredMSR |= msr;
|
||||||
if( (msr & 0x1) == 0){
|
if ((msr & 0x1) == 0)
|
||||||
|
{
|
||||||
// done: check for trouble
|
// done: check for trouble
|
||||||
//errlogPrintf("Axis %d finished\n", axisNo_);
|
// errlogPrintf("Axis %d finished\n", axisNo_);
|
||||||
*moving = false;
|
*moving = false;
|
||||||
setIntegerParam(pC_->motorStatusDone_, true);
|
setIntegerParam(pC_->motorStatusDone_, true);
|
||||||
|
|
||||||
next_poll = time(NULL)+IDLEPOLL;
|
next_poll = time(NULL) + IDLEPOLL;
|
||||||
if(oredMSR & 0x10){
|
if (oredMSR & 0x10)
|
||||||
|
{
|
||||||
setIntegerParam(pC_->motorStatusLowLimit_, true);
|
setIntegerParam(pC_->motorStatusLowLimit_, true);
|
||||||
updateMsgTxtFromDriver("Lower Limit Hit");
|
updateMsgTxtFromDriver("Lower Limit Hit");
|
||||||
errorReported = 1;
|
errorReported = 1;
|
||||||
comStatus = asynError;
|
comStatus = asynError;
|
||||||
goto skip;
|
goto skip;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
setIntegerParam(pC_->motorStatusLowLimit_, false);
|
setIntegerParam(pC_->motorStatusLowLimit_, false);
|
||||||
}
|
}
|
||||||
if(oredMSR & 0x20){
|
if (oredMSR & 0x20)
|
||||||
|
{
|
||||||
setIntegerParam(pC_->motorStatusHighLimit_, true);
|
setIntegerParam(pC_->motorStatusHighLimit_, true);
|
||||||
updateMsgTxtFromDriver("Upper Limit Hit");
|
updateMsgTxtFromDriver("Upper Limit Hit");
|
||||||
errorReported = 1;
|
errorReported = 1;
|
||||||
comStatus = asynError;
|
comStatus = asynError;
|
||||||
goto skip;
|
goto skip;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
setIntegerParam(pC_->motorStatusHighLimit_, false);
|
setIntegerParam(pC_->motorStatusHighLimit_, false);
|
||||||
}
|
}
|
||||||
if(homing){
|
if (homing)
|
||||||
|
{
|
||||||
setIntegerParam(pC_->motorStatusAtHome_, true);
|
setIntegerParam(pC_->motorStatusAtHome_, true);
|
||||||
}
|
}
|
||||||
if(oredMSR & 0x1000){
|
if (oredMSR & 0x1000)
|
||||||
|
{
|
||||||
setIntegerParam(pC_->motorStatusProblem_, true);
|
setIntegerParam(pC_->motorStatusProblem_, true);
|
||||||
// errlogPrintf("Detected air cushion error on %d", axisNo_);
|
// errlogPrintf("Detected air cushion error on %d", axisNo_);
|
||||||
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR, "Air cushion problem on %d", axisNo_);
|
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR, "Air cushion problem on %d", axisNo_);
|
||||||
@ -503,7 +547,8 @@ asynStatus EL734Axis::poll(bool *moving)
|
|||||||
comStatus = asynError;
|
comStatus = asynError;
|
||||||
goto skip;
|
goto skip;
|
||||||
}
|
}
|
||||||
if(oredMSR & 0x100){
|
if (oredMSR & 0x100)
|
||||||
|
{
|
||||||
setIntegerParam(pC_->motorStatusProblem_, true);
|
setIntegerParam(pC_->motorStatusProblem_, true);
|
||||||
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR, "Run failure at %d", axisNo_);
|
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR, "Run failure at %d", axisNo_);
|
||||||
updateMsgTxtFromDriver("Run failure");
|
updateMsgTxtFromDriver("Run failure");
|
||||||
@ -511,7 +556,8 @@ asynStatus EL734Axis::poll(bool *moving)
|
|||||||
errorReported = 1;
|
errorReported = 1;
|
||||||
goto skip;
|
goto skip;
|
||||||
}
|
}
|
||||||
if(oredMSR & 0x400){
|
if (oredMSR & 0x400)
|
||||||
|
{
|
||||||
setIntegerParam(pC_->motorStatusProblem_, true);
|
setIntegerParam(pC_->motorStatusProblem_, true);
|
||||||
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR, "Positioning failure at %d", axisNo_);
|
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR, "Positioning failure at %d", axisNo_);
|
||||||
updateMsgTxtFromDriver("Positioning failure");
|
updateMsgTxtFromDriver("Positioning failure");
|
||||||
@ -519,17 +565,20 @@ asynStatus EL734Axis::poll(bool *moving)
|
|||||||
errorReported = 1;
|
errorReported = 1;
|
||||||
goto skip;
|
goto skip;
|
||||||
}
|
}
|
||||||
if(oredMSR & 0x200 || oredMSR & 0x80) {
|
if (oredMSR & 0x200 || oredMSR & 0x80)
|
||||||
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_WARNING, "Positioning fault at %d", axisNo_);
|
{
|
||||||
}
|
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_WARNING, "Positioning fault at %d", axisNo_);
|
||||||
|
}
|
||||||
setIntegerParam(pC_->motorStatusProblem_, false);
|
setIntegerParam(pC_->motorStatusProblem_, false);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
*moving = true;
|
*moving = true;
|
||||||
next_poll = -1;
|
next_poll = -1;
|
||||||
setIntegerParam(pC_->motorStatusDone_, false);
|
setIntegerParam(pC_->motorStatusDone_, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
skip:
|
skip:
|
||||||
callParamCallbacks();
|
callParamCallbacks();
|
||||||
return comStatus;
|
return comStatus;
|
||||||
}
|
}
|
||||||
@ -538,9 +587,9 @@ asynStatus EL734Axis::poll(bool *moving)
|
|||||||
static const iocshArg EL734CreateControllerArg0 = {"Port name", iocshArgString};
|
static const iocshArg EL734CreateControllerArg0 = {"Port name", iocshArgString};
|
||||||
static const iocshArg EL734CreateControllerArg1 = {"EL734 port name", iocshArgString};
|
static const iocshArg EL734CreateControllerArg1 = {"EL734 port name", iocshArgString};
|
||||||
static const iocshArg EL734CreateControllerArg2 = {"Number of axes", iocshArgInt};
|
static const iocshArg EL734CreateControllerArg2 = {"Number of axes", iocshArgInt};
|
||||||
static const iocshArg * const EL734CreateControllerArgs[] = {&EL734CreateControllerArg0,
|
static const iocshArg *const EL734CreateControllerArgs[] = {&EL734CreateControllerArg0,
|
||||||
&EL734CreateControllerArg1,
|
&EL734CreateControllerArg1,
|
||||||
&EL734CreateControllerArg2};
|
&EL734CreateControllerArg2};
|
||||||
static const iocshFuncDef EL734CreateControllerDef = {"EL734CreateController", 3, EL734CreateControllerArgs};
|
static const iocshFuncDef EL734CreateControllerDef = {"EL734CreateController", 3, EL734CreateControllerArgs};
|
||||||
static void EL734CreateContollerCallFunc(const iocshArgBuf *args)
|
static void EL734CreateContollerCallFunc(const iocshArgBuf *args)
|
||||||
{
|
{
|
||||||
@ -552,6 +601,7 @@ static void EL734Register(void)
|
|||||||
iocshRegister(&EL734CreateControllerDef, EL734CreateContollerCallFunc);
|
iocshRegister(&EL734CreateControllerDef, EL734CreateContollerCallFunc);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" {
|
extern "C"
|
||||||
epicsExportRegistrar(EL734Register);
|
{
|
||||||
|
epicsExportRegistrar(EL734Register);
|
||||||
}
|
}
|
||||||
|
@ -28,31 +28,32 @@ public:
|
|||||||
asynStatus setClosedLoop(bool closedLoop);
|
asynStatus setClosedLoop(bool closedLoop);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EL734Controller *pC_; /**< Pointer to the asynMotorController to which this axis belongs.
|
EL734Controller *pC_; /**< Pointer to the asynMotorController to which this axis belongs.
|
||||||
* Abbreviated because it is used very frequently */
|
* Abbreviated because it is used very frequently */
|
||||||
int oredMSR;
|
int oredMSR;
|
||||||
double position;
|
double position;
|
||||||
int homing;
|
int homing;
|
||||||
time_t next_poll;
|
time_t next_poll;
|
||||||
int errorReported;
|
int errorReported;
|
||||||
|
|
||||||
friend class EL734Controller;
|
friend class EL734Controller;
|
||||||
};
|
};
|
||||||
|
|
||||||
class EL734Controller : public SINQController {
|
class EL734Controller : public SINQController
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
EL734Controller(const char *portName, const char *EL734PortName, int numAxes);
|
EL734Controller(const char *portName, const char *EL734PortName, int numAxes);
|
||||||
|
|
||||||
void report(FILE *fp, int level);
|
void report(FILE *fp, int level);
|
||||||
EL734Axis* getAxis(asynUser *pasynUser);
|
EL734Axis *getAxis(asynUser *pasynUser);
|
||||||
EL734Axis* getAxis(int axisNo);
|
EL734Axis *getAxis(int axisNo);
|
||||||
|
|
||||||
friend class EL734Axis;
|
friend class EL734Axis;
|
||||||
private:
|
|
||||||
asynUser *pasynUserController_;
|
|
||||||
|
|
||||||
asynStatus transactController(int axis, char command[COMLEN], char reply[COMLEN]);
|
private:
|
||||||
|
asynUser *pasynUserController_;
|
||||||
|
|
||||||
void switchRemote();
|
asynStatus transactController(int axis, char command[COMLEN], char reply[COMLEN]);
|
||||||
|
|
||||||
|
void switchRemote();
|
||||||
};
|
};
|
||||||
|
@ -32,6 +32,10 @@
|
|||||||
*
|
*
|
||||||
* Mark Koennecke, June 2023
|
* Mark Koennecke, June 2023
|
||||||
*
|
*
|
||||||
|
* Added driver for GirderAxis
|
||||||
|
*
|
||||||
|
* Stefan Mathis, July 2024
|
||||||
|
*
|
||||||
********************************************/
|
********************************************/
|
||||||
|
|
||||||
#include <epicsExit.h>
|
#include <epicsExit.h>
|
||||||
@ -1479,4 +1483,275 @@ asynStatus AmorDetectorAxis::poll(bool *moving)
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GirderAxis::GirderAxis(pmacController *pController, int axisNo)
|
||||||
|
: pmacV3Axis(pController, axisNo){
|
||||||
|
|
||||||
|
// GirderAxis expects a pmacV3Controller. Therefore it is checked whether the pointer pController can be cast
|
||||||
|
// to this object type. If this is not possible, the user made an error in the configuration files. This is documented
|
||||||
|
// in a corresponding error; after that, an exception is thrown to avoid returning an "illegal" instance of GirderAxis.
|
||||||
|
pmacV3Controller* pV3Controller = dynamic_cast<pmacV3Controller*>(pController);
|
||||||
|
if (pV3Controller == nullptr) {
|
||||||
|
errlogPrintf("A GirderAxis instance needs a pmacV3Controller. Please check the configuration files.");
|
||||||
|
throw std::invalid_argument("A GirderAxis instance needs a pmacV3Controller. Please check the configuration files.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initial values for member variables
|
||||||
|
next_poll = -1;
|
||||||
|
previous_position_ = 0.0;
|
||||||
|
previous_direction_ = 0;
|
||||||
|
status6Time = 0;
|
||||||
|
statusPos = 0.0;
|
||||||
|
homing = 0;
|
||||||
|
axisErrorCount = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
asynStatus GirderAxis::move(double position, int relative, double min_velocity, double max_velocity, double acceleration) {
|
||||||
|
|
||||||
|
// If the axis is not enabled, do nothing
|
||||||
|
if(!IsEnable) {
|
||||||
|
updateMsgTxtFromDriver("Error: axis disabled");
|
||||||
|
return asynError;
|
||||||
|
}
|
||||||
|
|
||||||
|
// =======================================
|
||||||
|
// Local variable declaration
|
||||||
|
|
||||||
|
asynStatus status = asynError;
|
||||||
|
char command[pC_->PMAC_MAXBUF_] = {0};
|
||||||
|
char response[pC_->PMAC_MAXBUF_] = {0};
|
||||||
|
double realPosition = 0;
|
||||||
|
|
||||||
|
// =======================================
|
||||||
|
|
||||||
|
updateMsgTxtFromDriver("");
|
||||||
|
static const char *functionName = "GirderAxis::move";
|
||||||
|
pC_->debugFlow(functionName);
|
||||||
|
|
||||||
|
if (relative) {
|
||||||
|
realPosition = previous_position_ + position / MULT;
|
||||||
|
} else {
|
||||||
|
realPosition = position / MULT;
|
||||||
|
}
|
||||||
|
startTime = time(NULL);
|
||||||
|
status6Time = 0;
|
||||||
|
starting = 1;
|
||||||
|
|
||||||
|
// Set target position
|
||||||
|
snprintf(command, sizeof(command), "Q251=%f", realPosition);
|
||||||
|
status = pC_->lowLevelWriteRead(axisNo_, command, response);
|
||||||
|
if (status == asynError) {
|
||||||
|
updateMsgTxtFromDriver("Error: Could not set target position");
|
||||||
|
return asynError;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start motion
|
||||||
|
snprintf(command, sizeof(command), "P150=1");
|
||||||
|
status = pC_->lowLevelWriteRead(axisNo_, command, response);
|
||||||
|
if (status == asynError) {
|
||||||
|
updateMsgTxtFromDriver("Error: Could not start motion");
|
||||||
|
return asynError;
|
||||||
|
}
|
||||||
|
|
||||||
|
next_poll = -1;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
asynStatus GirderAxis::stop(double acceleration) {
|
||||||
|
|
||||||
|
// =======================================
|
||||||
|
// Local variable declaration
|
||||||
|
|
||||||
|
asynStatus status = asynSuccess;
|
||||||
|
static const char *functionName = "GirderAxis::stop";
|
||||||
|
bool moving = false;
|
||||||
|
char command[pC_->PMAC_MAXBUF_] = {0};
|
||||||
|
char response[pC_->PMAC_MAXBUF_] = {0};
|
||||||
|
|
||||||
|
// =======================================
|
||||||
|
|
||||||
|
pC_->debugFlow(functionName);
|
||||||
|
this->poll(&moving);
|
||||||
|
|
||||||
|
if(moving) {
|
||||||
|
// only send a stop when actually moving
|
||||||
|
snprintf(command, sizeof(command), "P150=8");
|
||||||
|
status = pC_->lowLevelWriteRead(axisNo_, command, response);
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
asynStatus GirderAxis::poll(bool *moving) {
|
||||||
|
|
||||||
|
// =======================================
|
||||||
|
// Local variable declaration
|
||||||
|
|
||||||
|
asynStatus status = asynSuccess;
|
||||||
|
static const char *functionName = "GirderAxis::poll";
|
||||||
|
char command[pC_->PMAC_MAXBUF_] = {0};
|
||||||
|
char response[pC_->PMAC_MAXBUF_] = {0};
|
||||||
|
char message[132], *axMessage;
|
||||||
|
double position = 0;
|
||||||
|
int moving_to_position = 0, nvals = 0, axisProblemFlag = 0, axStat = 0, axError = 0, isEnabled = 1;
|
||||||
|
asynStatus st;
|
||||||
|
|
||||||
|
// =======================================
|
||||||
|
|
||||||
|
// Check for girder axis specific errors
|
||||||
|
snprintf(command, sizeof(command), "P159");
|
||||||
|
status = pC_->lowLevelWriteRead(axisNo_, command, response);
|
||||||
|
sscanf(response, "P159=%d", &axError);
|
||||||
|
switch(axError) {
|
||||||
|
case 1:
|
||||||
|
snprintf(message, sizeof(message), "PMAC: %s on %d",
|
||||||
|
"Axis not switched on", axisNo_);
|
||||||
|
updateMsgTxtFromDriver(message);
|
||||||
|
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR, "%s\n", message);
|
||||||
|
axisProblemFlag = 1;
|
||||||
|
isEnabled = 0;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
snprintf(message, sizeof(message), "PMAC: %s on %d",
|
||||||
|
"Axis not ready for new command", axisNo_);
|
||||||
|
updateMsgTxtFromDriver(message);
|
||||||
|
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR, "%s\n", message);
|
||||||
|
axisProblemFlag = 1;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
snprintf(message, sizeof(message), "PMAC: %s on %d",
|
||||||
|
"Axis 1 ERROR during motion", axisNo_);
|
||||||
|
updateMsgTxtFromDriver(message);
|
||||||
|
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR, "%s\n", message);
|
||||||
|
axisProblemFlag = 1;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
snprintf(message, sizeof(message), "PMAC: %s on %d",
|
||||||
|
"Axis 2 ERROR during motion", axisNo_);
|
||||||
|
updateMsgTxtFromDriver(message);
|
||||||
|
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR, "%s\n", message);
|
||||||
|
axisProblemFlag = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
st = setIntegerParam(pC_->motorStatusProblem_, axisProblemFlag);
|
||||||
|
status = status > st ? status : st;
|
||||||
|
|
||||||
|
// Downcast the pointer pmacController to pmacV3Controller in a typesafe manner
|
||||||
|
pmacV3Controller* p3C_ = dynamic_cast<pmacV3Controller*>(pC_);
|
||||||
|
if (p3C_ == nullptr) {
|
||||||
|
errlogPrintf("A GirderAxis instance needs a pmacV3Controller. Please check the configuration files.");
|
||||||
|
throw std::invalid_argument("A GirderAxis instance needs a pmacV3Controller. Please check the configuration files.");
|
||||||
|
}
|
||||||
|
setIntegerParam(p3C_->axisEnabled_, isEnabled);
|
||||||
|
|
||||||
|
st = setIntegerParam(p3C_->enableAxis_, isEnabled);
|
||||||
|
status = status > st ? status : st;
|
||||||
|
|
||||||
|
int direction = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
In GirderAxis::move, the user input is scaled by /MULT. Hence, the output of
|
||||||
|
Qxx10 needs to be scaled by *MULT
|
||||||
|
*/
|
||||||
|
st = setDoubleParam(pC_->motorPosition_, position * MULT);
|
||||||
|
status = status > st ? status : st;
|
||||||
|
st = setDoubleParam(pC_->motorEncoderPosition_, position * MULT);
|
||||||
|
status = status > st ? status : st;
|
||||||
|
|
||||||
|
// Calculate the current (or last) movement direction
|
||||||
|
if ((position - previous_position_) > 0) {
|
||||||
|
direction = 1;
|
||||||
|
} else if (position - previous_position_ == 0.0) {
|
||||||
|
direction = previous_direction_;
|
||||||
|
} else {
|
||||||
|
direction = 0;
|
||||||
|
}
|
||||||
|
st = setIntegerParam(pC_->motorStatusDirection_, direction);
|
||||||
|
status = status > st ? status : st;
|
||||||
|
|
||||||
|
// Store the position which was read out from the hardware together with the calculated direction for the next poll
|
||||||
|
previous_position_ = position;
|
||||||
|
previous_direction_ = direction;
|
||||||
|
|
||||||
|
// Is the axis currently moving?
|
||||||
|
snprintf(command, sizeof(command), "P154");
|
||||||
|
status = pC_->lowLevelWriteRead(axisNo_, command, response);
|
||||||
|
sscanf(response, "P154=%d", &moving_to_position);
|
||||||
|
|
||||||
|
/*
|
||||||
|
This code tests whether the axis is too long in status 5 or 6.
|
||||||
|
If the axis is in status 5 or 6, a time counter (status6Time) is started and updated during subsequent polls.
|
||||||
|
If status6Time exceeds the estimated arrival time of 120 seconds, a corresponding error is returned.
|
||||||
|
*/
|
||||||
|
int EstimatedTimeOfArrival = 120; // seconds
|
||||||
|
if (axStat == 5 || axStat == 6) {
|
||||||
|
if (status6Time == 0) {
|
||||||
|
status6Time = time(nullptr);
|
||||||
|
statusPos = position;
|
||||||
|
} else {
|
||||||
|
if (time(nullptr) > status6Time + EstimatedTimeOfArrival) {
|
||||||
|
/* trigger error only when not moving */
|
||||||
|
if (abs(position - statusPos) < .1) {
|
||||||
|
moving_to_position = 0;
|
||||||
|
errlogPrintf(
|
||||||
|
"Axis %d stayed in status 5 or 6 for more than %d seconds BROKEN\n",
|
||||||
|
axisNo_, EstimatedTimeOfArrival);
|
||||||
|
updateMsgTxtFromDriver("Axis stayed in status 5 or 6 for more than estimated time: BROKEN");
|
||||||
|
status6Time = 0;
|
||||||
|
return status;
|
||||||
|
} else {
|
||||||
|
status6Time = time(nullptr);
|
||||||
|
statusPos = position;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
If the axis is moving, set the corresponding flags in the pmacController (pC_) and end the poll.
|
||||||
|
*/
|
||||||
|
if (!moving_to_position) {
|
||||||
|
*moving = true;
|
||||||
|
st = setIntegerParam(pC_->motorStatusMoving_, true);
|
||||||
|
status = status > st ? status : st;
|
||||||
|
st = setIntegerParam(pC_->motorStatusDone_, false);
|
||||||
|
return status > st ? status : st;
|
||||||
|
} else {
|
||||||
|
*moving = false;
|
||||||
|
st = setIntegerParam(pC_->motorStatusMoving_, false);
|
||||||
|
status = status > st ? status : st;
|
||||||
|
st = setIntegerParam(pC_->motorStatusDone_, true);
|
||||||
|
status = status > st ? status : st;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set any axis specific general problem bits. */
|
||||||
|
if (axError != 0) {
|
||||||
|
axisProblemFlag = 1;
|
||||||
|
if (axisErrorCount < 10) {
|
||||||
|
axMessage = translateAxisError(axError);
|
||||||
|
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
|
||||||
|
"drvGirderAxisGetStatus: Axis %d is in deep trouble: axis error "
|
||||||
|
"code %d, translated: %s:, status code = %d\n",
|
||||||
|
axisNo_, axError, axMessage, axStat);
|
||||||
|
snprintf(message, sizeof(message), "GirderAxis error: %s", axMessage);
|
||||||
|
updateMsgTxtFromDriver(message);
|
||||||
|
if (axMessage != NULL) {
|
||||||
|
free(axMessage);
|
||||||
|
}
|
||||||
|
axisErrorCount++;
|
||||||
|
} else if (axisErrorCount == 10) {
|
||||||
|
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
|
||||||
|
"Suppressing further axis error messages\n");
|
||||||
|
axisErrorCount++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
axisProblemFlag = 0;
|
||||||
|
axisErrorCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
st = setIntegerParam(pC_->motorStatusProblem_, axisProblemFlag);
|
||||||
|
status = status > st ? status : st;
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
@ -189,4 +189,21 @@ protected:
|
|||||||
time_t det_startTime;
|
time_t det_startTime;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
class GirderAxis: public pmacV3Axis {
|
||||||
|
public:
|
||||||
|
GirderAxis(pmacController *pController, int axisNo);
|
||||||
|
asynStatus move(double position, int relative, double min_velocity, double max_velocity, double acceleration);
|
||||||
|
asynStatus stop(double acceleration);
|
||||||
|
asynStatus poll(bool *moving);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int IsEnable;
|
||||||
|
|
||||||
|
friend class pmacController;
|
||||||
|
friend class pmacV3Controller;
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* pmacAxis_H */
|
#endif /* pmacAxis_H */
|
||||||
|
@ -781,6 +781,34 @@ pC->unlock();
|
|||||||
return asynSuccess;
|
return asynSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* C wrapper for the GirderAxis constructor.
|
||||||
|
* See GirderAxis::GirderAxis.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
asynStatus pmacCreateGirderAxis(
|
||||||
|
const char *pmacName, /* specify which controller by port name */
|
||||||
|
int axis) /* axis number (start from 1). */
|
||||||
|
{
|
||||||
|
pmacController *pC;
|
||||||
|
pmacAxis *pAxis;
|
||||||
|
|
||||||
|
static const char *functionName = "pmacCreateGirderAxis";
|
||||||
|
|
||||||
|
pC = (pmacController *)findAsynPortDriver(pmacName);
|
||||||
|
if (!pC) {
|
||||||
|
printf("%s:%s: Error port %s not found\n", driverName, functionName,
|
||||||
|
pmacName);
|
||||||
|
return asynError;
|
||||||
|
}
|
||||||
|
|
||||||
|
pC->lock();
|
||||||
|
pAxis = new GirderAxis(pC, axis);
|
||||||
|
pAxis = NULL;
|
||||||
|
pC->unlock();
|
||||||
|
return asynSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
/*================================ SeleneController ===============================================*/
|
/*================================ SeleneController ===============================================*/
|
||||||
|
|
||||||
asynStatus SeleneController::writeFloat64(asynUser *pasynUser, epicsFloat64 value)
|
asynStatus SeleneController::writeFloat64(asynUser *pasynUser, epicsFloat64 value)
|
||||||
@ -1057,6 +1085,18 @@ static void configpmacAmorDetectorAxisCallFunc(const iocshArgBuf *args)
|
|||||||
pmacCreateAmorDetectorAxis(args[0].sval, args[1].ival, args[2].ival);
|
pmacCreateAmorDetectorAxis(args[0].sval, args[1].ival, args[2].ival);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* GirderCreateAxis */
|
||||||
|
static const iocshArg pmacCreateGirderAxisArg0 = {"Controller port name",
|
||||||
|
iocshArgString};
|
||||||
|
static const iocshArg pmacCreateGirderAxisArg1 = {"Axis number", iocshArgInt};
|
||||||
|
static const iocshArg *const pmacCreateGirderAxisArgs[] = {&pmacCreateGirderAxisArg0,
|
||||||
|
&pmacCreateGirderAxisArg1};
|
||||||
|
static const iocshFuncDef configpmacGirderAxis = {"pmacGirderCreateAxis", 2,
|
||||||
|
pmacCreateGirderAxisArgs};
|
||||||
|
|
||||||
|
static void configpmacGirderAxisCallFunc(const iocshArgBuf *args) {
|
||||||
|
pmacCreateGirderAxis(args[0].sval, args[1].ival);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void pmacControllerRegister(void)
|
static void pmacControllerRegister(void)
|
||||||
|
@ -140,6 +140,7 @@ class pmacController : public SINQController {
|
|||||||
friend class SeleneAxis;
|
friend class SeleneAxis;
|
||||||
friend class LiftAxis;
|
friend class LiftAxis;
|
||||||
friend class pmacV3Axis;
|
friend class pmacV3Axis;
|
||||||
|
friend class GirderAxis;
|
||||||
friend class AmorDetectorAxis;
|
friend class AmorDetectorAxis;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -182,6 +183,7 @@ public:
|
|||||||
|
|
||||||
friend class pmacV3Axis;
|
friend class pmacV3Axis;
|
||||||
friend class pmacAxis;
|
friend class pmacAxis;
|
||||||
|
friend class GirderAxis;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
pmacV3Axis **pAxes_; /**< Array of pointers to axis objects */
|
pmacV3Axis **pAxes_; /**< Array of pointers to axis objects */
|
||||||
|
Reference in New Issue
Block a user