From af4d16d25f3e569eb52eb2fe1012eb3561e266c1 Mon Sep 17 00:00:00 2001 From: koennecke Date: Mon, 20 Mar 2017 16:40:25 +0100 Subject: [PATCH] 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. --- iocBoot/iocsinqEPICS/envPaths | 1 + .../iocsinqEPICS/motor.substitutions.el734 | 13 ++++- iocBoot/iocsinqEPICS/st.cmd | 2 +- sinqEPICSApp/Db/motorMessage.db | 9 ++++ sinqEPICSApp/src/EL734Driver.cpp | 47 +++++++++++++++---- sinqEPICSApp/src/EL734Driver.h | 11 +++-- sinqEPICSApp/src/Makefile | 2 +- sinqEPICSApp/src/SINQAxis.cpp | 36 ++++++++++++++ sinqEPICSApp/src/SINQAxis.h | 29 ++++++++++++ sinqEPICSApp/src/SINQController.cpp | 25 ++++++++++ sinqEPICSApp/src/SINQController.h | 30 ++++++++++++ 11 files changed, 189 insertions(+), 16 deletions(-) create mode 100644 sinqEPICSApp/Db/motorMessage.db create mode 100644 sinqEPICSApp/src/SINQAxis.cpp create mode 100644 sinqEPICSApp/src/SINQAxis.h create mode 100644 sinqEPICSApp/src/SINQController.cpp create mode 100644 sinqEPICSApp/src/SINQController.h diff --git a/iocBoot/iocsinqEPICS/envPaths b/iocBoot/iocsinqEPICS/envPaths index 73243fb..c0477bb 100644 --- a/iocBoot/iocsinqEPICS/envPaths +++ b/iocBoot/iocsinqEPICS/envPaths @@ -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") diff --git a/iocBoot/iocsinqEPICS/motor.substitutions.el734 b/iocBoot/iocsinqEPICS/motor.substitutions.el734 index 51eaeb4..e8554a4 100644 --- a/iocBoot/iocsinqEPICS/motor.substitutions.el734 +++ b/iocBoot/iocsinqEPICS/motor.substitutions.el734 @@ -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} +} \ No newline at end of file diff --git a/iocBoot/iocsinqEPICS/st.cmd b/iocBoot/iocsinqEPICS/st.cmd index cade92a..59a5ea7 100755 --- a/iocBoot/iocsinqEPICS/st.cmd +++ b/iocBoot/iocsinqEPICS/st.cmd @@ -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 diff --git a/sinqEPICSApp/Db/motorMessage.db b/sinqEPICSApp/Db/motorMessage.db new file mode 100644 index 0000000..2bbfd4a --- /dev/null +++ b/sinqEPICSApp/Db/motorMessage.db @@ -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") +} \ No newline at end of file diff --git a/sinqEPICSApp/src/EL734Driver.cpp b/sinqEPICSApp/src/EL734Driver.cpp index 8762924..3515930 100644 --- a/sinqEPICSApp/src/EL734Driver.cpp +++ b/sinqEPICSApp/src/EL734Driver.cpp @@ -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; diff --git a/sinqEPICSApp/src/EL734Driver.h b/sinqEPICSApp/src/EL734Driver.h index 7486623..4074ecb 100644 --- a/sinqEPICSApp/src/EL734Driver.h +++ b/sinqEPICSApp/src/EL734Driver.h @@ -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); diff --git a/sinqEPICSApp/src/Makefile b/sinqEPICSApp/src/Makefile index 9324de3..5bcfe0f 100644 --- a/sinqEPICSApp/src/Makefile +++ b/sinqEPICSApp/src/Makefile @@ -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 diff --git a/sinqEPICSApp/src/SINQAxis.cpp b/sinqEPICSApp/src/SINQAxis.cpp new file mode 100644 index 0000000..bd7a6df --- /dev/null +++ b/sinqEPICSApp/src/SINQAxis.cpp @@ -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); +} diff --git a/sinqEPICSApp/src/SINQAxis.h b/sinqEPICSApp/src/SINQAxis.h new file mode 100644 index 0000000..9c065ab --- /dev/null +++ b/sinqEPICSApp/src/SINQAxis.h @@ -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 + diff --git a/sinqEPICSApp/src/SINQController.cpp b/sinqEPICSApp/src/SINQController.cpp new file mode 100644 index 0000000..afbe3ef --- /dev/null +++ b/sinqEPICSApp/src/SINQController.cpp @@ -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_); +} + + diff --git a/sinqEPICSApp/src/SINQController.h b/sinqEPICSApp/src/SINQController.h new file mode 100644 index 0000000..15850e3 --- /dev/null +++ b/sinqEPICSApp/src/SINQController.h @@ -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 +