Implemented a feature which allows for an additional field for having a text message

with a motor axis. To this purpose a new derived class SINQAxis and SINQController were
added which other drivers using this feature can derive from. The proof of concept and
test platform is the EL734 driver.
This commit is contained in:
2017-03-20 16:40:25 +01:00
parent 6ea6fdcb85
commit af4d16d25f
11 changed files with 189 additions and 16 deletions

View File

@ -1,6 +1,7 @@
epicsEnvSet("ARCH","linux-x86-debug")
epicsEnvSet("IOC","iocsinqEPICS")
epicsEnvSet("TOP","/afs/psi.ch/project/sinqdev/sinqepicsapp")
epicsEnvSet("SINQ","$(TOP)/sinqEPICSApp")
epicsEnvSet("EPICS_BASE","/usr/local/epics")
epicsEnvSet("ASYN","/usr/local/epics/support/asyn-4-18")
epicsEnvSet("MOTOR","/usr/local/epics/support/motor-6-7")

View File

@ -1,10 +1,21 @@
file "$(MOTOR)/db/basic_asyn_motor.db"
{
pattern
{P, N, M, DTYP, PORT, ADDR, DESC, EGU, DIR, VELO, VBAS, ACCL, BDST, BVEL, BACC, MRES, PREC, DHLM, DLLM, INIT}
{P, N, M, DTYP, PORT, ADDR, DESC, EGU, DIR, VELO, VBAS, ACCL, BDST, BVEL, BACC, MRES, PREC, DHLM, DLLM, INIT}
{NZ:mota:, 1, "m$(N)", "asynMotor", mota, 1, "sgu", degree, Pos, 2.0, 0.1, .2, 0, 1, .2, 1., 3, 20, -20, ""}
{NZ:mota:, 2, "m$(N)", "asynMotor", mota, 2, "sgl", degree, Pos, 2.0, 0.1, .2, 0, 1, .2, 1., 3, 20, -20, ""}
{NZ:mota:, 3, "m$(N)", "asynMotor", mota, 3, "sgd", degree, Pos, 2.0, 0.1, .2, 0, 1, .2, 1., 3, 20, -20, ""}
{NZ:mota:, 4, "m$(N)", "asynMotor", mota, 4, "som", degree, Pos, 2.0, 0.1, .2, 0, 1, .2, 0.001, 3, 37, -37, ""}
{NZ:mota:, 5, "m$(N)", "asynMotor", mota, 5, "sty", degree, Pos, 2.0, 0.1, .2, 0, 1, .2, 0.001, 3, 150, -149, ""}
}
file "$(SINQ)/Db/motorMessage.db"
{
pattern
{P,N, M,PORT}
{NZ:mota:, 1, "m$(N)",mota}
{NZ:mota:, 2, "m$(N)",mota}
{NZ:mota:, 3, "m$(N)",mota}
{NZ:mota:, 4, "m$(N)",mota}
{NZ:mota:, 5, "m$(N)",mota}
}

View File

@ -1,4 +1,4 @@
#!../../bin/linux-x86/sinqEPICS
#!../../bin/linux-x86-debug/sinqEPICS
## You may have to change sinqEPICS to something else
## everywhere it appears in this file

View File

@ -0,0 +1,9 @@
# The message text
record(waveform, "$(P)$(M)-MsgTxt") {
field(DTYP, "asynOctetRead")
field(INP, "@asyn($(PORT),$(N),1) MOTOR_MESSAGE_TEXT")
field(FTVL, "CHAR")
field(NELM, "80")
field(SCAN, "I/O Intr")
}

View File

