- Fixed a enable PV initialisation bug in MasterMACS

- Made the HRPT axis base itself on V3 of the pmacAxis
- Improved and added utils programs
This commit is contained in:
2024-06-07 08:58:53 +02:00
parent d9d6dae19f
commit 30228adf50
8 changed files with 156 additions and 25 deletions

View File

@ -4,6 +4,7 @@
Marcel Schildt
Mark Koennecke, March-August 2023
Mark Koenencke, More fixes in June 2024
*/
@ -13,6 +14,7 @@
#include <math.h>
#include <ctype.h>
#include <time.h>
#include <sys/time.h>
#include <unistd.h>
#include <iocsh.h>
@ -28,6 +30,18 @@
#define ABS(x) (x < 0 ? -(x) : (x))
#define debug 0
#define timeDebug 0
double DoubleTime(void)
{
struct timeval now;
/* the resolution of this function is usec, if the machine supports this
and the mantissa of a double is 51 bits or more (31 bits for seconds
and 20 for microseconds)
*/
gettimeofday(&now, NULL);
return now.tv_sec + now.tv_usec / 1e6;
}
/** Creates a new MasterMACSController object.
* \param[in] portName The name of the asyn port that will be created for this driver
@ -141,6 +155,7 @@ asynStatus
size_t in, out;
int reason, len, idx, lenPayload;
unsigned int i;
double startTime, now;
char *mmacsData =
NULL, ackchar, mmacsResponse[COMLEN], hexResponse[256];
SINQAxis *axis = getAxis(axisNo);
@ -173,10 +188,19 @@ asynStatus
errlogSevPrintf(errlogMajor,"Sending command: %s\n", command);
}
startTime = DoubleTime();
status =
pasynOctetSyncIO->writeRead(pasynUserController_, mmacsData,
len - 1, mmacsResponse, 35, 5., &out,
len - 1, mmacsResponse, 35, 10., &out,
&in, &reason);
if(timeDebug) {
now = DoubleTime();
if((now - startTime) > 1.) {
errlogSevPrintf(errlogMajor, "Unusual response time %lf to command %s\n", (now - startTime), command);
}
}
if (status != asynSuccess) {
if (axis != NULL) {
errlogSevPrintf(errlogMajor,
@ -247,6 +271,34 @@ asynStatus
return status;
}
/*--------------------------------------------------------------------------------------------*/
asynStatus
MasterMACSController::readInt32(asynUser * pasynUser,
epicsInt32 * value)
{
int function = pasynUser->reason;
MasterMACSAxis *pAxis = NULL;
int devStatus, isOn;
pAxis = (MasterMACSAxis *) (this->getAxis(pasynUser));
if (!pAxis) {
return asynError;
}
if (function == axisEnabled_) {
devStatus = pAxis->readStatus();
isOn = pAxis->isOn(devStatus);
// errlogPrintf("isOn in readInt32: %d, devStatus = %d\n", isOn, devStatus);
pAxis->setIntegerParam(enableAxis_, isOn);
pAxis->setIntegerParam(axisEnabled_, isOn);
*value = isOn;
callParamCallbacks();
return asynSuccess;
}
return asynMotorController::readInt32(pasynUser, value);
}
/*------------------------------------------------------------------------------------------*/
asynStatus
MasterMACSController::writeInt32(asynUser * pasynUser,
epicsInt32 value)
@ -305,10 +357,14 @@ asynStatus
errlogPrintf("MMACS: Failure to enable or disable axis %d",
pAxis->axisNo_);
}
/*
* wait max 2 seconds for success of the operation
*/
startTime = time(NULL);
while(time(NULL) < startTime + 2.){
// wait for the change to happen
devStatus = pAxis->readStatus();
// errlogPrintf("MMACS: switching enable: target, devStatus, isOn: %d, %d, %d\n", value, devStatus, pAxis->isOn(devStatus));
if(pAxis->isOn(devStatus) == value){
pAxis->active = true;
pAxis->poll(&moving); // to update the Enable_RBV field
@ -317,7 +373,7 @@ asynStatus
}
usleep(200);
}
errlogPrintf("MMACS: Failed to enable motor %d within 2 seconds\n", pAxis->axisNo_);
errlogPrintf("MMACS: Failed to dis/enable motor %d within 2 seconds\n", pAxis->axisNo_);
}
return asynMotorController::writeInt32(pasynUser, value);
}
@ -332,11 +388,17 @@ asynStatus
* Initializes register numbers, etc.
*/
MasterMACSAxis::MasterMACSAxis(MasterMACSController * pC, int axisNo):SINQAxis(pC, axisNo),
pC_
(pC)
pC_(pC)
{
hasStarted = false;
active = false;
errorCodeFound = 0;
/*
* Try to read the initial enable status of the motor
*/
int devStatus = readStatus();
setIntegerParam(pC_->enableAxis_, isOn(devStatus));
setIntegerParam(pC_->axisEnabled_, isOn(devStatus));
}
/** Reports on status of the axis
@ -361,7 +423,7 @@ int MasterMACSAxis::readStatus()
/*
* The MasterMACS sends invalid responses with a low frequency.
* Therefore I send cached status responses in such a case in order
* to help the logic evrywhere else in the code.
* to help the logic everywhere else in the code.
*/
sprintf(command, "%dR10", axisNo_);
status = pC_->transactController(axisNo_, command, reply);
@ -548,7 +610,7 @@ asynStatus MasterMACSAxis::poll(bool * moving)
{
asynStatus comStatus = asynSuccess;
char command[COMLEN], reply[COMLEN], *pPtr, buffer[80];
unsigned int errCode, derCode, devStatus;
unsigned int errCode, derCode, devStatus = 0;
float errStatus;
struct tm* tm_info;
time_t timer;
@ -599,7 +661,7 @@ asynStatus MasterMACSAxis::poll(bool * moving)
// Read the overall status of this motor */
devStatus = readStatus();
if(debug) {
if(debug || timeDebug) {
errlogPrintf("Axis %d, position %lf, devStatus %d\n", axisNo_,
position, devStatus);
}

View File

@ -62,6 +62,7 @@ public:
MasterMACSAxis* getAxis(int axisNo);
// overloaded because we want to enable/disable the motor
asynStatus readInt32(asynUser *pasynUser, epicsInt32 *value);
asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value);
friend class MasterMACSAxis;

View File

@ -596,7 +596,7 @@ asynStatus pmacHRPTAxis::getAxisStatus(bool *moving) {
char response[pC_->PMAC_MAXBUF_];
int cmdStatus = 0, nvals, crashSignal;
asynStatus result = pmacAxis::getAxisStatus(moving);
asynStatus result = pmacV3Axis::getAxisStatus(moving);
sprintf(command, "P%2.2d53", axisNo_);
cmdStatus = pC_->lowLevelWriteRead(axisNo_, command, response);
nvals = sscanf(response, "%d", &crashSignal);

View File

@ -70,22 +70,6 @@ protected:
friend class pmacController;
friend class pmacV3Controller;
};
/*----------------------------------------------------------------------------------------------*/
class pmacHRPTAxis : public pmacAxis
{
public:
pmacHRPTAxis(pmacController *pController, int axisNo) : pmacAxis(pController,axisNo) {};
/**
* Override getAxisStatus in order to read the special parameter indicating a
* slit blade crash at HRPT
*/
asynStatus getAxisStatus(bool *moving);
protected:
friend class pmacController;
};
/*--------------------------------------------------------------------------------------------*/
class SeleneAxis : public pmacAxis
{
@ -157,6 +141,23 @@ public:
friend class pmacV3Controller;
};
/*----------------------------------------------------------------------------------------------*/
class pmacHRPTAxis : public pmacV3Axis
{
public:
pmacHRPTAxis(pmacController *pController, int axisNo) : pmacV3Axis(pController,axisNo) {};
/**
* Override getAxisStatus in order to read the special parameter indicating a
* slit blade crash at HRPT
*/
asynStatus getAxisStatus(bool *moving);
protected:
friend class pmacController;
};
/*
* Special motors for the AMOR detector movement. The whole
* command set is different but on a pmac controller. This implements

View File

@ -869,10 +869,14 @@ static const char *functionName = "pmacV3Controller::writeInt32";
snprintf(command, sizeof(command), "P%2.2d00", pAxis->axisNo_);
this->lowLevelWriteRead(pAxis->axisNo_, command, response);
isOn = strtol(response, NULL, 10) != -3;
/* This was an attempt at automatically reading the encoder.
This is disabled as it did not work.
*/
if(value == 1 && isOn) {
sprintf(command, "M%2.2d=15", pAxis->axisNo_);
// lowLevelWriteRead(pAxis->axisNo_, command, response);
}
// Valid code continues here
sprintf(command, "M%2.2d14=%d", pAxis->axisNo_, value);
pAxis->updateMsgTxtFromDriver("");
if(isOn != value) {

View File

@ -1,3 +1,4 @@
#!/usr/bin/env python3
"""
Usage: macmaster.py macmasterhost port
Listen for commands to send and returns reponse

58
utils/physhell.tcl Executable file
View File

@ -0,0 +1,58 @@
#!/usr/bin/tclsh
# This is a little program which acts as a shell to the phytron.
# It connects to another program which is supposed to talk to the phytron controller
# It reads from stdin, packages the message into the phytron format and sends it to
# the phytron communication program. Then it reads from the phytron communication program
# and unpacks the reply.
#
# This is also a nice exampe for dealing with binary in Tcl
# Making the binary character only worked with %c
# The only way to do the comparison is with the string comare
#
# Mark Könnecke, September 2016
if {[llength $argv] < 1} {
puts stdout "Usage:\n\t physhell.tcl phytronprogram"
exit
}
set phprogram [lindex $argv 0]
set phyio [open "| $phprogram" "w+b"]
fconfigure $phyio -buffering none
fconfigure $phyio -translation {binary binary}
set etx [format "%c" 0x03]
set stx [format "%c" 0x02]
set ack [format "%c" 0x06]
set nack [format "%c" 0x05]
while {1} {
set inp [gets stdin]
puts -nonewline $phyio [format "%c%s%c" 0x02 $inp 0x03]
set mode start
set reply ""
while {[string compare $mode done] != 0 } {
set c [read $phyio 1]
switch $mode {
start {
if {[string compare $c $stx] == 0} {
set mode data
}
}
data {
if {[string compare $c $etx] == 0} {
puts stdout $reply
set mode done
} elseif {[string compare $c $nack] == 0} {
append reply NACK
} elseif {[string compare $c $ack] == 0} {
append reply ACK
} else {
append reply $c
}
}
}
}
}

View File

@ -11,6 +11,7 @@ Mark Koennecke, January 2023
import socket
import sys
import time
socke = None
sockfd = None
@ -33,6 +34,7 @@ def transact(command):
global socke, sockfd
sockfd.write(command + '\r')
sockfd.flush()
time.sleep(.1)
return sockfd.readline()
def find_commas(rawline):
@ -61,8 +63,10 @@ def fix_line(par_list, index_list):
addridx = index_list.index('ADDR')
motNo = par_list[addridx]
limits = transact('H ' + motNo)
time.sleep(.1)
l = limits.split()
lowidx = index_list.index('DLLM')
# import pdb; pdb.set_trace()
par_list[lowidx] = l[0]
highidx = index_list.index('DHLM')
par_list[highidx] = l[1]
@ -93,7 +97,7 @@ def scan_substitution_file(filename):
newlist = fix_line(l, index_list)
# newline = ','.join(newlist)
newline = pretty_line(newlist, comma_list)
sys.stdout.write('{' + newline)
sys.stdout.write('{' + newline + '\n')
else:
sys.stdout.write(rawline)
rawline = fin.readline()