Compare commits

...

11 Commits

Author SHA1 Message Date
69cad69c6f Updated sinqMotor
Some checks failed
Test And Build / Lint (push) Failing after 4s
Test And Build / Build (push) Failing after 8s
2026-03-10 13:22:14 +01:00
703519154a Added homing check to driver 2026-03-10 13:21:34 +01:00
6479642f47 Updated sinqMotor
Some checks failed
Test And Build / Lint (push) Failing after 4s
Test And Build / Build (push) Failing after 8s
2026-03-09 13:04:47 +01:00
8ef3e3a381 Added param callback 2026-03-09 11:56:06 +01:00
58b0e9fc77 Updated sinqMotor 2026-03-09 11:37:02 +01:00
f0fdedfd5a Updated error message 2026-03-06 14:26:13 +01:00
e7ce44fdb6 Test version for the homing check
Some checks failed
Test And Build / Lint (push) Failing after 4s
Test And Build / Build (push) Failing after 8s
2026-03-06 11:27:25 +01:00
08ce0999a3 Updated underlying version of motorBase to receive the RVEL bugfix
Some checks failed
Test And Build / Lint (push) Failing after 3s
Test And Build / Build (push) Failing after 6s
2026-02-12 12:05:34 +01:00
1d662ecd43 Use safe limit setter function from sinqMotor
Some checks failed
Test And Build / Lint (push) Failing after 3s
Test And Build / Build (push) Failing after 6s
2026-02-11 11:08:46 +01:00
bea68c807b Updated to new sinqMotor 1.6.0 version 2026-02-11 11:07:28 +01:00
01a04d3b24 Fixed of-by-one error
Some checks failed
Test And Build / Lint (push) Failing after 3s
Test And Build / Build (push) Failing after 8s
2026-02-03 14:05:12 +01:00
5 changed files with 77 additions and 54 deletions

View File

@@ -10,7 +10,7 @@ ARCH_FILTER=RHEL%
REQUIRED+=motorBase
# Specify the version of motorBase we want to build against
motorBase_VERSION=7.2.2
motorBase_VERSION=7.3.2
# These headers allow to depend on this library for derived drivers.
HEADERS += src/pmacAsynIPPort.h

View File

