1 Commits
1.4.2 ... v1.0

Author SHA1 Message Date
847f40970f Bugfix for 1.0 2025-06-17 16:32:59 +02:00
10 changed files with 564 additions and 406 deletions

View File

@@ -1,24 +0,0 @@
name: Test And Build
on: [push]
jobs:
Lint:
runs-on: linepics
steps:
- name: checkout repo
uses: actions/checkout@v4
- name: cppcheck
run: cppcheck --std=c++17 --addon=cert --addon=misc --error-exitcode=1 src/*.cpp
- name: formatting
run: clang-format --style=file --Werror --dry-run src/*.cpp
Build:
runs-on: linepics
steps:
- name: checkout repo
uses: actions/checkout@v4
with:
submodules: 'true'
- run: |
sed -i 's/ARCH_FILTER=.*/ARCH_FILTER=linux%/' Makefile
echo -e "\nIGNORE_SUBMODULES += sinqmotor" >> Makefile
make install

48
.gitlab-ci.yml Normal file
View File

@@ -0,0 +1,48 @@
default:
image: docker.psi.ch:5000/sinqdev/sinqepics:latest
stages:
- lint
- build
- test
cppcheck:
stage: lint
script:
- cppcheck --std=c++17 --addon=cert --addon=misc --suppress=cert-STR07-C --error-exitcode=1 src/*.cpp
artifacts:
expire_in: 1 week
tags:
- sinq
formatting:
stage: lint
script:
- clang-format --style=file --Werror --dry-run src/*.cpp
artifacts:
expire_in: 1 week
tags:
- sinq
build_module:
stage: build
script:
- export SINQMOTOR_VERSION="$(grep 'sinqMotor_VERSION=' Makefile | cut -d= -f2)"
- git clone --depth 1 --branch "${SINQMOTOR_VERSION}" https://gitlab-ci-token:${CI_JOB_TOKEN}@git.psi.ch/sinq-epics-modules/sinqmotor.git
- pushd sinqmotor
- sed -i 's/ARCH_FILTER=.*/ARCH_FILTER=linux%/' Makefile
- echo "LIBVERSION=${SINQMOTOR_VERSION}" >> Makefile
- make install
- popd
- sed -i 's/ARCH_FILTER=.*/ARCH_FILTER=linux%/' Makefile
- echo "LIBVERSION=${CI_COMMIT_TAG:-0.0.1}" >> Makefile
- make install
- cp -rT "/ioc/modules/masterMacs/$(ls -U /ioc/modules/masterMacs/ | head -1)" "./masterMacs-${CI_COMMIT_TAG:-$CI_COMMIT_SHORT_SHA}"
artifacts:
name: "masterMacs-${CI_COMMIT_TAG:-$CI_COMMIT_SHORT_SHA}"
paths:
- "masterMacs-${CI_COMMIT_TAG:-$CI_COMMIT_SHORT_SHA}/*"
expire_in: 1 week
when: always
tags:
- sinq

View File

@@ -23,7 +23,6 @@ SOURCES += src/masterMacsController.cpp
# Store the record files # Store the record files
TEMPLATES += sinqMotor/db/asynRecord.db TEMPLATES += sinqMotor/db/asynRecord.db
TEMPLATES += sinqMotor/db/sinqMotor.db TEMPLATES += sinqMotor/db/sinqMotor.db
TEMPLATES += db/masterMacs.db
# This file registers the motor-specific functions in the IOC shell. # This file registers the motor-specific functions in the IOC shell.
DBDS += sinqMotor/src/sinqMotor.dbd DBDS += sinqMotor/src/sinqMotor.dbd

View File

@@ -55,11 +55,11 @@ setMaxSubsequentTimeouts("$(NAME)", 20);
setThresholdComTimeout("$(NAME)", 100, 1); setThresholdComTimeout("$(NAME)", 100, 1);
# 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","$(masterMacs_DB)/sinqMotor.db") epicsEnvSet("SINQDBPATH","$(sinqMotor_DB)/sinqMotor.db")
dbLoadTemplate("$(TOP)/$(NAME).substitutions", "INSTR=$(INSTR)$(NAME):,CONTROLLER=$(NAME)") dbLoadTemplate("$(TOP)/$(NAME).substitutions", "INSTR=$(INSTR)$(NAME):,CONTROLLER=$(NAME)")
epicsEnvSet("SINQDBPATH","$(masterMacs_DB)/masterMacs.db") epicsEnvSet("SINQDBPATH","$(masterMacs_DB)/masterMacs.db")
dbLoadTemplate("$(TOP)/$(NAME).substitutions", "INSTR=$(INSTR)$(NAME):,CONTROLLER=$(NAME)") dbLoadTemplate("$(TOP)/$(NAME).substitutions", "INSTR=$(INSTR)$(NAME):,CONTROLLER=$(NAME)")
dbLoadRecords("$(masterMacs_DB)/asynRecord.db","P=$(INSTR)$(NAME),PORT=$(ASYN_PORT)") dbLoadRecords("$(sinqMotor_DB)/asynRecord.db","P=$(INSTR)$(NAME),PORT=$(ASYN_PORT)")
``` ```
### Versioning ### Versioning

View File

@@ -1,7 +0,0 @@
# Call the nodeReset function of the corresponding masterMacsAxis.
# This record is coupled to the parameter library via nodeReset_ -> NODE_RESET.
record(longout, "$(INSTR)$(M):NodeReset") {
field(DTYP, "asynInt32")
field(OUT, "@asyn($(CONTROLLER),$(AXIS),1) NODE_RESET")
field(PINI, "NO")
}

View File

