Compare commits
3 Commits
Author | SHA1 | Date | |
---|---|---|---|
d6adf1ad2a | |||
dfb55a1b76 | |||
8f597550fa |
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.7.0
|
sinqMotor_VERSION=0.8.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
|
||||||
|
52
README.md
52
README.md
@ -17,25 +17,45 @@ The folder "utils" contains utility scripts for working with pmac motor controll
|
|||||||
|
|
||||||
### Usage in IOC shell
|
### 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.
|
- `turboPmacController`: Create a new controller object.
|
||||||
- `turboPmacAxis`: Create a new axis object.
|
- `turboPmacAxis`: Create a new axis object.
|
||||||
These functions are parametrized as follows:
|
|
||||||
|
The full mcu.cmd file looks like this:
|
||||||
|
|
||||||
```
|
```
|
||||||
turboPmacController(
|
# Define the name of the controller and the corresponding port
|
||||||
"$(NAME)", # Name of the MCU, e.g. mcu1. This parameter should be provided by an environment variable.
|
epicsEnvSet("NAME","mcu")
|
||||||
"$(ASYN_PORT)", # IP-Port of the MCU. This parameter should be provided by an environment variable.
|
epicsEnvSet("ASYN_PORT","p$(NAME)")
|
||||||
8, # Maximum number of axes
|
|
||||||
0.05, # Busy poll period in seconds
|
# 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
|
||||||
1, # Idle poll period in seconds
|
drvAsynIPPortConfigure("$(ASYN_PORT)","172.28.101.24:1025")
|
||||||
0.05 # Communication timeout in seconds
|
|
||||||
);
|
# 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
|
||||||
turboPmacAxis(
|
# 0.05: Busy poll period in seconds
|
||||||
"$(NAME)", # Name of the associated MCU, e.g. mcu1. This parameter should be provided by an environment variable.
|
# 1: Idle poll period in seconds
|
||||||
1 # Index of the axis.
|
# 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
|
### Versioning
|
||||||
|
@ -35,7 +35,8 @@ static void epicsInithookFunction(initHookState iState) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
turboPmacAxis::turboPmacAxis(turboPmacController *pC, int axisNo)
|
turboPmacAxis::turboPmacAxis(turboPmacController *pC, int axisNo,
|
||||||
|
bool initialize)
|
||||||
: sinqAxis(pC, axisNo), pC_(pC) {
|
: sinqAxis(pC, axisNo), pC_(pC) {
|
||||||
|
|
||||||
asynStatus status = asynSuccess;
|
asynStatus status = asynSuccess;
|
||||||
@ -63,13 +64,17 @@ turboPmacAxis::turboPmacAxis(turboPmacController *pC, int axisNo)
|
|||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register the hook function during construction of the first axis object
|
if (initialize) {
|
||||||
if (axes.empty()) {
|
// Register the hook function during construction of the first axis
|
||||||
initHookRegister(&epicsInithookFunction);
|
// object
|
||||||
}
|
if (axes.empty()) {
|
||||||
|
initHookRegister(&epicsInithookFunction);
|
||||||
|
}
|
||||||
|
|
||||||
// Collect all axes into this list which will be used in the hook function
|
// Collect all axes into this list which will be used in the hook
|
||||||
axes.push_back(this);
|
// function
|
||||||
|
axes.push_back(this);
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize all member variables
|
// Initialize all member variables
|
||||||
waitForHandshake_ = false;
|
waitForHandshake_ = false;
|
||||||
@ -109,9 +114,6 @@ turboPmacAxis::~turboPmacAxis(void) {
|
|||||||
// clean up the pointer pC here.
|
// clean up the pointer pC here.
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
Read the configuration at the first poll
|
|
||||||
*/
|
|
||||||
asynStatus turboPmacAxis::init() {
|
asynStatus turboPmacAxis::init() {
|
||||||
|
|
||||||
// Local variable declaration
|
// Local variable declaration
|
||||||
@ -363,39 +365,43 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
|
|||||||
__PRETTY_FUNCTION__, __LINE__);
|
__PRETTY_FUNCTION__, __LINE__);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Intepret the status
|
// Create the unique callsite identifier manually so it can be used later in
|
||||||
|
// the shouldBePrinted calls.
|
||||||
|
msgPrintControlKey keyStatus = msgPrintControlKey(
|
||||||
|
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
|
||||||
|
bool resetCountStatus = true;
|
||||||
|
|
||||||
|
// Interpret the status
|
||||||
switch (axStatus) {
|
switch (axStatus) {
|
||||||
case -6:
|
case -6:
|
||||||
|
// Axis is stopping
|
||||||
*moving = true;
|
*moving = true;
|
||||||
|
|
||||||
asynPrint(
|
|
||||||
pC_->pasynUserSelf, ASYN_TRACE_FLOW,
|
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nAxis is stopping\n",
|
|
||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
|
|
||||||
break;
|
break;
|
||||||
case -5:
|
case -5:
|
||||||
|
// Axis is deactivated
|
||||||
*moving = false;
|
*moving = false;
|
||||||
|
|
||||||
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_FLOW,
|
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nAxis is "
|
|
||||||
"deactivated\n",
|
|
||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
|
|
||||||
|
|
||||||
pl_status = setStringParam(pC_->motorMessageText_, "Deactivated");
|
pl_status = setStringParam(pC_->motorMessageText_, "Deactivated");
|
||||||
if (pl_status != asynSuccess) {
|
if (pl_status != asynSuccess) {
|
||||||
return pC_->paramLibAccessFailed(pl_status, "motorMessageText_",
|
return pC_->paramLibAccessFailed(pl_status, "motorMessageText_",
|
||||||
axisNo_, __PRETTY_FUNCTION__,
|
axisNo_, __PRETTY_FUNCTION__,
|
||||||
__LINE__);
|
__LINE__);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case -4:
|
case -4:
|
||||||
|
// Emergency stop
|
||||||
*moving = false;
|
*moving = false;
|
||||||
|
|
||||||
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
|
if (pC_->msgPrintControl_.shouldBePrinted(keyStatus, true,
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nEmergency stop "
|
pC_->pasynUserSelf)) {
|
||||||
"activated\n",
|
asynPrint(
|
||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
|
pC_->pasynUserSelf, ASYN_TRACE_ERROR,
|
||||||
|
"Controller \"%s\", axis %d => %s, line %d\nEmergency stop "
|
||||||
|
"activated.%s\n",
|
||||||
|
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||||
|
pC_->msgPrintControl_.getSuffix());
|
||||||
|
}
|
||||||
|
resetCountStatus = false;
|
||||||
|
|
||||||
pl_status = setStringParam(pC_->motorMessageText_, "Emergency stop");
|
pl_status = setStringParam(pC_->motorMessageText_, "Emergency stop");
|
||||||
if (pl_status != asynSuccess) {
|
if (pl_status != asynSuccess) {
|
||||||
@ -406,13 +412,9 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
case -3:
|
case -3:
|
||||||
|
// Disabled
|
||||||
*moving = false;
|
*moving = false;
|
||||||
|
|
||||||
asynPrint(
|
|
||||||
pC_->pasynUserSelf, ASYN_TRACE_FLOW,
|
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nAxis %d is disabled\n",
|
|
||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, axisNo_);
|
|
||||||
|
|
||||||
pl_status = setStringParam(pC_->motorMessageText_, "Disabled");
|
pl_status = setStringParam(pC_->motorMessageText_, "Disabled");
|
||||||
if (pl_status != asynSuccess) {
|
if (pl_status != asynSuccess) {
|
||||||
return pC_->paramLibAccessFailed(pl_status, "motorMessageText_",
|
return pC_->paramLibAccessFailed(pl_status, "motorMessageText_",
|
||||||
@ -422,43 +424,24 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
|
// Idle
|
||||||
*moving = false;
|
*moving = false;
|
||||||
|
|
||||||
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_FLOW,
|
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nAxis is idle\n",
|
|
||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
|
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
|
// Move order acknowledged
|
||||||
*moving = true;
|
*moving = true;
|
||||||
|
|
||||||
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_FLOW,
|
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nMove order "
|
|
||||||
"acknowledged\n",
|
|
||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
|
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
|
// Move order confirmed possible
|
||||||
*moving = true;
|
*moving = true;
|
||||||
|
|
||||||
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_FLOW,
|
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nMove order is "
|
|
||||||
"possible\n",
|
|
||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
|
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
|
// Axis in Air Cushion Output status
|
||||||
*moving = true;
|
*moving = true;
|
||||||
|
|
||||||
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_FLOW,
|
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nAxis in Air "
|
|
||||||
"Cushion Output status\n",
|
|
||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
|
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
|
// Axis in Air Cushion Input status
|
||||||
*moving = true;
|
*moving = true;
|
||||||
|
|
||||||
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_FLOW,
|
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nAxis in Air "
|
|
||||||
"Cushion Input status\n",
|
|
||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
|
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
*moving = true;
|
*moving = true;
|
||||||
@ -472,15 +455,22 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
|
|||||||
default:
|
default:
|
||||||
*moving = false;
|
*moving = false;
|
||||||
|
|
||||||
asynPrint(
|
if (pC_->msgPrintControl_.shouldBePrinted(keyStatus, true,
|
||||||
pC_->pasynUserSelf, ASYN_TRACE_ERROR,
|
pC_->pasynUserSelf)) {
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nReached unreachable "
|
|
||||||
"state P%2.2d00 = %d\n",
|
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
|
||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, axisNo_,
|
"Controller \"%s\", axis %d => %s, line %d\nReached "
|
||||||
axStatus);
|
"unreachable state P%2.2d00 = %d.%s\n",
|
||||||
pl_status = setStringParam(
|
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||||
pC_->motorMessageText_,
|
axisNo_, axStatus, pC_->msgPrintControl_.getSuffix());
|
||||||
"Unreachable state has been reached. Please call the support.");
|
}
|
||||||
|
resetCountStatus = false;
|
||||||
|
|
||||||
|
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) {
|
if (pl_status != asynSuccess) {
|
||||||
return pC_->paramLibAccessFailed(pl_status, "motorMessageText_",
|
return pC_->paramLibAccessFailed(pl_status, "motorMessageText_",
|
||||||
axisNo_, __PRETTY_FUNCTION__,
|
axisNo_, __PRETTY_FUNCTION__,
|
||||||
@ -488,6 +478,10 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (resetCountStatus) {
|
||||||
|
pC_->msgPrintControl_.resetCount(keyStatus);
|
||||||
|
}
|
||||||
|
|
||||||
if (*moving) {
|
if (*moving) {
|
||||||
// If the axis is moving, evaluate the movement direction
|
// If the axis is moving, evaluate the movement direction
|
||||||
if ((currentPosition - previousPosition) > 0) {
|
if ((currentPosition - previousPosition) > 0) {
|
||||||
@ -497,19 +491,28 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error handling
|
// Create the unique callsite identifier manually so it can be used later in
|
||||||
|
// the shouldBePrinted calls.
|
||||||
|
msgPrintControlKey keyError = msgPrintControlKey(
|
||||||
|
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
|
||||||
|
bool resetError = true;
|
||||||
|
|
||||||
switch (error) {
|
switch (error) {
|
||||||
case 0:
|
case 0:
|
||||||
// No error
|
// No error -> Reset the message repetition watchdog
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
// EPICS should already prevent this issue in the first place,
|
// EPICS should already prevent this issue in the first place,
|
||||||
// since it contains the user limits
|
// since it contains the user limits
|
||||||
asynPrint(
|
if (pC_->msgPrintControl_.shouldBePrinted(keyError, true,
|
||||||
pC_->pasynUserSelf, ASYN_TRACE_ERROR,
|
pC_->pasynUserSelf)) {
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nTarget position would "
|
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
|
||||||
"exceed user limits.\n",
|
"Controller \"%s\", axis %d => %s, line %d\nTarget "
|
||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
|
"position would exceed user limits.%s\n",
|
||||||
|
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||||
|
pC_->msgPrintControl_.getSuffix());
|
||||||
|
}
|
||||||
|
resetError = false;
|
||||||
|
|
||||||
pl_status = setStringParam(pC_->motorMessageText_,
|
pl_status = setStringParam(pC_->motorMessageText_,
|
||||||
"Target position would exceed software "
|
"Target position would exceed software "
|
||||||
@ -524,11 +527,17 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
|
|||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
// Command not possible
|
// Command not possible
|
||||||
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
|
if (pC_->msgPrintControl_.shouldBePrinted(keyStatus, true,
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nAxis is "
|
pC_->pasynUserSelf)) {
|
||||||
"still moving, but received another move command. EPICS "
|
asynPrint(
|
||||||
"should prevent this, check if *moving is set correctly.\n",
|
pC_->pasynUserSelf, ASYN_TRACE_ERROR,
|
||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
|
"Controller \"%s\", axis %d => %s, line %d\nAxis is "
|
||||||
|
"still moving, but received another move command. EPICS "
|
||||||
|
"should prevent this, check if *moving is set correctly.%s\n",
|
||||||
|
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||||
|
pC_->msgPrintControl_.getSuffix());
|
||||||
|
}
|
||||||
|
resetError = false;
|
||||||
|
|
||||||
pl_status = setStringParam(pC_->motorMessageText_,
|
pl_status = setStringParam(pC_->motorMessageText_,
|
||||||
"Axis received move command while it is "
|
"Axis received move command while it is "
|
||||||
@ -542,12 +551,15 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
|
|||||||
poll_status = asynError;
|
poll_status = asynError;
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
asynPrint(
|
if (pC_->msgPrintControl_.shouldBePrinted(keyError, true,
|
||||||
pC_->pasynUserSelf, ASYN_TRACE_ERROR,
|
pC_->pasynUserSelf)) {
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nAir cushion feedback "
|
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
|
||||||
"stopped during movement (P%2.2d01 = %d).\n",
|
"Controller \"%s\", axis %d => %s, line %d\nAir cushion "
|
||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, axisNo_,
|
"feedback stopped during movement (P%2.2d01 = %d).%s\n",
|
||||||
error);
|
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||||
|
axisNo_, error, pC_->msgPrintControl_.getSuffix());
|
||||||
|
}
|
||||||
|
resetError = false;
|
||||||
|
|
||||||
snprintf(userMessage, sizeof(userMessage),
|
snprintf(userMessage, sizeof(userMessage),
|
||||||
"Air cushion feedback stopped during movement (P%2.2d01 = "
|
"Air cushion feedback stopped during movement (P%2.2d01 = "
|
||||||
@ -562,11 +574,16 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 9:
|
case 9:
|
||||||
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
|
if (pC_->msgPrintControl_.shouldBePrinted(keyError, true,
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nNo air cushion "
|
pC_->pasynUserSelf)) {
|
||||||
"feedback before movement start (P%2.2d01 = %d).\n",
|
asynPrint(
|
||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
pC_->pasynUserSelf, ASYN_TRACE_ERROR,
|
||||||
axisNo_, error);
|
"Controller \"%s\", axis %d => %s, line %d\nNo air cushion "
|
||||||
|
"feedback before movement start (P%2.2d01 = %d).%s\n",
|
||||||
|
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, axisNo_,
|
||||||
|
error, pC_->msgPrintControl_.getSuffix());
|
||||||
|
}
|
||||||
|
resetError = false;
|
||||||
|
|
||||||
snprintf(userMessage, sizeof(userMessage),
|
snprintf(userMessage, sizeof(userMessage),
|
||||||
"No air cushion feedback before movement start (P%2.2d01 = "
|
"No air cushion feedback before movement start (P%2.2d01 = "
|
||||||
@ -586,10 +603,17 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
|
|||||||
error case can only happen if either the axis has an incremental encoder
|
error case can only happen if either the axis has an incremental encoder
|
||||||
which is not properly homed or if a bug occured.
|
which is not properly homed or if a bug occured.
|
||||||
*/
|
*/
|
||||||
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
|
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nAxis hit the "
|
if (pC_->msgPrintControl_.shouldBePrinted(keyError, true,
|
||||||
"controller limits.\n",
|
pC_->pasynUserSelf)) {
|
||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
|
asynPrint(
|
||||||
|
pC_->pasynUserSelf, ASYN_TRACE_ERROR,
|
||||||
|
"Controller \"%s\", axis %d => %s, line %d\nAxis hit the "
|
||||||
|
"controller limits.%s\n",
|
||||||
|
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||||
|
pC_->msgPrintControl_.getSuffix());
|
||||||
|
}
|
||||||
|
resetError = false;
|
||||||
|
|
||||||
snprintf(userMessage, sizeof(userMessage),
|
snprintf(userMessage, sizeof(userMessage),
|
||||||
"Software limits or end switch hit (P%2.2d01 = %d). Try "
|
"Software limits or end switch hit (P%2.2d01 = %d). Try "
|
||||||
@ -609,10 +633,17 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
|
|||||||
break;
|
break;
|
||||||
case 11:
|
case 11:
|
||||||
// Following error
|
// Following error
|
||||||
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
|
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nMaximum allowed "
|
if (pC_->msgPrintControl_.shouldBePrinted(keyError, true,
|
||||||
"following error exceeded.\n",
|
pC_->pasynUserSelf)) {
|
||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
|
asynPrint(
|
||||||
|
pC_->pasynUserSelf, ASYN_TRACE_ERROR,
|
||||||
|
"Controller \"%s\", axis %d => %s, line %d\nMaximum allowed "
|
||||||
|
"following error exceeded.%s\n",
|
||||||
|
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||||
|
pC_->msgPrintControl_.getSuffix());
|
||||||
|
}
|
||||||
|
resetError = false;
|
||||||
|
|
||||||
snprintf(command, sizeof(command),
|
snprintf(command, sizeof(command),
|
||||||
"Maximum allowed following error exceeded (P%2.2d01 = %d). "
|
"Maximum allowed following error exceeded (P%2.2d01 = %d). "
|
||||||
@ -630,6 +661,16 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 12:
|
case 12:
|
||||||
|
if (pC_->msgPrintControl_.shouldBePrinted(keyError, true,
|
||||||
|
pC_->pasynUserSelf)) {
|
||||||
|
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
|
||||||
|
"Controller \"%s\", axis %d => %s, line %d\nSecurity "
|
||||||
|
"input is triggered (P%2.2d01 = %d).%s\n",
|
||||||
|
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||||
|
axisNo_, error, pC_->msgPrintControl_.getSuffix());
|
||||||
|
}
|
||||||
|
resetError = false;
|
||||||
|
|
||||||
snprintf(command, sizeof(command),
|
snprintf(command, sizeof(command),
|
||||||
"Security input is triggered (P%2.2d01 = %d). Check the SPS "
|
"Security input is triggered (P%2.2d01 = %d). Check the SPS "
|
||||||
"for errors (if available). Otherwise please call "
|
"for errors (if available). Otherwise please call "
|
||||||
@ -647,11 +688,17 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
|
|||||||
|
|
||||||
case 13:
|
case 13:
|
||||||
// Driver hardware error triggered
|
// Driver hardware error triggered
|
||||||
asynPrint(
|
|
||||||
pC_->pasynUserSelf, ASYN_TRACE_ERROR,
|
if (pC_->msgPrintControl_.shouldBePrinted(keyError, true,
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nDriver hardware error "
|
pC_->pasynUserSelf)) {
|
||||||
"triggered.\n",
|
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
|
||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
|
"Controller \"%s\", axis %d => %s, line %d\nDriver "
|
||||||
|
"hardware error triggered.%s\n",
|
||||||
|
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||||
|
pC_->msgPrintControl_.getSuffix());
|
||||||
|
}
|
||||||
|
resetError = false;
|
||||||
|
|
||||||
snprintf(command, sizeof(command),
|
snprintf(command, sizeof(command),
|
||||||
"Driver hardware error (P%2.2d01 = 13). "
|
"Driver hardware error (P%2.2d01 = 13). "
|
||||||
"Please call the support.",
|
"Please call the support.",
|
||||||
@ -668,18 +715,22 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
|
|||||||
case 14:
|
case 14:
|
||||||
// EPICS should already prevent this issue in the first place,
|
// EPICS should already prevent this issue in the first place,
|
||||||
// since it contains the user limits
|
// since it contains the user limits
|
||||||
asynPrint(
|
|
||||||
pC_->pasynUserSelf, ASYN_TRACE_ERROR,
|
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nMove command exceeds "
|
|
||||||
"hardware limits (P%2.2d01 = %d).\n",
|
|
||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, axisNo_,
|
|
||||||
error);
|
|
||||||
|
|
||||||
snprintf(command, sizeof(command),
|
if (pC_->msgPrintControl_.shouldBePrinted(keyError, true,
|
||||||
|
pC_->pasynUserSelf)) {
|
||||||
|
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
|
||||||
|
"Controller \"%s\", axis %d => %s, line %d\nMove "
|
||||||
|
"command exceeds hardware limits (P%2.2d01 = %d).%s\n",
|
||||||
|
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||||
|
axisNo_, error, pC_->msgPrintControl_.getSuffix());
|
||||||
|
}
|
||||||
|
resetError = false;
|
||||||
|
|
||||||
|
snprintf(userMessage, sizeof(userMessage),
|
||||||
"Move command exceeds hardware limits (P%2.2d01 = %d). Please "
|
"Move command exceeds hardware limits (P%2.2d01 = %d). Please "
|
||||||
"call the support.",
|
"call the support.",
|
||||||
axisNo_, error);
|
axisNo_, error);
|
||||||
pl_status = setStringParam(pC_->motorMessageText_, command);
|
pl_status = setStringParam(pC_->motorMessageText_, userMessage);
|
||||||
if (pl_status != asynSuccess) {
|
if (pl_status != asynSuccess) {
|
||||||
return pC_->paramLibAccessFailed(pl_status, "motorMessageText_",
|
return pC_->paramLibAccessFailed(pl_status, "motorMessageText_",
|
||||||
axisNo_, __PRETTY_FUNCTION__,
|
axisNo_, __PRETTY_FUNCTION__,
|
||||||
@ -689,15 +740,22 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
|
|||||||
poll_status = asynError;
|
poll_status = asynError;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
|
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nUnknown error "
|
|
||||||
"P%2.2d01 = %d.\n",
|
|
||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
|
||||||
axisNo_, error);
|
|
||||||
|
|
||||||
pl_status = setStringParam(
|
if (pC_->msgPrintControl_.shouldBePrinted(keyError, true,
|
||||||
pC_->motorMessageText_,
|
pC_->pasynUserSelf)) {
|
||||||
"Unknown error P%2.2d01 = %d. Please call the support.");
|
asynPrint(
|
||||||
|
pC_->pasynUserSelf, ASYN_TRACE_ERROR,
|
||||||
|
"Controller \"%s\", axis %d => %s, line %d\nUnknown error "
|
||||||
|
"P%2.2d01 = %d.%s\n",
|
||||||
|
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, axisNo_,
|
||||||
|
error, pC_->msgPrintControl_.getSuffix());
|
||||||
|
}
|
||||||
|
resetError = false;
|
||||||
|
|
||||||
|
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) {
|
if (pl_status != asynSuccess) {
|
||||||
return pC_->paramLibAccessFailed(pl_status, "motorMessageText_",
|
return pC_->paramLibAccessFailed(pl_status, "motorMessageText_",
|
||||||
axisNo_, __PRETTY_FUNCTION__,
|
axisNo_, __PRETTY_FUNCTION__,
|
||||||
@ -708,6 +766,10 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (resetError) {
|
||||||
|
pC_->msgPrintControl_.resetCount(keyError);
|
||||||
|
}
|
||||||
|
|
||||||
// Update the parameter library
|
// Update the parameter library
|
||||||
if (error != 0) {
|
if (error != 0) {
|
||||||
pl_status = setIntegerParam(pC_->motorStatusProblem_, true);
|
pl_status = setIntegerParam(pC_->motorStatusProblem_, true);
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
#include "sinqAxis.h"
|
#include "sinqAxis.h"
|
||||||
|
|
||||||
// Forward declaration of the controller class to resolve the cyclic dependency
|
// 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.
|
// https://en.cppreference.com/w/cpp/language/class.
|
||||||
class turboPmacController;
|
class turboPmacController;
|
||||||
|
|
||||||
@ -15,7 +15,8 @@ class turboPmacAxis : public sinqAxis {
|
|||||||
* @param pController Pointer to the associated controller
|
* @param pController Pointer to the associated controller
|
||||||
* @param axisNo Index of the axis
|
* @param axisNo Index of the axis
|
||||||
*/
|
*/
|
||||||
turboPmacAxis(turboPmacController *pController, int axisNo);
|
turboPmacAxis(turboPmacController *pController, int axisNo,
|
||||||
|
bool initialize = true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Destroy the turboPmacAxis
|
* @brief Destroy the turboPmacAxis
|
||||||
@ -74,7 +75,7 @@ class turboPmacAxis : public sinqAxis {
|
|||||||
* The following steps are performed:
|
* The following steps are performed:
|
||||||
* - Read out the motor status, motor position, velocity and acceleration
|
* - Read out the motor status, motor position, velocity and acceleration
|
||||||
* from the MCU and store this information in the parameter library.
|
* 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
|
* @return asynStatus
|
||||||
*/
|
*/
|
||||||
|
@ -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,
|
turboPmacController::turboPmacController(const char *portName,
|
||||||
const char *ipPortConfigName,
|
const char *ipPortConfigName,
|
||||||
int numAxes, double movingPollPeriod,
|
int numAxes, double movingPollPeriod,
|
||||||
double idlePollPeriod,
|
double idlePollPeriod,
|
||||||
double comTimeout)
|
double comTimeout, int numExtraParams)
|
||||||
: sinqController(
|
: sinqController(
|
||||||
portName, ipPortConfigName, numAxes, movingPollPeriod, idlePollPeriod,
|
portName, ipPortConfigName, numAxes, movingPollPeriod, idlePollPeriod,
|
||||||
/*
|
/*
|
||||||
@ -53,7 +41,7 @@ turboPmacController::turboPmacController(const char *portName,
|
|||||||
- REREAD_ENCODER_POSITION
|
- REREAD_ENCODER_POSITION
|
||||||
- READ_CONFIG
|
- READ_CONFIG
|
||||||
*/
|
*/
|
||||||
NUM_turboPmac_DRIVER_PARAMS)
|
numExtraParams + NUM_turboPmac_DRIVER_PARAMS)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -145,39 +133,18 @@ Access one of the axes of the controller via the axis adress stored in asynUser.
|
|||||||
If the axis does not exist or is not a Axis, a nullptr is returned and an
|
If the axis does not exist or is not a Axis, a nullptr is returned and an
|
||||||
error is emitted.
|
error is emitted.
|
||||||
*/
|
*/
|
||||||
turboPmacAxis *turboPmacController::getAxis(asynUser *pasynUser) {
|
turboPmacAxis *turboPmacController::getTurboPmacAxis(asynUser *pasynUser) {
|
||||||
asynMotorAxis *asynAxis = asynMotorController::getAxis(pasynUser);
|
asynMotorAxis *asynAxis = asynMotorController::getAxis(pasynUser);
|
||||||
return turboPmacController::castToAxis(asynAxis);
|
return dynamic_cast<turboPmacAxis *>(asynAxis);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Access one of the axes of the controller via the axis index.
|
Access one of the axes of the controller via the axis index.
|
||||||
If the axis does not exist or is not a Axis, the function must return Null
|
If the axis does not exist or is not a Axis, the function must return Null
|
||||||
*/
|
*/
|
||||||
turboPmacAxis *turboPmacController::getAxis(int axisNo) {
|
turboPmacAxis *turboPmacController::getTurboPmacAxis(int axisNo) {
|
||||||
asynMotorAxis *asynAxis = asynMotorController::getAxis(axisNo);
|
asynMotorAxis *asynAxis = asynMotorController::getAxis(axisNo);
|
||||||
return turboPmacController::castToAxis(asynAxis);
|
return dynamic_cast<turboPmacAxis *>(asynAxis);
|
||||||
}
|
|
||||||
|
|
||||||
turboPmacAxis *turboPmacController::castToAxis(asynMotorAxis *asynAxis) {
|
|
||||||
|
|
||||||
// =========================================================================
|
|
||||||
|
|
||||||
// If the axis slot of the pAxes_ array is empty, a nullptr must be returned
|
|
||||||
if (asynAxis == nullptr) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Here, an error is emitted since asyn_axis is not a nullptr but also not
|
|
||||||
// an instance of Axis
|
|
||||||
turboPmacAxis *axis = dynamic_cast<turboPmacAxis *>(asynAxis);
|
|
||||||
if (axis == nullptr) {
|
|
||||||
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
|
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nAxis is not "
|
|
||||||
"an instance of turboPmacAxis",
|
|
||||||
portName, axis->axisNo_, __PRETTY_FUNCTION__, __LINE__);
|
|
||||||
}
|
|
||||||
return axis;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
||||||
@ -216,7 +183,7 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
|||||||
|
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
|
|
||||||
turboPmacAxis *axis = getAxis(axisNo);
|
turboPmacAxis *axis = getTurboPmacAxis(axisNo);
|
||||||
if (axis == nullptr) {
|
if (axis == nullptr) {
|
||||||
// We already did the error logging directly in getAxis
|
// We already did the error logging directly in getAxis
|
||||||
return asynError;
|
return asynError;
|
||||||
@ -273,10 +240,6 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
|||||||
// +1 for the carriage return.
|
// +1 for the carriage return.
|
||||||
const size_t fullComandLength = offset + commandLength + 1;
|
const size_t fullComandLength = offset + commandLength + 1;
|
||||||
|
|
||||||
asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER,
|
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nSending command %s",
|
|
||||||
portName, axisNo, __PRETTY_FUNCTION__, __LINE__, fullCommand);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We use separated write and read commands here, not the combined writeRead
|
We use separated write and read commands here, not the combined writeRead
|
||||||
method, because the latter is actually a flushWriteRead (see
|
method, because the latter is actually a flushWriteRead (see
|
||||||
@ -294,12 +257,19 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
|||||||
status = pasynOctetSyncIO->write(lowLevelPortUser_, fullCommand,
|
status = pasynOctetSyncIO->write(lowLevelPortUser_, fullCommand,
|
||||||
fullComandLength, comTimeout_, &nbytesOut);
|
fullComandLength, comTimeout_, &nbytesOut);
|
||||||
|
|
||||||
|
msgPrintControlKey writeKey =
|
||||||
|
msgPrintControlKey(portName, axisNo, __PRETTY_FUNCTION__, __LINE__);
|
||||||
|
|
||||||
if (status == asynTimeout) {
|
if (status == asynTimeout) {
|
||||||
|
|
||||||
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
|
if (msgPrintControl_.shouldBePrinted(writeKey, true, pasynUserSelf)) {
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nTimeout while "
|
asynPrint(
|
||||||
"writing to the MCU\n",
|
this->pasynUserSelf, ASYN_TRACE_ERROR,
|
||||||
portName, axisNo, __PRETTY_FUNCTION__, __LINE__);
|
"Controller \"%s\", axis %d => %s, line %d\nTimeout while "
|
||||||
|
"writing to the MCU.%s\n",
|
||||||
|
portName, axisNo, __PRETTY_FUNCTION__, __LINE__,
|
||||||
|
msgPrintControl_.getSuffix());
|
||||||
|
}
|
||||||
|
|
||||||
timeoutStatus = checkComTimeoutWatchdog(axisNo, drvMessageText,
|
timeoutStatus = checkComTimeoutWatchdog(axisNo, drvMessageText,
|
||||||
sizeof(drvMessageText));
|
sizeof(drvMessageText));
|
||||||
@ -321,23 +291,35 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (status != asynSuccess) {
|
} else if (status != asynSuccess) {
|
||||||
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
|
if (msgPrintControl_.shouldBePrinted(writeKey, true, pasynUserSelf)) {
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nError %s while "
|
asynPrint(
|
||||||
"writing to the controller\n",
|
this->pasynUserSelf, ASYN_TRACE_ERROR,
|
||||||
portName, axisNo, __PRETTY_FUNCTION__, __LINE__,
|
"Controller \"%s\", axis %d => %s, line %d\nError %s while "
|
||||||
stringifyAsynStatus(status));
|
"writing to the controller.%s\n",
|
||||||
|
portName, axisNo, __PRETTY_FUNCTION__, __LINE__,
|
||||||
|
stringifyAsynStatus(status), msgPrintControl_.getSuffix());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
msgPrintControl_.resetCount(writeKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the response from the MCU buffer
|
// Read the response from the MCU buffer
|
||||||
status = pasynOctetSyncIO->read(lowLevelPortUser_, response, MAXBUF_,
|
status = pasynOctetSyncIO->read(lowLevelPortUser_, response, MAXBUF_,
|
||||||
comTimeout_, &nbytesIn, &eomReason);
|
comTimeout_, &nbytesIn, &eomReason);
|
||||||
|
|
||||||
|
msgPrintControlKey readKey =
|
||||||
|
msgPrintControlKey(portName, axisNo, __PRETTY_FUNCTION__, __LINE__);
|
||||||
|
|
||||||
if (status == asynTimeout) {
|
if (status == asynTimeout) {
|
||||||
|
|
||||||
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
|
if (msgPrintControl_.shouldBePrinted(readKey, true, pasynUserSelf)) {
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nTimeout while "
|
asynPrint(
|
||||||
"reading from the MCU\n",
|
this->pasynUserSelf, ASYN_TRACE_ERROR,
|
||||||
portName, axisNo, __PRETTY_FUNCTION__, __LINE__);
|
"Controller \"%s\", axis %d => %s, line %d\nTimeout while "
|
||||||
|
"reading from the MCU.%s\n",
|
||||||
|
portName, axisNo, __PRETTY_FUNCTION__, __LINE__,
|
||||||
|
msgPrintControl_.getSuffix());
|
||||||
|
}
|
||||||
|
|
||||||
// Add this event to the back of the timeout event counter
|
// Add this event to the back of the timeout event counter
|
||||||
timeoutStatus = checkComTimeoutWatchdog(axisNo, drvMessageText,
|
timeoutStatus = checkComTimeoutWatchdog(axisNo, drvMessageText,
|
||||||
@ -360,11 +342,16 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (status != asynSuccess) {
|
} else if (status != asynSuccess) {
|
||||||
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
|
if (msgPrintControl_.shouldBePrinted(readKey, true, pasynUserSelf)) {
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nError %s while "
|
asynPrint(
|
||||||
"reading from the controller\n",
|
this->pasynUserSelf, ASYN_TRACE_ERROR,
|
||||||
portName, axisNo, __PRETTY_FUNCTION__, __LINE__,
|
"Controller \"%s\", axis %d => %s, line %d\nError %s while "
|
||||||
stringifyAsynStatus(status));
|
"reading from the controller.%s\n",
|
||||||
|
portName, axisNo, __PRETTY_FUNCTION__, __LINE__,
|
||||||
|
stringifyAsynStatus(status), msgPrintControl_.getSuffix());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
msgPrintControl_.resetCount(readKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timeoutStatus == asynError) {
|
if (timeoutStatus == asynError) {
|
||||||
@ -372,6 +359,8 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The message should only ever terminate due to reason 2
|
// The message should only ever terminate due to reason 2
|
||||||
|
msgPrintControlKey terminateKey =
|
||||||
|
msgPrintControlKey(portName, axisNo, __PRETTY_FUNCTION__, __LINE__);
|
||||||
if (eomReason != 2) {
|
if (eomReason != 2) {
|
||||||
status = asynError;
|
status = asynError;
|
||||||
|
|
||||||
@ -379,10 +368,16 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
|||||||
"Terminated message due to reason %d (should be 2).",
|
"Terminated message due to reason %d (should be 2).",
|
||||||
eomReason);
|
eomReason);
|
||||||
|
|
||||||
asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER,
|
if (msgPrintControl_.shouldBePrinted(terminateKey, true,
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nMessage "
|
pasynUserSelf)) {
|
||||||
"terminated due to reason %i\n",
|
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
|
||||||
portName, axisNo, __PRETTY_FUNCTION__, __LINE__, eomReason);
|
"Controller \"%s\", axis %d => %s, line %d\nMessage "
|
||||||
|
"terminated due to reason %i.%s\n",
|
||||||
|
portName, axisNo, __PRETTY_FUNCTION__, __LINE__,
|
||||||
|
eomReason, msgPrintControl_.getSuffix());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
msgPrintControl_.resetCount(terminateKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -394,20 +389,30 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
|||||||
numReceivedResponses++;
|
numReceivedResponses++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
msgPrintControlKey numResponsesKey =
|
||||||
|
msgPrintControlKey(portName, axisNo, __PRETTY_FUNCTION__, __LINE__);
|
||||||
if (numExpectedResponses != numReceivedResponses) {
|
if (numExpectedResponses != numReceivedResponses) {
|
||||||
adjustResponseForPrint(modResponse, response, MAXBUF_);
|
adjustResponseForPrint(modResponse, response, MAXBUF_);
|
||||||
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
|
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nUnexpected "
|
if (msgPrintControl_.shouldBePrinted(numResponsesKey, true,
|
||||||
"response '%s' (carriage returns are replaced with spaces) "
|
pasynUserSelf)) {
|
||||||
"for command %s\n",
|
asynPrint(
|
||||||
portName, axisNo, __PRETTY_FUNCTION__, __LINE__, modResponse,
|
this->pasynUserSelf, ASYN_TRACE_ERROR,
|
||||||
command);
|
"Controller \"%s\", axis %d => %s, line %d\nUnexpected "
|
||||||
|
"response '%s' (carriage returns are replaced with spaces) "
|
||||||
|
"for command %s.%s\n",
|
||||||
|
portName, axisNo, __PRETTY_FUNCTION__, __LINE__, modResponse,
|
||||||
|
command, msgPrintControl_.getSuffix());
|
||||||
|
}
|
||||||
|
|
||||||
snprintf(drvMessageText, sizeof(drvMessageText),
|
snprintf(drvMessageText, sizeof(drvMessageText),
|
||||||
"Received unexpected response '%s' (carriage returns "
|
"Received unexpected response '%s' (carriage returns "
|
||||||
"are replaced with spaces) for command %s. "
|
"are replaced with spaces) for command %s. "
|
||||||
"Please call the support",
|
"Please call the support",
|
||||||
modResponse, command);
|
modResponse, command);
|
||||||
status = asynError;
|
status = asynError;
|
||||||
|
} else {
|
||||||
|
msgPrintControl_.resetCount(numResponsesKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create custom error messages for different failure modes, if no error
|
// Create custom error messages for different failure modes, if no error
|
||||||
@ -437,23 +442,12 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
|||||||
|
|
||||||
// Log the overall status (communication successfull or not)
|
// Log the overall status (communication successfull or not)
|
||||||
if (status == asynSuccess) {
|
if (status == asynSuccess) {
|
||||||
|
|
||||||
asynPrint(lowLevelPortUser_, ASYN_TRACEIO_DRIVER,
|
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nDevice "
|
|
||||||
"response: %s (carriage returns are replaced with spaces)\n",
|
|
||||||
portName, axisNo, __PRETTY_FUNCTION__, __LINE__, modResponse);
|
|
||||||
paramLibStatus = axis->setIntegerParam(this->motorStatusCommsError_, 0);
|
paramLibStatus = axis->setIntegerParam(this->motorStatusCommsError_, 0);
|
||||||
} else {
|
} else {
|
||||||
asynPrint(lowLevelPortUser_, ASYN_TRACE_ERROR,
|
// Check if the axis already is in an error communication mode. If
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nCommunication "
|
// it is not, upstream the error. This is done to avoid "flooding"
|
||||||
"failed for command %s (%s)\n",
|
// the user with different error messages if more than one error
|
||||||
portName, axisNo, __PRETTY_FUNCTION__, __LINE__, fullCommand,
|
// ocurred before an error-free communication
|
||||||
stringifyAsynStatus(status));
|
|
||||||
|
|
||||||
// Check if the axis already is in an error communication mode. If it is
|
|
||||||
// not, upstream the error. This is done to avoid "flooding" the user
|
|
||||||
// with different error messages if more than one error ocurred before
|
|
||||||
// an error-free communication
|
|
||||||
paramLibStatus =
|
paramLibStatus =
|
||||||
getIntegerParam(axisNo, motorStatusProblem_, &motorStatusProblem);
|
getIntegerParam(axisNo, motorStatusProblem_, &motorStatusProblem);
|
||||||
if (paramLibStatus != asynSuccess) {
|
if (paramLibStatus != asynSuccess) {
|
||||||
@ -494,11 +488,7 @@ asynStatus turboPmacController::writeInt32(asynUser *pasynUser,
|
|||||||
|
|
||||||
// =====================================================================
|
// =====================================================================
|
||||||
|
|
||||||
turboPmacAxis *axis = getAxis(pasynUser);
|
turboPmacAxis *axis = getTurboPmacAxis(pasynUser);
|
||||||
if (axis == nullptr) {
|
|
||||||
// We already did the error logging directly in getAxis
|
|
||||||
return asynError;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle custom PVs
|
// Handle custom PVs
|
||||||
if (function == rereadEncoderPosition_) {
|
if (function == rereadEncoderPosition_) {
|
||||||
@ -510,13 +500,14 @@ asynStatus turboPmacController::writeInt32(asynUser *pasynUser,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
asynStatus sinqController::readInt32(asynUser *pasynUser, epicsInt32 *value) {
|
asynStatus turboPmacController::readInt32(asynUser *pasynUser,
|
||||||
|
epicsInt32 *value) {
|
||||||
// PMACs can be disabled
|
// PMACs can be disabled
|
||||||
if (pasynUser->reason == motorCanDisable_) {
|
if (pasynUser->reason == motorCanDisable_) {
|
||||||
*value = 1;
|
*value = 1;
|
||||||
return asynSuccess;
|
return asynSuccess;
|
||||||
} else {
|
} else {
|
||||||
return asynMotorController::readInt32(pasynUser, value);
|
return sinqController::readInt32(pasynUser, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -549,8 +540,8 @@ asynStatus turboPmacCreateController(const char *portName,
|
|||||||
https://github.com/epics-modules/motor/blob/master/motorApp/MotorSrc/asynMotorController.cpp
|
https://github.com/epics-modules/motor/blob/master/motorApp/MotorSrc/asynMotorController.cpp
|
||||||
https://github.com/epics-modules/asyn/blob/master/asyn/asynPortDriver/asynPortDriver.cpp
|
https://github.com/epics-modules/asyn/blob/master/asyn/asynPortDriver/asynPortDriver.cpp
|
||||||
|
|
||||||
The created object is registered in EPICS in its constructor and can safely
|
The created object is registered in EPICS in its constructor and can
|
||||||
be "leaked" here.
|
safely be "leaked" here.
|
||||||
*/
|
*/
|
||||||
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
|
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
|
||||||
#pragma GCC diagnostic ignored "-Wunused-variable"
|
#pragma GCC diagnostic ignored "-Wunused-variable"
|
||||||
@ -582,17 +573,17 @@ static const iocshArg CreateControllerArg5 = {"Communication timeout (s)",
|
|||||||
static const iocshArg *const CreateControllerArgs[] = {
|
static const iocshArg *const CreateControllerArgs[] = {
|
||||||
&CreateControllerArg0, &CreateControllerArg1, &CreateControllerArg2,
|
&CreateControllerArg0, &CreateControllerArg1, &CreateControllerArg2,
|
||||||
&CreateControllerArg3, &CreateControllerArg4, &CreateControllerArg5};
|
&CreateControllerArg3, &CreateControllerArg4, &CreateControllerArg5};
|
||||||
static const iocshFuncDef configturboPmacCreateController = {
|
static const iocshFuncDef configTurboPmacCreateController = {
|
||||||
"turboPmacController", 6, CreateControllerArgs};
|
"turboPmacController", 6, CreateControllerArgs};
|
||||||
static void configTurboPmacCreateControllerCallFunc(const iocshArgBuf *args) {
|
static void configTurboPmacCreateControllerCallFunc(const iocshArgBuf *args) {
|
||||||
turboPmacCreateController(args[0].sval, args[1].sval, args[2].ival,
|
turboPmacCreateController(args[0].sval, args[1].sval, args[2].ival,
|
||||||
args[3].dval, args[4].dval, args[5].dval);
|
args[3].dval, args[4].dval, args[5].dval);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function is made known to EPICS in turboPmac.dbd and is called by EPICS
|
// This function is made known to EPICS in turboPmac.dbd and is called by
|
||||||
// in order to register both functions in the IOC shell
|
// EPICS in order to register both functions in the IOC shell
|
||||||
static void turboPmacControllerRegister(void) {
|
static void turboPmacControllerRegister(void) {
|
||||||
iocshRegister(&configturboPmacCreateController,
|
iocshRegister(&configTurboPmacCreateController,
|
||||||
configTurboPmacCreateControllerCallFunc);
|
configTurboPmacCreateControllerCallFunc);
|
||||||
}
|
}
|
||||||
epicsExportRegistrar(turboPmacControllerRegister);
|
epicsExportRegistrar(turboPmacControllerRegister);
|
||||||
|
@ -13,10 +13,10 @@
|
|||||||
#include "turboPmacAxis.h"
|
#include "turboPmacAxis.h"
|
||||||
|
|
||||||
class turboPmacController : public sinqController {
|
class turboPmacController : public sinqController {
|
||||||
|
|
||||||
public:
|
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 portName See sinqController constructor
|
||||||
* @param ipPortConfigName 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,
|
* @param comTimeout When trying to communicate with the device,
|
||||||
the underlying asynOctetSyncIO interface waits for a response until this
|
the underlying asynOctetSyncIO interface waits for a response until this
|
||||||
time (in seconds) has passed, then it declares a timeout.
|
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,
|
turboPmacController(const char *portName, const char *ipPortConfigName,
|
||||||
int numAxes, double movingPollPeriod,
|
int numAxes, double movingPollPeriod,
|
||||||
double idlePollPeriod, double comTimeout);
|
double idlePollPeriod, double comTimeout,
|
||||||
|
int numExtraParams = 0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the axis object
|
* @brief Get the axis object
|
||||||
@ -38,7 +40,7 @@ class turboPmacController : public sinqController {
|
|||||||
* @return turboPmacAxis* If no axis could be found, this is a
|
* @return turboPmacAxis* If no axis could be found, this is a
|
||||||
* nullptr
|
* nullptr
|
||||||
*/
|
*/
|
||||||
turboPmacAxis *getAxis(asynUser *pasynUser);
|
turboPmacAxis *getTurboPmacAxis(asynUser *pasynUser);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the axis object
|
* @brief Get the axis object
|
||||||
@ -47,7 +49,18 @@ class turboPmacController : public sinqController {
|
|||||||
* @return turboPmacAxis* If no axis could be found, this is a
|
* @return turboPmacAxis* If no axis could be found, this is a
|
||||||
* nullptr
|
* nullptr
|
||||||
*/
|
*/
|
||||||
turboPmacAxis *getAxis(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
|
||||||
@ -58,7 +71,7 @@ class turboPmacController : public sinqController {
|
|||||||
* @param value New value
|
* @param value New value
|
||||||
* @return asynStatus
|
* @return asynStatus
|
||||||
*/
|
*/
|
||||||
asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value);
|
virtual asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
asynUser *lowLevelPortUser_;
|
asynUser *lowLevelPortUser_;
|
||||||
@ -82,15 +95,6 @@ class turboPmacController : public sinqController {
|
|||||||
asynStatus writeRead(int axisNo, const char *command, char *response,
|
asynStatus writeRead(int axisNo, const char *command, char *response,
|
||||||
int numExpectedResponses);
|
int numExpectedResponses);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Save cast of the given asynAxis pointer to a turboPmacAxis
|
|
||||||
* pointer. If the cast fails, this function returns a nullptr.
|
|
||||||
*
|
|
||||||
* @param asynAxis
|
|
||||||
* @return turboPmacAxis*
|
|
||||||
*/
|
|
||||||
turboPmacAxis *castToAxis(asynMotorAxis *asynAxis);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Specialized version of sinqController::errMsgCouldNotParseResponse
|
* @brief Specialized version of sinqController::errMsgCouldNotParseResponse
|
||||||
* for turboPmac
|
* for turboPmac
|
||||||
@ -114,7 +118,7 @@ class turboPmacController : public sinqController {
|
|||||||
const char *functionName,
|
const char *functionName,
|
||||||
int lineNumber);
|
int lineNumber);
|
||||||
|
|
||||||
private:
|
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.
|
||||||
|
Reference in New Issue
Block a user