@@ -91,9 +91,9 @@ turboPmacAxis::turboPmacAxis(turboPmacController *pC, int axisNo,
}
// Even though this happens already in sinqAxis, a default value for
// motorMessageText is set here again, because apparently the sinqAxis
// motorErrorMessage is set here again, because apparently the sinqAxis
// constructor is not run before the string is accessed?
status = setStringParam(pC_->motorMessageText(), "");
status = setStringParam(pC_->motorErrorMessage(), "");
if (status != asynSuccess) {
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d:\nFATAL ERROR "
@@ -140,6 +140,9 @@ asynStatus turboPmacAxis::init() {
// Deadband in counts. Can be a fraction of a count, hence double.
double deadband_counts = 0.0;
// Read from the controller if the motor has been homed before
int hasBeenHomed = 0;
// Offset time for the movement watchdog caused by the air cushions in
// milliseconds.
int acoDelay = 0.0;
@@ -176,9 +179,11 @@ asynStatus turboPmacAxis::init() {
Ixx65.
*/
snprintf(command, sizeof(command),
"Q%2.2d10 Q%2.2d03 Q%2.2d04 Q%2.2d06 P%2.2d22 Q%2.2d00 I%2.2d65",
axisNo_, axisNo_, axisNo_, axisNo_, axisNo_, axisNo_, axisNo_);
status = pC_->writeRead(axisNo_, command, response, 7);
"Q%2.2d10 Q%2.2d03 Q%2.2d04 Q%2.2d06 P%2.2d22 Q%2.2d00 I%2.2d65 "
"M%2.2d45",
axisNo_, axisNo_, axisNo_, axisNo_, axisNo_, axisNo_, axisNo_,
axisNo_);
status = pC_->writeRead(axisNo_, command, response, 8);
msgPrintControlKey keyDisconnected = msgPrintControlKey(
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, 1);
@@ -205,9 +210,14 @@ asynStatus turboPmacAxis::init() {
pC_->getMsgPrintControl().resetCount(keyDisconnected, pC_->pasynUser());
}
nvals = sscanf(response, "%lf %lf %lf %lf %d %lf %lf", &motorPos,
nvals = sscanf(response, "%lf %lf %lf %lf %d %lf %lf %d", &motorPos,
&motorVmax, &motorVelocity, &motorAccel, &acoDelay,
&counts_to_eu, &deadband_counts);
&counts_to_eu, &deadband_counts, &hasBeenHomed);
if (nvals != 8) {
return pC_->couldNotParseResponse(command, response, axisNo_,
__PRETTY_FUNCTION__, __LINE__);
}
// The acoDelay is given in milliseconds -> Convert to seconds, rounded
// up
@@ -218,11 +228,6 @@ asynStatus turboPmacAxis::init() {
// here to mm/s^2.
motorAccel = motorAccel * 1000;
if (nvals != 8) {
return pC_->couldNotParseResponse(command, response, axisNo_,
__PRETTY_FUNCTION__, __LINE__);
}
// Store these values in the parameter library
status = setMotorPosition(motorPos);
if (status != asynSuccess) {
@@ -282,6 +287,9 @@ asynStatus turboPmacAxis::init() {
pTurboPmacA_->needInit = false;
}
// Use the homing status reported by the controller
setAxisParamChecked(this, motorStatusHomed, hasBeenHomed);
return status;
}
@@ -339,7 +347,7 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
}
if (timedOut) {
setAxisParamChecked(this, motorMessageText,
setAxisParamChecked(this, motorErrorMessage,
"Timed out while waiting for a handshake");
pTurboPmacA_->waitForHandshake = false;
}
@@ -459,7 +467,7 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
pC_->getMsgPrintControl().getSuffix());
}
resetCountStatus = false;
setAxisParamChecked(this, motorMessageText, "Emergency stop");
setAxisParamChecked(this, motorErrorMessage, "Emergency stop");
break;
case -3:
// Disabled
@@ -552,7 +560,7 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
userMessage, sizeof(userMessage),
"Reached unknown state P%2.2d00 = %d. Please call the support.",
axisNo_, error);
setAxisParamChecked(this, motorMessageText, userMessage);
setAxisParamChecked(this, motorErrorMessage, userMessage);
}
if (resetCountStatus) {
@@ -582,8 +590,10 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
getAxisParamChecked(this, limFromHardware, &limFromHardware);
if (limFromHardware != 0) {
setAxisParamChecked(this, motorHighLimitFromDriver, highLimit);
setAxisParamChecked(this, motorLowLimitFromDriver, lowLimit);
status = setLimits(highLimit, lowLimit);
if (status != asynSuccess) {
return status;
}
}
status = setMotorPosition(currentPosition);
@@ -614,7 +624,7 @@ asynStatus turboPmacAxis::handleError(int error, char *userMessage,
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
pC_->getMsgPrintControl().getSuffix());
}
setAxisParamChecked(this, motorMessageText,
setAxisParamChecked(this, motorErrorMessage,
"Target position would exceed software limits");
break;
case 5:
@@ -630,7 +640,7 @@ asynStatus turboPmacAxis::handleError(int error, char *userMessage,
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
pC_->getMsgPrintControl().getSuffix());
}
setAxisParamChecked(this, motorMessageText,
setAxisParamChecked(this, motorErrorMessage,
"Axis received move command while it is still "
"moving. Please call the support.");
break;
@@ -651,7 +661,7 @@ asynStatus turboPmacAxis::handleError(int error, char *userMessage,
"(P%2.2d01 = "
"%d). Please call the support.",
axisNo_, error);
setAxisParamChecked(this, motorMessageText, userMessage);
setAxisParamChecked(this, motorErrorMessage, userMessage);
break;
case 9:
if (pC_->getMsgPrintControl().shouldBePrinted(
@@ -670,7 +680,7 @@ asynStatus turboPmacAxis::handleError(int error, char *userMessage,
"No feedback from auxiliary device before movement (P%2.2d01 = "
"%d). Please call the support.",
axisNo_, error);
setAxisParamChecked(this, motorMessageText, userMessage);
setAxisParamChecked(this, motorErrorMessage, userMessage);
break;
case 10:
/*
@@ -696,7 +706,7 @@ asynStatus turboPmacAxis::handleError(int error, char *userMessage,
"the SPS for errors (if available). "
"Otherwise please call the support.",
axisNo_, error);
setAxisParamChecked(this, motorMessageText, userMessage);
setAxisParamChecked(this, motorErrorMessage, userMessage);
break;
case 11:
// Following error
@@ -716,7 +726,7 @@ asynStatus turboPmacAxis::handleError(int error, char *userMessage,
"Check if movement range is blocked. "
"Otherwise please call the support.",
axisNo_, error);
setAxisParamChecked(this, motorMessageText, userMessage);
setAxisParamChecked(this, motorErrorMessage, userMessage);
break;
case 12:
@@ -734,7 +744,7 @@ asynStatus turboPmacAxis::handleError(int error, char *userMessage,
"for errors (if available). Otherwise please call "
"the support.",
axisNo_, error);
setAxisParamChecked(this, motorMessageText, userMessage);
setAxisParamChecked(this, motorErrorMessage, userMessage);
break;
case 13:
@@ -753,7 +763,7 @@ asynStatus turboPmacAxis::handleError(int error, char *userMessage,
"Driver hardware error (P%2.2d01 = 13). Please call the "
"support.",
axisNo_);
setAxisParamChecked(this, motorMessageText, userMessage);
setAxisParamChecked(this, motorErrorMessage, userMessage);
break;
case 14:
// EPICS should already prevent this issue in the first place,
@@ -771,7 +781,7 @@ asynStatus turboPmacAxis::handleError(int error, char *userMessage,
"Move command exceeds hardware limits (P%2.2d01 = %d). Please "
"call the support.",
axisNo_, error);
setAxisParamChecked(this, motorMessageText, userMessage);
setAxisParamChecked(this, motorErrorMessage, userMessage);
break;
default:
@@ -785,7 +795,7 @@ asynStatus turboPmacAxis::handleError(int error, char *userMessage,
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, axisNo_,
error, pC_->getMsgPrintControl().getSuffix());
}
setAxisParamChecked(this, motorMessageText, userMessage);
setAxisParamChecked(this, motorErrorMessage, userMessage);
break;
}
return status;
@@ -1102,7 +1112,7 @@ asynStatus turboPmacAxis::rereadEncoder() {
"disabled before rereading the encoder.\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
setAxisParamChecked(
this, motorMessageText,
this, motorErrorMessage,
"Axis must be disabled before rereading the encoder.");
return asynError;
} else {
@@ -1165,7 +1175,7 @@ asynStatus turboPmacAxis::enable(bool on) {
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
axStatus);
setAxisParamChecked(this, motorMessageText,
setAxisParamChecked(this, motorErrorMessage,
"Axis cannot be disabled while it is moving.");
pTurboPmacA_->enableDisable = false;
return asynError;
@@ -1235,7 +1245,9 @@ asynStatus turboPmacAxis::enable(bool on) {
// Enabling / disabling procedure is completed (successfully)
pTurboPmacA_->enableDisable = false;
return asynSuccess;
// Reinitialize the motor
return init();
}
}
@@ -1250,7 +1262,7 @@ 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);
setAxisParamChecked(this, motorMessageText, command);
setAxisParamChecked(this, motorErrorMessage, command);
// Enabling / disabling procedure failed
pTurboPmacA_->enableDisable = false;

View File

@@ -445,7 +445,7 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
getAxisParamChecked(axis, motorStatusProblem, &motorStatusProblem);
if (motorStatusProblem == 0) {
setAxisParamChecked(axis, motorMessageText, drvMessageText);
setAxisParamChecked(axis, motorErrorMessage, drvMessageText);
setAxisParamChecked(axis, motorStatusProblem, true);
setAxisParamChecked(axis, motorStatusCommsError, true);
}

View File

@@ -9,45 +9,55 @@ Stefan Mathis, December 2024
import struct
import socket
import curses
import time
def packPmacCommand(command):
# 0x40 = VR_DOWNLOAD
# 0x40 = VR_DOWNLOAD
# 0xBF = VR_PMAC_GETRESPONSE
buf = struct.pack('BBHHH',0x40,0xBF,0,0,socket.htons(len(command)))
buf = buf + bytes(command,'utf-8')
buf = struct.pack('BBHHH', 0x40, 0xBF, 0, 0, socket.htons(len(command)))
buf = buf + command.encode('utf-8')
return buf
def readPmacReply(input):
def readPmacReply(sock):
msg = bytearray()
expectAck = True
sock.settimeout(2.0)
while True:
b = input.recv(1)
bint = int.from_bytes(b,byteorder='little')
if bint == 2 or bint == 7: #STX or BELL
try:
b = sock.recv(1)
except socket.timeout:
print('Timed out')
return None
bint = int.from_bytes(b, byteorder='little')
if bint == 2 or bint == 7: # STX or BELL
expectAck = False
continue
if expectAck and bint == 6: # ACK
if expectAck and bint == 6: # ACK
return bytes(msg)
else:
if bint == 13 and not expectAck: # CR
if bint == 13 and not expectAck: # CR
return bytes(msg)
else:
msg.append(bint)
if __name__ == "__main__":
from sys import argv
try:
addr = argv[1].split(':')
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect((addr[0],int(addr[1])))
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((addr[0], int(addr[1])))
if len(argv) == 3:
buf = packPmacCommand(argv[2])
s.send(buf)
reply = readPmacReply(s)
print(reply.decode('utf-8') + '\n')
if reply:
print(reply.decode('utf-8') + '\n')
else:
@@ -81,13 +91,13 @@ if __name__ == "__main__":
if ptr > 0:
ptr -= 1
stdscr.addch("\r")
stdscr.clrtoeol()
stdscr.clrtoeol()
stdscr.addstr(">> " + history[ptr])
elif c == curses.KEY_DOWN:
if ptr < len(history) - 1:
ptr += 1
stdscr.addch("\r")
stdscr.clrtoeol()
stdscr.clrtoeol()
stdscr.addstr(">> " + history[ptr])
elif c == curses.KEY_ENTER or c == ord('\n') or c == ord('\r'):
if history[ptr] == 'quit':
@@ -113,7 +123,7 @@ if __name__ == "__main__":
stdscr.refresh()
else:
if ptr < len(history) - 1: # Modifying previous input
if ptr < len(history) - 1: # Modifying previous input
if len(history[-1]) == 0:
history[-1] = history[ptr]
ptr = len(history) - 1
@@ -126,18 +136,20 @@ if __name__ == "__main__":
if len(history[ptr]) == 0:
continue
(y, x) = stdscr.getyx()
history[ptr] = history[ptr][0:x-4] + history[ptr][x-3:]
history[ptr] = history[ptr][0:x-4] + \
history[ptr][x-3:]
stdscr.addch("\r")
stdscr.clrtoeol()
stdscr.clrtoeol()
stdscr.addstr(">> " + history[ptr])
stdscr.move(y, x-1)
stdscr.refresh()
else:
(y, x) = stdscr.getyx()
history[ptr] = history[ptr][0:x-3] + chr(c) + history[ptr][x-3:]
history[ptr] = history[ptr][0:x-3] + \
chr(c) + history[ptr][x-3:]
stdscr.addch("\r")
stdscr.clrtoeol()
stdscr.clrtoeol()
stdscr.addstr(">> " + history[ptr])
stdscr.move(y, x+1)
stdscr.refresh()
@@ -169,4 +181,3 @@ if __name__ == "__main__":
the reponse, before being prompted to again enter a command. Type
'quit' to close prompt.
""")