Updated EuromoveDriver to work with Prologix GPIB-Ethernet

Improved threshold handling on EL737
Minor changes
This commit is contained in:
2021-06-17 09:30:28 +02:00
parent 6de4a878ef
commit efbd0e19cf
7 changed files with 102 additions and 49 deletions

View File

@ -4,10 +4,12 @@ include /ioc/tools/driver.makefile
MODULE=sinq
LIBVERSION=koennecke
BUILDCLASSES=Linux
EPICS_VERSIONS=3.14.12
# additional module dependencies
REQUIRED+=SynApps
REQUIRED+=stream
REQUIRED+=scaler
# using a test version
scaler_VERSION=koennecke

View File

@ -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)
EuroMoveCreateController("llb","serial1",1);
EuroMoveCreateController("llb","serial1", 10, 1);
### Motors

View File

@ -147,7 +147,7 @@ asynStatus EL734Controller::transactController(int axisNo,char command[COMLEN],
pasynOctetSyncIO->flush(pasynUserController_);
status = pasynOctetSyncIO->writeRead(pasynUserController_, command, strlen(command),
reply,COMLEN, 1.,&out,&in,&reason);
reply,COMLEN, 2.,&out,&in,&reason);
if(status != asynSuccess){
if(axis!= NULL){
axis->updateMsgTxtFromDriver("Lost connection to motor controller");
@ -409,6 +409,7 @@ asynStatus EL734Axis::poll(bool *moving)
}
count = sscanf(reply,"%lf", &position);
if(count != 1) {
if(!homing) {
snprintf(errTxt,sizeof(errTxt),"Bad reply %s when reading position for %d", reply, axisNo_);
setIntegerParam(pC_->motorStatusProblem_, true);
errorReported = 1;
@ -416,10 +417,11 @@ asynStatus EL734Axis::poll(bool *moving)
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);
}
// Read the moving status of this motor
sprintf(command,"msr %d",axisNo_);

View File

@ -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
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] 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)
{
asynStatus status;
static const char *functionName = "EuroMoveController::EuroMoveController";
size_t out, in;
int reason;
char command[80], reply[80];
/* Connect to EuroMove controller */
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",
functionName);
}
const char *terminator = "\r";
const char *terminator = "\r\n";
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++){
new EuroMoveAxis(this, i+1);
@ -60,11 +84,12 @@ EuroMoveController::EuroMoveController(const char *portName, const char *EuroMov
* 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] 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
*/
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);
}
@ -119,7 +144,17 @@ asynStatus EuroMoveController::transactController(int axisNo,char command[COMLEN
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),
reply,sizeof(reply), 10.,&out,&in,&reason);
if(status != asynSuccess){
@ -606,15 +641,17 @@ static void EuroMoveConfigCallFunc(const iocshArgBuf *args)
/** Code for iocsh registration */
static const iocshArg EuroMoveCreateControllerArg0 = {"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,
&EuroMoveCreateControllerArg1,
&EuroMoveCreateControllerArg2
&EuroMoveCreateControllerArg2,
&EuroMoveCreateControllerArg3
};
static const iocshFuncDef EuroMoveCreateControllerDef = {"EuroMoveCreateController", 3, EuroMoveCreateControllerArgs};
static const iocshFuncDef EuroMoveCreateControllerDef = {"EuroMoveCreateController", 4, EuroMoveCreateControllerArgs};
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)

View File

@ -53,7 +53,7 @@ private:
class EuroMoveController : public SINQController {
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);
EuroMoveAxis* getAxis(asynUser *pasynUser);
@ -63,6 +63,8 @@ public:
friend class EuroMoveAxis;
private:
asynUser *pasynUserController_;
unsigned int gpibAddr;
char addrCommand[50];
asynStatus transactController(int axisNo, char command[COMLEN], char reply[COMLEN]);

View File

@ -27,7 +27,7 @@
*
* 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.
*
* 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
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);
if(dbStatus != 0){
errSymLookup(dbStatus,errName,sizeof(errName));
@ -425,13 +425,15 @@ static void runEvents(EL737priv *priv)
we have to set the threshold
*/
dbStatus = dbGetField(&priv->threshCounter,DBR_LONG,&threshCounter, &options, &nElements,NULL);
if(dbStatus != 0){
if(dbStatus != 0) {
errSymLookup(dbStatus,errName,sizeof(errName));
errlogPrintf("Reading thresholdCounter failed with %s\n", errName);
} else {
if(threshCounter > 0) {
/* The threshCounter is valid */
sprintf(command,"DL %d %d", (int)threshCounter,
(int)myThreshold);
//errlogPrintf("Sending threshold command %s\n", command);
errlogPrintf("Sending threshold command %s\n", command);
status = el737_transactCommand(priv,command,reply);
sprintf(command,"DR %d", (int)threshCounter);
status = el737_transactCommand(priv, command,reply);
@ -439,22 +441,30 @@ static void runEvents(EL737priv *priv)
priv->sendThreshold = 0;
priv->thresholdValue = myThreshold;
}
} else {
errlogPrintf("Invalid threshold monitor %ld, no threshold sent", threshCounter);
}
}
}
}
}
if(priv->sendThreshold == 1){
if(priv->sendThreshold == 1) {
// fallback when we do not have the DB fields or threshCounter is invalid
if(priv->presets[THRESHMON] <= 0) {
errlogPrintf("Invalid threshold monitor %ld, no threshold sent", priv->presets[THRESHMON]);
} else {
sprintf(command,"DL %d %d", (int)priv->presets[THRESHMON],
(int)priv->presets[THRESHVAL]);
//errlogPrintf("Sending threshold command %s\n", command);
errlogPrintf("Sending threshold from presets, command %s\n", command);
status = el737_transactCommand(priv,command,reply);
sprintf(command,"DR %d", (int)priv->presets[THRESHMON]);
status = el737_transactCommand(priv, command,reply);
if(status == asynSuccess){
if(status == asynSuccess) {
priv->sendThreshold = 0;
}
}
}
//errlogPrintf("Doing a count command: %d\n", priv->countCommand);
if(priv->countCommand == 1){
@ -542,7 +552,6 @@ static void el737Thread(void *param)
evStatus = epicsEventWaitWithTimeout(priv->wakeUp,timeout);
//errlogPrintf("EL737 thread woke up with %d\n", evStatus);
if(evStatus == epicsEventWaitOK) {
/*
FEAR: we received a command!!!!

View File

@ -594,7 +594,7 @@ asynStatus pmacHRPTAxis::getAxisStatus(bool *moving)
/*================================= SeleneAxis code ======================================================*/
SeleneAxis::SeleneAxis(SeleneController *pC, int axisNo, double limitTarget)
: pmacAxis(pC, axisNo)
: pmacAxis(pC, axisNo, false)
{
static const char *functionName = "pmacAxis::pmacAxis";