Compare commits
10 Commits
1.2.2
...
fix_timing
| Author | SHA1 | Date | |
|---|---|---|---|
| 62a3d8c834 | |||
| fd2afa9ec6 | |||
| 949e9faef3 | |||
| 5df84d6017 | |||
| 08c85129f3 | |||
| a980740fd5 | |||
| 338b4d61b4 | |||
| 25b832a6e9 | |||
| 1e8a6495b8 | |||
| 6b91ab6d51 |
@@ -1,6 +1,6 @@
|
|||||||
# turboPmac
|
# 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
|
## Overview
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@ This is a driver for the Turbo PMAC motion controller with the SINQ communicatio
|
|||||||
|
|
||||||
## User guide
|
## 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.
|
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.
|
- 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
|
### 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
|
### 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: 55a9fe6f3e...c65a8de5dd
@@ -15,6 +15,14 @@
|
|||||||
|
|
||||||
struct turboPmacAxisImpl {
|
struct turboPmacAxisImpl {
|
||||||
bool waitForHandshake;
|
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;
|
time_t timeAtHandshake;
|
||||||
// The axis status is used when enabling / disabling the motor
|
// The axis status is used when enabling / disabling the motor
|
||||||
int axisStatus;
|
int axisStatus;
|
||||||
@@ -64,6 +72,7 @@ turboPmacAxis::turboPmacAxis(turboPmacController *pC, int axisNo,
|
|||||||
|
|
||||||
pTurboPmacA_ = std::make_unique<turboPmacAxisImpl>(
|
pTurboPmacA_ = std::make_unique<turboPmacAxisImpl>(
|
||||||
(turboPmacAxisImpl){.waitForHandshake = false,
|
(turboPmacAxisImpl){.waitForHandshake = false,
|
||||||
|
.enableDisable = false,
|
||||||
.timeAtHandshake = 0,
|
.timeAtHandshake = 0,
|
||||||
.axisStatus = 0,
|
.axisStatus = 0,
|
||||||
.needInit = false});
|
.needInit = false});
|
||||||
@@ -253,9 +262,6 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
|
|||||||
double lowLimit = 0.0;
|
double lowLimit = 0.0;
|
||||||
double limitsOffset = 0.0;
|
double limitsOffset = 0.0;
|
||||||
|
|
||||||
// Was the axis idle during the previous poll?
|
|
||||||
int previousStatusDone = 1;
|
|
||||||
|
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
|
|
||||||
if (pTurboPmacA_->needInit) {
|
if (pTurboPmacA_->needInit) {
|
||||||
@@ -332,8 +338,6 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
getAxisParamChecked(this, motorStatusDone, &previousStatusDone);
|
|
||||||
|
|
||||||
// Query the axis status
|
// Query the axis status
|
||||||
snprintf(command, sizeof(command),
|
snprintf(command, sizeof(command),
|
||||||
"P%2.2d00 Q%2.2d10 P%2.2d01 Q%2.2d13 Q%2.2d14", axisNo_, axisNo_,
|
"P%2.2d00 Q%2.2d10 P%2.2d01 Q%2.2d13 Q%2.2d14", axisNo_, axisNo_,
|
||||||
@@ -369,9 +373,12 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
|
|||||||
// Store the axis status
|
// Store the axis status
|
||||||
pTurboPmacA_->axisStatus = axStatus;
|
pTurboPmacA_->axisStatus = axStatus;
|
||||||
|
|
||||||
// Update the enablement PV
|
// Update the enablement PV, if we are not in the middle of a enabling /
|
||||||
setAxisParamChecked(this, motorEnableRBV,
|
// disabling procedure.
|
||||||
(axStatus != -3 && axStatus != -5));
|
if (!(pTurboPmacA_->enableDisable)) {
|
||||||
|
setAxisParamChecked(this, motorEnableRBV,
|
||||||
|
(axStatus != -3 && axStatus != -5));
|
||||||
|
}
|
||||||
|
|
||||||
// Create the unique callsite identifier manually so it can be used later in
|
// Create the unique callsite identifier manually so it can be used later in
|
||||||
// the shouldBePrinted calls.
|
// the shouldBePrinted calls.
|
||||||
@@ -833,7 +840,6 @@ asynStatus turboPmacAxis::doMove(double position, int relative,
|
|||||||
|
|
||||||
asynStatus turboPmacAxis::stop(double acceleration) {
|
asynStatus turboPmacAxis::stop(double acceleration) {
|
||||||
|
|
||||||
// Status of read-write-operations of ASCII commands to the controller
|
|
||||||
asynStatus status = asynSuccess;
|
asynStatus status = asynSuccess;
|
||||||
|
|
||||||
char command[pC_->MAXBUF_] = {0};
|
char command[pC_->MAXBUF_] = {0};
|
||||||
@@ -857,6 +863,18 @@ asynStatus turboPmacAxis::stop(double acceleration) {
|
|||||||
// if we're currently inside it.
|
// if we're currently inside it.
|
||||||
pTurboPmacA_->waitForHandshake = false;
|
pTurboPmacA_->waitForHandshake = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
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;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -886,7 +904,8 @@ asynStatus turboPmacAxis::doReset() {
|
|||||||
// if we're currently inside it.
|
// if we're currently inside it.
|
||||||
pTurboPmacA_->waitForHandshake = false;
|
pTurboPmacA_->waitForHandshake = false;
|
||||||
|
|
||||||
return status;
|
// Disable the axis
|
||||||
|
return enable(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1045,7 +1064,7 @@ asynStatus turboPmacAxis::rereadEncoder() {
|
|||||||
|
|
||||||
asynStatus turboPmacAxis::enable(bool on) {
|
asynStatus turboPmacAxis::enable(bool on) {
|
||||||
|
|
||||||
int timeout_enable_disable = 2;
|
int timeout_enable_disable = 5;
|
||||||
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;
|
||||||
@@ -1073,13 +1092,16 @@ asynStatus turboPmacAxis::enable(bool on) {
|
|||||||
axStatus == 5 || axStatus == 6 || axStatus == 7 || axStatus == 8 ||
|
axStatus == 5 || axStatus == 6 || axStatus == 7 || axStatus == 8 ||
|
||||||
axStatus == 9 || axStatus == 10 || axStatus == 11 || axStatus == 12 ||
|
axStatus == 9 || axStatus == 10 || axStatus == 11 || axStatus == 12 ||
|
||||||
axStatus == 13 || axStatus == 15 || axStatus == 16) {
|
axStatus == 13 || axStatus == 15 || axStatus == 16) {
|
||||||
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
|
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nAxis is not "
|
asynPrint(
|
||||||
"idle and can therefore not be enabled / disabled.\n",
|
pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
|
"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,
|
setAxisParamChecked(this, motorMessageText,
|
||||||
"Axis cannot be disabled while it is moving.");
|
"Axis cannot be disabled while it is moving.");
|
||||||
|
pTurboPmacA_->enableDisable = false;
|
||||||
return asynError;
|
return asynError;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1102,7 +1124,10 @@ asynStatus turboPmacAxis::enable(bool on) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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);
|
snprintf(command, sizeof(command), "M%2.2d14=%d", axisNo_, 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",
|
||||||
@@ -1120,10 +1145,14 @@ asynStatus turboPmacAxis::enable(bool on) {
|
|||||||
int startTime = time(NULL);
|
int startTime = time(NULL);
|
||||||
while (time(NULL) < startTime + timeout_enable_disable) {
|
while (time(NULL) < startTime + timeout_enable_disable) {
|
||||||
|
|
||||||
|
// Wait a bit between status updates from the controller.
|
||||||
|
usleep(10000);
|
||||||
|
|
||||||
// Read the axis status
|
// Read the axis status
|
||||||
usleep(100000);
|
|
||||||
status = pC_->writeRead(axisNo_, command, response, 1);
|
status = pC_->writeRead(axisNo_, command, response, 1);
|
||||||
if (status != asynSuccess) {
|
if (status != asynSuccess) {
|
||||||
|
// Enabling / disabling procedure failed
|
||||||
|
pTurboPmacA_->enableDisable = false;
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
nvals = sscanf(response, "%d", &pTurboPmacA_->axisStatus);
|
nvals = sscanf(response, "%d", &pTurboPmacA_->axisStatus);
|
||||||
@@ -1133,9 +1162,13 @@ asynStatus turboPmacAxis::enable(bool on) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((pTurboPmacA_->axisStatus != -3) == on) {
|
if ((pTurboPmacA_->axisStatus != -3) == on) {
|
||||||
|
usleep(500000);
|
||||||
|
|
||||||
bool moving = false;
|
bool moving = false;
|
||||||
// Perform a poll to update the parameter library
|
forcedPoll(&moving);
|
||||||
poll(&moving);
|
|
||||||
|
// Enabling / disabling procedure is completed (successfully)
|
||||||
|
pTurboPmacA_->enableDisable = false;
|
||||||
return asynSuccess;
|
return asynSuccess;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1152,6 +1185,9 @@ asynStatus turboPmacAxis::enable(bool on) {
|
|||||||
snprintf(command, sizeof(command), "Failed to %s within %d seconds",
|
snprintf(command, sizeof(command), "Failed to %s within %d seconds",
|
||||||
on ? "enable" : "disable", timeout_enable_disable);
|
on ? "enable" : "disable", timeout_enable_disable);
|
||||||
setAxisParamChecked(this, motorMessageText, command);
|
setAxisParamChecked(this, motorMessageText, command);
|
||||||
|
|
||||||
|
// Enabling / disabling procedure failed
|
||||||
|
pTurboPmacA_->enableDisable = false;
|
||||||
return asynError;
|
return asynError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -207,7 +207,6 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
|||||||
// Definition of local variables.
|
// Definition of local variables.
|
||||||
asynStatus status = asynSuccess;
|
asynStatus status = asynSuccess;
|
||||||
asynStatus timeoutStatus = asynSuccess;
|
asynStatus timeoutStatus = asynSuccess;
|
||||||
// char fullCommand[MAXBUF_] = {0};
|
|
||||||
char drvMessageText[MAXBUF_] = {0};
|
char drvMessageText[MAXBUF_] = {0};
|
||||||
char modResponse[MAXBUF_] = {0};
|
char modResponse[MAXBUF_] = {0};
|
||||||
int motorStatusProblem = 0;
|
int motorStatusProblem = 0;
|
||||||
@@ -255,6 +254,10 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
|||||||
pasynOctetSyncIOipPort(), command, commandLength, response, MAXBUF_,
|
pasynOctetSyncIOipPort(), command, commandLength, response, MAXBUF_,
|
||||||
pTurboPmacC_->comTimeout, &nbytesOut, &nbytesIn, &eomReason);
|
pTurboPmacC_->comTimeout, &nbytesOut, &nbytesIn, &eomReason);
|
||||||
|
|
||||||
|
// if (strchr(command, '=')) {
|
||||||
|
// usleep(20000);
|
||||||
|
// }
|
||||||
|
|
||||||
msgPrintControlKey comKey =
|
msgPrintControlKey comKey =
|
||||||
msgPrintControlKey(portName, axisNo, __PRETTY_FUNCTION__, __LINE__);
|
msgPrintControlKey(portName, axisNo, __PRETTY_FUNCTION__, __LINE__);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user