Compare commits
7 Commits
Author | SHA1 | Date | |
---|---|---|---|
295cd34993 | |||
b62a5fd699 | |||
a990da4245 | |||
83a74ce8d0 | |||
445dd44c19 | |||
d471041c59 | |||
967613447b |
2
Makefile
2
Makefile
@ -14,7 +14,7 @@ REQUIRED+=sinqMotor
|
|||||||
motorBase_VERSION=7.2.2
|
motorBase_VERSION=7.2.2
|
||||||
|
|
||||||
# Specify the version of sinqMotor we want to build against
|
# Specify the version of sinqMotor we want to build against
|
||||||
sinqMotor_VERSION=0.8.0
|
sinqMotor_VERSION=0.11.0
|
||||||
|
|
||||||
# These headers allow to depend on this library for derived drivers.
|
# These headers allow to depend on this library for derived drivers.
|
||||||
HEADERS += src/turboPmacAxis.h
|
HEADERS += src/turboPmacAxis.h
|
||||||
|
10
README.md
10
README.md
@ -1,5 +1,7 @@
|
|||||||
# turboPmac
|
# turboPmac
|
||||||
|
|
||||||
|
## <span style="color:red">Please read the documentation of sinqMotor first: https://git.psi.ch/sinq-epics-modules/sinqmotor</span>
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
This is a driver for the Turbo PMAC motion controller with the SINQ communication protocol. It is based on the sinqMotor shared library (https://git.psi.ch/sinq-epics-modules/sinqmotor). The header files contain detailed documentation for all public functions. The headers themselves are exported when building the library to allow other drivers to depend on this one.
|
This is a driver for the Turbo PMAC motion controller with the SINQ communication protocol. It is based on the sinqMotor shared library (https://git.psi.ch/sinq-epics-modules/sinqmotor). The header files contain detailed documentation for all public functions. The headers themselves are exported when building the library to allow other drivers to depend on this one.
|
||||||
@ -21,11 +23,11 @@ turboPmac exports the following IOC shell functions:
|
|||||||
- `turboPmacController`: Create a new controller object.
|
- `turboPmacController`: Create a new controller object.
|
||||||
- `turboPmacAxis`: Create a new axis object.
|
- `turboPmacAxis`: Create a new axis object.
|
||||||
|
|
||||||
The full mcu.cmd file looks like this:
|
The full turboPmacX.cmd file looks like this:
|
||||||
|
|
||||||
```
|
```
|
||||||
# Define the name of the controller and the corresponding port
|
# Define the name of the controller and the corresponding port
|
||||||
epicsEnvSet("NAME","mcu")
|
epicsEnvSet("NAME","turboPmacX")
|
||||||
epicsEnvSet("ASYN_PORT","p$(NAME)")
|
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
|
# 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
|
||||||
@ -47,8 +49,8 @@ turboPmacAxis("$(NAME)",5);
|
|||||||
# Set the number of subsequent timeouts
|
# Set the number of subsequent timeouts
|
||||||
setMaxSubsequentTimeouts("$(NAME)", 20);
|
setMaxSubsequentTimeouts("$(NAME)", 20);
|
||||||
|
|
||||||
# Configure the timeout frequency watchdog:
|
# Configure the timeout frequency watchdog: A maximum of 10 timeouts are allowed in 300 seconds before an alarm message is sent.
|
||||||
setThresholdComTimeout("$(NAME)", 100, 1);
|
setThresholdComTimeout("$(NAME)", 300, 10);
|
||||||
|
|
||||||
# Parametrize the EPICS record database with the substitution file named after the MCU.
|
# Parametrize the EPICS record database with the substitution file named after the MCU.
|
||||||
epicsEnvSet("SINQDBPATH","$(sinqMotor_DB)/sinqMotor.db")
|
epicsEnvSet("SINQDBPATH","$(sinqMotor_DB)/sinqMotor.db")
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -81,6 +81,14 @@ class turboPmacAxis : public sinqAxis {
|
|||||||
*/
|
*/
|
||||||
asynStatus init();
|
asynStatus init();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Implementation of the `doReset` function from sinqAxis.
|
||||||
|
*
|
||||||
|
* @param on
|
||||||
|
* @return asynStatus
|
||||||
|
*/
|
||||||
|
asynStatus doReset();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Enable / disable the axis.
|
* @brief Enable / disable the axis.
|
||||||
*
|
*
|
||||||
@ -104,6 +112,16 @@ class turboPmacAxis : public sinqAxis {
|
|||||||
*/
|
*/
|
||||||
asynStatus rereadEncoder();
|
asynStatus rereadEncoder();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Interpret the error code and populate the user message accordingly
|
||||||
|
*
|
||||||
|
* @param error
|
||||||
|
* @param userMessage
|
||||||
|
* @param sizeUserMessage
|
||||||
|
* @return asynStatus
|
||||||
|
*/
|
||||||
|
asynStatus handleError(int error, char *userMessage, int sizeUserMessage);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
turboPmacController *pC_;
|
turboPmacController *pC_;
|
||||||
|
|
||||||
@ -112,9 +130,6 @@ class turboPmacAxis : public sinqAxis {
|
|||||||
|
|
||||||
// The axis status is used when enabling / disabling the motor
|
// The axis status is used when enabling / disabling the motor
|
||||||
int axisStatus_;
|
int axisStatus_;
|
||||||
|
|
||||||
private:
|
|
||||||
friend class turboPmacController;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -49,27 +49,12 @@ turboPmacController::turboPmacController(const char *portName,
|
|||||||
asynStatus status = asynSuccess;
|
asynStatus status = asynSuccess;
|
||||||
|
|
||||||
// Initialization of all member variables
|
// Initialization of all member variables
|
||||||
lowLevelPortUser_ = nullptr;
|
|
||||||
comTimeout_ = comTimeout;
|
comTimeout_ = comTimeout;
|
||||||
|
|
||||||
// Maximum allowed number of subsequent timeouts before the user is
|
// Maximum allowed number of subsequent timeouts before the user is
|
||||||
// informed.
|
// informed.
|
||||||
maxSubsequentTimeouts_ = 10;
|
maxSubsequentTimeouts_ = 10;
|
||||||
|
|
||||||
// =========================================================================;
|
|
||||||
|
|
||||||
/*
|
|
||||||
We try to connect to the port via the port name provided by the constructor.
|
|
||||||
If this fails, the function is terminated via exit
|
|
||||||
*/
|
|
||||||
pasynOctetSyncIO->connect(ipPortConfigName, 0, &lowLevelPortUser_, NULL);
|
|
||||||
if (status != asynSuccess || lowLevelPortUser_ == nullptr) {
|
|
||||||
errlogPrintf("Controller \"%s\" => %s, line %d\nFATAL ERROR "
|
|
||||||
"(cannot connect to MCU controller).\nTerminating IOC",
|
|
||||||
portName, __PRETTY_FUNCTION__, __LINE__);
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
// Create additional parameter library entries
|
// Create additional parameter library entries
|
||||||
|
|
||||||
@ -103,15 +88,15 @@ turboPmacController::turboPmacController(const char *portName,
|
|||||||
const char *message_from_device =
|
const char *message_from_device =
|
||||||
"\006"; // Hex-code for ACK (acknowledge) -> Each message from the MCU
|
"\006"; // Hex-code for ACK (acknowledge) -> Each message from the MCU
|
||||||
// is terminated by this value
|
// is terminated by this value
|
||||||
status = pasynOctetSyncIO->setInputEos(
|
status = pasynOctetSyncIO->setInputEos(ipPortUser_, message_from_device,
|
||||||
lowLevelPortUser_, message_from_device, strlen(message_from_device));
|
strlen(message_from_device));
|
||||||
if (status != asynSuccess) {
|
if (status != asynSuccess) {
|
||||||
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
|
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
|
||||||
"Controller \"%s\" => %s, line %d\nFATAL ERROR "
|
"Controller \"%s\" => %s, line %d\nFATAL ERROR "
|
||||||
"(setting input EOS failed with %s).\nTerminating IOC",
|
"(setting input EOS failed with %s).\nTerminating IOC",
|
||||||
portName, __PRETTY_FUNCTION__, __LINE__,
|
portName, __PRETTY_FUNCTION__, __LINE__,
|
||||||
stringifyAsynStatus(status));
|
stringifyAsynStatus(status));
|
||||||
pasynOctetSyncIO->disconnect(lowLevelPortUser_);
|
pasynOctetSyncIO->disconnect(ipPortUser_);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,7 +108,7 @@ turboPmacController::turboPmacController(const char *portName,
|
|||||||
"with %s).\nTerminating IOC",
|
"with %s).\nTerminating IOC",
|
||||||
portName, __PRETTY_FUNCTION__, __LINE__,
|
portName, __PRETTY_FUNCTION__, __LINE__,
|
||||||
stringifyAsynStatus(status));
|
stringifyAsynStatus(status));
|
||||||
pasynOctetSyncIO->disconnect(lowLevelPortUser_);
|
pasynOctetSyncIO->disconnect(ipPortUser_);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -254,8 +239,8 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
|||||||
trying to reconnect. If the problem persists, ask them to call the support
|
trying to reconnect. If the problem persists, ask them to call the support
|
||||||
*/
|
*/
|
||||||
|
|
||||||
status = pasynOctetSyncIO->write(lowLevelPortUser_, fullCommand,
|
status = pasynOctetSyncIO->write(ipPortUser_, fullCommand, fullComandLength,
|
||||||
fullComandLength, comTimeout_, &nbytesOut);
|
comTimeout_, &nbytesOut);
|
||||||
|
|
||||||
msgPrintControlKey writeKey =
|
msgPrintControlKey writeKey =
|
||||||
msgPrintControlKey(portName, axisNo, __PRETTY_FUNCTION__, __LINE__);
|
msgPrintControlKey(portName, axisNo, __PRETTY_FUNCTION__, __LINE__);
|
||||||
@ -279,7 +264,7 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
|||||||
checkMaxSubsequentTimeouts(timeoutCounter, axis);
|
checkMaxSubsequentTimeouts(timeoutCounter, axis);
|
||||||
timeoutCounter += 1;
|
timeoutCounter += 1;
|
||||||
|
|
||||||
status = pasynOctetSyncIO->write(lowLevelPortUser_, fullCommand,
|
status = pasynOctetSyncIO->write(ipPortUser_, fullCommand,
|
||||||
fullComandLength, comTimeout_,
|
fullComandLength, comTimeout_,
|
||||||
&nbytesOut);
|
&nbytesOut);
|
||||||
if (status != asynTimeout) {
|
if (status != asynTimeout) {
|
||||||
@ -300,12 +285,12 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
|||||||
stringifyAsynStatus(status), msgPrintControl_.getSuffix());
|
stringifyAsynStatus(status), msgPrintControl_.getSuffix());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
msgPrintControl_.resetCount(writeKey);
|
msgPrintControl_.resetCount(writeKey, pasynUserSelf);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the response from the MCU buffer
|
// Read the response from the MCU buffer
|
||||||
status = pasynOctetSyncIO->read(lowLevelPortUser_, response, MAXBUF_,
|
status = pasynOctetSyncIO->read(ipPortUser_, response, MAXBUF_, comTimeout_,
|
||||||
comTimeout_, &nbytesIn, &eomReason);
|
&nbytesIn, &eomReason);
|
||||||
|
|
||||||
msgPrintControlKey readKey =
|
msgPrintControlKey readKey =
|
||||||
msgPrintControlKey(portName, axisNo, __PRETTY_FUNCTION__, __LINE__);
|
msgPrintControlKey(portName, axisNo, __PRETTY_FUNCTION__, __LINE__);
|
||||||
@ -330,9 +315,8 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
|||||||
checkMaxSubsequentTimeouts(timeoutCounter, axis);
|
checkMaxSubsequentTimeouts(timeoutCounter, axis);
|
||||||
timeoutCounter += 1;
|
timeoutCounter += 1;
|
||||||
|
|
||||||
status =
|
status = pasynOctetSyncIO->read(ipPortUser_, response, MAXBUF_,
|
||||||
pasynOctetSyncIO->read(lowLevelPortUser_, response, MAXBUF_,
|
comTimeout_, &nbytesIn, &eomReason);
|
||||||
comTimeout_, &nbytesIn, &eomReason);
|
|
||||||
if (status != asynTimeout) {
|
if (status != asynTimeout) {
|
||||||
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
|
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
|
||||||
"Controller \"%s\", axis %d => %s, line "
|
"Controller \"%s\", axis %d => %s, line "
|
||||||
@ -351,7 +335,7 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
|||||||
stringifyAsynStatus(status), msgPrintControl_.getSuffix());
|
stringifyAsynStatus(status), msgPrintControl_.getSuffix());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
msgPrintControl_.resetCount(readKey);
|
msgPrintControl_.resetCount(readKey, pasynUserSelf);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timeoutStatus == asynError) {
|
if (timeoutStatus == asynError) {
|
||||||
@ -377,7 +361,7 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
|||||||
eomReason, msgPrintControl_.getSuffix());
|
eomReason, msgPrintControl_.getSuffix());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
msgPrintControl_.resetCount(terminateKey);
|
msgPrintControl_.resetCount(terminateKey, pasynUserSelf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -412,7 +396,7 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
|||||||
modResponse, command);
|
modResponse, command);
|
||||||
status = asynError;
|
status = asynError;
|
||||||
} else {
|
} else {
|
||||||
msgPrintControl_.resetCount(numResponsesKey);
|
msgPrintControl_.resetCount(numResponsesKey, pasynUserSelf);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create custom error messages for different failure modes, if no error
|
// Create custom error messages for different failure modes, if no error
|
||||||
@ -500,23 +484,14 @@ asynStatus turboPmacController::writeInt32(asynUser *pasynUser,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
asynStatus turboPmacController::readInt32(asynUser *pasynUser,
|
asynStatus turboPmacController::couldNotParseResponse(const char *command,
|
||||||
epicsInt32 *value) {
|
const char *response,
|
||||||
// PMACs can be disabled
|
int axisNo,
|
||||||
if (pasynUser->reason == motorCanDisable_) {
|
const char *functionName,
|
||||||
*value = 1;
|
int lineNumber) {
|
||||||
return asynSuccess;
|
|
||||||
} else {
|
|
||||||
return sinqController::readInt32(pasynUser, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
asynStatus turboPmacController::errMsgCouldNotParseResponse(
|
|
||||||
const char *command, const char *response, int axisNo,
|
|
||||||
const char *functionName, int lineNumber) {
|
|
||||||
char modifiedResponse[MAXBUF_] = {0};
|
char modifiedResponse[MAXBUF_] = {0};
|
||||||
adjustResponseForPrint(modifiedResponse, response, MAXBUF_);
|
adjustResponseForPrint(modifiedResponse, response, MAXBUF_);
|
||||||
return sinqController::errMsgCouldNotParseResponse(
|
return sinqController::couldNotParseResponse(
|
||||||
command, modifiedResponse, axisNo, functionName, lineNumber);
|
command, modifiedResponse, axisNo, functionName, lineNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,17 +51,6 @@ class turboPmacController : public sinqController {
|
|||||||
*/
|
*/
|
||||||
turboPmacAxis *getTurboPmacAxis(int axisNo);
|
turboPmacAxis *getTurboPmacAxis(int axisNo);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Overloaded function of sinqController
|
|
||||||
*
|
|
||||||
* The function is overloaded in order to read motorCanDisable_.
|
|
||||||
*
|
|
||||||
* @param pasynUser
|
|
||||||
* @param value
|
|
||||||
* @return asynStatus
|
|
||||||
*/
|
|
||||||
virtual asynStatus readInt32(asynUser *pasynUser, epicsInt32 *value);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Overloaded function of sinqController
|
* @brief Overloaded function of sinqController
|
||||||
*
|
*
|
||||||
@ -73,9 +62,6 @@ class turboPmacController : public sinqController {
|
|||||||
*/
|
*/
|
||||||
virtual asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value);
|
virtual asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value);
|
||||||
|
|
||||||
protected:
|
|
||||||
asynUser *lowLevelPortUser_;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Send a command to the hardware and receive a response
|
* @brief Send a command to the hardware and receive a response
|
||||||
*
|
*
|
||||||
@ -96,13 +82,13 @@ class turboPmacController : public sinqController {
|
|||||||
int numExpectedResponses);
|
int numExpectedResponses);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Specialized version of sinqController::errMsgCouldNotParseResponse
|
* @brief Specialized version of sinqController::couldNotParseResponse
|
||||||
* for turboPmac
|
* for turboPmac
|
||||||
*
|
*
|
||||||
* This is an overloaded version of
|
* This is an overloaded version of
|
||||||
* sinqController::errMsgCouldNotParseResponse which calls
|
* sinqController::couldNotParseResponse which calls
|
||||||
* adjustResponseForLogging on response before handing it over to
|
* adjustResponseForLogging on response before handing it over to
|
||||||
* sinqController::errMsgCouldNotParseResponse.
|
* sinqController::couldNotParseResponse.
|
||||||
*
|
*
|
||||||
* @param command Command which led to the unparseable message
|
* @param command Command which led to the unparseable message
|
||||||
* @param response Response which wasn't parseable
|
* @param response Response which wasn't parseable
|
||||||
@ -113,17 +99,20 @@ class turboPmacController : public sinqController {
|
|||||||
called. It is recommended to use a macro, e.g. __LINE__.
|
called. It is recommended to use a macro, e.g. __LINE__.
|
||||||
* @return asynStatus Returns asynError.
|
* @return asynStatus Returns asynError.
|
||||||
*/
|
*/
|
||||||
asynStatus errMsgCouldNotParseResponse(const char *command,
|
asynStatus couldNotParseResponse(const char *command, const char *response,
|
||||||
const char *response, int axisNo_,
|
int axisNo_, const char *functionName,
|
||||||
const char *functionName,
|
int lineNumber);
|
||||||
int lineNumber);
|
|
||||||
|
// Accessors for additional PVs
|
||||||
|
int rereadEncoderPosition() { return rereadEncoderPosition_; }
|
||||||
|
int readConfig() { return readConfig_; }
|
||||||
|
|
||||||
protected:
|
|
||||||
// Set the maximum buffer size. This is an empirical value which must be
|
// Set the maximum buffer size. This is an empirical value which must be
|
||||||
// large enough to avoid overflows for all commands to the device /
|
// large enough to avoid overflows for all commands to the device /
|
||||||
// responses from it.
|
// responses from it.
|
||||||
static const uint32_t MAXBUF_ = 200;
|
static const uint32_t MAXBUF_ = 200;
|
||||||
|
|
||||||
|
protected:
|
||||||
/*
|
/*
|
||||||
Timeout for the communication process in seconds
|
Timeout for the communication process in seconds
|
||||||
*/
|
*/
|
||||||
@ -136,8 +125,6 @@ class turboPmacController : public sinqController {
|
|||||||
int rereadEncoderPosition_;
|
int rereadEncoderPosition_;
|
||||||
int readConfig_;
|
int readConfig_;
|
||||||
#define LAST_turboPmac_PARAM readConfig_
|
#define LAST_turboPmac_PARAM readConfig_
|
||||||
|
|
||||||
friend class turboPmacAxis;
|
|
||||||
};
|
};
|
||||||
#define NUM_turboPmac_DRIVER_PARAMS \
|
#define NUM_turboPmac_DRIVER_PARAMS \
|
||||||
(&LAST_turboPmac_PARAM - &FIRST_turboPmac_PARAM + 1)
|
(&LAST_turboPmac_PARAM - &FIRST_turboPmac_PARAM + 1)
|
||||||
|
Reference in New Issue
Block a user