diff --git a/Makefile b/Makefile index 3f1a147..a9d4d74 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ REQUIRED+=sinqMotor motorBase_VERSION=7.2.2 # Specify the version of sinqMotor we want to build against -sinqMotor_VERSION=0.7.0 +sinqMotor_VERSION=mathis_s # These headers allow to depend on this library for derived drivers. HEADERS += src/turboPmacAxis.h diff --git a/README.md b/README.md index 1d827cd..6483063 100644 --- a/README.md +++ b/README.md @@ -17,25 +17,45 @@ The folder "utils" contains utility scripts for working with pmac motor controll ### Usage in IOC shell -turboPmac exposes the following IOC shell functions (all in turboPmacController.cpp): +turboPmac exports the following IOC shell functions: - `turboPmacController`: Create a new controller object. - `turboPmacAxis`: Create a new axis object. -These functions are parametrized as follows: + +The full mcu.cmd file looks like this: + ``` -turboPmacController( - "$(NAME)", # Name of the MCU, e.g. mcu1. This parameter should be provided by an environment variable. - "$(ASYN_PORT)", # IP-Port of the MCU. This parameter should be provided by an environment variable. - 8, # Maximum number of axes - 0.05, # Busy poll period in seconds - 1, # Idle poll period in seconds - 0.05 # Communication timeout in seconds - ); -``` -``` -turboPmacAxis( - "$(NAME)", # Name of the associated MCU, e.g. mcu1. This parameter should be provided by an environment variable. - 1 # Index of the axis. - ); +# Define the name of the controller and the corresponding port +epicsEnvSet("NAME","mcu") +epicsEnvSet("ASYN_PORT","p$(NAME)") + +# Create the TCP/IP socket used to talk with the controller. The socket can be adressed from within the IOC shell via the port name +drvAsynIPPortConfigure("$(ASYN_PORT)","172.28.101.24:1025") + +# Create the controller object with the defined name and connect it to the socket via the port name. +# The other parameters are as follows: +# 8: Maximum number of axes +# 0.05: Busy poll period in seconds +# 1: Idle poll period in seconds +# 1: Socket communication timeout in seconds +turboPmacController("$(NAME)", "$(ASYN_PORT)", 8, 0.05, 1, 1); + +# Define some axes for the specified MCU at the given slot (1, 2 and 5). No slot may be used twice! +turboPmacAxis("$(NAME)",1); +turboPmacAxis("$(NAME)",2); +turboPmacAxis("$(NAME)",5); + +# Set the number of subsequent timeouts +setMaxSubsequentTimeouts("$(NAME)", 20); + +# Configure the timeout frequency watchdog: +setThresholdComTimeout("$(NAME)", 100, 1); + +# Parametrize the EPICS record database with the substitution file named after the MCU. +epicsEnvSet("SINQDBPATH","$(sinqMotor_DB)/sinqMotor.db") +dbLoadTemplate("$(TOP)/$(NAME).substitutions", "INSTR=$(INSTR)$(NAME):,CONTROLLER=$(NAME)") +epicsEnvSet("SINQDBPATH","$(turboPmac_DB)/turboPmac.db") +dbLoadTemplate("$(TOP)/$(NAME).substitutions", "INSTR=$(INSTR)$(NAME):,CONTROLLER=$(NAME)") +dbLoadRecords("$(sinqMotor_DB)/asynRecord.db","P=$(INSTR)$(NAME),PORT=$(ASYN_PORT)") ``` ### Versioning diff --git a/src/turboPmacAxis.cpp b/src/turboPmacAxis.cpp index 96e8875..a5e3ac1 100644 --- a/src/turboPmacAxis.cpp +++ b/src/turboPmacAxis.cpp @@ -109,9 +109,6 @@ turboPmacAxis::~turboPmacAxis(void) { // clean up the pointer pC here. } -/** -Read the configuration at the first poll - */ asynStatus turboPmacAxis::init() { // Local variable declaration @@ -478,9 +475,11 @@ asynStatus turboPmacAxis::doPoll(bool *moving) { "state P%2.2d00 = %d\n", pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, axisNo_, axStatus); - pl_status = setStringParam( - pC_->motorMessageText_, - "Unreachable state has been reached. Please call the support."); + snprintf(userMessage, sizeof(userMessage), + "Unknown state P%2.2d00 = %d has been reached. Please call " + "the support.", + axisNo_, error); + pl_status = setStringParam(pC_->motorMessageText_, userMessage); if (pl_status != asynSuccess) { return pC_->paramLibAccessFailed(pl_status, "motorMessageText_", axisNo_, __PRETTY_FUNCTION__, @@ -675,11 +674,11 @@ asynStatus turboPmacAxis::doPoll(bool *moving) { pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, axisNo_, error); - snprintf(command, sizeof(command), + snprintf(userMessage, sizeof(userMessage), "Move command exceeds hardware limits (P%2.2d01 = %d). Please " "call the support.", axisNo_, error); - pl_status = setStringParam(pC_->motorMessageText_, command); + pl_status = setStringParam(pC_->motorMessageText_, userMessage); if (pl_status != asynSuccess) { return pC_->paramLibAccessFailed(pl_status, "motorMessageText_", axisNo_, __PRETTY_FUNCTION__, @@ -695,9 +694,10 @@ asynStatus turboPmacAxis::doPoll(bool *moving) { pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, axisNo_, error); - pl_status = setStringParam( - pC_->motorMessageText_, - "Unknown error P%2.2d01 = %d. Please call the support."); + snprintf(userMessage, sizeof(userMessage), + "Unknown error P%2.2d01 = %d. Please call the support.", + axisNo_, error); + pl_status = setStringParam(pC_->motorMessageText_, userMessage); if (pl_status != asynSuccess) { return pC_->paramLibAccessFailed(pl_status, "motorMessageText_", axisNo_, __PRETTY_FUNCTION__, diff --git a/src/turboPmacAxis.h b/src/turboPmacAxis.h index 96da1c1..c11029a 100644 --- a/src/turboPmacAxis.h +++ b/src/turboPmacAxis.h @@ -3,7 +3,7 @@ #include "sinqAxis.h" // Forward declaration of the controller class to resolve the cyclic dependency -// between C804Controller.h and C804Axis.h. See +// between the controller and the axis .h-file. See // https://en.cppreference.com/w/cpp/language/class. class turboPmacController; @@ -74,7 +74,7 @@ class turboPmacAxis : public sinqAxis { * The following steps are performed: * - Read out the motor status, motor position, velocity and acceleration * from the MCU and store this information in the parameter library. - * - Set the enable PV accordint to the initial status of the axis. + * - Set the enable PV according to the initial status of the axis. * * @return asynStatus */ diff --git a/src/turboPmacController.cpp b/src/turboPmacController.cpp index 07b5466..fe367ad 100644 --- a/src/turboPmacController.cpp +++ b/src/turboPmacController.cpp @@ -29,23 +29,11 @@ void adjustResponseForPrint(char *dst, const char *src, size_t buf_length) { } } -/** - * @brief Construct a new turboPmacController::turboPmacController object - * - * @param portName See documentation of sinqController - * @param ipPortConfigName See documentation of sinqController - * @param numAxes See documentation of sinqController - * @param movingPollPeriod See documentation of sinqController - * @param idlePollPeriod See documentation of sinqController - * @param comTimeout Time after which a communication timeout error - * is declared in writeRead (in seconds) - * @param extraParams See documentation of sinqController - */ turboPmacController::turboPmacController(const char *portName, const char *ipPortConfigName, int numAxes, double movingPollPeriod, double idlePollPeriod, - double comTimeout) + double comTimeout, int numExtraParams) : sinqController( portName, ipPortConfigName, numAxes, movingPollPeriod, idlePollPeriod, /* @@ -53,7 +41,7 @@ turboPmacController::turboPmacController(const char *portName, - REREAD_ENCODER_POSITION - READ_CONFIG */ - NUM_turboPmac_DRIVER_PARAMS) + numExtraParams + NUM_turboPmac_DRIVER_PARAMS) { @@ -510,13 +498,14 @@ asynStatus turboPmacController::writeInt32(asynUser *pasynUser, } } -asynStatus sinqController::readInt32(asynUser *pasynUser, epicsInt32 *value) { +asynStatus turboPmacController::readInt32(asynUser *pasynUser, + epicsInt32 *value) { // PMACs can be disabled if (pasynUser->reason == motorCanDisable_) { *value = 1; return asynSuccess; } else { - return asynMotorController::readInt32(pasynUser, value); + return sinqController::readInt32(pasynUser, value); } } @@ -582,7 +571,7 @@ static const iocshArg CreateControllerArg5 = {"Communication timeout (s)", static const iocshArg *const CreateControllerArgs[] = { &CreateControllerArg0, &CreateControllerArg1, &CreateControllerArg2, &CreateControllerArg3, &CreateControllerArg4, &CreateControllerArg5}; -static const iocshFuncDef configturboPmacCreateController = { +static const iocshFuncDef configTurboPmacCreateController = { "turboPmacController", 6, CreateControllerArgs}; static void configTurboPmacCreateControllerCallFunc(const iocshArgBuf *args) { turboPmacCreateController(args[0].sval, args[1].sval, args[2].ival, @@ -592,7 +581,7 @@ static void configTurboPmacCreateControllerCallFunc(const iocshArgBuf *args) { // This function is made known to EPICS in turboPmac.dbd and is called by EPICS // in order to register both functions in the IOC shell static void turboPmacControllerRegister(void) { - iocshRegister(&configturboPmacCreateController, + iocshRegister(&configTurboPmacCreateController, configTurboPmacCreateControllerCallFunc); } epicsExportRegistrar(turboPmacControllerRegister); diff --git a/src/turboPmacController.h b/src/turboPmacController.h index 28b6524..b0f8824 100644 --- a/src/turboPmacController.h +++ b/src/turboPmacController.h @@ -13,10 +13,10 @@ #include "turboPmacAxis.h" class turboPmacController : public sinqController { - public: /** - * @brief Construct a new turboPmacController object + * @brief Construct a new turboPmacController object. This function is meant + to be called from a child class constructor. * * @param portName See sinqController constructor * @param ipPortConfigName See sinqController constructor @@ -26,10 +26,12 @@ class turboPmacController : public sinqController { * @param comTimeout When trying to communicate with the device, the underlying asynOctetSyncIO interface waits for a response until this time (in seconds) has passed, then it declares a timeout. + * @param numExtraParams Number of extra parameters from a child class */ turboPmacController(const char *portName, const char *ipPortConfigName, int numAxes, double movingPollPeriod, - double idlePollPeriod, double comTimeout); + double idlePollPeriod, double comTimeout, + int numExtraParams = 0); /** * @brief Get the axis object @@ -49,6 +51,17 @@ class turboPmacController : public sinqController { */ turboPmacAxis *getAxis(int axisNo); + /** + * @brief Overloaded function of sinqController + * + * The function is overloaded in order to read motorCanDisable_ + * + * @param pasynUser + * @param value + * @return asynStatus + */ + asynStatus readInt32(asynUser *pasynUser, epicsInt32 *value); + /** * @brief Overloaded function of sinqController * @@ -114,7 +127,7 @@ class turboPmacController : public sinqController { const char *functionName, int lineNumber); - private: + protected: // Set the maximum buffer size. This is an empirical value which must be // large enough to avoid overflows for all commands to the device / // responses from it.