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:
@ -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")
|
||||
|
@ -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}
|
||||
}
|
@ -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
|
||||
|
9
sinqEPICSApp/Db/motorMessage.db
Normal file
9
sinqEPICSApp/Db/motorMessage.db
Normal 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")
|
||||
}
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
36
sinqEPICSApp/src/SINQAxis.cpp
Normal file
36
sinqEPICSApp/src/SINQAxis.cpp
Normal 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);
|
||||
}
|
29
sinqEPICSApp/src/SINQAxis.h
Normal file
29
sinqEPICSApp/src/SINQAxis.h
Normal 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
|
||||
|
25
sinqEPICSApp/src/SINQController.cpp
Normal file
25
sinqEPICSApp/src/SINQController.cpp
Normal 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_);
|
||||
}
|
||||
|
||||
|
30
sinqEPICSApp/src/SINQController.h
Normal file
30
sinqEPICSApp/src/SINQController.h
Normal 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
|
||||
|
Reference in New Issue
Block a user