Compare commits

...

7 Commits

Author SHA1 Message Date
mathis_s 9098a932fa Fixed bug in response parsing
Test And Build / Lint (push) Failing after 4s
Test And Build / Build (push) Successful in 8s
If the byte 15 is encountered in the message, the parseResponse function
must return asynDisconnected (instead of asynSuccess) so the state of
the axis is accounted for properly.
2026-04-09 10:47:27 +02:00
mathis_s b96605916f Rolled back to motorBase 7.3.2 because 7.4.0 is bugged
Test And Build / Lint (push) Failing after 5s
Test And Build / Build (push) Successful in 8s
In particular, the following problem can happen (shown for a TurboPMAC,
but MasterMACS will run into the same issue):

2026/03/31 11:45:04.698 asynPortDriver:getDoubleParam: port=turboPmac1 error getting parameter 42 MOTOR_STATUS_HOMED, in list 1, wrong type
2026/03/31 11:45:04.698 Controller "turboPmac1", axis 1 => virtual asynStatus turboPmacAxis::init(), line 168:
Accessing the parameter library failed for parameter motorRecResolution_ with error wrong type.

This is definitely because of 7.4.0, because forcing 7.3.2 fixes it.
2026-04-01 10:37:06 +02:00
mathis_s 4d65dd238d Incremented required motorBase version to match upstream (7.3.2 was a local patch version which doesn't exist upstream)
Test And Build / Lint (push) Failing after 4s
Test And Build / Build (push) Successful in 8s
2026-03-24 14:26:25 +01:00
mathis_s b5dcc7bdf1 Fixed scaling of the written motorVelocity value
Test And Build / Lint (push) Failing after 4s
Test And Build / Build (push) Successful in 7s
2026-02-12 12:04:20 +01:00
mathis_s 9a332f7a19 Squashed commit of the following:
commit d90869cbca
Author: smathis <stefan.mathis@psi.ch>
Date:   Tue Feb 10 13:18:43 2026 +0100

    Added reminder comment

commit eadce0f594
Author: smathis <stefan.mathis@psi.ch>
Date:   Tue Feb 10 12:31:01 2026 +0100

    Draft velocity mode

    See TODO in src/masterMacsAxis.cpp, line 552. The velocity readback is
    the only thing that doesn't work properly, everything else does work.
    Once a solution has been found here, this can be a new minor release.

commit 0e1f95a94b
Author: smathis <stefan.mathis@psi.ch>
Date:   Tue Feb 10 09:04:04 2026 +0100

    Updated sinqMotor and use setLimits

commit b01f398533
Author: smathis <stefan.mathis@psi.ch>
Date:   Tue Feb 10 09:00:58 2026 +0100

    Set move flag correctly in velocity / jog mode

commit 56d9d20c3a
Author: smathis <stefan.mathis@psi.ch>
Date:   Tue Feb 3 17:57:00 2026 +0100

    Simplified handling of velocity mode using standard EPICS motor record fields

commit 4634609891
Author: smathis <stefan.mathis@psi.ch>
Date:   Tue Feb 3 13:35:24 2026 +0100

    Rolled back to sinqMotor 1.5.7
2026-02-12 11:38:42 +01:00
mathis_s b81e7926d1 Fixed limitswitch errors during homing 2026-02-12 11:35:21 +01:00
mathis_s dbb4e92171 Rolled back to sinqMotor 1.5.7
Test And Build / Lint (push) Failing after 4s
Test And Build / Build (push) Successful in 7s
2026-02-11 10:45:25 +01:00
4 changed files with 106 additions and 98 deletions
+1 -3
View File
@@ -7,9 +7,7 @@ EPICS_VERSIONS=7.0.7
ARCH_FILTER=RHEL% ARCH_FILTER=RHEL%
# Specify the version of asynMotor we want to build against # Specify the version of asynMotor we want to build against
motorBase_VERSION=7.2.2 motorBase_VERSION=7.3.2
LIBVERSION=homeerror
# These headers allow to depend on this library for derived drivers. # These headers allow to depend on this library for derived drivers.
HEADERS += src/masterMacsAxis.h HEADERS += src/masterMacsAxis.h
+95 -89
View File
@@ -11,6 +11,11 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
enum moveMode {
positionMode,
velocityMode,
};
struct masterMacsAxisImpl { struct masterMacsAxisImpl {
/* /*
The axis status and axis error of MasterMACS are given as an integer from The axis status and axis error of MasterMACS are given as an integer from
@@ -24,6 +29,7 @@ struct masterMacsAxisImpl {
bool needInit = true; bool needInit = true;
bool targetReachedUninitialized; bool targetReachedUninitialized;
bool dynamicLimits; bool dynamicLimits;
moveMode lastMoveCommand;
}; };
/* /*
@@ -94,6 +100,7 @@ masterMacsAxis::masterMacsAxis(masterMacsController *pC, int axisNo)
.timeAtHandshake = 0, .timeAtHandshake = 0,
.targetReachedUninitialized = true, .targetReachedUninitialized = true,
.dynamicLimits = false, .dynamicLimits = false,
.lastMoveCommand = positionMode,
})) { })) {
asynStatus status = asynSuccess; asynStatus status = asynSuccess;
@@ -190,9 +197,7 @@ asynStatus masterMacsAxis::init() {
double motVelocity = 0.0; double motVelocity = 0.0;
double motVmax = 0.0; double motVmax = 0.0;
double motAccel = 0.0; double motAccel = 0.0;
int motMode = 0;
int dynamicLimits = 0; int dynamicLimits = 0;
int motCanSetMode = 0;
// ========================================================================= // =========================================================================
@@ -262,7 +267,7 @@ asynStatus masterMacsAxis::init() {
__PRETTY_FUNCTION__, __LINE__); __PRETTY_FUNCTION__, __LINE__);
} }
status = setVeloFields(motVelocity, 0.0, motVmax); status = setVeloFields(abs(motVelocity), 0.0, motVmax);
if (status != asynSuccess) { if (status != asynSuccess) {
return status; return status;
} }
@@ -306,37 +311,6 @@ asynStatus masterMacsAxis::init() {
} }
pMasterMacsA_->dynamicLimits = bool(dynamicLimits); pMasterMacsA_->dynamicLimits = bool(dynamicLimits);
// Check the current motor mode
status = pC_->read(axisNo_, 07, response);
if (status != asynSuccess) {
return status;
}
nvals = sscanf(response, "%d", &motMode);
if (nvals != 1) {
return pC_->couldNotParseResponse("R07", response, axisNo_,
__PRETTY_FUNCTION__, __LINE__);
}
// If the readback value from the controller is 3, it is in velocity mode,
// which sinqMotor encodes as a 1. Otherwise, it is in position mode.
setAxisParamChecked(this, motorMode, motMode == 3);
// Check if the motor can switch its mode
status = pC_->read(axisNo_, 31, response);
if (status != asynSuccess) {
return status;
}
nvals = sscanf(response, "%d", &motCanSetMode);
if (nvals != 1) {
return pC_->couldNotParseResponse("R31", response, axisNo_,
__PRETTY_FUNCTION__, __LINE__);
}
// If the readback value from the controller is 3, the motor supports both
// velocity and position mode, otherwise just one of them (the one read out
// with motMode).
setAxisParamChecked(this, motorCanSetMode, motCanSetMode == 3);
status = readEncoderType(); status = readEncoderType();
if (status != asynSuccess) { if (status != asynSuccess) {
return status; return status;
@@ -419,10 +393,7 @@ asynStatus masterMacsAxis::readLimits() {
highLimit = highLimit - limitsOffset; highLimit = highLimit - limitsOffset;
lowLimit = lowLimit + limitsOffset; lowLimit = lowLimit + limitsOffset;
setAxisParamChecked(this, motorHighLimitFromDriver, highLimit); return setLimits(highLimit, lowLimit);
setAxisParamChecked(this, motorLowLimitFromDriver, lowLimit);
return status;
} }
// Perform the actual poll // Perform the actual poll
@@ -432,10 +403,10 @@ asynStatus masterMacsAxis::doPoll(bool *moving) {
asynStatus poll_status = asynSuccess; asynStatus poll_status = asynSuccess;
// Status of read-write-operations of ASCII commands to the controller // Status of read-write-operations of ASCII commands to the controller
asynStatus rw_status = asynSuccess; asynStatus rwStatus = asynSuccess;
// Status of parameter library operations // Status of parameter library operations
asynStatus pl_status = asynSuccess; asynStatus plStatus = asynSuccess;
char response[pC_->MAXBUF_] = {0}; char response[pC_->MAXBUF_] = {0};
int nvals = 0; int nvals = 0;
@@ -484,8 +455,8 @@ asynStatus masterMacsAxis::doPoll(bool *moving) {
} }
pC_->read(axisNo_, 86, response); pC_->read(axisNo_, 86, response);
if (rw_status != asynSuccess) { if (rwStatus != asynSuccess) {
return rw_status; return rwStatus;
} }
nvals = sscanf(response, "%lf", &handshakePerformed); nvals = sscanf(response, "%lf", &handshakePerformed);
@@ -511,38 +482,20 @@ asynStatus masterMacsAxis::doPoll(bool *moving) {
getAxisParamChecked(this, motorRecResolution, &motorRecResolution); getAxisParamChecked(this, motorRecResolution, &motorRecResolution);
// Read the previous motor position // Read the previous motor position
pl_status = motorPosition(&previousPosition); plStatus = motorPosition(&previousPosition);
if (pl_status != asynSuccess) { if (plStatus != asynSuccess) {
return pl_status; return plStatus;
} }
// Update the axis status // Update the axis status
rw_status = readAxisStatus(); rwStatus = readAxisStatus();
if (rw_status != asynSuccess) { if (rwStatus != asynSuccess) {
return rw_status; return rwStatus;
} }
// If we wait for a handshake, but the motor was moving in its last poll rwStatus = pC_->read(axisNo_, 12, response);
// cycle and has reached its target, it is not moving. Otherwise it is if (rwStatus != asynSuccess) {
// considered moving, even if we're still waiting for the handshake. return rwStatus;
if (pMasterMacsA_->targetReachedUninitialized) {
*moving = false;
} else {
if (targetReached() || !switchedOn()) {
*moving = false;
} else {
*moving = true;
}
}
if (targetReached()) {
pMasterMacsA_->targetReachedUninitialized = false;
}
// Read the current position
rw_status = pC_->read(axisNo_, 12, response);
if (rw_status != asynSuccess) {
return rw_status;
} }
nvals = sscanf(response, "%lf", &currentPosition); nvals = sscanf(response, "%lf", &currentPosition);
if (nvals != 1) { if (nvals != 1) {
@@ -550,12 +503,59 @@ asynStatus masterMacsAxis::doPoll(bool *moving) {
__PRETTY_FUNCTION__, __LINE__); __PRETTY_FUNCTION__, __LINE__);
} }
plStatus = setMotorPosition(currentPosition);
if (plStatus != asynSuccess) {
return plStatus;
}
setAxisParamChecked(this, motorEncoderPosition, currentPosition);
if (pMasterMacsA_->lastMoveCommand == velocityMode && !speedEqualZero()) {
double actualVelocity = 0.0;
rwStatus = pC_->read(axisNo_, 14, response);
if (rwStatus != asynSuccess) {
return rwStatus;
}
nvals = sscanf(response, "%lf", &actualVelocity);
if (nvals != 1) {
return pC_->couldNotParseResponse("R14", response, axisNo_,
__PRETTY_FUNCTION__, __LINE__);
}
// Writes the actual speed in steps per second to the paramLib. This
// value is then returned by the RVEL field of the motor record.
setAxisParamChecked(this, motorVelocity,
actualVelocity / motorRecResolution);
// Motor is moving in velocity mode
*moving = true;
} else {
// 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) {
*moving = false;
} else {
if (targetReached() || !switchedOn()) {
*moving = false;
} else {
*moving = true;
}
}
if (targetReached()) {
pMasterMacsA_->targetReachedUninitialized = false;
}
}
/* /*
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
if a movement has just ended. or if a movement has just ended.
*/ */
if (faultConditionSet() || !(*moving)) { if (faultConditionSet() || !(*moving)) {
rw_status = readAxisError(); rwStatus = readAxisError();
} }
msgPrintControlKey keyError = msgPrintControlKey( msgPrintControlKey keyError = msgPrintControlKey(
@@ -776,9 +776,9 @@ asynStatus masterMacsAxis::doPoll(bool *moving) {
// Read out the limits, if the motor is not moving and if the limits are // Read out the limits, if the motor is not moving and if the limits are
// dynamic // dynamic
if (pMasterMacsA_->dynamicLimits && !(*moving)) { if (pMasterMacsA_->dynamicLimits && !(*moving)) {
rw_status = readLimits(); rwStatus = readLimits();
if (rw_status != asynSuccess) { if (rwStatus != asynSuccess) {
return rw_status; return rwStatus;
} }
} }
@@ -803,16 +803,11 @@ asynStatus masterMacsAxis::doPoll(bool *moving) {
setAxisParamChecked(this, motorStatusDone, !(*moving)); setAxisParamChecked(this, motorStatusDone, !(*moving));
setAxisParamChecked(this, motorStatusDirection, direction); setAxisParamChecked(this, motorStatusDirection, direction);
pl_status = setMotorPosition(currentPosition);
if (pl_status != asynSuccess) {
return pl_status;
}
return poll_status; return poll_status;
} }
asynStatus masterMacsAxis::doMoveVelocity(double minVelocity, asynStatus masterMacsAxis::moveVelocity(double minVelocity, double maxVelocity,
double maxVelocity, double acceleration) {
double acceleration) {
// Suppress unused variable warning // Suppress unused variable warning
(void)minVelocity; (void)minVelocity;
(void)acceleration; (void)acceleration;
@@ -863,7 +858,14 @@ asynStatus masterMacsAxis::doMoveVelocity(double minVelocity,
// Start the move. We do not use the MovTimeout watchdog here, because the // Start the move. We do not use the MovTimeout watchdog here, because the
// motor can move for any time in velocity mode. // motor can move for any time in velocity mode.
return pC_->write(axisNo_, 00, "3", timeout); status = pC_->write(axisNo_, 00, "3", timeout);
if (status != asynSuccess) {
return status;
}
// Cache the information that the current movement is in velocity mode
pMasterMacsA_->lastMoveCommand = velocityMode;
return status;
} }
asynStatus masterMacsAxis::doMove(double position, int relative, asynStatus masterMacsAxis::doMove(double position, int relative,
@@ -971,6 +973,8 @@ asynStatus masterMacsAxis::doMove(double position, int relative,
return asynError; return asynError;
} }
// Cache the information that the current movement is in position mode
pMasterMacsA_->lastMoveCommand = positionMode;
return status; return status;
} }
@@ -1271,8 +1275,8 @@ asynStatus masterMacsAxis::readAxisStatus() {
// ========================================================================= // =========================================================================
asynStatus rw_status = pC_->read(axisNo_, 10, response); asynStatus rwStatus = pC_->read(axisNo_, 10, response);
if (rw_status == asynSuccess) { if (rwStatus == asynSuccess) {
float axisStatus = 0; float axisStatus = 0;
int nvals = sscanf(response, "%f", &axisStatus); int nvals = sscanf(response, "%f", &axisStatus);
@@ -1284,7 +1288,7 @@ asynStatus masterMacsAxis::readAxisStatus() {
pMasterMacsA_->axisStatus = toBitset(axisStatus); pMasterMacsA_->axisStatus = toBitset(axisStatus);
} }
return rw_status; return rwStatus;
} }
asynStatus masterMacsAxis::readAxisError() { asynStatus masterMacsAxis::readAxisError() {
@@ -1292,8 +1296,8 @@ asynStatus masterMacsAxis::readAxisError() {
// ========================================================================= // =========================================================================
asynStatus rw_status = pC_->read(axisNo_, 11, response); asynStatus rwStatus = pC_->read(axisNo_, 11, response);
if (rw_status == asynSuccess) { if (rwStatus == asynSuccess) {
float axisError = 0; float axisError = 0;
int nvals = sscanf(response, "%f", &axisError); int nvals = sscanf(response, "%f", &axisError);
@@ -1303,7 +1307,7 @@ asynStatus masterMacsAxis::readAxisError() {
} }
pMasterMacsA_->axisError = toBitset(axisError); pMasterMacsA_->axisError = toBitset(axisError);
} }
return rw_status; return rwStatus;
} }
bool masterMacsAxis::readyToBeSwitchedOn() { bool masterMacsAxis::readyToBeSwitchedOn() {
@@ -1330,6 +1334,8 @@ bool masterMacsAxis::remoteMode() { return pMasterMacsA_->axisStatus[9]; }
bool masterMacsAxis::targetReached() { return pMasterMacsA_->axisStatus[10]; } bool masterMacsAxis::targetReached() { return pMasterMacsA_->axisStatus[10]; }
bool masterMacsAxis::speedEqualZero() { return pMasterMacsA_->axisStatus[12]; }
bool masterMacsAxis::internalLimitActive() { bool masterMacsAxis::internalLimitActive() {
return pMasterMacsA_->axisStatus[11]; return pMasterMacsA_->axisStatus[11];
} }
+9 -5
View File
@@ -52,17 +52,15 @@ class HIDDEN masterMacsAxis : public sinqAxis {
asynStatus doPoll(bool *moving); asynStatus doPoll(bool *moving);
/** /**
* @brief Implementation of the `doMoveVelocity` function from sinqAxis. The * @brief TODO
* parameters are described in the documentation of
* `sinqAxis::doMoveVelocity`.
* *
* @param minVelocity * @param minVelocity
* @param maxVelocity * @param maxVelocity
* @param acceleration * @param acceleration
* @return asynStatus * @return asynStatus
*/ */
asynStatus doMoveVelocity(double minVelocity, double maxVelocity, asynStatus moveVelocity(double minVelocity, double maxVelocity,
double acceleration); double acceleration);
/** /**
* @brief Implementation of the `doMove` function from sinqAxis. The * @brief Implementation of the `doMove` function from sinqAxis. The
@@ -252,6 +250,12 @@ class HIDDEN masterMacsAxis : public sinqAxis {
*/ */
bool internalLimitActive(); bool internalLimitActive();
/**
* @brief Read the property from axisStatus (see masterMacsAxisImpl
* redefinition in masterMacsAxis.cpp)
*/
bool speedEqualZero();
// Bits 12 and 13 are unused // Bits 12 and 13 are unused
/** /**
+1 -1
View File
@@ -493,7 +493,7 @@ asynStatus masterMacsController::parseResponse(
} }
} }
} }
break; return asynDisconnected;
} else if (fullResponse[i] == '\x18') { } else if (fullResponse[i] == '\x18') {
// CAN // CAN
snprintf(drvMessageText, MAXBUF_, snprintf(drvMessageText, MAXBUF_,