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
|
||||
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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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_);
|
||||
|
@ -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)
|
||||
|
@ -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]);
|
||||
|
||||
|
@ -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!!!!
|
||||
|
@ -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";
|
||||
|
||||
|
Reference in New Issue
Block a user