- 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:
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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
58
utils/physhell.tcl
Executable 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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()
|
||||
|
Reference in New Issue
Block a user