@ -33,18 +33,14 @@ February 2013
* \param[in] numAxes The number of axes that this controller supports
*/
EL734Controller::EL734Controller(const char *portName, const char *EL734PortName, int numAxes)
: asynMotorController(portName, numAxes+1, 0,
0, // No additional interfaces beyond those in base class
0, // No additional callback interfaces beyond those in base class
ASYN_CANBLOCK | ASYN_MULTIDEVICE,
1, // autoconnect
0, 0) // Default priority and stack size
: SINQController(portName, EL734PortName, numAxes)
{
int axis;
asynStatus status;
EL734Axis *pAxis;
static const char *functionName = "EL734Controller::EL734Controller";
/* Connect to EL734 controller */
status = pasynOctetSyncIO->connect(EL734PortName, 0, &pasynUserController_, NULL);
if (status) {
@ -200,8 +196,7 @@ asynStatus EL734Controller::transactController(char command[COMLEN], char reply[
* Initializes register numbers, etc.
*/
EL734Axis::EL734Axis(EL734Controller *pC, int axisNo)
: asynMotorAxis(pC, axisNo),
pC_(pC)
: SINQAxis(pC, axisNo), pC_(pC)
{
}
@ -240,6 +235,9 @@ asynStatus EL734Axis::move(double position, int relative, double minVelocity, do
homing = 0;
sprintf(command, "p %d %.3f", axisNo_, position/1000.);
status = pC_->transactController(command,reply);
if(status == asynError){
updateMsgTxtFromDriver(reply);
}
next_poll = -1;
return status;
}
@ -256,7 +254,10 @@ asynStatus EL734Axis::home(double minVelocity, double maxVelocity, double accele
homing = 1;
next_poll= -1;
status = pC_->transactController(command,reply);
return status;
if(status == asynError){
updateMsgTxtFromDriver(reply);
}
return status;
}
asynStatus EL734Axis::moveVelocity(double minVelocity, double maxVelocity, double acceleration)
@ -278,6 +279,9 @@ asynStatus EL734Axis::moveVelocity(double minVelocity, double maxVelocity, doubl
sprintf(command, "FB %d", axisNo_);
}
status = pC_->transactController(command,reply);
if(status == asynError){
updateMsgTxtFromDriver(reply);
}
next_poll = -1;
return status;
}
@ -291,6 +295,7 @@ asynStatus EL734Axis::stop(double acceleration )
sprintf(command, "S %d", axisNo_);
status = pC_->transactController(command,reply);
errlogPrintf("Sent STOP on Axis %d\n", axisNo_);
updateMsgTxtFromDriver("Axis interrupted");
return status;
}
@ -303,6 +308,9 @@ asynStatus EL734Axis::setPosition(double position)
sprintf(command, "P %d %f", axisNo_, position/1000.);
status = pC_->transactController(command,reply);
if(status == asynError){
updateMsgTxtFromDriver(reply);
}
next_poll = -1;
return status;
@ -331,6 +339,7 @@ asynStatus EL734Axis::poll(bool *moving)
int msr;
asynStatus comStatus;
char command[COMLEN], reply[COMLEN];
int driverError = 0;
// protect against excessive polling
@ -342,15 +351,22 @@ asynStatus EL734Axis::poll(bool *moving)
// Read the current motor position
sprintf(command,"u %d", axisNo_);
comStatus = pC_->transactController(command,reply);
if(comStatus == asynError){
updateMsgTxtFromDriver(reply);
driverError = 1;
}
if(comStatus) goto skip;
if(strstr(reply,"*ES") != NULL){
*moving = false;
setIntegerParam(pC_->motorStatusDone_, true);
setIntegerParam(pC_->motorStatusProblem_, true);
updateMsgTxtFromDriver("Emergency Stop Engaged");
driverError = 1;
goto skip;
} else if(strstr(reply,"?BSY") != NULL){
*moving = true;
setIntegerParam(pC_->motorStatusDone_, false);
updateMsgTxtFromDriver(NULL);
goto skip;
}
sscanf(reply,"%lf", &position);
@ -373,11 +389,15 @@ asynStatus EL734Axis::poll(bool *moving)
next_poll = time(NULL)+IDLEPOLL;
if(oredMSR & 0x10){
setIntegerParam(pC_->motorStatusLowLimit_, true);
updateMsgTxtFromDriver("Lower Limit Hit");
driverError = 1;
} else {
setIntegerParam(pC_->motorStatusLowLimit_, false);
}
if(oredMSR & 0x20){
setIntegerParam(pC_->motorStatusHighLimit_, true);
updateMsgTxtFromDriver("Upper Limit Hit");
driverError = 1;
} else {
setIntegerParam(pC_->motorStatusHighLimit_, false);
}
@ -388,20 +408,29 @@ asynStatus EL734Axis::poll(bool *moving)
if(oredMSR &0x1000){
setIntegerParam(pC_->motorStatusProblem_, true);
errlogSevPrintf(errlogMajor, "Air cushion problem on %d", axisNo_);
updateMsgTxtFromDriver("Air cushion error");
driverError = 1;
}
if(oredMSR &0x80){
setIntegerParam(pC_->motorStatusProblem_, true);
errlogSevPrintf(errlogMajor, "Positioning fault at %d", axisNo_);
updateMsgTxtFromDriver("Positioning fault");
driverError = 1;
}
*moving = false;
setIntegerParam(pC_->motorStatusDone_, true);
//updateMsgTxtFromDriver("Believed to be on position");
} else {
*moving = true;
next_poll = -1;
setIntegerParam(pC_->motorStatusDone_, false);
//updateMsgTxtFromDriver("Creeping");
}
skip:
if(driverError == 0){
updateMsgTxtFromDriver(NULL);
}
setIntegerParam(pC_->motorStatusProblem_, comStatus ? 1:0);
callParamCallbacks();
return comStatus ? asynError : asynSuccess;

View File

@ -7,13 +7,13 @@ February 2013
*/
#include "asynMotorController.h"
#include "asynMotorAxis.h"
#include "SINQController.h"
#include "SINQAxis.h"
#define MAX_EL734_AXES 12
#define COMLEN 80
class EL734Axis : public asynMotorAxis
class EL734Axis : public SINQAxis
{
public:
/* These are the methods we override from the base class */
@ -34,11 +34,14 @@ private:
double position;
int homing;
time_t next_poll;
int ErrTxtIdx;
void forwardErrorTxt(EL734Axis *axis);
friend class EL734Controller;
};
class EL734Controller : public asynMotorController {
class EL734Controller : public SINQController {
public:
EL734Controller(const char *portName, const char *EL734PortName, int numAxes);

View File

@ -24,7 +24,7 @@ sinqEPICS_LIBS += motor asyn std anc350 anc350AsynMotor stream busy
# sinqEPICS_registerRecordDeviceDriver.cpp derives from sinqEPICS.dbd
sinqEPICS_SRCS += sinqEPICS_registerRecordDeviceDriver.cpp
sinqEPICS_SRCS += EL734Driver.cpp devScalerEL737.c pmacAsynIPPort.c
sinqEPICS_SRCS += EL734Driver.cpp devScalerEL737.c pmacAsynIPPort.c SINQAxis.cpp SINQController.cpp
sinqEPICS_SRCS += pmacController.cpp pmacAxis.cpp
sinqEPICS_SRCS += NanotecDriver.cpp stptok.cpp

View File

@ -0,0 +1,36 @@
/*
This is a version of the motor axis record which adds code for having an
text field with an error message to go with the motor. The code is
courtesey Torsten Boergershausen from ESS and from the axisRecord.
Mark Koennecke, March 2017
*/
#include "SINQAxis.h"
#include "SINQController.h"
SINQAxis::SINQAxis(class SINQController *pC, int axis)
: asynMotorAxis((asynMotorController *)pC, axis),
pC_(pC)
{
}
void SINQAxis::updateMsgTxtFromDriver(const char *value)
{
if (value && value[0]) {
pC_->setIntegerParam(axisNo_,pC_->motorMessageIsFromDriver_, 1);
setStringParam(pC_->motorMessageText_,value);
} else {
pC_->setIntegerParam(axisNo_,pC_->motorMessageIsFromDriver_, 0);
}
}
/**
* Sets the value for a string for this axis in the parameter library.
* \param[in] function The function (parameter) number
* \param[in] value Value to set */
asynStatus SINQAxis::setStringParam(int function, const char *value)
{
// Call the base class method
return pC_->setStringParam(axisNo_, function, value);
}

View File

@ -0,0 +1,29 @@
/*
This is a version of the motor axis record which adds code for having an
text field with an error message to go with the motor. The code is
courtesey Torsten Boergershausen from ESS and from the axisRecord.
Mark Koennecke, March 2017
*/
#ifndef __SINQDRIVER
#define __SINQDRIVER
#include "asynMotorAxis.h"
class epicsShareClass SINQAxis : public asynMotorAxis
{
public:
SINQAxis(class SINQController *pC_, int axis);
asynStatus setStringParam(int function, const char *value);
friend class SINQController;
protected:
void updateMsgTxtFromDriver(const char *value);
private:
SINQController *pC_;
};
#endif

View File

@ -0,0 +1,25 @@
/*
This class contains the necessary changes to have an additional text fields for messages
with each axis.
Code lifted from Torsten Boegershausen ESS code.
Mark Koennecke, March 2017
*/
#include "SINQController.h"
#include "asynMotorController.h"
SINQController::SINQController(const char *portName, const char *SINQPortName, int numAxes)
: asynMotorController(portName, numAxes+1, NUM_MOTOR_DRIVER_PARAMS+2,
0, // No additional interfaces beyond those in base class
0, // No additional callback interfaces beyond those in base class
ASYN_CANBLOCK | ASYN_MULTIDEVICE,
1, // autoconnect
0, 0) // Default priority and stack size
{
createParam(motorMessageIsFromDriverString, asynParamInt32, &motorMessageIsFromDriver_);
createParam(motorMessageTextString, asynParamOctet, &motorMessageText_);
}

View File

@ -0,0 +1,30 @@
/*
This class contains the necessary changes to have an additional text fields for messages
with each axis.
Code lifted from Torsten Boegershausens ESS code.
Mark Koennecke, March 2017
*/
#ifndef __SINQCONTROLLER
#define __SINQCONTROLLER
#include "asynMotorController.h"
#define motorMessageIsFromDriverString "MOTOR_MESSAGE_DRIVER"
#define motorMessageTextString "MOTOR_MESSAGE_TEXT"
class epicsShareClass SINQController : public asynMotorController
{
public:
SINQController(const char *portName, const char *SINQPortName, int numAxes);
friend class SINQAxis;
protected:
int motorMessageIsFromDriver_;
int motorMessageText_;
};
#endif