@@ -19,6 +19,7 @@ struct masterMacsAxisImpl {
std::bitset<16> axisStatus; std::bitset<16> axisStatus;
std::bitset<16> axisError; std::bitset<16> axisError;
double lastSetSpeed;
bool waitForHandshake; bool waitForHandshake;
time_t timeAtHandshake; time_t timeAtHandshake;
bool needInit = true; bool needInit = true;
@@ -121,6 +122,7 @@ masterMacsAxis::masterMacsAxis(masterMacsController *pC, int axisNo)
pMasterMacsA_ = std::make_unique<masterMacsAxisImpl>((masterMacsAxisImpl){ pMasterMacsA_ = std::make_unique<masterMacsAxisImpl>((masterMacsAxisImpl){
.axisStatus = std::bitset<16>(0), .axisStatus = std::bitset<16>(0),
.axisError = std::bitset<16>(0), .axisError = std::bitset<16>(0),
.lastSetSpeed = 0.0,
.waitForHandshake = false, .waitForHandshake = false,
.timeAtHandshake = 0, .timeAtHandshake = 0,
.targetReachedUninitialized = true, .targetReachedUninitialized = true,
@@ -260,6 +262,11 @@ asynStatus masterMacsAxis::init() {
__PRETTY_FUNCTION__, __LINE__); __PRETTY_FUNCTION__, __LINE__);
} }
// Cache the motor speed. If this value differs from the one in the motor
// record at the start of a movement, the motor record value is sent to
// MasterMACS.
pMasterMacsA_->lastSetSpeed = motorVelocity;
// Store the motor position in the parameter library // Store the motor position in the parameter library
pl_status = setMotorPosition(motorPosition); pl_status = setMotorPosition(motorPosition);
if (pl_status != asynSuccess) { if (pl_status != asynSuccess) {
@@ -356,11 +363,14 @@ asynStatus masterMacsAxis::doPoll(bool *moving) {
} }
if (timedOut) { if (timedOut) {
setAxisParamChecked(this, motorMessageText, pl_status =
"Timed out while waiting for a handshake. " setStringParam(pC_->motorMessageText(),
"Please call the support."); "Timed out while waiting for a handshake");
if (pl_status != asynSuccess) {
poll_status = asynError; return pC_->paramLibAccessFailed(pl_status, "motorMessageText_",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
} }
pC_->read(axisNo_, 86, response); pC_->read(axisNo_, 86, response);
@@ -380,15 +390,36 @@ asynStatus masterMacsAxis::doPoll(bool *moving) {
pMasterMacsA_->waitForHandshake = false; pMasterMacsA_->waitForHandshake = false;
pMasterMacsA_->targetReachedUninitialized = false; pMasterMacsA_->targetReachedUninitialized = false;
} else { } else {
// Still waiting for the handshake - try again in the next busy
// poll. This is already part of the movement procedure.
*moving = true; *moving = true;
setAxisParamChecked(this, motorStatusMoving, *moving);
setAxisParamChecked(this, motorStatusDone, !(*moving)); pl_status = setIntegerParam(pC_->motorStatusMoving(), *moving);
return poll_status; if (pl_status != asynSuccess) {
return pC_->paramLibAccessFailed(pl_status,
"motorStatusMoving_", axisNo_,
__PRETTY_FUNCTION__, __LINE__);
}
pl_status = setIntegerParam(pC_->motorStatusDone(), !(*moving));
if (pl_status != asynSuccess) {
return pC_->paramLibAccessFailed(pl_status, "motorStatusDone_",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
return asynSuccess;
} }
} }
// Motor resolution from parameter library // Motor resolution from parameter library
getAxisParamChecked(this, motorRecResolution, &motorRecResolution); pl_status = pC_->getDoubleParam(axisNo_, pC_->motorRecResolution(),
&motorRecResolution);
if (pl_status != asynSuccess) {
return pC_->paramLibAccessFailed(pl_status, "motorRecResolution_",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
// Read the previous motor position // Read the previous motor position
pl_status = motorPosition(&previousPosition); pl_status = motorPosition(&previousPosition);
@@ -402,9 +433,6 @@ asynStatus masterMacsAxis::doPoll(bool *moving) {
return rw_status; return rw_status;
} }
// If we wait for a handshake, but the motor was moving in its last poll
// cycle and has reached its target, it is not moving. Otherwise it is
// considered moving, even if we're still waiting for the handshake.
if (pMasterMacsA_->targetReachedUninitialized) { if (pMasterMacsA_->targetReachedUninitialized) {
*moving = false; *moving = false;
} else { } else {
@@ -434,181 +462,195 @@ asynStatus masterMacsAxis::doPoll(bool *moving) {
Read out the error if either a fault condition status flag has been set or Read out the error if either a fault condition status flag has been set or
if a movement has just ended. if a movement has just ended.
*/ */
if (faultConditionSet() || !(*moving)) {
rw_status = readAxisError();
}
msgPrintControlKey keyError = msgPrintControlKey( msgPrintControlKey keyError = msgPrintControlKey(
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__); pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
/* if (faultConditionSet() || !(*moving)) {
A communication error is a special case. If a communication between rw_status = readAxisError();
controller and axis error occurred, all subsequent errors are ignored,
since this information is not reliable.
*/
if (communicationError()) {
if (pC_->getMsgPrintControl().shouldBePrinted(keyError, true,
pC_->pasynUser())) {
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line "
"%d\nCommunication error.%s\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
pC_->getMsgPrintControl().getSuffix());
}
setAxisParamChecked(this, motorMessageText,
"Communication error between PC and motor "
"controller. Please call the support.");
poll_status = asynError;
} else {
// This buffer must be initialized to zero because we build the
// error message by appending strings.
char errorMessage[pC_->MAXBUF_] = {0};
char shellMessage[pC_->MAXBUF_] = {0};
// Concatenate all other errors
if (shortCircuit()) {
appendErrorMessage(shellMessage, sizeof(shellMessage),
"Short circuit fault.");
appendErrorMessage(errorMessage, sizeof(errorMessage),
"Short circuit error. Please call the support.");
poll_status = asynError;
}
if (encoderError()) {
appendErrorMessage(shellMessage, sizeof(shellMessage),
"Encoder error.");
appendErrorMessage(errorMessage, sizeof(errorMessage),
"Encoder error. Please call the support.");
poll_status = asynError;
}
if (followingError()) {
appendErrorMessage(shellMessage, sizeof(shellMessage),
"Maximum callowed following error exceeded.");
appendErrorMessage(
errorMessage, sizeof(errorMessage),
"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(errorMessage, sizeof(errorMessage),
"Feedback error. Please call the support.");
poll_status = asynError;
}
/* /*
Either the software limits or the end switches of the controller A communication error is a special case. If a communication between
have been hit. Since the EPICS limits are derived from the software controller and axis error occurred, all subsequent errors are ignored,
limits and are a little bit smaller, these error cases can only since this information is not reliable.
happen if either the axis has an incremental encoder which is not */
properly homed or if a bug occured. if (communicationError()) {
*/
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(
errorMessage, sizeof(errorMessage),
"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(errorMessage, sizeof(errorMessage),
"Overcurrent error. Please call the support.");
poll_status = asynError;
}
if (overTemperature()) {
appendErrorMessage(shellMessage, sizeof(shellMessage),
"Overtemperature error.");
appendErrorMessage(
errorMessage, sizeof(errorMessage),
"Overtemperature error. Please call the support.");
poll_status = asynError;
}
if (overVoltage()) {
appendErrorMessage(shellMessage, sizeof(shellMessage),
"Overvoltage error.");
appendErrorMessage(errorMessage, sizeof(errorMessage),
"Overvoltage error. Please call the support.");
poll_status = asynError;
}
if (underVoltage()) {
appendErrorMessage(shellMessage, sizeof(shellMessage),
"Undervoltage error.");
appendErrorMessage(errorMessage, sizeof(errorMessage),
"Undervoltage error. Please call the support.");
poll_status = asynError;
}
if (stoFault()) {
appendErrorMessage(shellMessage, sizeof(shellMessage),
"STO input is on disable state.");
appendErrorMessage(errorMessage, sizeof(errorMessage),
"STO fault. Please call the support.");
poll_status = asynError;
}
if (strlen(shellMessage) > 0) {
if (pC_->getMsgPrintControl().shouldBePrinted(keyError, true, if (pC_->getMsgPrintControl().shouldBePrinted(keyError, true,
pC_->pasynUser())) { pC_->pasynUser())) {
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR, asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line " "Controller \"%s\", axis %d => %s, line "
"%d\n%s%s\n", "%d\nCommunication error.%s\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
shellMessage, pC_->getMsgPrintControl().getSuffix()); pC_->getMsgPrintControl().getSuffix());
}
pl_status =
setStringParam(pC_->motorMessageText(),
"Communication error between PC and motor "
"controller. Please call the support.");
if (pl_status != asynSuccess) {
return pC_->paramLibAccessFailed(pl_status, "motorMessageText_",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
poll_status = asynError;
} else {
// This buffer must be initialized to zero because we build the
// error message by appending strings.
char errorMessage[pC_->MAXBUF_] = {0};
char shellMessage[pC_->MAXBUF_] = {0};
// Concatenate all other errors
if (shortCircuit()) {
appendErrorMessage(shellMessage, sizeof(shellMessage),
"Short circuit fault.");
appendErrorMessage(
errorMessage, sizeof(errorMessage),
"Short circuit error. Please call the support.");
poll_status = asynError;
}
if (encoderError()) {
appendErrorMessage(shellMessage, sizeof(shellMessage),
"Encoder error.");
appendErrorMessage(errorMessage, sizeof(errorMessage),
"Encoder error. Please call the support.");
poll_status = asynError;
}
if (followingError()) {
appendErrorMessage(
shellMessage, sizeof(shellMessage),
"Maximum callowed following error exceeded.");
appendErrorMessage(
errorMessage, sizeof(errorMessage),
"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(errorMessage, sizeof(errorMessage),
"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(
errorMessage, sizeof(errorMessage),
"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(
errorMessage, sizeof(errorMessage),
"Overcurrent error. Please call the support.");
poll_status = asynError;
}
if (overTemperature()) {
appendErrorMessage(shellMessage, sizeof(shellMessage),
"Overtemperature error.");
appendErrorMessage(
errorMessage, sizeof(errorMessage),
"Overtemperature error. Please call the support.");
poll_status = asynError;
}
if (overVoltage()) {
appendErrorMessage(shellMessage, sizeof(shellMessage),
"Overvoltage error.");
appendErrorMessage(
errorMessage, sizeof(errorMessage),
"Overvoltage error. Please call the support.");
poll_status = asynError;
}
if (underVoltage()) {
appendErrorMessage(shellMessage, sizeof(shellMessage),
"Undervoltage error.");
appendErrorMessage(
errorMessage, sizeof(errorMessage),
"Undervoltage error. Please call the support.");
poll_status = asynError;
}
if (stoFault()) {
appendErrorMessage(shellMessage, sizeof(shellMessage),
"STO input is on disable state.");
appendErrorMessage(errorMessage, sizeof(errorMessage),
"STO fault. Please call the support.");
poll_status = asynError;
}
if (strlen(shellMessage) > 0) {
if (pC_->getMsgPrintControl().shouldBePrinted(
keyError, true, pC_->pasynUser())) {
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line "
"%d\n%s%s\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__,
__LINE__, shellMessage,
pC_->getMsgPrintControl().getSuffix());
}
}
pl_status = setStringParam(pC_->motorMessageText(), errorMessage);
if (pl_status != asynSuccess) {
return pC_->paramLibAccessFailed(pl_status, "motorMessageText_",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
} }
} }
} else {
setAxisParamChecked(this, motorMessageText, errorMessage);
}
// No error has been detected -> Reset the error count
if (poll_status == asynSuccess) {
pC_->getMsgPrintControl().resetCount(keyError, pC_->pasynUser()); pC_->getMsgPrintControl().resetCount(keyError, pC_->pasynUser());
} }
@@ -647,18 +689,40 @@ asynStatus masterMacsAxis::doPoll(bool *moving) {
directly, but need to shrink them a bit. In this case, we're shrinking directly, but need to shrink them a bit. In this case, we're shrinking
them by 0.1 mm or 0.1 degree (depending on the axis type) on both sides. them by 0.1 mm or 0.1 degree (depending on the axis type) on both sides.
*/ */
getAxisParamChecked(this, motorLimitsOffset, &limitsOffset); pl_status = pC_->getDoubleParam(axisNo_, pC_->motorLimitsOffset(),
&limitsOffset);
if (pl_status != asynSuccess) {
return pC_->paramLibAccessFailed(pl_status, "motorLimitsOffset_",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
highLimit = highLimit - limitsOffset; highLimit = highLimit - limitsOffset;
lowLimit = lowLimit + limitsOffset; lowLimit = lowLimit + limitsOffset;
setAxisParamChecked(this, motorHighLimitFromDriver, highLimit); pl_status = pC_->setDoubleParam(
setAxisParamChecked(this, motorLowLimitFromDriver, lowLimit); axisNo_, pC_->motorHighLimitFromDriver(), highLimit);
if (pl_status != asynSuccess) {
return pC_->paramLibAccessFailed(
pl_status, "motorHighLimitFromDriver_", axisNo_,
__PRETTY_FUNCTION__, __LINE__);
}
pl_status = pC_->setDoubleParam(axisNo_, pC_->motorLowLimitFromDriver(),
lowLimit);
if (pl_status != asynSuccess) {
return pC_->paramLibAccessFailed(pl_status, "motorLowLimit_",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
} }
// Update the enable PV // Update the enable PV
setAxisParamChecked(this, motorEnableRBV, pl_status = setIntegerParam(pC_->motorEnableRBV(),
readyToBeSwitchedOn() && switchedOn()); readyToBeSwitchedOn() && switchedOn());
if (pl_status != asynSuccess) {
return pC_->paramLibAccessFailed(pl_status, "motorEnableRBV_", axisNo_,
__PRETTY_FUNCTION__, __LINE__);
}
if (*moving) { if (*moving) {
// If the axis is moving, evaluate the movement direction // If the axis is moving, evaluate the movement direction
@@ -671,16 +735,38 @@ asynStatus masterMacsAxis::doPoll(bool *moving) {
// Update the parameter library // Update the parameter library
if (hasError) { if (hasError) {
setAxisParamChecked(this, motorStatusProblem, true); pl_status = setIntegerParam(pC_->motorStatusProblem(), true);
if (pl_status != asynSuccess) {
return pC_->paramLibAccessFailed(pl_status, "motorStatusProblem_",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
}
pl_status = setIntegerParam(pC_->motorStatusMoving(), *moving);
if (pl_status != asynSuccess) {
return pC_->paramLibAccessFailed(pl_status, "motorStatusMoving_",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
pl_status = setIntegerParam(pC_->motorStatusDone(), !(*moving));
if (pl_status != asynSuccess) {
return pC_->paramLibAccessFailed(pl_status, "motorStatusDone_", axisNo_,
__PRETTY_FUNCTION__, __LINE__);
}
pl_status = setIntegerParam(pC_->motorStatusDirection(), direction);
if (pl_status != asynSuccess) {
return pC_->paramLibAccessFailed(pl_status, "motorStatusDirection_",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
} }
setAxisParamChecked(this, motorStatusMoving, *moving);
setAxisParamChecked(this, motorStatusDone, !(*moving));
setAxisParamChecked(this, motorStatusDirection, direction);
pl_status = setMotorPosition(currentPosition); pl_status = setMotorPosition(currentPosition);
if (pl_status != asynSuccess) { if (pl_status != asynSuccess) {
return pl_status; return pl_status;
} }
return poll_status; return poll_status;
} }
@@ -689,7 +775,10 @@ asynStatus masterMacsAxis::doMove(double position, int relative,
double acceleration) { double acceleration) {
// Status of read-write-operations of ASCII commands to the controller // Status of read-write-operations of ASCII commands to the controller
asynStatus status = asynSuccess; asynStatus rw_status = asynSuccess;
// Status of parameter library operations
asynStatus pl_status = asynSuccess;
char value[pC_->MAXBUF_]; char value[pC_->MAXBUF_];
double motorCoordinatesPosition = 0.0; double motorCoordinatesPosition = 0.0;
@@ -700,8 +789,19 @@ asynStatus masterMacsAxis::doMove(double position, int relative,
// ========================================================================= // =========================================================================
getAxisParamChecked(this, motorEnableRBV, &enabled); pl_status = pC_->getIntegerParam(axisNo_, pC_->motorEnableRBV(), &enabled);
getAxisParamChecked(this, motorRecResolution, &motorRecResolution); if (pl_status != asynSuccess) {
return pC_->paramLibAccessFailed(pl_status, "enableMotorRBV_", axisNo_,
__PRETTY_FUNCTION__, __LINE__);
}
pl_status = pC_->getDoubleParam(axisNo_, pC_->motorRecResolution(),
&motorRecResolution);
if (pl_status != asynSuccess) {
return pC_->paramLibAccessFailed(pl_status, "motorRecResolution_",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
if (enabled == 0) { if (enabled == 0) {
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR, asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
@@ -721,24 +821,42 @@ asynStatus masterMacsAxis::doMove(double position, int relative,
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, position); pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, position);
// Check if the speed is allowed to be changed // Check if the speed is allowed to be changed
getAxisParamChecked(this, motorCanSetSpeed, &motorCanSetSpeed); pl_status = pC_->getIntegerParam(axisNo_, pC_->motorCanSetSpeed(),
&motorCanSetSpeed);
if (pl_status != asynSuccess) {
return pC_->paramLibAccessFailed(pl_status, "motorCanSetSpeed_",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
// Initialize the movement handshake // Initialize the movement handshake
status = pC_->write(axisNo_, 86, "0"); rw_status = pC_->write(axisNo_, 86, "0");
if (status != asynSuccess) { if (rw_status != asynSuccess) {
setAxisParamChecked(this, motorStatusProblem, true); pl_status = setIntegerParam(pC_->motorStatusProblem(), true);
return status; if (pl_status != asynSuccess) {
return pC_->paramLibAccessFailed(pl_status, "motorStatusProblem_",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
return rw_status;
} }
// Set the new motor speed, if the user is allowed to do so and if the // Set the new motor speed, if the user is allowed to do so and if the
// motor speed changed since the last move command. // motor speed changed since the last move command.
if (motorCanSetSpeed != 0) { if (motorCanSetSpeed != 0 && pMasterMacsA_->lastSetSpeed != motorVelocity) {
pMasterMacsA_->lastSetSpeed = motorVelocity;
snprintf(value, sizeof(value), "%lf", motorVelocity); snprintf(value, sizeof(value), "%lf", motorVelocity);
status = pC_->write(axisNo_, 05, value); rw_status = pC_->write(axisNo_, 05, value);
if (status != asynSuccess) { if (rw_status != asynSuccess) {
setAxisParamChecked(this, motorStatusProblem, true); pl_status = setIntegerParam(pC_->motorStatusProblem(), true);
return status; if (pl_status != asynSuccess) {
return pC_->paramLibAccessFailed(pl_status,
"motorStatusProblem_", axisNo_,
__PRETTY_FUNCTION__, __LINE__);
}
return rw_status;
} }
asynPrint(pC_->pasynUser(), ASYN_TRACE_FLOW, asynPrint(pC_->pasynUser(), ASYN_TRACE_FLOW,
@@ -750,10 +868,15 @@ asynStatus masterMacsAxis::doMove(double position, int relative,
// Set the target position // Set the target position
snprintf(value, sizeof(value), "%lf", motorCoordinatesPosition); snprintf(value, sizeof(value), "%lf", motorCoordinatesPosition);
status = pC_->write(axisNo_, 02, value); rw_status = pC_->write(axisNo_, 02, value);
if (status != asynSuccess) { if (rw_status != asynSuccess) {
setAxisParamChecked(this, motorStatusProblem, true); pl_status = setIntegerParam(pC_->motorStatusProblem(), true);
return status; if (pl_status != asynSuccess) {
return pC_->paramLibAccessFailed(pl_status, "motorStatusProblem_",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
return rw_status;
} }
// If the motor has just been enabled, use Enable // If the motor has just been enabled, use Enable
@@ -765,13 +888,18 @@ asynStatus masterMacsAxis::doMove(double position, int relative,
// Start the move // Start the move
if (relative) { if (relative) {
status = pC_->write(axisNo_, 00, "2", timeout); rw_status = pC_->write(axisNo_, 00, "2", timeout);
} else { } else {
status = pC_->write(axisNo_, 00, "1", timeout); rw_status = pC_->write(axisNo_, 00, "1", timeout);
} }
if (status != asynSuccess) { if (rw_status != asynSuccess) {
setAxisParamChecked(this, motorStatusProblem, true); pl_status = setIntegerParam(pC_->motorStatusProblem(), true);
return status; if (pl_status != asynSuccess) {
return pC_->paramLibAccessFailed(pl_status, "motorStatusProblem_",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
return rw_status;
} }
// In the next poll, we will check if the handshake has been performed in a // In the next poll, we will check if the handshake has been performed in a
@@ -785,61 +913,60 @@ asynStatus masterMacsAxis::doMove(double position, int relative,
return asynError; return asynError;
} }
return status; return rw_status;
} }
asynStatus masterMacsAxis::stop(double acceleration) { asynStatus masterMacsAxis::stop(double acceleration) {
asynStatus status = pC_->write(axisNo_, 00, "8"); // Status of read-write-operations of ASCII commands to the controller
if (status != asynSuccess) { asynStatus rw_status = asynSuccess;
setAxisParamChecked(this, motorStatusProblem, true);
// Status of parameter library operations
asynStatus pl_status = asynSuccess;
// =========================================================================
rw_status = pC_->write(axisNo_, 00, "8");
if (rw_status != asynSuccess) {
pl_status = setIntegerParam(pC_->motorStatusProblem(), true);
if (pl_status != asynSuccess) {
return pC_->paramLibAccessFailed(pl_status, "motorStatusProblem_",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
} }
// Reset the driver to idle state and move out of the handshake wait loop, // Reset the driver to idle state and move out of the handshake wait loop,
// if we're currently inside it. // if we're currently inside it.
pMasterMacsA_->waitForHandshake = false; pMasterMacsA_->waitForHandshake = false;
return status; return rw_status;
} }
asynStatus masterMacsAxis::doReset() { asynStatus masterMacsAxis::doReset() {
// Status of read-write-operations of ASCII commands to the controller
asynStatus rw_status = asynSuccess;
asynStatus status = asynSuccess; // Status of parameter library operations
asynStatus pl_status = asynSuccess;
// Reset any errors // =========================================================================
status = pC_->write(axisNo_, 17, "");
if (status != asynSuccess) { rw_status = pC_->write(axisNo_, 17, "");
setAxisParamChecked(this, motorStatusProblem, true); if (rw_status != asynSuccess) {
pl_status = setIntegerParam(pC_->motorStatusProblem(), true);
if (pl_status != asynSuccess) {
return pC_->paramLibAccessFailed(pl_status, "motorStatusProblem_",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
} }
// Move out of the handshake wait loop, if we're currently inside it. // Reset the driver to idle state and move out of the handshake wait loop,
// if we're currently inside it.
pMasterMacsA_->waitForHandshake = false; pMasterMacsA_->waitForHandshake = false;
// Disable the axis return rw_status;
return enable(false);
}
asynStatus masterMacsAxis::nodeReset() {
asynStatus status = asynSuccess;
// Reset the controller ("node reset"). Since the node reset results in a
// power cycle, we use the corresponding timeout.
status = pC_->write(axisNo_, 16, "", PowerCycleTimeout);
if (status != asynSuccess) {
setAxisParamChecked(this, motorStatusProblem, true);
}
// Move out of the handshake wait loop, if we're currently inside it.
pMasterMacsA_->waitForHandshake = false;
// Reinitialize the axis
status = masterMacsAxis::init();
if (status != asynSuccess) {
return status;
}
bool moving = false;
return forcedPoll(&moving);
} }
/* /*
@@ -848,25 +975,41 @@ Home the axis. On absolute encoder systems, this is a no-op
asynStatus masterMacsAxis::doHome(double min_velocity, double max_velocity, asynStatus masterMacsAxis::doHome(double min_velocity, double max_velocity,
double acceleration, int forwards) { double acceleration, int forwards) {
// Status of read-write-operations of ASCII commands to the controller
asynStatus rw_status = asynSuccess;
// Status of parameter library operations
asynStatus pl_status = asynSuccess;
char response[pC_->MAXBUF_] = {0}; char response[pC_->MAXBUF_] = {0};
// ========================================================================= // =========================================================================
getAxisParamChecked(this, encoderType, &response); pl_status = pC_->getStringParam(axisNo_, pC_->encoderType(),
sizeof(response), response);
if (pl_status != asynSuccess) {
return pC_->paramLibAccessFailed(pl_status, "encoderType_", axisNo_,
__PRETTY_FUNCTION__, __LINE__);
}
// Only send the home command if the axis has an incremental encoder // Only send the home command if the axis has an incremental encoder
if (strcmp(response, IncrementalEncoder) == 0) { if (strcmp(response, IncrementalEncoder) == 0) {
// Initialize the movement handshake // Initialize the movement handshake
asynStatus status = pC_->write(axisNo_, 86, "0"); rw_status = pC_->write(axisNo_, 86, "0");
if (status != asynSuccess) { if (rw_status != asynSuccess) {
setAxisParamChecked(this, motorStatusProblem, true); pl_status = setIntegerParam(pC_->motorStatusProblem(), true);
return status; if (pl_status != asynSuccess) {
return pC_->paramLibAccessFailed(pl_status,
"motorStatusProblem_", axisNo_,
__PRETTY_FUNCTION__, __LINE__);
}
return rw_status;
} }
status = pC_->write(axisNo_, 00, "9"); rw_status = pC_->write(axisNo_, 00, "9");
if (status != asynSuccess) { if (rw_status != asynSuccess) {
return status; return rw_status;
} }
// In the next poll, we will check if the handshake has been performed // In the next poll, we will check if the handshake has been performed
@@ -884,6 +1027,12 @@ Read the encoder type and update the parameter library accordingly
*/ */
asynStatus masterMacsAxis::readEncoderType() { asynStatus masterMacsAxis::readEncoderType() {
// Status of read-write-operations of ASCII commands to the controller
asynStatus rw_status = asynSuccess;
// Status of parameter library operations
asynStatus pl_status = asynSuccess;
char command[pC_->MAXBUF_] = {0}; char command[pC_->MAXBUF_] = {0};
char response[pC_->MAXBUF_] = {0}; char response[pC_->MAXBUF_] = {0};
int nvals = 0; int nvals = 0;
@@ -892,9 +1041,9 @@ asynStatus masterMacsAxis::readEncoderType() {
// ========================================================================= // =========================================================================
// Check if this is an absolute encoder // Check if this is an absolute encoder
asynStatus status = pC_->read(axisNo_, 60, response); rw_status = pC_->read(axisNo_, 60, response);
if (status != asynSuccess) { if (rw_status != asynSuccess) {
return status; return rw_status;
} }
nvals = sscanf(response, "%d", &encoder_id); nvals = sscanf(response, "%d", &encoder_id);
@@ -910,18 +1059,28 @@ asynStatus masterMacsAxis::readEncoderType() {
2=SSI (Absolute encoder with BiSS interface) 2=SSI (Absolute encoder with BiSS interface)
*/ */
if (encoder_id == 0) { if (encoder_id == 0) {
setAxisParamChecked(this, encoderType, IncrementalEncoder); pl_status = setStringParam(pC_->encoderType(), IncrementalEncoder);
} else { } else {
setAxisParamChecked(this, encoderType, AbsoluteEncoder); pl_status = setStringParam(pC_->encoderType(), AbsoluteEncoder);
} }
if (pl_status != asynSuccess) {
return pC_->paramLibAccessFailed(pl_status, "encoderType_", axisNo_,
__PRETTY_FUNCTION__, __LINE__);
}
return asynSuccess; return asynSuccess;
} }
asynStatus masterMacsAxis::enable(bool on) { asynStatus masterMacsAxis::enable(bool on) {
int timeout_enable_disable = 2; int timeout_enable_disable = 2;
char msg[pC_->MAXBUF_]; char value[pC_->MAXBUF_];
// Status of read-write-operations of ASCII commands to the controller
asynStatus rw_status = asynSuccess;
// Status of parameter library operations
asynStatus pl_status = asynSuccess;
// ========================================================================= // =========================================================================
@@ -951,8 +1110,14 @@ asynStatus masterMacsAxis::enable(bool on) {
"idle and can therefore not be disabled.\n", "idle and can therefore not be disabled.\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__); pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
setAxisParamChecked(this, motorMessageText, pl_status =
"Axis cannot be disabled while it is moving."); setStringParam(pC_->motorMessageText(),
"Axis cannot be disabled while it is moving.");
if (pl_status != asynSuccess) {
return pC_->paramLibAccessFailed(pl_status, "motorMessageText_",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
return asynError; return asynError;
} }
@@ -970,7 +1135,7 @@ asynStatus masterMacsAxis::enable(bool on) {
} }
// Enable / disable the axis if it is not moving // Enable / disable the axis if it is not moving
snprintf(msg, sizeof(msg), "%d", on); snprintf(value, sizeof(value), "%d", on);
asynPrint(pC_->pasynUser(), ASYN_TRACE_FLOW, asynPrint(pC_->pasynUser(), ASYN_TRACE_FLOW,
"Controller \"%s\", axis %d => %s, line %d:\n%s axis.\n", "Controller \"%s\", axis %d => %s, line %d:\n%s axis.\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
@@ -985,9 +1150,9 @@ asynStatus masterMacsAxis::enable(bool on) {
timeout = PowerCycleTimeout; timeout = PowerCycleTimeout;
} }
asynStatus status = pC_->write(axisNo_, 04, msg, timeout); rw_status = pC_->write(axisNo_, 04, value, timeout);
if (status != asynSuccess) { if (rw_status != asynSuccess) {
return status; return rw_status;
} }
// Query the axis status every few milliseconds until the axis has been // Query the axis status every few milliseconds until the axis has been
@@ -997,15 +1162,15 @@ asynStatus masterMacsAxis::enable(bool on) {
// Read the axis status // Read the axis status
usleep(100000); usleep(100000);
status = readAxisStatus(); rw_status = readAxisStatus();
if (status != asynSuccess) { if (rw_status != asynSuccess) {
return status; return rw_status;
} }
if (switchedOn() == on) { if (switchedOn() == on) {
bool moving = false; bool moving = false;
// Perform a poll to update the parameter library // Perform a poll to update the parameter library
forcedPoll(&moving); poll(&moving);
return asynSuccess; return asynSuccess;
} }
} }
@@ -1019,10 +1184,14 @@ asynStatus masterMacsAxis::enable(bool on) {
on ? "enable" : "disable", timeout_enable_disable); on ? "enable" : "disable", timeout_enable_disable);
// Output message to user // Output message to user
snprintf(msg, sizeof(msg), "Failed to %s within %d seconds", snprintf(value, sizeof(value), "Failed to %s within %d seconds",
on ? "enable" : "disable", timeout_enable_disable); on ? "enable" : "disable", timeout_enable_disable);
pl_status = setStringParam(pC_->motorMessageText(), value);
setAxisParamChecked(this, motorMessageText, msg); if (pl_status != asynSuccess) {
return pC_->paramLibAccessFailed(pl_status, "motorMessageText_",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
return asynError; return asynError;
} }

View File

@@ -1,12 +1,16 @@
#ifndef masterMacsAXIS_H #ifndef masterMacsAXIS_H
#define masterMacsAXIS_H #define masterMacsAXIS_H
#include "masterMacsController.h"
#include "sinqAxis.h" #include "sinqAxis.h"
#include <memory> #include <memory>
struct HIDDEN masterMacsAxisImpl; // Forward declaration of the controller class to resolve the cyclic dependency
// between the controller and the axis .h-file. See
// https://en.cppreference.com/w/cpp/language/class.
class masterMacsController;
class HIDDEN masterMacsAxis : public sinqAxis { struct masterMacsAxisImpl;
class masterMacsAxis : public sinqAxis {
public: public:
/** /**
* @brief Construct a new masterMacsAxis * @brief Construct a new masterMacsAxis
@@ -75,27 +79,12 @@ class HIDDEN masterMacsAxis : public sinqAxis {
*/ */
asynStatus doReset(); asynStatus doReset();
/**
* @brief Performs a "node reset" on the axis as defined in the CANopen
* standard
*
* A "node reset" is a factory reset on the axis which completely deletes
* all configured information (e.g. limits or speed) from the axis. The
* MasterMACS controller then reapplies the initial configuration to this
* axis. It can therefore be seen as a "hard" version of the normal error
* reset performed by the `doReset` method.
*
* @return asynStatus
*/
asynStatus nodeReset();
/** /**
* @brief Readout of some values from the controller at IOC startup * @brief Readout of some values from the controller at IOC startup
* *
* The following steps are performed: * The following steps are performed:
* - Read out the motor status, motor position, velocity and * - Read out the motor status, motor position, velocity and acceleration
* acceleration from the MCU and store this information in the parameter * from the MCU and store this information in the parameter library.
* library.
* - Set the enable PV accordint to the initial status of the axis. * - Set the enable PV accordint to the initial status of the axis.
* *
* @return asynStatus * @return asynStatus
@@ -111,8 +100,8 @@ class HIDDEN masterMacsAxis : public sinqAxis {
asynStatus enable(bool on); asynStatus enable(bool on);
/** /**
* @brief Read the encoder type (incremental or absolute) for this axis * @brief Read the encoder type (incremental or absolute) for this axis from
* from the MCU and store the information in the PV ENCODER_TYPE. * the MCU and store the information in the PV ENCODER_TYPE.
* *
* @return asynStatus * @return asynStatus
*/ */
@@ -127,21 +116,17 @@ class HIDDEN masterMacsAxis : public sinqAxis {
bool needInit(); bool needInit();
/** /**
* @brief Instruct the axis to run its init() function during the next * @brief Instruct the axis to run its init() function during the next poll
* poll
* *
* @param needInit * @param needInit
*/ */
void setNeedInit(bool needInit); void setNeedInit(bool needInit);
/** asynStatus readConfig();
* @brief Return a pointer to the axis controller
*/
virtual masterMacsController *pController() override { return pC_; };
/** /**
* @brief Read the Master MACS status with the xR10 command and store * @brief Read the Master MACS status with the xR10 command and store the
* the result in axisStatus_ * result in axisStatus_
* *
*/ */
asynStatus readAxisStatus(); asynStatus readAxisStatus();
@@ -219,8 +204,8 @@ class HIDDEN masterMacsAxis : public sinqAxis {
bool powerEnabled(); bool powerEnabled();
/** /**
* @brief Read the Master MACS status with the xR10 command and store * @brief Read the Master MACS status with the xR10 command and store the
* the result in axisStatus_ * result in axisStatus_
* *
*/ */
asynStatus readAxisError(); asynStatus readAxisError();

View File

@@ -14,9 +14,6 @@
struct masterMacsControllerImpl { struct masterMacsControllerImpl {
double comTimeout; double comTimeout;
// Indices of additional ParamLib entries
int nodeReset;
}; };
/** /**
@@ -71,20 +68,6 @@ masterMacsController::masterMacsController(const char *portName,
.comTimeout = comTimeout, .comTimeout = comTimeout,
}); });
// =========================================================================
// Create additional parameter library entries
status =
createParam("NODE_RESET", asynParamInt32, &pMasterMacsC_->nodeReset);
if (status != asynSuccess) {
asynPrint(this->pasynUser(), ASYN_TRACE_ERROR,
"Controller \"%s\" => %s, line %d\nFATAL ERROR (creating a "
"parameter failed with %s).\nTerminating IOC",
portName, __PRETTY_FUNCTION__, __LINE__,
stringifyAsynStatus(status));
exit(-1);
}
// ========================================================================= // =========================================================================
/* /*
@@ -137,22 +120,6 @@ masterMacsAxis *masterMacsController::getMasterMacsAxis(int axisNo) {
return dynamic_cast<masterMacsAxis *>(asynAxis); return dynamic_cast<masterMacsAxis *>(asynAxis);
} }
asynStatus masterMacsController::writeInt32(asynUser *pasynUser,
epicsInt32 value) {
int function = pasynUser->reason;
// =====================================================================
masterMacsAxis *axis = getMasterMacsAxis(pasynUser);
// Handle custom PVs
if (function == nodeReset()) {
return axis->nodeReset();
} else {
return sinqController::writeInt32(pasynUser, value);
}
}
asynStatus masterMacsController::read(int axisNo, int tcpCmd, char *response, asynStatus masterMacsController::read(int axisNo, int tcpCmd, char *response,
double comTimeout) { double comTimeout) {
return writeRead(axisNo, tcpCmd, NULL, response); return writeRead(axisNo, tcpCmd, NULL, response);
@@ -169,6 +136,7 @@ asynStatus masterMacsController::writeRead(int axisNo, int tcpCmd,
// Definition of local variables. // Definition of local variables.
asynStatus status = asynSuccess; asynStatus status = asynSuccess;
asynStatus pl_status = asynSuccess;
char fullCommand[MAXBUF_] = {0}; char fullCommand[MAXBUF_] = {0};
char fullResponse[MAXBUF_] = {0}; char fullResponse[MAXBUF_] = {0};
char drvMessageText[MAXBUF_] = {0}; char drvMessageText[MAXBUF_] = {0};
@@ -287,7 +255,7 @@ asynStatus masterMacsController::writeRead(int axisNo, int tcpCmd,
// Log the overall status (communication successfull or not) // Log the overall status (communication successfull or not)
if (status == asynSuccess) { if (status == asynSuccess) {
setAxisParamChecked(axis, motorStatusCommsError, false); pl_status = axis->setIntegerParam(this->motorStatusCommsError_, 0);
} else { } else {
/* /*
@@ -306,12 +274,35 @@ asynStatus masterMacsController::writeRead(int axisNo, int tcpCmd,
the user with different error messages if more than one error the user with different error messages if more than one error
ocurred before an error-free communication ocurred before an error-free communication
*/ */
getAxisParamChecked(axis, motorStatusProblem, &motorStatusProblem); pl_status =
getIntegerParam(axisNo, motorStatusProblem_, &motorStatusProblem);
if (pl_status != asynSuccess) {
return paramLibAccessFailed(pl_status, "motorStatusProblem", axisNo,
__PRETTY_FUNCTION__, __LINE__);
}
if (motorStatusProblem == 0) { if (motorStatusProblem == 0) {
setAxisParamChecked(axis, motorMessageText, drvMessageText); pl_status =
setAxisParamChecked(axis, motorStatusProblem, true); axis->setStringParam(motorMessageText(), drvMessageText);
setAxisParamChecked(axis, motorStatusCommsError, false); if (pl_status != asynSuccess) {
return paramLibAccessFailed(pl_status, "motorMessageText",
axisNo, __PRETTY_FUNCTION__,
__LINE__);
}
pl_status = axis->setIntegerParam(motorStatusProblem_, 1);
if (pl_status != asynSuccess) {
return paramLibAccessFailed(pl_status, "motorStatusProblem",
axisNo, __PRETTY_FUNCTION__,
__LINE__);
}
pl_status = axis->setIntegerParam(motorStatusProblem_, 1);
if (pl_status != asynSuccess) {
return paramLibAccessFailed(pl_status, "motorStatusCommsError_",
axisNo, __PRETTY_FUNCTION__,
__LINE__);
}
} }
} }
@@ -341,13 +332,12 @@ asynStatus masterMacsController::parseResponse(
msgPrintControlKey parseKey = msgPrintControlKey parseKey =
msgPrintControlKey(portName, axisNo, __PRETTY_FUNCTION__, __LINE__); msgPrintControlKey(portName, axisNo, __PRETTY_FUNCTION__, __LINE__);
masterMacsAxis *axis = getMasterMacsAxis(axisNo);
if (axis == nullptr) {
return asynError;
}
// Was the motor previously connected? // Was the motor previously connected?
getAxisParamChecked(axis, motorConnected, &prevConnected); status = getIntegerParam(axisNo, motorConnected(), &prevConnected);
if (status != asynSuccess) {
return paramLibAccessFailed(status, "motorConnected", axisNo,
__PRETTY_FUNCTION__, __LINE__);
}
// We don't use strlen here since the C string terminator 0x00 // We don't use strlen here since the C string terminator 0x00
// occurs in the middle of the char array. // occurs in the middle of the char array.
@@ -371,7 +361,16 @@ asynStatus masterMacsController::parseResponse(
"connected.\n", "connected.\n",
portName, axisNo, __PRETTY_FUNCTION__, __LINE__); portName, axisNo, __PRETTY_FUNCTION__, __LINE__);
setAxisParamChecked(axis, motorConnected, true); masterMacsAxis *axis = getMasterMacsAxis(axisNo);
if (axis == nullptr) {
return asynError;
}
status = axis->setIntegerParam(motorConnected(), 1);
if (status != asynSuccess) {
return paramLibAccessFailed(status, "motorConnected",
axisNo, __PRETTY_FUNCTION__,
__LINE__);
}
status = callParamCallbacks(); status = callParamCallbacks();
if (status != asynSuccess) { if (status != asynSuccess) {
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
@@ -399,7 +398,16 @@ asynStatus masterMacsController::parseResponse(
"disconnected.\n", "disconnected.\n",
portName, axisNo, __PRETTY_FUNCTION__, __LINE__); portName, axisNo, __PRETTY_FUNCTION__, __LINE__);
setAxisParamChecked(axis, motorConnected, false); masterMacsAxis *axis = getMasterMacsAxis(axisNo);
if (axis == nullptr) {
return asynError;
}
status = axis->setIntegerParam(motorConnected(), 0);
if (status != asynSuccess) {
return paramLibAccessFailed(status, "motorConnected",
axisNo, __PRETTY_FUNCTION__,
__LINE__);
}
status = callParamCallbacks(); status = callParamCallbacks();
if (status != asynSuccess) { if (status != asynSuccess) {
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
@@ -492,8 +500,6 @@ asynStatus masterMacsController::readInt32(asynUser *pasynUser,
double masterMacsController::comTimeout() { return pMasterMacsC_->comTimeout; } double masterMacsController::comTimeout() { return pMasterMacsC_->comTimeout; }
int masterMacsController::nodeReset() { return pMasterMacsC_->nodeReset; }
/***************************************************************************/ /***************************************************************************/
/** The following functions are C-wrappers, and can be called directly from /** The following functions are C-wrappers, and can be called directly from
* iocsh */ * iocsh */

View File

@@ -8,18 +8,14 @@
#ifndef masterMacsController_H #ifndef masterMacsController_H
#define masterMacsController_H #define masterMacsController_H
#include "masterMacsAxis.h"
#include "sinqAxis.h" #include "sinqAxis.h"
#include "sinqController.h" #include "sinqController.h"
#include <memory> #include <memory>
// Forward declaration of the controller class to resolve the cyclic dependency struct masterMacsControllerImpl;
// between the controller and the axis .h-file. See
// https://en.cppreference.com/w/cpp/language/class.
class HIDDEN masterMacsAxis;
struct HIDDEN masterMacsControllerImpl; class masterMacsController : public sinqController {
class HIDDEN masterMacsController : public sinqController {
public: public:
/** /**
@@ -65,17 +61,6 @@ class HIDDEN masterMacsController : public sinqController {
*/ */
masterMacsAxis *getMasterMacsAxis(int axisNo); masterMacsAxis *getMasterMacsAxis(int axisNo);
/**
* @brief Overloaded function of sinqController
*
* The function is overloaded to allow resetting the node
*
* @param pasynUser Specify the axis via the asynUser
* @param value New value
* @return asynStatus
*/
virtual asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value);
/** /**
* @brief Send a command to the hardware (S mode) * @brief Send a command to the hardware (S mode)
* *
@@ -152,9 +137,6 @@ class HIDDEN masterMacsController : public sinqController {
*/ */
double comTimeout(); double comTimeout();
// Accessors for additional PVs
int nodeReset();
private: private:
std::unique_ptr<masterMacsControllerImpl> pMasterMacsC_; std::unique_ptr<masterMacsControllerImpl> pMasterMacsC_;
}; };