Add a set PV for the SeleneMotor
- make the number of extra parameters in SINQController configurable - add database entry for the motor set field - add the new function "setMotorPosition_" to the Selene controller - execute Qx59=<pos> to set the new position
This commit is contained in:
@ -25,17 +25,20 @@ TEMPLATE_TOP=$(EPICS_BASE)/templates/makeBaseApp/top
|
|||||||
#SNCSEQ=$(EPICS_BASE)/../modules/soft/seq
|
#SNCSEQ=$(EPICS_BASE)/../modules/soft/seq
|
||||||
|
|
||||||
# EPICS_BASE usually appears last so other apps can override stuff:
|
# EPICS_BASE usually appears last so other apps can override stuff:
|
||||||
EPICS_BASE=/opt/epics/bases/base-3.14.12.5
|
|
||||||
|
#EPICS_BASE=
|
||||||
|
#MODULES=/home/epics/modules
|
||||||
|
|
||||||
# Set RULES here if you want to take build rules from somewhere
|
# Set RULES here if you want to take build rules from somewhere
|
||||||
# other than EPICS_BASE:
|
# other than EPICS_BASE:
|
||||||
#RULES=/path/to/epics/support/module/rules/x-y
|
##RULES=/path/to/epics/support/module/rules/x-y
|
||||||
MOTOR=/opt/epics/modules/motor/6.10.0/3.14.12.5
|
#MOTOR=/opt/epics/modules/motor/6.10.0/3.14.12.5
|
||||||
ASYN=/opt/epics/modules/asyn/4.27.0/3.14.12.5
|
#ASYN=/opt/epics/modules/asyn/4.27.0/3.14.12.5
|
||||||
SYNAPPSSTD=/opt/epics/modules/synAppsStd/3.4.1/3.14.12.5/
|
#SYNAPPSSTD=/opt/epics/modules/synAppsStd/3.4.1/3.14.12.5/
|
||||||
#ANC=/usr/local/epics/anc350v17
|
##ANC=/usr/local/epics/anc350v17
|
||||||
STREAMS=/opt/epics/modules/streamdevice/2.6.0/3.14.12.5
|
#STREAMS=/opt/epics/modules/streamdevice/2.6.0/3.14.12.5
|
||||||
#LAKESHORE336=/usr/local/epics/support/lakeshore336
|
##LAKESHORE336=/usr/local/epics/support/lakeshore336
|
||||||
BUSY=/opt/epics/modules/busy/1.6.0/3.14.12.5
|
#BUSY=/opt/epics/modules/busy/1.6.0/3.14.12.5
|
||||||
#OXINSTCRYOJET=/usr/local/epics/support/OxInstCryojet-2-18-3
|
##OXINSTCRYOJET=/usr/local/epics/support/OxInstCryojet-2-18-3
|
||||||
PCRE=/opt/epics/modules/pcre/8.36.0/3.14.12.5
|
#PCRE=/opt/epics/modules/pcre/8.36.0/3.14.12.5
|
||||||
|
|
||||||
|
6
sinqEPICSApp/Db/motorSet.db
Normal file
6
sinqEPICSApp/Db/motorSet.db
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# workaround over set position
|
||||||
|
record(ao, "$(P)$(M)-SetPosition") {
|
||||||
|
field(DTYP, "asynFloat64")
|
||||||
|
field(OUT, "@asyn($(PORT),$(N),1) SET_MOTOR_POSITION")
|
||||||
|
field(PINI, "YES")
|
||||||
|
}
|
@ -10,8 +10,8 @@
|
|||||||
#include "SINQController.h"
|
#include "SINQController.h"
|
||||||
#include "asynMotorController.h"
|
#include "asynMotorController.h"
|
||||||
|
|
||||||
SINQController::SINQController(const char *portName, const char *SINQPortName, int numAxes)
|
SINQController::SINQController(const char *portName, const char *SINQPortName, int numAxes, const int& extraParams)
|
||||||
: asynMotorController(portName, numAxes+1, NUM_MOTOR_DRIVER_PARAMS+2,
|
: asynMotorController(portName, numAxes+1, NUM_MOTOR_DRIVER_PARAMS+extraParams,
|
||||||
0, // No additional interfaces beyond those in base class
|
0, // No additional interfaces beyond those in base class
|
||||||
0, // No additional callback interfaces beyond those in base class
|
0, // No additional callback interfaces beyond those in base class
|
||||||
ASYN_CANBLOCK | ASYN_MULTIDEVICE,
|
ASYN_CANBLOCK | ASYN_MULTIDEVICE,
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
class epicsShareClass SINQController : public asynMotorController
|
class epicsShareClass SINQController : public asynMotorController
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SINQController(const char *portName, const char *SINQPortName, int numAxes);
|
SINQController(const char *portName, const char *SINQPortName, int numAxes, const int& extraParams=2);
|
||||||
|
|
||||||
friend class SINQAxis;
|
friend class SINQAxis;
|
||||||
protected:
|
protected:
|
||||||
|
@ -8,9 +8,9 @@
|
|||||||
* 23 May 2012
|
* 23 May 2012
|
||||||
*
|
*
|
||||||
* Substantially modified for use at SINQ at PSI.
|
* Substantially modified for use at SINQ at PSI.
|
||||||
* The thing with the PMACS is that they can be programmed.
|
* The thing with the PMAC's is that they can be programmed.
|
||||||
* This affects also the commands they understand.
|
* This affects also the commands they understand.
|
||||||
* Our PMACS also do not seem to like to return multiple replies.....
|
* Our PMAC's also do not seem to like to return multiple replies.....
|
||||||
*
|
*
|
||||||
* I use a starting flag to catch a peculiar feature of our PMAC implementation:
|
* I use a starting flag to catch a peculiar feature of our PMAC implementation:
|
||||||
* when the motor is hung, it wont start. I check for this and cause an alarm.
|
* when the motor is hung, it wont start. I check for this and cause an alarm.
|
||||||
@ -44,6 +44,8 @@
|
|||||||
|
|
||||||
#define MULT 1000.
|
#define MULT 1000.
|
||||||
|
|
||||||
|
#define ABS(x) (x < 0 ? -(x) : (x))
|
||||||
|
|
||||||
extern "C" void shutdownCallback(void *pPvt)
|
extern "C" void shutdownCallback(void *pPvt)
|
||||||
{
|
{
|
||||||
pmacController *pC = static_cast<pmacController *>(pPvt);
|
pmacController *pC = static_cast<pmacController *>(pPvt);
|
||||||
@ -244,7 +246,8 @@ asynStatus pmacAxis::setPosition(double position)
|
|||||||
{
|
{
|
||||||
//int status = 0;
|
//int status = 0;
|
||||||
static const char *functionName = "pmacAxis::setPosition";
|
static const char *functionName = "pmacAxis::setPosition";
|
||||||
|
errlogPrintf("executing : %s\n", functionName);
|
||||||
|
|
||||||
pC_->debugFlow(functionName);
|
pC_->debugFlow(functionName);
|
||||||
|
|
||||||
// Cannot do this.
|
// Cannot do this.
|
||||||
@ -417,6 +420,8 @@ asynStatus pmacAxis::getAxisStatus(bool *moving)
|
|||||||
previous_position_ = position;
|
previous_position_ = position;
|
||||||
previous_direction_ = direction;
|
previous_direction_ = direction;
|
||||||
|
|
||||||
|
// errlogPrintf("Polling, axStat = %d, axErr = %d, position = %f\n", axStat, axErr, position);
|
||||||
|
|
||||||
/* are we done? */
|
/* are we done? */
|
||||||
if((axStat == 0 || axStat == 14 || axStat < 0) && starting == 0 ){
|
if((axStat == 0 || axStat == 14 || axStat < 0) && starting == 0 ){
|
||||||
done = 1;
|
done = 1;
|
||||||
@ -561,3 +566,122 @@ asynStatus pmacHRPTAxis::getAxisStatus(bool *moving)
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*================================= SeleneAxis code ======================================================*/
|
||||||
|
asynStatus SeleneAxis::home(double min_velocity, double max_velocity, double acceleration, int forwards)
|
||||||
|
{
|
||||||
|
asynStatus status = asynError;
|
||||||
|
static const char *functionName = "SeleneAxis::home";
|
||||||
|
|
||||||
|
pC_->debugFlow(functionName);
|
||||||
|
|
||||||
|
updateMsgTxtFromDriver("Cannot home on this axis type");
|
||||||
|
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------------------------------------------------*/
|
||||||
|
asynStatus SeleneAxis::move(double position, int relative, double min_velocity, double max_velocity, double acceleration)
|
||||||
|
{
|
||||||
|
asynStatus status = asynError;
|
||||||
|
static const char *functionName = "SeleneAxis::move";
|
||||||
|
double realPosition;
|
||||||
|
|
||||||
|
updateMsgTxtFromDriver("");
|
||||||
|
|
||||||
|
pC_->debugFlow(functionName);
|
||||||
|
|
||||||
|
char command[128] = {0};
|
||||||
|
char response[32] = {0};
|
||||||
|
|
||||||
|
pC_->debugFlow(functionName);
|
||||||
|
|
||||||
|
if(relative){
|
||||||
|
realPosition = previous_position_ + position/MULT;
|
||||||
|
} else {
|
||||||
|
realPosition = position/MULT;
|
||||||
|
}
|
||||||
|
startTime = time(NULL);
|
||||||
|
status6Time = 0;
|
||||||
|
starting = 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Run into limit when asked for by a suitable position, else
|
||||||
|
position absolutely
|
||||||
|
*/
|
||||||
|
if(ABS(realPosition - limitTarget) < .05){
|
||||||
|
sprintf(command,"P%d50=3", axisNo_);
|
||||||
|
} else {
|
||||||
|
sprintf(command,"Q%d51=%f P%x50=1",axisNo_, realPosition, axisNo_);
|
||||||
|
}
|
||||||
|
|
||||||
|
errlogPrintf("Sending drive command: %s\n", command);
|
||||||
|
|
||||||
|
status = pC_->lowLevelWriteRead(axisNo_,command, response);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------------------------------------*/
|
||||||
|
asynStatus SeleneAxis::setPosition(double position) {
|
||||||
|
asynStatus status = asynError;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
/*======================================= Selene Lift Axis Code ===========================================*/
|
||||||
|
asynStatus LiftAxis::move(double position, int relative, double min_velocity,
|
||||||
|
double max_velocity, double acceleration)
|
||||||
|
{
|
||||||
|
asynStatus status = asynError;
|
||||||
|
static const char *functionName = "LiftAxis::move";
|
||||||
|
double realPosition;
|
||||||
|
|
||||||
|
updateMsgTxtFromDriver("");
|
||||||
|
pC_->debugFlow(functionName);
|
||||||
|
|
||||||
|
char command[128] = {0};
|
||||||
|
char response[32] = {0};
|
||||||
|
|
||||||
|
pC_->debugFlow(functionName);
|
||||||
|
|
||||||
|
if(relative){
|
||||||
|
realPosition = previous_position_ + position/MULT;
|
||||||
|
} else {
|
||||||
|
realPosition = position/MULT;
|
||||||
|
}
|
||||||
|
startTime = time(NULL);
|
||||||
|
status6Time = 0;
|
||||||
|
starting = 1;
|
||||||
|
|
||||||
|
sprintf( command, "Q15%d=%12.4f", axisNo_, realPosition);
|
||||||
|
|
||||||
|
status = pC_->lowLevelWriteRead(axisNo_,command, response);
|
||||||
|
waitStart = 1;
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------------------------------------------
|
||||||
|
Return *moving until the motor moved started moving. This enables the start command
|
||||||
|
to be sent separatly.
|
||||||
|
----------------------------------------------------------------------------------------------------------*/
|
||||||
|
asynStatus LiftAxis::poll(bool *moving)
|
||||||
|
{
|
||||||
|
asynStatus status;
|
||||||
|
|
||||||
|
status = getAxisStatus(moving);
|
||||||
|
if(*moving == false && waitStart == 1){
|
||||||
|
*moving = true;
|
||||||
|
setIntegerParam(pC_->motorStatusMoving_, true);
|
||||||
|
setIntegerParam(pC_->motorStatusDone_, false);
|
||||||
|
}
|
||||||
|
if(*moving){
|
||||||
|
waitStart = 0;
|
||||||
|
}
|
||||||
|
callParamCallbacks();
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------------------------------------------------*/
|
||||||
|
asynStatus LiftAxis::stop(double acceleration)
|
||||||
|
{
|
||||||
|
waitStart = 0;
|
||||||
|
return pmacAxis::stop(acceleration);
|
||||||
|
}
|
||||||
|
/*-------------------------------------------------------------------------------------------------------------*/
|
||||||
|
@ -10,6 +10,9 @@
|
|||||||
* Modified to use the MsgTxt field for SINQ
|
* Modified to use the MsgTxt field for SINQ
|
||||||
*
|
*
|
||||||
* Mark Koennecke, January 2019
|
* Mark Koennecke, January 2019
|
||||||
|
*
|
||||||
|
* EXtended with special motor axis for the Selene
|
||||||
|
* guide, Mark Koennecke, February 2020
|
||||||
********************************************/
|
********************************************/
|
||||||
|
|
||||||
#ifndef pmacAxis_H
|
#ifndef pmacAxis_H
|
||||||
@ -19,6 +22,7 @@
|
|||||||
#include "SINQAxis.h"
|
#include "SINQAxis.h"
|
||||||
|
|
||||||
class pmacController;
|
class pmacController;
|
||||||
|
class SeleneController;
|
||||||
|
|
||||||
class pmacAxis : public SINQAxis
|
class pmacAxis : public SINQAxis
|
||||||
{
|
{
|
||||||
@ -76,4 +80,49 @@ class pmacHRPTAxis : public pmacAxis
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SeleneAxis : public pmacAxis
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
SeleneAxis(SeleneController *pController, int axisNo, double limitTarget) : pmacAxis((pmacController *)pController,axisNo)
|
||||||
|
{
|
||||||
|
this->limitTarget = limitTarget;
|
||||||
|
};
|
||||||
|
asynStatus move(double position, int relative, double min_velocity, double max_velocity, double acceleration);
|
||||||
|
asynStatus setPosition(double position);
|
||||||
|
asynStatus home(double min_velocity, double max_velocity, double acceleration, int forwards);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
friend class SeleneController;
|
||||||
|
friend class pmacController;
|
||||||
|
|
||||||
|
private:
|
||||||
|
double limitTarget;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Yet another special set of motors for the Selene Guide at AMOR. Each segment can be lifted or tilted. This is
|
||||||
|
two motors. One acts as a slave and only writes a new target, the other also sets a new target and sends the
|
||||||
|
actual movement command. Both motors are coordianted in the motor controller in order to avoid tension on
|
||||||
|
the guide elements. This gaves rise to the function code LIFTSLAVE and LIFTMASTER.
|
||||||
|
|
||||||
|
In another mode the whole guide can be lifted or tilted. Then motor 1 and 6 get new values and one of them
|
||||||
|
sends the drive command. This causes all 6 motors to drive synchronously to their new targets. This is
|
||||||
|
implemented through the LIFTSEGMENT function code.
|
||||||
|
|
||||||
|
Mark Koennecke, February 2020
|
||||||
|
|
||||||
|
*/
|
||||||
|
class LiftAxis : public pmacAxis
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LiftAxis(pmacController *pController, int axisNo) : pmacAxis((pmacController *)pController,axisNo) {};
|
||||||
|
asynStatus move(double position, int relative, double min_velocity, double max_velocity, double acceleration);
|
||||||
|
asynStatus poll(bool *moving);
|
||||||
|
asynStatus stop(double acceleration);
|
||||||
|
private:
|
||||||
|
int waitStart;
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* pmacAxis_H */
|
#endif /* pmacAxis_H */
|
||||||
|
@ -39,6 +39,7 @@ using std::endl;
|
|||||||
#include <iocsh.h>
|
#include <iocsh.h>
|
||||||
#include <drvSup.h>
|
#include <drvSup.h>
|
||||||
#include <registryFunction.h>
|
#include <registryFunction.h>
|
||||||
|
#include <errlog.h>
|
||||||
|
|
||||||
#include "asynOctetSyncIO.h"
|
#include "asynOctetSyncIO.h"
|
||||||
|
|
||||||
@ -130,6 +131,8 @@ const epicsUInt32 pmacController::PMAX_AXIS_GENERAL_PROB2 = (PMAC_STATUS2_DESIRE
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
asynStatus pmacCreateController(const char *portName, const char *lowLevelPortName, int lowLevelPortAddress,
|
asynStatus pmacCreateController(const char *portName, const char *lowLevelPortName, int lowLevelPortAddress,
|
||||||
int numAxes, int movingPollPeriod, int idlePollPeriod);
|
int numAxes, int movingPollPeriod, int idlePollPeriod);
|
||||||
|
asynStatus SeleneCreateController(const char *portName, const char *lowLevelPortName, int lowLevelPortAddress,
|
||||||
|
int numAxes, int movingPollPeriod, int idlePollPeriod);
|
||||||
|
|
||||||
asynStatus pmacCreateAxis(const char *pmacName, int axis);
|
asynStatus pmacCreateAxis(const char *pmacName, int axis);
|
||||||
asynStatus pmacCreateAxis(const char *pmacName, int numAxis);
|
asynStatus pmacCreateAxis(const char *pmacName, int numAxis);
|
||||||
@ -137,8 +140,8 @@ extern "C" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pmacController::pmacController(const char *portName, const char *lowLevelPortName, int lowLevelPortAddress,
|
pmacController::pmacController(const char *portName, const char *lowLevelPortName, int lowLevelPortAddress,
|
||||||
int numAxes, double movingPollPeriod, double idlePollPeriod)
|
int numAxes, double movingPollPeriod, double idlePollPeriod, const int& extraParams)
|
||||||
: SINQController(portName, lowLevelPortName, numAxes+1)
|
: SINQController(portName, lowLevelPortName, numAxes+1, extraParams)
|
||||||
{
|
{
|
||||||
static const char *functionName = "pmacController::pmacController";
|
static const char *functionName = "pmacController::pmacController";
|
||||||
|
|
||||||
@ -154,7 +157,7 @@ pmacController::pmacController(const char *portName, const char *lowLevelPortNam
|
|||||||
createParam(PMAC_C_CommsErrorString, asynParamInt32, &PMAC_C_CommsError_);
|
createParam(PMAC_C_CommsErrorString, asynParamInt32, &PMAC_C_CommsError_);
|
||||||
|
|
||||||
// Connect our Asyn user to the low level port that is a parameter to this constructor
|
// Connect our Asyn user to the low level port that is a parameter to this constructor
|
||||||
if (lowLevelPortConnect(lowLevelPortName, lowLevelPortAddress, &lowLevelPortUser_, "\006", "\r") != asynSuccess) {
|
if (lowLevelPortConnect(lowLevelPortName, lowLevelPortAddress, &lowLevelPortUser_, "\006", (char *)"\r") != asynSuccess) {
|
||||||
printf("%s: Failed to connect to low level asynOctetSyncIO port %s\n", functionName, lowLevelPortName);
|
printf("%s: Failed to connect to low level asynOctetSyncIO port %s\n", functionName, lowLevelPortName);
|
||||||
setIntegerParam(PMAC_C_CommsError_, 1);
|
setIntegerParam(PMAC_C_CommsError_, 1);
|
||||||
} else {
|
} else {
|
||||||
@ -344,8 +347,6 @@ asynStatus pmacController::writeFloat64(asynUser *pasynUser, epicsFloat64 value)
|
|||||||
pmacAxis *pAxis = NULL;
|
pmacAxis *pAxis = NULL;
|
||||||
char command[64] = {0};
|
char command[64] = {0};
|
||||||
char response[64] = {0};
|
char response[64] = {0};
|
||||||
double encRatio = 1.0;
|
|
||||||
epicsInt32 encposition = 0;
|
|
||||||
char message[132];
|
char message[132];
|
||||||
|
|
||||||
static const char *functionName = "pmacController::writeFloat64";
|
static const char *functionName = "pmacController::writeFloat64";
|
||||||
@ -532,6 +533,31 @@ asynStatus pmacCreateController(const char *portName, const char *lowLevelPortNa
|
|||||||
return asynSuccess;
|
return asynSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
asynStatus SeleneCreateController(const char *portName, const char *lowLevelPortName, int lowLevelPortAddress,
|
||||||
|
int numAxes, int movingPollPeriod, int idlePollPeriod)
|
||||||
|
{
|
||||||
|
|
||||||
|
SeleneController *ppmacController
|
||||||
|
= new SeleneController(portName, lowLevelPortName, lowLevelPortAddress, numAxes, movingPollPeriod/1000., idlePollPeriod/1000.);
|
||||||
|
ppmacController = NULL;
|
||||||
|
|
||||||
|
return asynSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SeleneController::SeleneController(const char *portName, const char *lowLevelPortName, int lowLevelPortAddress,
|
||||||
|
int numAxes, double movingPollPeriod, double idlePollPeriod) : pmacController(portName,
|
||||||
|
lowLevelPortName,
|
||||||
|
lowLevelPortAddress,
|
||||||
|
numAxes,
|
||||||
|
movingPollPeriod,
|
||||||
|
idlePollPeriod, 3) {
|
||||||
|
static const char *functionName = "seleneController::seleneController";
|
||||||
|
createParam(MotorSetPositionString, asynParamFloat64, &setMotorPosition_);
|
||||||
|
callParamCallbacks();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* C wrapper for the pmacAxis constructor.
|
* C wrapper for the pmacAxis constructor.
|
||||||
* See pmacAxis::pmacAxis.
|
* See pmacAxis::pmacAxis.
|
||||||
@ -585,6 +611,61 @@ asynStatus pmacCreateHRPTAxis(const char *pmacName, /* specify which con
|
|||||||
return asynSuccess;
|
return asynSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* C wrapper for the SeleneAxis constructor.
|
||||||
|
* See SeleneAxis::SeleneAxis.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
asynStatus SeleneCreateAxis(const char *pmacName, /* specify which controller by port name */
|
||||||
|
int axis, /* axis number (start from 1). */
|
||||||
|
double limitTarget)
|
||||||
|
{
|
||||||
|
SeleneController *pC;
|
||||||
|
SeleneAxis *pAxis;
|
||||||
|
|
||||||
|
static const char *functionName = "SeleneCreateAxis";
|
||||||
|
|
||||||
|
pC = (SeleneController*) findAsynPortDriver(pmacName);
|
||||||
|
if (!pC) {
|
||||||
|
printf("%s:%s: Error port %s not found\n",
|
||||||
|
driverName, functionName, pmacName);
|
||||||
|
return asynError;
|
||||||
|
}
|
||||||
|
|
||||||
|
pC->lock();
|
||||||
|
pAxis = new SeleneAxis(pC, axis, limitTarget);
|
||||||
|
pAxis = NULL;
|
||||||
|
pC->unlock();
|
||||||
|
return asynSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* C wrapper for the Selene LiftAxis constructor.
|
||||||
|
* See LiftAxis::LiftAxis.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
asynStatus LiftCreateAxis(const char *pmacName, /* specify which controller by port name */
|
||||||
|
int axis) /* axis number (start from 1). */
|
||||||
|
{
|
||||||
|
pmacController *pC;
|
||||||
|
LiftAxis *pAxis;
|
||||||
|
|
||||||
|
static const char *functionName = "LiftCreateAxis";
|
||||||
|
|
||||||
|
pC = (pmacController*) findAsynPortDriver(pmacName);
|
||||||
|
if (!pC) {
|
||||||
|
printf("%s:%s: Error port %s not found\n",
|
||||||
|
driverName, functionName, pmacName);
|
||||||
|
return asynError;
|
||||||
|
}
|
||||||
|
|
||||||
|
pC->lock();
|
||||||
|
pAxis = new LiftAxis(pC, axis);
|
||||||
|
pAxis = NULL;
|
||||||
|
pC->unlock();
|
||||||
|
return asynSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* C Wrapper function for pmacHRPTAxis constructor.
|
* C Wrapper function for pmacHRPTAxis constructor.
|
||||||
* See pmacAxis::pmacAxis.
|
* See pmacAxis::pmacAxis.
|
||||||
@ -617,6 +698,67 @@ asynStatus pmacCreateAxes(const char *pmacName,
|
|||||||
return asynSuccess;
|
return asynSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*================================ SeleneController ===============================================*/
|
||||||
|
|
||||||
|
asynStatus SeleneController::writeFloat64(asynUser *pasynUser, epicsFloat64 value)
|
||||||
|
{
|
||||||
|
int function = pasynUser->reason;
|
||||||
|
asynStatus status = asynError;
|
||||||
|
SeleneAxis *pAxis = NULL;
|
||||||
|
char command[64] = {0};
|
||||||
|
char response[64] = {0};
|
||||||
|
char message[132];
|
||||||
|
|
||||||
|
static const char *functionName = "SeleneController::writeFloat64";
|
||||||
|
|
||||||
|
sprintf(message,"%s, reason %d", functionName, function);
|
||||||
|
|
||||||
|
pAxis = (SeleneAxis *)this->getAxis(pasynUser);
|
||||||
|
if (!pAxis) {
|
||||||
|
return asynError;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Set the parameter and readback in the parameter library. */
|
||||||
|
status = pAxis->setDoubleParam(function, value);
|
||||||
|
|
||||||
|
// TODO: somethign is really shitty here: lowLimit and highLimit cannot be on the command
|
||||||
|
if (function == motorLowLimit_) {
|
||||||
|
sprintf(command, "Q%d54=%d", pAxis->axisNo_, (int)(value/pAxis->scale_/MULT));
|
||||||
|
asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW,
|
||||||
|
"%s: Setting low limit on controller %s, axis %d to %f\n",
|
||||||
|
functionName, portName, pAxis->axisNo_, value);
|
||||||
|
errlogPrintf("Setting low limit of axis %d to %f, command = %s\n", pAxis->axisNo_, value, command);
|
||||||
|
} else if (function == motorHighLimit_) {
|
||||||
|
sprintf(command, "Q%d53=%d", pAxis->axisNo_, (int)(value/pAxis->scale_/MULT));
|
||||||
|
asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW,
|
||||||
|
"%s: Setting high limit on controller %s, axis %d to %f\n",
|
||||||
|
functionName, portName, pAxis->axisNo_, value);
|
||||||
|
errlogPrintf("Setting high limit of axis %d to %f, command = %s\n", pAxis->axisNo_, value, command);
|
||||||
|
} else if(function == setMotorPosition_){
|
||||||
|
snprintf(command,sizeof(command),"Q%d59=%f", pAxis->axisNo_, value);
|
||||||
|
asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW,
|
||||||
|
"%s: Defining position of axis%d to %f\n",
|
||||||
|
functionName, pAxis->axisNo_, value);
|
||||||
|
errlogPrintf("Defining position of axis %d to %f, command = %s\n", pAxis->axisNo_, value, command);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Execute the command.
|
||||||
|
if (command[0] != 0 && status == asynSuccess) {
|
||||||
|
status = lowLevelWriteRead(pAxis->axisNo_,command, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Call base class method
|
||||||
|
//This will handle callCallbacks even if the function was handled here.
|
||||||
|
status = asynMotorController::writeFloat64(pasynUser, value);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Code for iocsh registration */
|
/* Code for iocsh registration */
|
||||||
|
|
||||||
#ifdef vxWorks
|
#ifdef vxWorks
|
||||||
@ -641,6 +783,12 @@ static void configpmacCreateControllerCallFunc(const iocshArgBuf *args)
|
|||||||
pmacCreateController(args[0].sval, args[1].sval, args[2].ival, args[3].ival, args[4].ival, args[5].ival);
|
pmacCreateController(args[0].sval, args[1].sval, args[2].ival, args[3].ival, args[4].ival, args[5].ival);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const iocshFuncDef configSeleneCreateController = {"SeleneCreateController", 6, pmacCreateControllerArgs};
|
||||||
|
static void configSeleneCreateControllerCallFunc(const iocshArgBuf *args)
|
||||||
|
{
|
||||||
|
SeleneCreateController(args[0].sval, args[1].sval, args[2].ival, args[3].ival, args[4].ival, args[5].ival);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* pmacCreateAxis */
|
/* pmacCreateAxis */
|
||||||
static const iocshArg pmacCreateAxisArg0 = {"Controller port name", iocshArgString};
|
static const iocshArg pmacCreateAxisArg0 = {"Controller port name", iocshArgString};
|
||||||
@ -666,6 +814,34 @@ static void configpmacHRPTAxisCallFunc(const iocshArgBuf *args)
|
|||||||
pmacCreateHRPTAxis(args[0].sval, args[1].ival);
|
pmacCreateHRPTAxis(args[0].sval, args[1].ival);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* SeleneCreateAxis */
|
||||||
|
static const iocshArg SeleneCreateAxisArg0 = {"Controller port name", iocshArgString};
|
||||||
|
static const iocshArg SeleneCreateAxisArg1 = {"Axis number", iocshArgInt};
|
||||||
|
static const iocshArg SeleneCreateAxisArg2 = {"limitTraget", iocshArgDouble};
|
||||||
|
static const iocshArg * const SeleneCreateAxisArgs[] = {&SeleneCreateAxisArg0,
|
||||||
|
&SeleneCreateAxisArg1,
|
||||||
|
&SeleneCreateAxisArg2};
|
||||||
|
static const iocshFuncDef configSeleneCreateAxis = {"SeleneCreateAxis", 3, SeleneCreateAxisArgs};
|
||||||
|
|
||||||
|
static void configSeleneCreateAxisCallFunc(const iocshArgBuf *args)
|
||||||
|
{
|
||||||
|
SeleneCreateAxis(args[0].sval, args[1].ival,args[2].dval);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LiftCreateAxis */
|
||||||
|
static const iocshArg LiftCreateAxisArg0 = {"Controller port name", iocshArgString};
|
||||||
|
static const iocshArg LiftCreateAxisArg1 = {"Axis number", iocshArgInt};
|
||||||
|
static const iocshArg * const LiftCreateAxisArgs[] = {&LiftCreateAxisArg0,
|
||||||
|
&LiftCreateAxisArg1};
|
||||||
|
static const iocshFuncDef configLiftAxis = {"LiftCreateAxis", 2, LiftCreateAxisArgs};
|
||||||
|
|
||||||
|
static void configLiftAxisCallFunc(const iocshArgBuf *args)
|
||||||
|
{
|
||||||
|
LiftCreateAxis(args[0].sval, args[1].ival);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* pmacCreateAxes */
|
/* pmacCreateAxes */
|
||||||
static const iocshArg pmacCreateAxesArg0 = {"Controller port name", iocshArgString};
|
static const iocshArg pmacCreateAxesArg0 = {"Controller port name", iocshArgString};
|
||||||
static const iocshArg pmacCreateAxesArg1 = {"Num Axes", iocshArgInt};
|
static const iocshArg pmacCreateAxesArg1 = {"Num Axes", iocshArgInt};
|
||||||
@ -683,8 +859,11 @@ static void configpmacAxesCallFunc(const iocshArgBuf *args)
|
|||||||
static void pmacControllerRegister(void)
|
static void pmacControllerRegister(void)
|
||||||
{
|
{
|
||||||
iocshRegister(&configpmacCreateController, configpmacCreateControllerCallFunc);
|
iocshRegister(&configpmacCreateController, configpmacCreateControllerCallFunc);
|
||||||
|
iocshRegister(&configSeleneCreateController, configSeleneCreateControllerCallFunc);
|
||||||
iocshRegister(&configpmacAxis, configpmacAxisCallFunc);
|
iocshRegister(&configpmacAxis, configpmacAxisCallFunc);
|
||||||
iocshRegister(&configpmacHRPTAxis, configpmacHRPTAxisCallFunc);
|
iocshRegister(&configpmacHRPTAxis, configpmacHRPTAxisCallFunc);
|
||||||
|
iocshRegister(&configSeleneCreateAxis, configSeleneCreateAxisCallFunc);
|
||||||
|
iocshRegister(&configLiftAxis, configLiftAxisCallFunc);
|
||||||
iocshRegister(&configpmacAxes, configpmacAxesCallFunc);
|
iocshRegister(&configpmacAxes, configpmacAxesCallFunc);
|
||||||
}
|
}
|
||||||
epicsExportRegistrar(pmacControllerRegister);
|
epicsExportRegistrar(pmacControllerRegister);
|
||||||
@ -693,3 +872,4 @@ epicsExportRegistrar(pmacControllerRegister);
|
|||||||
|
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|
||||||
|
|
||||||
|
@ -26,8 +26,8 @@
|
|||||||
class pmacController : public SINQController {
|
class pmacController : public SINQController {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
pmacController(const char *portName, const char *lowLevelPortName, int lowLevelPortAddress, int numAxes, double movingPollPeriod,
|
pmacController(const char *portName, const char *lowLevelPortName, int lowLevelPortAddress, int numAxes, double movingPollPeriod,
|
||||||
double idlePollPeriod);
|
double idlePollPeriod, const int& extraParams=2);
|
||||||
|
|
||||||
virtual ~pmacController();
|
virtual ~pmacController();
|
||||||
|
|
||||||
@ -49,13 +49,13 @@ class pmacController : public SINQController {
|
|||||||
int PMAC_C_GlobalStatus_;
|
int PMAC_C_GlobalStatus_;
|
||||||
int PMAC_C_CommsError_;
|
int PMAC_C_CommsError_;
|
||||||
#define LAST_PMAC_PARAM PMAC_C_CommsError__
|
#define LAST_PMAC_PARAM PMAC_C_CommsError__
|
||||||
|
void debugFlow(const char *message);
|
||||||
|
asynStatus lowLevelWriteRead(int axisNo, const char *command, char *response);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
asynUser* lowLevelPortUser_;
|
asynUser* lowLevelPortUser_;
|
||||||
epicsUInt32 debugFlag_;
|
epicsUInt32 debugFlag_;
|
||||||
asynStatus lowLevelWriteRead(int axisNo, const char *command, char *response);
|
|
||||||
int lowLevelPortConnect(const char *port, int addr, asynUser **ppasynUser, char *inputEos, char *outputEos);
|
int lowLevelPortConnect(const char *port, int addr, asynUser **ppasynUser, char *inputEos, char *outputEos);
|
||||||
void debugFlow(const char *message);
|
|
||||||
|
|
||||||
//static class data members
|
//static class data members
|
||||||
|
|
||||||
@ -137,9 +137,31 @@ class pmacController : public SINQController {
|
|||||||
|
|
||||||
friend class pmacAxis;
|
friend class pmacAxis;
|
||||||
friend class pmacHRPTAxis;
|
friend class pmacHRPTAxis;
|
||||||
|
friend class SeleneAxis;
|
||||||
|
friend class LiftAxis;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NUM_PMAC_PARAMS (&LAST_PMAC_PARAM - &FIRST_PMAC_PARAM + 1)
|
#define NUM_PMAC_PARAMS (&LAST_PMAC_PARAM - &FIRST_PMAC_PARAM + 1)
|
||||||
|
|
||||||
|
#define MotorSetPositionString "SET_MOTOR_POSITION"
|
||||||
|
|
||||||
|
class SeleneController : public pmacController {
|
||||||
|
public:
|
||||||
|
SeleneController(const char *portName, const char *lowLevelPortName, int lowLevelPortAddress,
|
||||||
|
int numAxes, double movingPollPeriod, double idlePollPeriod);
|
||||||
|
|
||||||
|
~SeleneController(void) { }
|
||||||
|
|
||||||
|
// overloaded because we have a different command to set the limits
|
||||||
|
asynStatus writeFloat64(asynUser *pasynUser, epicsFloat64 value);
|
||||||
|
|
||||||
|
friend class SeleneAxis;
|
||||||
|
friend class pmacAxis;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int setMotorPosition_;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif /* pmacController_H */
|
#endif /* pmacController_H */
|
||||||
|
Reference in New Issue
Block a user