Updated EuromoveDriver to work with Prologix GPIB-Ethernet
Improved threshold handling on EL737 Minor changes
This commit is contained in:
@ -4,10 +4,12 @@ include /ioc/tools/driver.makefile
|
|||||||
MODULE=sinq
|
MODULE=sinq
|
||||||
LIBVERSION=koennecke
|
LIBVERSION=koennecke
|
||||||
BUILDCLASSES=Linux
|
BUILDCLASSES=Linux
|
||||||
|
EPICS_VERSIONS=3.14.12
|
||||||
|
|
||||||
# additional module dependencies
|
# additional module dependencies
|
||||||
REQUIRED+=SynApps
|
REQUIRED+=SynApps
|
||||||
REQUIRED+=stream
|
REQUIRED+=stream
|
||||||
|
REQUIRED+=scaler
|
||||||
|
|
||||||
# using a test version
|
# using a test version
|
||||||
scaler_VERSION=koennecke
|
scaler_VERSION=koennecke
|
||||||
|
@ -9,9 +9,10 @@ cd ${TOP}
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
drvAsynIPPortConfigure("serial1", "amor-ts:3002",0,0,0)
|
drvAsynIPPortConfigure("serial1", "129.129.195.83:1234",0,0,0)
|
||||||
|
#drvAsynIPPortConfigure("serial1", "amor-ts:3002",0,0,0)
|
||||||
#drvAsynIPPortConfigure("serial1", "localhost:9090",0,0,0)
|
#drvAsynIPPortConfigure("serial1", "localhost:9090",0,0,0)
|
||||||
EuroMoveCreateController("llb","serial1",1);
|
EuroMoveCreateController("llb","serial1", 10, 1);
|
||||||
|
|
||||||
### Motors
|
### Motors
|
||||||
|
|
||||||
|
@ -147,7 +147,7 @@ asynStatus EL734Controller::transactController(int axisNo,char command[COMLEN],
|
|||||||
pasynOctetSyncIO->flush(pasynUserController_);
|
pasynOctetSyncIO->flush(pasynUserController_);
|
||||||
|
|
||||||
status = pasynOctetSyncIO->writeRead(pasynUserController_, command, strlen(command),
|
status = pasynOctetSyncIO->writeRead(pasynUserController_, command, strlen(command),
|
||||||
reply,COMLEN, 1.,&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");
|
||||||
@ -409,17 +409,19 @@ asynStatus EL734Axis::poll(bool *moving)
|
|||||||
}
|
}
|
||||||
count = sscanf(reply,"%lf", &position);
|
count = sscanf(reply,"%lf", &position);
|
||||||
if(count != 1) {
|
if(count != 1) {
|
||||||
snprintf(errTxt,sizeof(errTxt),"Bad reply %s when reading position for %d", reply, axisNo_);
|
if(!homing) {
|
||||||
setIntegerParam(pC_->motorStatusProblem_, true);
|
snprintf(errTxt,sizeof(errTxt),"Bad reply %s when reading position for %d", reply, axisNo_);
|
||||||
errorReported = 1;
|
setIntegerParam(pC_->motorStatusProblem_, true);
|
||||||
updateMsgTxtFromDriver(errTxt);
|
errorReported = 1;
|
||||||
comStatus = asynError;
|
updateMsgTxtFromDriver(errTxt);
|
||||||
goto skip;
|
comStatus = asynError;
|
||||||
|
goto skip;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//errlogPrintf("Axis %d, reply %s, position %lf\n", axisNo_, reply, position);
|
||||||
|
setDoubleParam(pC_->motorPosition_, position*1000);
|
||||||
|
//setDoubleParam(pC_->motorEncoderPosition_, position);
|
||||||
}
|
}
|
||||||
//errlogPrintf("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_);
|
||||||
|
@ -5,6 +5,9 @@ USAGE... Motor driver support for the EuroMove motor controller from LLB.
|
|||||||
This is a driver for the EuroMove motor controller from LLB. This device talks to us either via
|
This is a driver for the EuroMove motor controller from LLB. This device talks to us either via
|
||||||
GPIB or USB. The controller is fairly simple. It can control quite a number of motors.
|
GPIB or USB. The controller is fairly simple. It can control quite a number of motors.
|
||||||
|
|
||||||
|
Reworked in 06/2021 to work with the Prologix GPIV-Ethernte converter
|
||||||
|
|
||||||
|
mark.koennecke@psi.ch
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@ -32,11 +35,14 @@ GPIB or USB. The controller is fairly simple. It can control quite a number of m
|
|||||||
* \param[in] EuroMovePortName The name of the drvAsynSerialPort that was created previously to connect to the EuroMove controller
|
* \param[in] EuroMovePortName The name of the drvAsynSerialPort that was created previously to connect to the EuroMove controller
|
||||||
* \param[in] numAxes The number of axes that this controller supports
|
* \param[in] numAxes The number of axes that this controller supports
|
||||||
*/
|
*/
|
||||||
EuroMoveController::EuroMoveController(const char *portName, const char *EuroMovePortName, int numAxis)
|
EuroMoveController::EuroMoveController(const char *portName, const char *EuroMovePortName, int gpibAddr, int numAxis)
|
||||||
: SINQController(portName, EuroMovePortName,numAxis+1)
|
: SINQController(portName, EuroMovePortName,numAxis+1)
|
||||||
{
|
{
|
||||||
asynStatus status;
|
asynStatus status;
|
||||||
static const char *functionName = "EuroMoveController::EuroMoveController";
|
static const char *functionName = "EuroMoveController::EuroMoveController";
|
||||||
|
size_t out, in;
|
||||||
|
int reason;
|
||||||
|
char command[80], reply[80];
|
||||||
|
|
||||||
/* Connect to EuroMove controller */
|
/* Connect to EuroMove controller */
|
||||||
status = pasynOctetSyncIO->connect(EuroMovePortName, 0, &pasynUserController_, NULL);
|
status = pasynOctetSyncIO->connect(EuroMovePortName, 0, &pasynUserController_, NULL);
|
||||||
@ -45,9 +51,27 @@ EuroMoveController::EuroMoveController(const char *portName, const char *EuroMov
|
|||||||
"%s: cannot connect to EuroMove controller\n",
|
"%s: cannot connect to EuroMove controller\n",
|
||||||
functionName);
|
functionName);
|
||||||
}
|
}
|
||||||
const char *terminator = "\r";
|
const char *terminator = "\r\n";
|
||||||
pasynOctetSyncIO->setOutputEos(pasynUserController_,terminator,strlen(terminator));
|
pasynOctetSyncIO->setOutputEos(pasynUserController_,terminator,strlen(terminator));
|
||||||
pasynOctetSyncIO->setInputEos(pasynUserController_,terminator,strlen(terminator));
|
const char *repTerminator = "\r";
|
||||||
|
pasynOctetSyncIO->setInputEos(pasynUserController_,repTerminator,strlen(repTerminator));
|
||||||
|
|
||||||
|
/* Save gpib address and prepare addr string */
|
||||||
|
this->gpibAddr = gpibAddr;
|
||||||
|
snprintf(addrCommand,strlen(addrCommand), "++addr %d", gpibAddr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Configure the Prologix interface to our liking
|
||||||
|
The thing sends no response on configuration commands
|
||||||
|
*/
|
||||||
|
strcpy(command,"++mode 1"); /* Make it a controller */
|
||||||
|
status = pasynOctetSyncIO->write(pasynUserController_, command, strlen(command), 2, &out);
|
||||||
|
strcpy(command,"++auto 1"); /* ask for response automatically */
|
||||||
|
status = pasynOctetSyncIO->write(pasynUserController_, command, strlen(command), 2, &out);
|
||||||
|
strcpy(command,"++eos 1"); /* CR */
|
||||||
|
status = pasynOctetSyncIO->write(pasynUserController_, command, strlen(command), 2, &out);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for(int i = 0; i < numAxis; i++){
|
for(int i = 0; i < numAxis; i++){
|
||||||
new EuroMoveAxis(this, i+1);
|
new EuroMoveAxis(this, i+1);
|
||||||
@ -59,12 +83,13 @@ EuroMoveController::EuroMoveController(const char *portName, const char *EuroMov
|
|||||||
/** Creates a new EuroMoveController object.
|
/** Creates a new EuroMoveController 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] EuroMovePortName The name of the drvAsynIPPPort that was created previously to connect to the EuroMove controller
|
* \param[in] EuroMovePortName The name of the drvAsynIPPPort that was created previously to connect to the EuroMove controller
|
||||||
|
* \param[in] gpibAddr The address of the controller on the GPIB bus
|
||||||
* \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 EuroMoveCreateController(const char *portName, const char *EuroMovePortName, const int numAxis)
|
extern "C" int EuroMoveCreateController(const char *portName, const char *EuroMovePortName, const int gpibAddr, const int numAxis)
|
||||||
{
|
{
|
||||||
new EuroMoveController(portName, EuroMovePortName, numAxis);
|
new EuroMoveController(portName, EuroMovePortName, gpibAddr, numAxis);
|
||||||
return(asynSuccess);
|
return(asynSuccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,7 +144,17 @@ asynStatus EuroMoveController::transactController(int axisNo,char command[COMLEN
|
|||||||
|
|
||||||
pasynOctetSyncIO->flush(pasynUserController_);
|
pasynOctetSyncIO->flush(pasynUserController_);
|
||||||
|
|
||||||
|
/* set address first */
|
||||||
|
status = pasynOctetSyncIO->write(pasynUserController_, this->addrCommand, strlen(this->addrCommand), 2, &out);
|
||||||
|
if(status != asynSuccess){
|
||||||
|
if(axis!= NULL){
|
||||||
|
axis->updateMsgTxtFromDriver("Lost connection to motor controller");
|
||||||
|
errlogPrintf("Lost connection to motor controller\n");
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* now the actual command */
|
||||||
status = pasynOctetSyncIO->writeRead(pasynUserController_, command, strlen(command),
|
status = pasynOctetSyncIO->writeRead(pasynUserController_, command, strlen(command),
|
||||||
reply,sizeof(reply), 10.,&out,&in,&reason);
|
reply,sizeof(reply), 10.,&out,&in,&reason);
|
||||||
if(status != asynSuccess){
|
if(status != asynSuccess){
|
||||||
@ -606,15 +641,17 @@ static void EuroMoveConfigCallFunc(const iocshArgBuf *args)
|
|||||||
/** Code for iocsh registration */
|
/** Code for iocsh registration */
|
||||||
static const iocshArg EuroMoveCreateControllerArg0 = {"Port name", iocshArgString};
|
static const iocshArg EuroMoveCreateControllerArg0 = {"Port name", iocshArgString};
|
||||||
static const iocshArg EuroMoveCreateControllerArg1 = {"EuroMove port name", iocshArgString};
|
static const iocshArg EuroMoveCreateControllerArg1 = {"EuroMove port name", iocshArgString};
|
||||||
static const iocshArg EuroMoveCreateControllerArg2 = {"Number of axis", iocshArgInt};
|
static const iocshArg EuroMoveCreateControllerArg2 = {"GPIB Address", iocshArgInt};
|
||||||
|
static const iocshArg EuroMoveCreateControllerArg3 = {"Number of axis", iocshArgInt};
|
||||||
static const iocshArg * const EuroMoveCreateControllerArgs[] = {&EuroMoveCreateControllerArg0,
|
static const iocshArg * const EuroMoveCreateControllerArgs[] = {&EuroMoveCreateControllerArg0,
|
||||||
&EuroMoveCreateControllerArg1,
|
&EuroMoveCreateControllerArg1,
|
||||||
&EuroMoveCreateControllerArg2
|
&EuroMoveCreateControllerArg2,
|
||||||
|
&EuroMoveCreateControllerArg3
|
||||||
};
|
};
|
||||||
static const iocshFuncDef EuroMoveCreateControllerDef = {"EuroMoveCreateController", 3, EuroMoveCreateControllerArgs};
|
static const iocshFuncDef EuroMoveCreateControllerDef = {"EuroMoveCreateController", 4, EuroMoveCreateControllerArgs};
|
||||||
static void EuroMoveCreateControllerCallFunc(const iocshArgBuf *args)
|
static void EuroMoveCreateControllerCallFunc(const iocshArgBuf *args)
|
||||||
{
|
{
|
||||||
EuroMoveCreateController(args[0].sval, args[1].sval, args[2].ival);
|
EuroMoveCreateController(args[0].sval, args[1].sval, args[2].ival, args[3].ival);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void EuroMoveRegister(void)
|
static void EuroMoveRegister(void)
|
||||||
|
@ -53,7 +53,7 @@ private:
|
|||||||
|
|
||||||
class EuroMoveController : public SINQController {
|
class EuroMoveController : public SINQController {
|
||||||
public:
|
public:
|
||||||
EuroMoveController(const char *portName, const char *EuroMovePortName, const int nAxis);
|
EuroMoveController(const char *portName, const char *EuroMovePortName, const int gpibAddr, const int nAxis);
|
||||||
|
|
||||||
void report(FILE *fp, int level);
|
void report(FILE *fp, int level);
|
||||||
EuroMoveAxis* getAxis(asynUser *pasynUser);
|
EuroMoveAxis* getAxis(asynUser *pasynUser);
|
||||||
@ -63,6 +63,8 @@ public:
|
|||||||
friend class EuroMoveAxis;
|
friend class EuroMoveAxis;
|
||||||
private:
|
private:
|
||||||
asynUser *pasynUserController_;
|
asynUser *pasynUserController_;
|
||||||
|
unsigned int gpibAddr;
|
||||||
|
char addrCommand[50];
|
||||||
|
|
||||||
asynStatus transactController(int axisNo, char command[COMLEN], char reply[COMLEN]);
|
asynStatus transactController(int axisNo, char command[COMLEN], char reply[COMLEN]);
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
*
|
*
|
||||||
* Mark Koennecke, February 2013
|
* Mark Koennecke, February 2013
|
||||||
*
|
*
|
||||||
* Enhanced by adding an addtional external pause and status flag in the databse and code in here
|
* Enhanced by adding an addtional external pause and status flag in the database and code in here
|
||||||
* to handle this. Moreover an external MsgTxt field in the DB can be filled with an error message.
|
* to handle this. Moreover an external MsgTxt field in the DB can be filled with an error message.
|
||||||
*
|
*
|
||||||
* Mark Koennecke, July 2017
|
* Mark Koennecke, July 2017
|
||||||
@ -414,7 +414,7 @@ static void runEvents(EL737priv *priv)
|
|||||||
This is the better way to set the threshold rather then the old way below which uses
|
This is the better way to set the threshold rather then the old way below which uses
|
||||||
presets for that function. This one uses separate fields.
|
presets for that function. This one uses separate fields.
|
||||||
*/
|
*/
|
||||||
if(priv->dbInit == 1) {
|
if(priv->dbInit == 1 && priv->sendThreshold) {
|
||||||
dbStatus = dbGetField(&priv->threshold,DBR_LONG,&myThreshold,&options, &nElements,NULL);
|
dbStatus = dbGetField(&priv->threshold,DBR_LONG,&myThreshold,&options, &nElements,NULL);
|
||||||
if(dbStatus != 0){
|
if(dbStatus != 0){
|
||||||
errSymLookup(dbStatus,errName,sizeof(errName));
|
errSymLookup(dbStatus,errName,sizeof(errName));
|
||||||
@ -425,34 +425,44 @@ static void runEvents(EL737priv *priv)
|
|||||||
we have to set the threshold
|
we have to set the threshold
|
||||||
*/
|
*/
|
||||||
dbStatus = dbGetField(&priv->threshCounter,DBR_LONG,&threshCounter, &options, &nElements,NULL);
|
dbStatus = dbGetField(&priv->threshCounter,DBR_LONG,&threshCounter, &options, &nElements,NULL);
|
||||||
if(dbStatus != 0){
|
if(dbStatus != 0) {
|
||||||
errSymLookup(dbStatus,errName,sizeof(errName));
|
errSymLookup(dbStatus,errName,sizeof(errName));
|
||||||
errlogPrintf("Reading thresholdCounter failed with %s\n", errName);
|
errlogPrintf("Reading thresholdCounter failed with %s\n", errName);
|
||||||
} else {
|
} else {
|
||||||
sprintf(command,"DL %d %d", (int)threshCounter,
|
if(threshCounter > 0) {
|
||||||
(int)myThreshold);
|
/* The threshCounter is valid */
|
||||||
//errlogPrintf("Sending threshold command %s\n", command);
|
sprintf(command,"DL %d %d", (int)threshCounter,
|
||||||
status = el737_transactCommand(priv,command,reply);
|
(int)myThreshold);
|
||||||
sprintf(command,"DR %d", (int)threshCounter);
|
errlogPrintf("Sending threshold command %s\n", command);
|
||||||
status = el737_transactCommand(priv, command,reply);
|
status = el737_transactCommand(priv,command,reply);
|
||||||
if(status == asynSuccess){
|
sprintf(command,"DR %d", (int)threshCounter);
|
||||||
priv->sendThreshold = 0;
|
status = el737_transactCommand(priv, command,reply);
|
||||||
priv->thresholdValue = myThreshold;
|
if(status == asynSuccess){
|
||||||
|
priv->sendThreshold = 0;
|
||||||
|
priv->thresholdValue = myThreshold;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
errlogPrintf("Invalid threshold monitor %ld, no threshold sent", threshCounter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(priv->sendThreshold == 1){
|
if(priv->sendThreshold == 1) {
|
||||||
sprintf(command,"DL %d %d", (int)priv->presets[THRESHMON],
|
// fallback when we do not have the DB fields or threshCounter is invalid
|
||||||
(int)priv->presets[THRESHVAL]);
|
if(priv->presets[THRESHMON] <= 0) {
|
||||||
//errlogPrintf("Sending threshold command %s\n", command);
|
errlogPrintf("Invalid threshold monitor %ld, no threshold sent", priv->presets[THRESHMON]);
|
||||||
status = el737_transactCommand(priv,command,reply);
|
} else {
|
||||||
sprintf(command,"DR %d", (int)priv->presets[THRESHMON]);
|
sprintf(command,"DL %d %d", (int)priv->presets[THRESHMON],
|
||||||
status = el737_transactCommand(priv, command,reply);
|
(int)priv->presets[THRESHVAL]);
|
||||||
if(status == asynSuccess){
|
errlogPrintf("Sending threshold from presets, command %s\n", command);
|
||||||
priv->sendThreshold = 0;
|
status = el737_transactCommand(priv,command,reply);
|
||||||
|
sprintf(command,"DR %d", (int)priv->presets[THRESHMON]);
|
||||||
|
status = el737_transactCommand(priv, command,reply);
|
||||||
|
if(status == asynSuccess) {
|
||||||
|
priv->sendThreshold = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -542,7 +552,6 @@ static void el737Thread(void *param)
|
|||||||
evStatus = epicsEventWaitWithTimeout(priv->wakeUp,timeout);
|
evStatus = epicsEventWaitWithTimeout(priv->wakeUp,timeout);
|
||||||
//errlogPrintf("EL737 thread woke up with %d\n", evStatus);
|
//errlogPrintf("EL737 thread woke up with %d\n", evStatus);
|
||||||
|
|
||||||
|
|
||||||
if(evStatus == epicsEventWaitOK) {
|
if(evStatus == epicsEventWaitOK) {
|
||||||
/*
|
/*
|
||||||
FEAR: we received a command!!!!
|
FEAR: we received a command!!!!
|
||||||
|
@ -594,7 +594,7 @@ asynStatus pmacHRPTAxis::getAxisStatus(bool *moving)
|
|||||||
|
|
||||||
/*================================= SeleneAxis code ======================================================*/
|
/*================================= SeleneAxis code ======================================================*/
|
||||||
SeleneAxis::SeleneAxis(SeleneController *pC, int axisNo, double limitTarget)
|
SeleneAxis::SeleneAxis(SeleneController *pC, int axisNo, double limitTarget)
|
||||||
: pmacAxis(pC, axisNo)
|
: pmacAxis(pC, axisNo, false)
|
||||||
{
|
{
|
||||||
static const char *functionName = "pmacAxis::pmacAxis";
|
static const char *functionName = "pmacAxis::pmacAxis";
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user