Compare commits
34 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d41e7bf054 | |||
| 30bfa1cac5 | |||
| 235816fd20 | |||
| bd0966d2c9 | |||
| 9d5d90574a | |||
| 6effc5e906 | |||
| bc5de11b16 | |||
| aa488627f9 | |||
| ccaee6c5d1 | |||
| 323b030581 | |||
| b206012df2 | |||
| 21ec7e8467 | |||
| 398bc8241a | |||
| 8ca684604d | |||
| 72fe2b3681 | |||
| 5911e62029 | |||
| 682024091f | |||
| 335de72bc5 | |||
| 8e5055d6b8 | |||
| 1cab6e14ff | |||
| 1e8a6495b8 | |||
| 6b91ab6d51 | |||
| f423002d23 | |||
| 79ec79fac1 | |||
| 1703542770 | |||
| c7d1dc4930 | |||
| 6fd3848f13 | |||
| 56f08f3c76 | |||
| 168bfae983 | |||
| 0e29750d13 | |||
| ba5b921aca | |||
| 1b810fb353 | |||
| 4bc3388bc6 | |||
| c759156058 |
24
.gitea/workflows/action.yaml
Normal file
24
.gitea/workflows/action.yaml
Normal file
@@ -0,0 +1,24 @@
|
||||
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
|
||||
@@ -1,58 +0,0 @@
|
||||
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 --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
|
||||
|
||||
# clangtidy:
|
||||
# stage: lint
|
||||
# script:
|
||||
# - curl https://docker.psi.ch:5000/v2/_catalog
|
||||
# # - dnf update -y
|
||||
# # - dnf install -y clang-tools-extra
|
||||
# # - clang-tidy sinqEPICSApp/src/*.cpp sinqEPICSApp/src/*.c sinqEPICSApp/src/*.h -checks=cppcoreguidelines-*,cert-*
|
||||
# # 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/turboPmac/$(ls -U /ioc/modules/turboPmac/ | head -1)" "./turboPmac-${CI_COMMIT_TAG:-$CI_COMMIT_SHORT_SHA}"
|
||||
artifacts:
|
||||
name: "turboPmac-${CI_COMMIT_TAG:-$CI_COMMIT_SHORT_SHA}"
|
||||
paths:
|
||||
- "turboPmac-${CI_COMMIT_TAG:-$CI_COMMIT_SHORT_SHA}/*"
|
||||
expire_in: 1 week
|
||||
when: always
|
||||
tags:
|
||||
- sinq
|
||||
2
Makefile
2
Makefile
@@ -34,4 +34,4 @@ TEMPLATES += db/turboPmac.db
|
||||
DBDS += sinqMotor/src/sinqMotor.dbd
|
||||
DBDS += src/turboPmac.dbd
|
||||
|
||||
USR_CFLAGS += -Wall -Wextra -Weffc++ -Wunused-result -Werror # -Wpedantic // Does not work because EPICS macros trigger warnings
|
||||
USR_CFLAGS += -Wall -Wextra -Weffc++ -Wunused-result -Werror -fvisibility=hidden # -Wpedantic // Does not work because EPICS macros trigger warnings
|
||||
@@ -1,6 +1,6 @@
|
||||
# turboPmac
|
||||
|
||||
## <span style="color:red">Please read the documentation of sinqMotor first: https://git.psi.ch/sinq-epics-modules/sinqmotor</span>
|
||||
## <span style="color:red">Please read the documentation of sinqMotor first: https://gitea.psi.ch/lin-epics-modules/sinqMotor</span>
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -8,7 +8,7 @@ This is a driver for the Turbo PMAC motion controller with the SINQ communicatio
|
||||
|
||||
## User guide
|
||||
|
||||
This driver is a standard sinqMotor-derived which however uses a special low level IP Port driver (`pmacAsynIPPortConfigure`) instead of the standard `drvAsynIPPortConfigure`. For the general configuration, please see https://git.psi.ch/sinq-epics-modules/sinqmotor/-/blob/main/README.md.
|
||||
This driver is a standard sinqMotor-derived which however uses a special low level IP Port driver (`pmacAsynIPPortConfigure`) instead of the standard `drvAsynIPPortConfigure`. For the general configuration, please see https://gitea.psi.ch/lin-epics-modules/sinqMotor/src/branch/main/README.md.
|
||||
|
||||
The folder "utils" contains utility scripts for working with pmac motor controllers. To read their manual, run the scripts without any arguments.
|
||||
- writeRead.py: Allows sending commands to and receiving commands from a pmac controller over an ethernet connection.
|
||||
@@ -67,8 +67,8 @@ dbLoadRecords("$(turboPmac_DB)/asynRecord.db","P=$(INSTR)$(DRIVER_PORT),PORT=$(I
|
||||
|
||||
### Versioning
|
||||
|
||||
Please see the documentation for the module sinqMotor: https://git.psi.ch/sinq-epics-modules/sinqmotor/-/blob/main/README.md.
|
||||
Please see the documentation for the module sinqMotor: https://gitea.psi.ch/lin-epics-modules/sinqMotor/src/branch/main/README.md.
|
||||
|
||||
### How to build it
|
||||
|
||||
This driver can be compiled and installed by running `make install` from the same directory where the Makefile is located. However, since it uses the git submodule sinqMotor, make sure that the correct version of the submodule repository is checked out AND the change is commited (`git status` shows no non-committed changes). Please see the section "Usage as static dependency" in https://git.psi.ch/sinq-epics-modules/sinqmotor/-/blob/main/README.md for more details.
|
||||
This driver can be compiled and installed by running `make install` from the same directory where the Makefile is located. However, since it uses the git submodule sinqMotor, make sure that the correct version of the submodule repository is checked out AND the change is commited (`git status` shows no non-committed changes). Please see the section "Usage as static dependency" in https://gitea.psi.ch/lin-epics-modules/sinqMotor/src/branch/main/README.md for more details.
|
||||
|
||||
Submodule sinqMotor updated: bdefc6090d...8689c79f19
@@ -230,8 +230,7 @@ static asynStatus sendPmacGetBuffer(pmacPvt *pPmacPvt, asynUser *pasynUser,
|
||||
|
||||
// =============================================================================
|
||||
|
||||
epicsShareFunc int pmacAsynIPPortConfigure(const char *portName,
|
||||
const char *hostInfo) {
|
||||
int pmacAsynIPPortConfigure(const char *portName, const char *hostInfo) {
|
||||
asynStatus status = asynSuccess;
|
||||
asynInterface *int32LowerLevelInterface = NULL;
|
||||
asynInterface *octetLowerLevelInterface = NULL;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define asynInterposePmac_H
|
||||
|
||||
#include <epicsExport.h>
|
||||
#include <macros.h>
|
||||
#include <shareLib.h>
|
||||
|
||||
/*
|
||||
@@ -25,8 +26,7 @@ extern "C" {
|
||||
* 172.23.243.156:1025)
|
||||
* @return status
|
||||
*/
|
||||
epicsShareFunc int pmacAsynIPPortConfigure(const char *portName,
|
||||
const char *hostInfo);
|
||||
int HIDDEN pmacAsynIPPortConfigure(const char *portName, const char *hostInfo);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -15,6 +15,14 @@
|
||||
|
||||
struct turboPmacAxisImpl {
|
||||
bool waitForHandshake;
|
||||
/*
|
||||
This flag is set to true, if the controller is currently enabling /
|
||||
disabling the motor and false otherwise. This flag is used in the doPoll
|
||||
method to check if the enableRBV PV should be set or not in order to prevent
|
||||
a premature change of state (controller reports that the motor is already
|
||||
enabled / disabled while it is not ready yet to receive new commands).
|
||||
*/
|
||||
bool enableDisable;
|
||||
time_t timeAtHandshake;
|
||||
// The axis status is used when enabling / disabling the motor
|
||||
int axisStatus;
|
||||
@@ -64,6 +72,7 @@ turboPmacAxis::turboPmacAxis(turboPmacController *pC, int axisNo,
|
||||
|
||||
pTurboPmacA_ = std::make_unique<turboPmacAxisImpl>(
|
||||
(turboPmacAxisImpl){.waitForHandshake = false,
|
||||
.enableDisable = false,
|
||||
.timeAtHandshake = 0,
|
||||
.axisStatus = 0,
|
||||
.needInit = false});
|
||||
@@ -194,11 +203,7 @@ asynStatus turboPmacAxis::init() {
|
||||
}
|
||||
|
||||
// Initial motor status is idle
|
||||
status = pC_->setIntegerParam(axisNo_, pC_->motorStatusDone(), 1);
|
||||
if (status != asynSuccess) {
|
||||
return pC_->paramLibAccessFailed(status, "motorStatusDone_", axisNo_,
|
||||
__PRETTY_FUNCTION__, __LINE__);
|
||||
}
|
||||
setAxisParamChecked(this, motorStatusDone, 1);
|
||||
|
||||
// Write to the motor record fields
|
||||
status = setVeloFields(motorVelocity, 0.0, motorVmax);
|
||||
@@ -239,10 +244,7 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
|
||||
asynStatus errorStatus = asynSuccess;
|
||||
|
||||
// Status of read-write-operations of ASCII commands to the controller
|
||||
asynStatus rw_status = asynSuccess;
|
||||
|
||||
// Status of parameter library operations
|
||||
asynStatus pl_status = asynSuccess;
|
||||
asynStatus status = asynSuccess;
|
||||
|
||||
char command[pC_->MAXBUF_] = {0};
|
||||
char response[pC_->MAXBUF_] = {0};
|
||||
@@ -260,15 +262,12 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
|
||||
double lowLimit = 0.0;
|
||||
double limitsOffset = 0.0;
|
||||
|
||||
// Was the axis idle during the previous poll?
|
||||
int previousStatusDone = 1;
|
||||
|
||||
// =========================================================================
|
||||
|
||||
if (pTurboPmacA_->needInit) {
|
||||
rw_status = init();
|
||||
if (rw_status != asynSuccess) {
|
||||
return rw_status;
|
||||
status = init();
|
||||
if (status != asynSuccess) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -292,22 +291,16 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
|
||||
}
|
||||
|
||||
if (timedOut) {
|
||||
pl_status =
|
||||
setStringParam(pC_->motorMessageText(),
|
||||
"Timed out while waiting for a handshake");
|
||||
if (pl_status != asynSuccess) {
|
||||
return pC_->paramLibAccessFailed(pl_status, "motorMessageText_",
|
||||
axisNo_, __PRETTY_FUNCTION__,
|
||||
__LINE__);
|
||||
}
|
||||
setAxisParamChecked(this, motorMessageText,
|
||||
"Timed out while waiting for a handshake");
|
||||
pTurboPmacA_->waitForHandshake = false;
|
||||
}
|
||||
|
||||
snprintf(command, sizeof(command), "P%2.2d23 P%2.2d01", axisNo_,
|
||||
axisNo_);
|
||||
rw_status = pC_->writeRead(axisNo_, command, response, 2);
|
||||
if (rw_status != asynSuccess) {
|
||||
return rw_status;
|
||||
status = pC_->writeRead(axisNo_, command, response, 2);
|
||||
if (status != asynSuccess) {
|
||||
return status;
|
||||
}
|
||||
|
||||
nvals = sscanf(response, "%d %d", &handshakePerformed, &error);
|
||||
@@ -330,52 +323,28 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
|
||||
// poll. This is already part of the movement procedure.
|
||||
*moving = true;
|
||||
|
||||
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__);
|
||||
}
|
||||
setAxisParamChecked(this, motorStatusMoving, *moving);
|
||||
setAxisParamChecked(this, motorStatusDone, !(*moving));
|
||||
|
||||
return asynSuccess;
|
||||
}
|
||||
}
|
||||
|
||||
pl_status = pC_->getDoubleParam(axisNo_, pC_->motorRecResolution(),
|
||||
&motorRecResolution);
|
||||
if (pl_status != asynSuccess) {
|
||||
return pC_->paramLibAccessFailed(pl_status, "motorRecResolution_",
|
||||
axisNo_, __PRETTY_FUNCTION__,
|
||||
__LINE__);
|
||||
}
|
||||
getAxisParamChecked(this, motorRecResolution, &motorRecResolution);
|
||||
|
||||
// Read the previous motor position
|
||||
pl_status = motorPosition(&previousPosition);
|
||||
if (pl_status != asynSuccess) {
|
||||
return pl_status;
|
||||
}
|
||||
|
||||
pl_status = pC_->getIntegerParam(axisNo_, pC_->motorStatusDone(),
|
||||
&previousStatusDone);
|
||||
if (pl_status != asynSuccess) {
|
||||
return pC_->paramLibAccessFailed(pl_status, "motorStatusDone_", axisNo_,
|
||||
__PRETTY_FUNCTION__, __LINE__);
|
||||
status = motorPosition(&previousPosition);
|
||||
if (status != asynSuccess) {
|
||||
return status;
|
||||
}
|
||||
|
||||
// Query the axis status
|
||||
snprintf(command, sizeof(command),
|
||||
"P%2.2d00 Q%2.2d10 P%2.2d01 Q%2.2d13 Q%2.2d14", axisNo_, axisNo_,
|
||||
axisNo_, axisNo_, axisNo_);
|
||||
rw_status = pC_->writeRead(axisNo_, command, response, 5);
|
||||
if (rw_status != asynSuccess) {
|
||||
return rw_status;
|
||||
status = pC_->writeRead(axisNo_, command, response, 5);
|
||||
if (status != asynSuccess) {
|
||||
return status;
|
||||
}
|
||||
|
||||
nvals = sscanf(response, "%d %lf %d %lf %lf", &axStatus, ¤tPosition,
|
||||
@@ -397,25 +366,18 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
|
||||
directly, but need to shrink them a bit. In this case, we're shrinking them
|
||||
by limitsOffset on both sides.
|
||||
*/
|
||||
pl_status =
|
||||
pC_->getDoubleParam(axisNo_, pC_->motorLimitsOffset(), &limitsOffset);
|
||||
if (pl_status != asynSuccess) {
|
||||
return pC_->paramLibAccessFailed(pl_status, "motorLimitsOffset_",
|
||||
axisNo_, __PRETTY_FUNCTION__,
|
||||
__LINE__);
|
||||
}
|
||||
getAxisParamChecked(this, motorLimitsOffset, &limitsOffset);
|
||||
highLimit = highLimit - limitsOffset;
|
||||
lowLimit = lowLimit + limitsOffset;
|
||||
|
||||
// Store the axis status
|
||||
pTurboPmacA_->axisStatus = axStatus;
|
||||
|
||||
// Update the enablement PV
|
||||
pl_status = setIntegerParam(pC_->motorEnableRBV(),
|
||||
(axStatus != -3 && axStatus != -5));
|
||||
if (pl_status != asynSuccess) {
|
||||
return pC_->paramLibAccessFailed(pl_status, "motorEnableRBV_", axisNo_,
|
||||
__PRETTY_FUNCTION__, __LINE__);
|
||||
// Update the enablement PV, if we are not in the middle of a enabling /
|
||||
// disabling procedure.
|
||||
if (!(pTurboPmacA_->enableDisable)) {
|
||||
setAxisParamChecked(this, motorEnableRBV,
|
||||
(axStatus != -3 && axStatus != -5));
|
||||
}
|
||||
|
||||
// Create the unique callsite identifier manually so it can be used later in
|
||||
@@ -448,13 +410,7 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
|
||||
pC_->getMsgPrintControl().getSuffix());
|
||||
}
|
||||
resetCountStatus = false;
|
||||
|
||||
pl_status = setStringParam(pC_->motorMessageText(), "Emergency stop");
|
||||
if (pl_status != asynSuccess) {
|
||||
return pC_->paramLibAccessFailed(pl_status, "motorMessageText_",
|
||||
axisNo_, __PRETTY_FUNCTION__,
|
||||
__LINE__);
|
||||
}
|
||||
setAxisParamChecked(this, motorMessageText, "Emergency stop");
|
||||
break;
|
||||
case -3:
|
||||
// Disabled
|
||||
@@ -547,12 +503,7 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
|
||||
userMessage, sizeof(userMessage),
|
||||
"Reached unknown state P%2.2d00 = %d. Please call the support.",
|
||||
axisNo_, error);
|
||||
pl_status = setStringParam(pC_->motorMessageText(), userMessage);
|
||||
if (pl_status != asynSuccess) {
|
||||
return pC_->paramLibAccessFailed(pl_status, "motorMessageText_",
|
||||
axisNo_, __PRETTY_FUNCTION__,
|
||||
__LINE__);
|
||||
}
|
||||
setAxisParamChecked(this, motorMessageText, userMessage);
|
||||
}
|
||||
|
||||
if (resetCountStatus) {
|
||||
@@ -572,88 +523,44 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
|
||||
|
||||
// Update the parameter library
|
||||
if (error != 0) {
|
||||
pl_status = setIntegerParam(pC_->motorStatusProblem(), true);
|
||||
if (pl_status != asynSuccess) {
|
||||
return pC_->paramLibAccessFailed(pl_status, "motorStatusProblem_",
|
||||
axisNo_, __PRETTY_FUNCTION__,
|
||||
__LINE__);
|
||||
}
|
||||
setAxisParamChecked(this, motorStatusProblem, true);
|
||||
}
|
||||
|
||||
if (*moving == false) {
|
||||
pl_status = setIntegerParam(pC_->motorMoveToHome(), 0);
|
||||
if (pl_status != asynSuccess) {
|
||||
return pC_->paramLibAccessFailed(pl_status, "motorMoveToHome_",
|
||||
axisNo_, __PRETTY_FUNCTION__,
|
||||
__LINE__);
|
||||
}
|
||||
setAxisParamChecked(this, motorMoveToHome, false);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
int limFromHardware = 0;
|
||||
pl_status =
|
||||
pC_->getIntegerParam(axisNo_, pC_->limFromHardware(), &limFromHardware);
|
||||
if (pl_status != asynSuccess) {
|
||||
return pC_->paramLibAccessFailed(pl_status, "limFromHardware", axisNo_,
|
||||
__PRETTY_FUNCTION__, __LINE__);
|
||||
}
|
||||
getAxisParamChecked(this, limFromHardware, &limFromHardware);
|
||||
|
||||
if (limFromHardware != 0) {
|
||||
pl_status = pC_->setDoubleParam(
|
||||
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__);
|
||||
}
|
||||
setAxisParamChecked(this, motorHighLimitFromDriver, highLimit);
|
||||
setAxisParamChecked(this, motorLowLimitFromDriver, lowLimit);
|
||||
}
|
||||
|
||||
pl_status = setMotorPosition(currentPosition);
|
||||
if (pl_status != asynSuccess) {
|
||||
return pl_status;
|
||||
status = setMotorPosition(currentPosition);
|
||||
if (status != asynSuccess) {
|
||||
return status;
|
||||
}
|
||||
return errorStatus;
|
||||
}
|
||||
|
||||
asynStatus turboPmacAxis::handleError(int error, char *userMessage,
|
||||
int sizeUserMessage) {
|
||||
asynStatus status = asynSuccess;
|
||||
asynStatus status = asynError;
|
||||
|
||||
// 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) {
|
||||
case 0:
|
||||
status = asynSuccess;
|
||||
// No error -> Reset the message repetition watchdog
|
||||
break;
|
||||
case 1:
|
||||
@@ -667,17 +574,8 @@ asynStatus turboPmacAxis::handleError(int error, char *userMessage,
|
||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||
pC_->getMsgPrintControl().getSuffix());
|
||||
}
|
||||
resetError = false;
|
||||
|
||||
status = setStringParam(pC_->motorMessageText(),
|
||||
"Target position would exceed software limits");
|
||||
if (status != asynSuccess) {
|
||||
return pC_->paramLibAccessFailed(status, "motorMessageText_",
|
||||
axisNo_, __PRETTY_FUNCTION__,
|
||||
__LINE__);
|
||||
}
|
||||
|
||||
status = asynError;
|
||||
setAxisParamChecked(this, motorMessageText,
|
||||
"Target position would exceed software limits");
|
||||
break;
|
||||
case 5:
|
||||
// Command not possible
|
||||
@@ -691,18 +589,9 @@ asynStatus turboPmacAxis::handleError(int error, char *userMessage,
|
||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||
pC_->getMsgPrintControl().getSuffix());
|
||||
}
|
||||
resetError = false;
|
||||
|
||||
status = setStringParam(pC_->motorMessageText(),
|
||||
"Axis received move command while it is "
|
||||
"still moving. Please call the support.");
|
||||
if (status != asynSuccess) {
|
||||
return pC_->paramLibAccessFailed(status, "motorMessageText_",
|
||||
axisNo_, __PRETTY_FUNCTION__,
|
||||
__LINE__);
|
||||
}
|
||||
|
||||
status = asynError;
|
||||
setAxisParamChecked(this, motorMessageText,
|
||||
"Axis received move command while it is still "
|
||||
"moving. Please call the support.");
|
||||
break;
|
||||
case 8:
|
||||
if (pC_->getMsgPrintControl().shouldBePrinted(keyError, true,
|
||||
@@ -713,19 +602,11 @@ asynStatus turboPmacAxis::handleError(int error, char *userMessage,
|
||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||
axisNo_, error, pC_->getMsgPrintControl().getSuffix());
|
||||
}
|
||||
resetError = false;
|
||||
|
||||
snprintf(userMessage, sizeUserMessage,
|
||||
"Air cushion feedback stopped during movement (P%2.2d01 = "
|
||||
"%d). Please call the support.",
|
||||
axisNo_, error);
|
||||
|
||||
status = setStringParam(pC_->motorMessageText(), userMessage);
|
||||
if (status != asynSuccess) {
|
||||
return pC_->paramLibAccessFailed(status, "motorMessageText_",
|
||||
axisNo_, __PRETTY_FUNCTION__,
|
||||
__LINE__);
|
||||
}
|
||||
setAxisParamChecked(this, motorMessageText, userMessage);
|
||||
break;
|
||||
case 9:
|
||||
if (pC_->getMsgPrintControl().shouldBePrinted(keyError, true,
|
||||
@@ -737,18 +618,12 @@ asynStatus turboPmacAxis::handleError(int error, char *userMessage,
|
||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, axisNo_,
|
||||
error, pC_->getMsgPrintControl().getSuffix());
|
||||
}
|
||||
resetError = false;
|
||||
|
||||
snprintf(userMessage, sizeUserMessage,
|
||||
"No air cushion feedback before movement start (P%2.2d01 = "
|
||||
"%d). Please call the support.",
|
||||
axisNo_, error);
|
||||
status = setStringParam(pC_->motorMessageText(), userMessage);
|
||||
if (status != asynSuccess) {
|
||||
return pC_->paramLibAccessFailed(status, "motorMessageText_",
|
||||
axisNo_, __PRETTY_FUNCTION__,
|
||||
__LINE__);
|
||||
}
|
||||
setAxisParamChecked(this, motorMessageText, userMessage);
|
||||
break;
|
||||
case 10:
|
||||
/*
|
||||
@@ -767,23 +642,13 @@ asynStatus turboPmacAxis::handleError(int error, char *userMessage,
|
||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||
pC_->getMsgPrintControl().getSuffix());
|
||||
}
|
||||
resetError = false;
|
||||
|
||||
snprintf(userMessage, sizeUserMessage,
|
||||
"Software limits or end switch hit (P%2.2d01 = %d). Try "
|
||||
"homing the motor, moving in the opposite direction or check "
|
||||
"the SPS for errors (if available). "
|
||||
"Otherwise please call the support.",
|
||||
axisNo_, error);
|
||||
|
||||
status = setStringParam(pC_->motorMessageText(), userMessage);
|
||||
if (status != asynSuccess) {
|
||||
return pC_->paramLibAccessFailed(status, "motorMessageText_",
|
||||
axisNo_, __PRETTY_FUNCTION__,
|
||||
__LINE__);
|
||||
}
|
||||
|
||||
status = asynError;
|
||||
setAxisParamChecked(this, motorMessageText, userMessage);
|
||||
break;
|
||||
case 11:
|
||||
// Following error
|
||||
@@ -797,21 +662,12 @@ asynStatus turboPmacAxis::handleError(int error, char *userMessage,
|
||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||
pC_->getMsgPrintControl().getSuffix());
|
||||
}
|
||||
resetError = false;
|
||||
|
||||
snprintf(userMessage, sizeUserMessage,
|
||||
"Maximum allowed following error exceeded (P%2.2d01 = %d). "
|
||||
"Check if movement range is blocked. "
|
||||
"Otherwise please call the support.",
|
||||
axisNo_, error);
|
||||
status = setStringParam(pC_->motorMessageText(), userMessage);
|
||||
if (status != asynSuccess) {
|
||||
return pC_->paramLibAccessFailed(status, "motorMessageText_",
|
||||
axisNo_, __PRETTY_FUNCTION__,
|
||||
__LINE__);
|
||||
}
|
||||
|
||||
status = asynError;
|
||||
setAxisParamChecked(this, motorMessageText, userMessage);
|
||||
break;
|
||||
|
||||
case 12:
|
||||
@@ -823,21 +679,12 @@ asynStatus turboPmacAxis::handleError(int error, char *userMessage,
|
||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||
axisNo_, error, pC_->getMsgPrintControl().getSuffix());
|
||||
}
|
||||
resetError = false;
|
||||
|
||||
snprintf(userMessage, sizeUserMessage,
|
||||
"Security input is triggered (P%2.2d01 = %d). Check the SPS "
|
||||
"for errors (if available). Otherwise please call "
|
||||
"the support.",
|
||||
axisNo_, error);
|
||||
status = setStringParam(pC_->motorMessageText(), userMessage);
|
||||
if (status != asynSuccess) {
|
||||
return pC_->paramLibAccessFailed(status, "motorMessageText_",
|
||||
axisNo_, __PRETTY_FUNCTION__,
|
||||
__LINE__);
|
||||
}
|
||||
|
||||
status = asynError;
|
||||
setAxisParamChecked(this, motorMessageText, userMessage);
|
||||
break;
|
||||
|
||||
case 13:
|
||||
@@ -851,25 +698,15 @@ asynStatus turboPmacAxis::handleError(int error, char *userMessage,
|
||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||
pC_->getMsgPrintControl().getSuffix());
|
||||
}
|
||||
resetError = false;
|
||||
|
||||
snprintf(
|
||||
userMessage, sizeUserMessage,
|
||||
"Driver hardware error (P%2.2d01 = 13). Please call the support.",
|
||||
axisNo_);
|
||||
status = setStringParam(pC_->motorMessageText(), userMessage);
|
||||
if (status != asynSuccess) {
|
||||
return pC_->paramLibAccessFailed(status, "motorMessageText_",
|
||||
axisNo_, __PRETTY_FUNCTION__,
|
||||
__LINE__);
|
||||
}
|
||||
|
||||
status = asynError;
|
||||
setAxisParamChecked(this, motorMessageText, userMessage);
|
||||
break;
|
||||
case 14:
|
||||
// EPICS should already prevent this issue in the first place,
|
||||
// since it contains the user limits
|
||||
|
||||
if (pC_->getMsgPrintControl().shouldBePrinted(keyError, true,
|
||||
pC_->pasynUser())) {
|
||||
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||
@@ -878,20 +715,11 @@ asynStatus turboPmacAxis::handleError(int error, char *userMessage,
|
||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||
axisNo_, error, pC_->getMsgPrintControl().getSuffix());
|
||||
}
|
||||
resetError = false;
|
||||
|
||||
snprintf(userMessage, sizeUserMessage,
|
||||
"Move command exceeds hardware limits (P%2.2d01 = %d). Please "
|
||||
"call the support.",
|
||||
axisNo_, error);
|
||||
status = setStringParam(pC_->motorMessageText(), userMessage);
|
||||
if (status != asynSuccess) {
|
||||
return pC_->paramLibAccessFailed(status, "motorMessageText_",
|
||||
axisNo_, __PRETTY_FUNCTION__,
|
||||
__LINE__);
|
||||
}
|
||||
|
||||
status = asynError;
|
||||
setAxisParamChecked(this, motorMessageText, userMessage);
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -904,23 +732,11 @@ asynStatus turboPmacAxis::handleError(int error, char *userMessage,
|
||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, axisNo_,
|
||||
error, pC_->getMsgPrintControl().getSuffix());
|
||||
}
|
||||
resetError = false;
|
||||
|
||||
snprintf(userMessage, sizeUserMessage,
|
||||
"Unknown error P%2.2d01 = %d. Please call the support.",
|
||||
axisNo_, error);
|
||||
status = setStringParam(pC_->motorMessageText(), userMessage);
|
||||
if (status != asynSuccess) {
|
||||
return pC_->paramLibAccessFailed(status, "motorMessageText_",
|
||||
axisNo_, __PRETTY_FUNCTION__,
|
||||
__LINE__);
|
||||
}
|
||||
|
||||
status = asynError;
|
||||
setAxisParamChecked(this, motorMessageText, userMessage);
|
||||
break;
|
||||
}
|
||||
|
||||
if (resetError) {
|
||||
if (status == asynSuccess) {
|
||||
pC_->getMsgPrintControl().resetCount(keyError, pC_->pasynUser());
|
||||
}
|
||||
return status;
|
||||
@@ -931,10 +747,7 @@ asynStatus turboPmacAxis::doMove(double position, int relative,
|
||||
double acceleration) {
|
||||
|
||||
// Status of read-write-operations of ASCII commands to the controller
|
||||
asynStatus rw_status = asynSuccess;
|
||||
|
||||
// Status of parameter library operations
|
||||
asynStatus pl_status = asynSuccess;
|
||||
asynStatus status = asynSuccess;
|
||||
|
||||
char command[pC_->MAXBUF_] = {0};
|
||||
char response[pC_->MAXBUF_] = {0};
|
||||
@@ -947,19 +760,8 @@ asynStatus turboPmacAxis::doMove(double position, int relative,
|
||||
|
||||
// =========================================================================
|
||||
|
||||
pl_status = pC_->getIntegerParam(axisNo_, pC_->motorEnableRBV(), &enabled);
|
||||
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__);
|
||||
}
|
||||
getAxisParamChecked(this, motorEnableRBV, &enabled);
|
||||
getAxisParamChecked(this, motorRecResolution, &motorRecResolution);
|
||||
|
||||
if (enabled == 0) {
|
||||
asynPrint(
|
||||
@@ -979,13 +781,7 @@ asynStatus turboPmacAxis::doMove(double position, int relative,
|
||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, position);
|
||||
|
||||
// Check if the speed is allowed to be changed
|
||||
pl_status = pC_->getIntegerParam(axisNo_, pC_->motorCanSetSpeed(),
|
||||
&motorCanSetSpeed);
|
||||
if (pl_status != asynSuccess) {
|
||||
return pC_->paramLibAccessFailed(pl_status, "motorCanSetSpeed_",
|
||||
axisNo_, __PRETTY_FUNCTION__,
|
||||
__LINE__);
|
||||
}
|
||||
getAxisParamChecked(this, motorCanSetSpeed, &motorCanSetSpeed);
|
||||
|
||||
// Prepend the new motor speed, if the user is allowed to set the speed.
|
||||
// Mind the " " (space) before the closing "", as the command created here
|
||||
@@ -1015,8 +811,8 @@ asynStatus turboPmacAxis::doMove(double position, int relative,
|
||||
}
|
||||
|
||||
// We don't expect an answer
|
||||
rw_status = pC_->writeRead(axisNo_, command, response, 0);
|
||||
if (rw_status != asynSuccess) {
|
||||
status = pC_->writeRead(axisNo_, command, response, 0);
|
||||
if (status != asynSuccess) {
|
||||
|
||||
asynPrint(
|
||||
pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||
@@ -1024,13 +820,8 @@ asynStatus turboPmacAxis::doMove(double position, int relative,
|
||||
"target position %lf failed.\n",
|
||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||
motorCoordinatesPosition);
|
||||
pl_status = setIntegerParam(pC_->motorStatusProblem(), true);
|
||||
if (pl_status != asynSuccess) {
|
||||
return pC_->paramLibAccessFailed(pl_status, "motorStatusProblem_",
|
||||
axisNo_, __PRETTY_FUNCTION__,
|
||||
__LINE__);
|
||||
}
|
||||
return rw_status;
|
||||
setAxisParamChecked(this, motorStatusProblem, true);
|
||||
return status;
|
||||
}
|
||||
|
||||
// In the next poll, we will check if the handshake has been performed in a
|
||||
@@ -1044,16 +835,12 @@ asynStatus turboPmacAxis::doMove(double position, int relative,
|
||||
return asynError;
|
||||
}
|
||||
|
||||
return rw_status;
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus turboPmacAxis::stop(double acceleration) {
|
||||
|
||||
// Status of read-write-operations of ASCII commands to the controller
|
||||
asynStatus rw_status = asynSuccess;
|
||||
|
||||
// Status of parameter library operations
|
||||
asynStatus pl_status = asynSuccess;
|
||||
asynStatus status = asynSuccess;
|
||||
|
||||
char command[pC_->MAXBUF_] = {0};
|
||||
char response[pC_->MAXBUF_] = {0};
|
||||
@@ -1061,37 +848,40 @@ asynStatus turboPmacAxis::stop(double acceleration) {
|
||||
// =========================================================================
|
||||
|
||||
snprintf(command, sizeof(command), "M%2.2d=8", axisNo_);
|
||||
rw_status = pC_->writeRead(axisNo_, command, response, 0);
|
||||
status = pC_->writeRead(axisNo_, command, response, 0);
|
||||
|
||||
if (rw_status != asynSuccess) {
|
||||
if (status != asynSuccess) {
|
||||
asynPrint(
|
||||
pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||
"Controller \"%s\", axis %d => %s, line %d\nStopping the movement "
|
||||
"failed.\n",
|
||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
|
||||
|
||||
pl_status = setIntegerParam(pC_->motorStatusProblem(), true);
|
||||
if (pl_status != asynSuccess) {
|
||||
return pC_->paramLibAccessFailed(pl_status, "motorStatusProblem_",
|
||||
axisNo_, __PRETTY_FUNCTION__,
|
||||
__LINE__);
|
||||
}
|
||||
setAxisParamChecked(this, motorStatusProblem, true);
|
||||
}
|
||||
|
||||
// Reset the driver to idle state and move out of the handshake wait loop,
|
||||
// if we're currently inside it.
|
||||
pTurboPmacA_->waitForHandshake = false;
|
||||
|
||||
return rw_status;
|
||||
/*
|
||||
Stopping the motor results in a movement and further move commands have to
|
||||
wait until the stopping movement is done. Therefore, we need to wait until
|
||||
the poller "sees" the changed state (otherwise, we risk issuing move
|
||||
commands while the motor is stopping). To ensure that at least one poll is
|
||||
done, this thread (which also runs move commands) is paused for twice the
|
||||
idle poll period.
|
||||
*/
|
||||
unsigned int idlePollMicros =
|
||||
(unsigned int)ceil(pC_->idlePollPeriod() * 1e6);
|
||||
usleep(2 * idlePollMicros);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus turboPmacAxis::doReset() {
|
||||
|
||||
// Status of read-write-operations of ASCII commands to the controller
|
||||
asynStatus rw_status = asynSuccess;
|
||||
|
||||
// Status of parameter library operations
|
||||
asynStatus pl_status = asynSuccess;
|
||||
asynStatus status = asynSuccess;
|
||||
|
||||
char command[pC_->MAXBUF_] = {0};
|
||||
char response[pC_->MAXBUF_] = {0};
|
||||
@@ -1100,27 +890,22 @@ asynStatus turboPmacAxis::doReset() {
|
||||
|
||||
// Reset the error for this axis manually
|
||||
snprintf(command, sizeof(command), "P%2.2d01=0", axisNo_);
|
||||
rw_status = pC_->writeRead(axisNo_, command, response, 0);
|
||||
status = pC_->writeRead(axisNo_, command, response, 0);
|
||||
|
||||
if (rw_status != asynSuccess) {
|
||||
if (status != asynSuccess) {
|
||||
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||
"Controller \"%s\", axis %d => %s, line %d\nResetting the "
|
||||
"error failed\n",
|
||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
|
||||
|
||||
pl_status = setIntegerParam(pC_->motorStatusProblem(), true);
|
||||
if (pl_status != asynSuccess) {
|
||||
return pC_->paramLibAccessFailed(pl_status, "motorStatusProblem_",
|
||||
axisNo_, __PRETTY_FUNCTION__,
|
||||
__LINE__);
|
||||
}
|
||||
setAxisParamChecked(this, motorStatusProblem, true);
|
||||
}
|
||||
|
||||
// Reset the driver to idle state and move out of the handshake wait loop,
|
||||
// if we're currently inside it.
|
||||
pTurboPmacA_->waitForHandshake = false;
|
||||
|
||||
return rw_status;
|
||||
// Disable the axis
|
||||
return enable(false);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1130,38 +915,25 @@ asynStatus turboPmacAxis::doHome(double min_velocity, double max_velocity,
|
||||
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;
|
||||
asynStatus status = asynSuccess;
|
||||
|
||||
char command[pC_->MAXBUF_] = {0};
|
||||
char response[pC_->MAXBUF_] = {0};
|
||||
|
||||
// =========================================================================
|
||||
|
||||
pl_status = pC_->getStringParam(axisNo_, pC_->encoderType(),
|
||||
sizeof(response), response);
|
||||
if (pl_status != asynSuccess) {
|
||||
return pC_->paramLibAccessFailed(pl_status, "encoderType_", axisNo_,
|
||||
__PRETTY_FUNCTION__, __LINE__);
|
||||
}
|
||||
getAxisParamChecked(this, encoderType, &response);
|
||||
|
||||
// Only send the home command if the axis has an incremental encoder
|
||||
if (strcmp(response, IncrementalEncoder) == 0) {
|
||||
|
||||
snprintf(command, sizeof(command), "M%2.2d=9", axisNo_);
|
||||
rw_status = pC_->writeRead(axisNo_, command, response, 0);
|
||||
if (rw_status != asynSuccess) {
|
||||
return rw_status;
|
||||
status = pC_->writeRead(axisNo_, command, response, 0);
|
||||
if (status != asynSuccess) {
|
||||
return status;
|
||||
}
|
||||
|
||||
pl_status = setIntegerParam(pC_->motorMoveToHome(), 1);
|
||||
if (pl_status != asynSuccess) {
|
||||
return pC_->paramLibAccessFailed(pl_status, "motorMoveToHome_",
|
||||
axisNo_, __PRETTY_FUNCTION__,
|
||||
__LINE__);
|
||||
}
|
||||
setAxisParamChecked(this, motorMoveToHome, true);
|
||||
return callParamCallbacks();
|
||||
}
|
||||
|
||||
@@ -1174,10 +946,7 @@ Read the encoder type and update the parameter library accordingly
|
||||
asynStatus turboPmacAxis::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;
|
||||
asynStatus status = asynSuccess;
|
||||
|
||||
char command[pC_->MAXBUF_] = {0};
|
||||
char response[pC_->MAXBUF_] = {0};
|
||||
@@ -1188,9 +957,9 @@ asynStatus turboPmacAxis::readEncoderType() {
|
||||
|
||||
// Check if this is an absolute encoder
|
||||
snprintf(command, sizeof(command), "I%2.2d04", axisNo_);
|
||||
rw_status = pC_->writeRead(axisNo_, command, response, 1);
|
||||
if (rw_status != asynSuccess) {
|
||||
return rw_status;
|
||||
status = pC_->writeRead(axisNo_, command, response, 1);
|
||||
if (status != asynSuccess) {
|
||||
return status;
|
||||
}
|
||||
|
||||
int reponse_length = strlen(response);
|
||||
@@ -1208,22 +977,17 @@ asynStatus turboPmacAxis::readEncoderType() {
|
||||
}
|
||||
|
||||
snprintf(command, sizeof(command), "P46");
|
||||
rw_status = pC_->writeRead(axisNo_, command, response, 1);
|
||||
if (rw_status != asynSuccess) {
|
||||
return rw_status;
|
||||
status = pC_->writeRead(axisNo_, command, response, 1);
|
||||
if (status != asynSuccess) {
|
||||
return status;
|
||||
}
|
||||
int number_of_axes = strtol(response, NULL, 10);
|
||||
|
||||
// If true, the encoder is incremental
|
||||
if (encoder_id <= number_of_axes) {
|
||||
pl_status = setStringParam(pC_->encoderType(), IncrementalEncoder);
|
||||
setAxisParamChecked(this, encoderType, IncrementalEncoder);
|
||||
} else {
|
||||
pl_status = setStringParam(pC_->encoderType(), AbsoluteEncoder);
|
||||
}
|
||||
|
||||
if (pl_status != asynSuccess) {
|
||||
return pC_->paramLibAccessFailed(pl_status, "encoderType_", axisNo_,
|
||||
__PRETTY_FUNCTION__, __LINE__);
|
||||
setAxisParamChecked(this, encoderType, AbsoluteEncoder);
|
||||
}
|
||||
return asynSuccess;
|
||||
}
|
||||
@@ -1243,24 +1007,16 @@ asynStatus turboPmacAxis::rereadEncoder() {
|
||||
char encoderType[pC_->MAXBUF_] = {0};
|
||||
|
||||
// Status of read-write-operations of ASCII commands to the controller
|
||||
asynStatus rw_status = asynSuccess;
|
||||
|
||||
// Status of parameter library operations
|
||||
asynStatus pl_status = asynSuccess;
|
||||
asynStatus status = asynSuccess;
|
||||
|
||||
// =========================================================================
|
||||
|
||||
// Check if this is an absolute encoder
|
||||
rw_status = readEncoderType();
|
||||
if (rw_status != asynSuccess) {
|
||||
return rw_status;
|
||||
}
|
||||
pl_status = pC_->getStringParam(axisNo_, pC_->encoderType(),
|
||||
sizeof(encoderType), encoderType);
|
||||
if (pl_status != asynSuccess) {
|
||||
return pC_->paramLibAccessFailed(pl_status, "encoderType_", axisNo_,
|
||||
__PRETTY_FUNCTION__, __LINE__);
|
||||
status = readEncoderType();
|
||||
if (status != asynSuccess) {
|
||||
return status;
|
||||
}
|
||||
getAxisParamChecked(this, encoderType, &encoderType);
|
||||
|
||||
// Abort if the axis is incremental
|
||||
if (strcmp(encoderType, IncrementalEncoder) == 0) {
|
||||
@@ -1274,25 +1030,16 @@ asynStatus turboPmacAxis::rereadEncoder() {
|
||||
// Check if the axis is disabled. If not, inform the user that this
|
||||
// is necessary
|
||||
int enabled = 0;
|
||||
pl_status = pC_->getIntegerParam(axisNo_, pC_->motorEnableRBV(), &enabled);
|
||||
if (pl_status != asynSuccess) {
|
||||
return pC_->paramLibAccessFailed(pl_status, "enableMotorRBV_", axisNo_,
|
||||
__PRETTY_FUNCTION__, __LINE__);
|
||||
}
|
||||
getAxisParamChecked(this, motorEnableRBV, &enabled);
|
||||
|
||||
if (enabled == 1) {
|
||||
asynPrint(pC_->pasynUser(), ASYN_TRACE_WARNING,
|
||||
"Controller \"%s\", axis %d => %s, line %d\nAxis must be "
|
||||
"disabled before rereading the encoder.\n",
|
||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
|
||||
pl_status = setStringParam(
|
||||
pC_->motorMessageText(),
|
||||
setAxisParamChecked(
|
||||
this, motorMessageText,
|
||||
"Axis must be disabled before rereading the encoder.");
|
||||
if (pl_status != asynSuccess) {
|
||||
return pC_->paramLibAccessFailed(pl_status, "motorMessageText_",
|
||||
axisNo_, __PRETTY_FUNCTION__,
|
||||
__LINE__);
|
||||
}
|
||||
return asynError;
|
||||
} else {
|
||||
snprintf(command, sizeof(command), "M%2.2d=15", axisNo_);
|
||||
@@ -1309,30 +1056,21 @@ asynStatus turboPmacAxis::rereadEncoder() {
|
||||
// it is actually finished, so we instead wait for 0.5 seconds.
|
||||
usleep(500000);
|
||||
|
||||
// turn off parameter as finished rereading
|
||||
// this will only be immediately noticed in the read back variable
|
||||
// though
|
||||
pl_status = pC_->setIntegerParam(pC_->rereadEncoderPosition(), 0);
|
||||
if (pl_status != asynSuccess) {
|
||||
return pC_->paramLibAccessFailed(pl_status, "rereadEncoderPosition_",
|
||||
axisNo_, __PRETTY_FUNCTION__,
|
||||
__LINE__);
|
||||
}
|
||||
// Turn off parameter as finished rereading, this will only be immediately
|
||||
// noticed in the read back variable though
|
||||
setAxisParamChecked(this, rereadEncoderPosition, false);
|
||||
return asynSuccess;
|
||||
}
|
||||
|
||||
asynStatus turboPmacAxis::enable(bool on) {
|
||||
|
||||
int timeout_enable_disable = 2;
|
||||
int timeout_enable_disable = 5;
|
||||
char command[pC_->MAXBUF_] = {0};
|
||||
char response[pC_->MAXBUF_] = {0};
|
||||
int nvals = 0;
|
||||
|
||||
// Status of read-write-operations of ASCII commands to the controller
|
||||
asynStatus rw_status = asynSuccess;
|
||||
|
||||
// Status of parameter library operations
|
||||
asynStatus pl_status = asynSuccess;
|
||||
asynStatus status = asynSuccess;
|
||||
|
||||
// =========================================================================
|
||||
|
||||
@@ -1354,20 +1092,16 @@ asynStatus turboPmacAxis::enable(bool on) {
|
||||
axStatus == 5 || axStatus == 6 || axStatus == 7 || axStatus == 8 ||
|
||||
axStatus == 9 || axStatus == 10 || axStatus == 11 || axStatus == 12 ||
|
||||
axStatus == 13 || axStatus == 15 || axStatus == 16) {
|
||||
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||
"Controller \"%s\", axis %d => %s, line %d\nAxis is not "
|
||||
"idle and can therefore not be enabled / disabled.\n",
|
||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
|
||||
|
||||
pl_status =
|
||||
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__);
|
||||
}
|
||||
asynPrint(
|
||||
pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||
"Controller \"%s\", axis %d => %s, line %d\nAxis is not "
|
||||
"idle (status %d) and can therefore not be enabled / disabled.\n",
|
||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, axStatus);
|
||||
|
||||
setAxisParamChecked(this, motorMessageText,
|
||||
"Axis cannot be disabled while it is moving.");
|
||||
pTurboPmacA_->enableDisable = false;
|
||||
return asynError;
|
||||
}
|
||||
|
||||
@@ -1384,22 +1118,25 @@ asynStatus turboPmacAxis::enable(bool on) {
|
||||
|
||||
// Reread the encoder, if the axis is going to be enabled
|
||||
if (on != 0) {
|
||||
rw_status = rereadEncoder();
|
||||
if (rw_status != asynSuccess) {
|
||||
return rw_status;
|
||||
status = rereadEncoder();
|
||||
if (status != asynSuccess) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
// Enable / disable the axis if it is not moving
|
||||
// Now the actual enabling / disabling starts
|
||||
pTurboPmacA_->enableDisable = true;
|
||||
|
||||
// Enable / disable the axis
|
||||
snprintf(command, sizeof(command), "M%2.2d14=%d", axisNo_, on);
|
||||
asynPrint(pC_->pasynUser(), ASYN_TRACE_FLOW,
|
||||
"Controller \"%s\", axis %d => %s, line %d\n%s axis\n",
|
||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||
on ? "Enable" : "Disable");
|
||||
|
||||
rw_status = pC_->writeRead(axisNo_, command, response, 0);
|
||||
if (rw_status != asynSuccess) {
|
||||
return rw_status;
|
||||
status = pC_->writeRead(axisNo_, command, response, 0);
|
||||
if (status != asynSuccess) {
|
||||
return status;
|
||||
}
|
||||
|
||||
// Query the axis status every few milliseconds until the axis has been
|
||||
@@ -1408,11 +1145,15 @@ asynStatus turboPmacAxis::enable(bool on) {
|
||||
int startTime = time(NULL);
|
||||
while (time(NULL) < startTime + timeout_enable_disable) {
|
||||
|
||||
// Wait a bit between status updates from the controller.
|
||||
usleep(10000);
|
||||
|
||||
// Read the axis status
|
||||
usleep(100000);
|
||||
rw_status = pC_->writeRead(axisNo_, command, response, 1);
|
||||
if (rw_status != asynSuccess) {
|
||||
return rw_status;
|
||||
status = pC_->writeRead(axisNo_, command, response, 1);
|
||||
if (status != asynSuccess) {
|
||||
// Enabling / disabling procedure failed
|
||||
pTurboPmacA_->enableDisable = false;
|
||||
return status;
|
||||
}
|
||||
nvals = sscanf(response, "%d", &pTurboPmacA_->axisStatus);
|
||||
if (nvals != 1) {
|
||||
@@ -1421,9 +1162,13 @@ asynStatus turboPmacAxis::enable(bool on) {
|
||||
}
|
||||
|
||||
if ((pTurboPmacA_->axisStatus != -3) == on) {
|
||||
usleep(500000);
|
||||
|
||||
bool moving = false;
|
||||
// Perform a poll to update the parameter library
|
||||
poll(&moving);
|
||||
forcedPoll(&moving);
|
||||
|
||||
// Enabling / disabling procedure is completed (successfully)
|
||||
pTurboPmacA_->enableDisable = false;
|
||||
return asynSuccess;
|
||||
}
|
||||
}
|
||||
@@ -1439,12 +1184,10 @@ asynStatus turboPmacAxis::enable(bool on) {
|
||||
// Output message to user
|
||||
snprintf(command, sizeof(command), "Failed to %s within %d seconds",
|
||||
on ? "enable" : "disable", timeout_enable_disable);
|
||||
pl_status = setStringParam(pC_->motorMessageText(), command);
|
||||
if (pl_status != asynSuccess) {
|
||||
return pC_->paramLibAccessFailed(pl_status, "motorMessageText_",
|
||||
axisNo_, __PRETTY_FUNCTION__,
|
||||
__LINE__);
|
||||
}
|
||||
setAxisParamChecked(this, motorMessageText, command);
|
||||
|
||||
// Enabling / disabling procedure failed
|
||||
pTurboPmacA_->enableDisable = false;
|
||||
return asynError;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +1,12 @@
|
||||
#ifndef turboPmacAXIS_H
|
||||
#define turboPmacAXIS_H
|
||||
#include "sinqAxis.h"
|
||||
#include "sinqController.h"
|
||||
#include "turboPmacController.h"
|
||||
#include <memory>
|
||||
|
||||
struct turboPmacAxisImpl;
|
||||
struct HIDDEN turboPmacAxisImpl;
|
||||
|
||||
// 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 turboPmacController;
|
||||
|
||||
class turboPmacAxis : public sinqAxis {
|
||||
class HIDDEN turboPmacAxis : public sinqAxis {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new turboPmacAxis
|
||||
@@ -24,6 +20,7 @@ class turboPmacAxis : public sinqAxis {
|
||||
/**
|
||||
* @brief Destroy the turboPmacAxis
|
||||
*
|
||||
* This destructor is necessary in order to use the PIMPL idiom.
|
||||
*/
|
||||
virtual ~turboPmacAxis();
|
||||
|
||||
@@ -141,6 +138,11 @@ class turboPmacAxis : public sinqAxis {
|
||||
*/
|
||||
void setNeedInit(bool needInit);
|
||||
|
||||
/**
|
||||
* @brief Return a pointer to the axis controller
|
||||
*/
|
||||
virtual turboPmacController *pController() override { return pC_; };
|
||||
|
||||
private:
|
||||
turboPmacController *pC_;
|
||||
std::unique_ptr<turboPmacAxisImpl> pTurboPmacA_;
|
||||
|
||||
@@ -179,6 +179,8 @@ turboPmacController::turboPmacController(const char *portName,
|
||||
}
|
||||
}
|
||||
|
||||
turboPmacController::~turboPmacController() {}
|
||||
|
||||
/*
|
||||
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
|
||||
@@ -204,9 +206,7 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
||||
|
||||
// Definition of local variables.
|
||||
asynStatus status = asynSuccess;
|
||||
asynStatus paramLibStatus = asynSuccess;
|
||||
asynStatus timeoutStatus = asynSuccess;
|
||||
// char fullCommand[MAXBUF_] = {0};
|
||||
char drvMessageText[MAXBUF_] = {0};
|
||||
char modResponse[MAXBUF_] = {0};
|
||||
int motorStatusProblem = 0;
|
||||
@@ -254,6 +254,22 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
||||
pasynOctetSyncIOipPort(), command, commandLength, response, MAXBUF_,
|
||||
pTurboPmacC_->comTimeout, &nbytesOut, &nbytesIn, &eomReason);
|
||||
|
||||
/*
|
||||
If sth. is written to the controller, it needs some time to process the
|
||||
command. However, the controller returns the acknowledgment via
|
||||
pasynOctetSyncIO->writeRead immediately, signalling to the driver that it is
|
||||
ready to receive the next command. In practice, this can result in commands
|
||||
getting discarded on the driver side or in bringing the driver in undefined
|
||||
states (e.g. stuck in status 1).
|
||||
|
||||
To prevent this, we wait for 20 ms after a write command to give the
|
||||
controller enough time to process everything. A write command can be
|
||||
identified by looking for the equal sign.
|
||||
*/
|
||||
if (strchr(command, '=')) {
|
||||
usleep(20000);
|
||||
}
|
||||
|
||||
msgPrintControlKey comKey =
|
||||
msgPrintControlKey(portName, axisNo, __PRETTY_FUNCTION__, __LINE__);
|
||||
|
||||
@@ -426,41 +442,18 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
||||
|
||||
// Log the overall status (communication successfull or not)
|
||||
if (status == asynSuccess) {
|
||||
paramLibStatus = axis->setIntegerParam(this->motorStatusCommsError_, 0);
|
||||
setAxisParamChecked(axis, motorStatusCommsError, false);
|
||||
} else {
|
||||
// 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 =
|
||||
getIntegerParam(axisNo, motorStatusProblem_, &motorStatusProblem);
|
||||
if (paramLibStatus != asynSuccess) {
|
||||
return paramLibAccessFailed(paramLibStatus, "motorStatusProblem",
|
||||
axisNo, __PRETTY_FUNCTION__, __LINE__);
|
||||
}
|
||||
getAxisParamChecked(axis, motorStatusProblem, &motorStatusProblem);
|
||||
|
||||
if (motorStatusProblem == 0) {
|
||||
paramLibStatus =
|
||||
axis->setStringParam(motorMessageText(), drvMessageText);
|
||||
if (paramLibStatus != asynSuccess) {
|
||||
return paramLibAccessFailed(paramLibStatus, "motorMessageText",
|
||||
axisNo, __PRETTY_FUNCTION__,
|
||||
__LINE__);
|
||||
}
|
||||
|
||||
paramLibStatus = axis->setIntegerParam(motorStatusProblem_, 1);
|
||||
if (paramLibStatus != asynSuccess) {
|
||||
return paramLibAccessFailed(paramLibStatus,
|
||||
"motorStatusProblem", axisNo,
|
||||
__PRETTY_FUNCTION__, __LINE__);
|
||||
}
|
||||
|
||||
paramLibStatus = axis->setIntegerParam(motorStatusProblem_, 1);
|
||||
if (paramLibStatus != asynSuccess) {
|
||||
return paramLibAccessFailed(paramLibStatus,
|
||||
"motorStatusCommsError", axisNo,
|
||||
__PRETTY_FUNCTION__, __LINE__);
|
||||
}
|
||||
setAxisParamChecked(axis, motorMessageText, drvMessageText);
|
||||
setAxisParamChecked(axis, motorStatusProblem, true);
|
||||
setAxisParamChecked(axis, motorStatusCommsError, true);
|
||||
}
|
||||
}
|
||||
return status;
|
||||
|
||||
@@ -10,12 +10,16 @@
|
||||
#define turboPmacController_H
|
||||
#include "sinqAxis.h"
|
||||
#include "sinqController.h"
|
||||
#include "turboPmacAxis.h"
|
||||
#include <memory>
|
||||
|
||||
struct turboPmacControllerImpl;
|
||||
// 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 HIDDEN turboPmacAxis;
|
||||
|
||||
class turboPmacController : public sinqController {
|
||||
struct HIDDEN turboPmacControllerImpl;
|
||||
|
||||
class HIDDEN turboPmacController : public sinqController {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new turboPmacController object. This function is meant
|
||||
@@ -36,6 +40,13 @@ class turboPmacController : public sinqController {
|
||||
double idlePollPeriod, double comTimeout,
|
||||
int numExtraParams = 0);
|
||||
|
||||
/**
|
||||
* @brief Destroy the controller. Its implementation is empty, however the
|
||||
* destructor needs to be provided for handling turboPmacControllerImpl.
|
||||
*
|
||||
*/
|
||||
virtual ~turboPmacController();
|
||||
|
||||
/**
|
||||
* @brief Get the axis object
|
||||
*
|
||||
@@ -82,7 +93,8 @@ class turboPmacController : public sinqController {
|
||||
* @return asynStatus
|
||||
*/
|
||||
asynStatus writeRead(int axisNo, const char *command, char *response,
|
||||
int numExpectedResponses);
|
||||
int numExpectedResponses)
|
||||
__attribute__((visibility("hidden")));
|
||||
|
||||
/**
|
||||
* @brief Specialized version of sinqController::couldNotParseResponse
|
||||
|
||||
Reference in New Issue
Block a user