Added new feature msgPrintControl from sinqMotor 0.8.0.

Correspondingly, the minimum version requirement for sinqMotor has been bumped to 0.8.0.
This commit is contained in:
2025-03-04 12:41:20 +01:00
parent cb91a8aa36
commit 4ad842c097
8 changed files with 299 additions and 408 deletions

View File

@@ -34,6 +34,32 @@ static void epicsInithookFunction(initHookState iState) {
}
}
void appendErrorMessage(char *fullMessage, size_t capacityFullMessage,
const char *toBeAppended) {
size_t lenFullMessage = strlen(fullMessage);
size_t lenToBeAppended = strlen(toBeAppended);
if (lenFullMessage == 0) {
// The error message is empty -> Just copy the content of toBeAppended
// into fullMessage, if the formers capacity suffices
if (lenToBeAppended < capacityFullMessage) {
strcpy(fullMessage, toBeAppended);
}
} else {
// Append the message and add a linebreak in between, if the capacity of
// fullMessage suffices. We need capacity for one additional character
// because of the linebreak.
if (lenFullMessage + lenToBeAppended + 1 < capacityFullMessage) {
// Append the linebreak and readd the null terminator behind it
// fullMessage[lenFullMessage] = '\n';
// fullMessage[lenFullMessage + 1] = '\0';
// Append the actual message
strcat(fullMessage, toBeAppended);
}
}
}
masterMacsAxis::masterMacsAxis(masterMacsController *pC, int axisNo)
: sinqAxis(pC, axisNo), pC_(pC) {
@@ -340,8 +366,9 @@ asynStatus masterMacsAxis::doPoll(bool *moving) {
return rw_status;
}
// Check if we reached the target
if (targetReached()) {
// If the motor is switched off or if it reached its target, it is not
// moving.
if (targetReached() || !switchedOn()) {
*moving = false;
} else {
*moving = true;
@@ -362,70 +389,26 @@ asynStatus masterMacsAxis::doPoll(bool *moving) {
Read out the error if either a fault condition status flag has been set or
if a movement has just ended.
*/
if (faultConditionSet()) {
msgPrintControlKey keyError = msgPrintControlKey(
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
if (faultConditionSet() || !(*moving)) {
rw_status = readAxisError();
if (shortCircuit()) {
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nShort "
"circuit fault.\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
pl_status =
setStringParam(pC_->motorMessageText_,
"Short circuit error. Please call the support.");
if (pl_status != asynSuccess) {
return pC_->paramLibAccessFailed(pl_status, "motorMessageText_",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
poll_status = asynError;
}
if (encoderError()) {
asynPrint(
pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nEncoder error.\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
pl_status =
setStringParam(pC_->motorMessageText_,
"Encoder error. Please call the support.");
if (pl_status != asynSuccess) {
return pC_->paramLibAccessFailed(pl_status, "motorMessageText_",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
poll_status = asynError;
}
if (followingError()) {
asynPrint(
pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nMaximum allowed "
"following error exceeded.\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
pl_status = setStringParam(
pC_->motorMessageText_,
"Maximum allowed following error exceeded.Check if movement "
"range is blocked. Otherwise please call the support.");
if (pl_status != asynSuccess) {
return pC_->paramLibAccessFailed(pl_status, "motorMessageText_",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
poll_status = asynError;
}
/*
A communication error is a special case. If a communication between
controller and axis error occurred, all subsequent errors are ignored,
since this information is not reliable.
*/
if (communicationError()) {
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line "
"%d\nCommunication error.\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
if (pC_->msgPrintControl_.shouldBePrinted(keyError, true,
pC_->pasynUserSelf)) {
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line "
"%d\nCommunication error.%s\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
pC_->msgPrintControl_.getSuffix());
}
pl_status =
setStringParam(pC_->motorMessageText_,
@@ -438,172 +421,164 @@ asynStatus masterMacsAxis::doPoll(bool *moving) {
}
poll_status = asynError;
}
} else {
if (feedbackError()) {
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line "
"%d\nFeedback error.\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
// This buffer must be initialized to zero because we build the
// error message by appending strings.
char userMessage[pC_->MAXBUF_] = {0};
char shellMessage[pC_->MAXBUF_] = {0};
pl_status =
setStringParam(pC_->motorMessageText_,
"Feedback error. Please call the support.");
// Concatenate all other errors
if (shortCircuit()) {
appendErrorMessage(shellMessage, sizeof(shellMessage),
"Short circuit fault.");
appendErrorMessage(
userMessage, sizeof(userMessage),
"Short circuit error. Please call the support.");
poll_status = asynError;
}
if (encoderError()) {
appendErrorMessage(shellMessage, sizeof(shellMessage),
"Encoder error.");
appendErrorMessage(userMessage, sizeof(userMessage),
"Encoder error. Please call the support.");
poll_status = asynError;
}
if (followingError()) {
appendErrorMessage(
shellMessage, sizeof(shellMessage),
"Maximum callowed following error exceeded.");
appendErrorMessage(
userMessage, sizeof(userMessage),
"Maximum allowed following error exceeded.Check if "
"movement range is blocked. Otherwise please call the "
"support.");
poll_status = asynError;
}
if (feedbackError()) {
appendErrorMessage(shellMessage, sizeof(shellMessage),
"Feedback error.");
appendErrorMessage(userMessage, sizeof(userMessage),
"Feedback error. Please call the support.");
poll_status = asynError;
}
/*
Either the software limits or the end switches of the controller
have been hit. Since the EPICS limits are derived from the software
limits and are a little bit smaller, these error cases can only
happen if either the axis has an incremental encoder which is not
properly homed or if a bug occured.
*/
if (positiveLimitSwitch() || negativeLimitSwitch() ||
positiveSoftwareLimit() || negativeSoftwareLimit()) {
// Distinction for developers
if (positiveLimitSwitch()) {
appendErrorMessage(shellMessage, sizeof(shellMessage),
"Positive limit switch.");
}
if (negativeLimitSwitch()) {
appendErrorMessage(shellMessage, sizeof(shellMessage),
"Negative limit switch.");
}
if (positiveSoftwareLimit()) {
appendErrorMessage(shellMessage, sizeof(shellMessage),
"Positive software limit.");
}
if (negativeSoftwareLimit()) {
appendErrorMessage(shellMessage, sizeof(shellMessage),
"Negative software limit.");
}
// Generic error message for user
appendErrorMessage(
userMessage, sizeof(userMessage),
"Software limits or end switch hit. Try homing the motor, "
"moving in the opposite direction or check the SPS for "
"errors (if available). Otherwise please call the "
"support.");
poll_status = asynError;
}
if (overCurrent()) {
appendErrorMessage(shellMessage, sizeof(shellMessage),
"Overcurrent error.");
appendErrorMessage(
userMessage, sizeof(userMessage),
"Overcurrent error. Please call the support.");
poll_status = asynError;
}
if (overTemperature()) {
appendErrorMessage(shellMessage, sizeof(shellMessage),
"Overtemperature error.");
appendErrorMessage(
userMessage, sizeof(userMessage),
"Overtemperature error. Please call the support.");
poll_status = asynError;
}
if (overVoltage()) {
appendErrorMessage(shellMessage, sizeof(shellMessage),
"Overvoltage error.");
appendErrorMessage(
userMessage, sizeof(userMessage),
"Overvoltage error. Please call the support.");
poll_status = asynError;
}
if (underVoltage()) {
appendErrorMessage(shellMessage, sizeof(shellMessage),
"Undervoltage error.");
appendErrorMessage(
userMessage, sizeof(userMessage),
"Undervoltage error. Please call the support.");
poll_status = asynError;
}
if (stoFault()) {
appendErrorMessage(shellMessage, sizeof(shellMessage),
"STO input is on disable state.");
appendErrorMessage(userMessage, sizeof(userMessage),
"STO fault. Please call the support.");
poll_status = asynError;
}
if (strlen(shellMessage) > 0) {
if (pC_->msgPrintControl_.shouldBePrinted(keyError, true,
pC_->pasynUserSelf)) {
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line "
"%d\n%s.%s\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__,
__LINE__, shellMessage,
pC_->msgPrintControl_.getSuffix());
}
}
pl_status = setStringParam(pC_->motorMessageText_, userMessage);
if (pl_status != asynSuccess) {
return pC_->paramLibAccessFailed(pl_status, "motorMessageText_",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
poll_status = asynError;
}
/*
Either the software limits or the end switches of the controller have
been hit. Since the EPICS limits are derived from the software limits
and are a little bit smaller, these error cases can only happen if
either the axis has an incremental encoder which is not properly homed
or if a bug occured.
*/
if (positiveLimitSwitch() || negativeLimitSwitch() ||
positiveSoftwareLimit() || negativeSoftwareLimit()) {
// Distinction for developers
if (positiveLimitSwitch()) {
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nAxis "
"hit the positive limit end switch.\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
if (negativeLimitSwitch()) {
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nAxis "
"hit the negative limit end switch.\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
if (positiveSoftwareLimit()) {
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nAxis "
"hit the positive software limit.\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
if (negativeSoftwareLimit()) {
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nAxis "
"hit the negative software limit.\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
// Generic error message for user
pl_status = setStringParam(
pC_->motorMessageText_,
"Software limits or end switch hit. Try homing the motor, "
"moving in the opposite direction or check the SPS for "
"errors (if available). Otherwise please call the "
"support.");
if (pl_status != asynSuccess) {
return pC_->paramLibAccessFailed(pl_status, "motorMessageText_",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
poll_status = asynError;
}
if (overCurrent()) {
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nOvercurrent "
"error.\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
pl_status =
setStringParam(pC_->motorMessageText_,
"Overcurrent error. Please call the support.");
if (pl_status != asynSuccess) {
return pC_->paramLibAccessFailed(pl_status, "motorMessageText_",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
poll_status = asynError;
}
if (overTemperature()) {
asynPrint(
pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nOvertemperature "
"error.\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
pl_status = setStringParam(
pC_->motorMessageText_,
"Overtemperature error. Please call the support.");
if (pl_status != asynSuccess) {
return pC_->paramLibAccessFailed(pl_status, "motorMessageText_",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
poll_status = asynError;
}
if (overVoltage()) {
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nOvervoltage "
"error.\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
pl_status =
setStringParam(pC_->motorMessageText_,
"Overvoltage error. Please call the support.");
if (pl_status != asynSuccess) {
return pC_->paramLibAccessFailed(pl_status, "motorMessageText_",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
poll_status = asynError;
}
if (underVoltage()) {
asynPrint(
pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nUndervoltage "
"error.\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
pl_status =
setStringParam(pC_->motorMessageText_,
"Undervoltage error. Please call the support.");
if (pl_status != asynSuccess) {
return pC_->paramLibAccessFailed(pl_status, "motorMessageText_",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
poll_status = asynError;
}
if (stoFault()) {
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nSTO fault - "
"STO input is on disable state.\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
pl_status = setStringParam(pC_->motorMessageText_,
"STO fault. Please call the support.");
if (pl_status != asynSuccess) {
return pC_->paramLibAccessFailed(pl_status, "motorMessageText_",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
poll_status = asynError;
}
} else {
pC_->msgPrintControl_.resetCount(keyError);
}
// Read out the limits, if the motor is not moving