Final version of the SINQ EPICS module for RHEL7 in 2023

- Fixes to MasterMACS, mostly.
- Minor changes
This commit is contained in:
2024-01-11 14:05:49 +01:00
parent 9422353107
commit b4e201ae86
9 changed files with 212 additions and 153 deletions

View File

@ -2,7 +2,6 @@
include /ioc/tools/driver.makefile
MODULE=sinq
LIBVERSION=koennecke
BUILDCLASSES=Linux
EPICS_VERSIONS=3.14.12 7.0.4.1

View File

@ -0,0 +1,48 @@
record(motor,"$(P)$(M)")
{
field(DESC,"$(DESC)")
field(DTYP,"$(DTYP)")
field(DIR,"$(DIR)")
field(VELO,"$(VELO)")
field(VMAX,"$(VMAX=$(VELO))")
field(VBAS,"$(VBAS)")
field(ACCL,"$(ACCL)")
field(BDST,"$(BDST)")
field(BVEL,"$(BVEL)")
field(BACC,"$(BACC)")
field(OUT,"@asyn($(PORT),$(ADDR))")
field(MRES,"$(MRES)")
field(PREC,"$(PREC)")
field(EGU,"$(EGU)")
field(DHLM,"$(DHLM)")
field(DLLM,"$(DLLM)")
field(INIT,"$(INIT)")
field(TWV,"1")
field(RDBD,"$(RDBD)")
}
# The message text
record(waveform, "$(P)$(M)-MsgTxt") {
field(DTYP, "asynOctetRead")
field(INP, "@asyn($(PORT),$(N),1) MOTOR_MESSAGE_TEXT")
field(FTVL, "CHAR")
field(NELM, "80")
field(SCAN, "I/O Intr")
}
# enable axis
record(longout, "$(P)$(M):Enable") {
field(DTYP, "asynInt32")
field(OUT, "@asyn($(PORT),$(N),1) ENABLE_AXIS")
field(PINI, "YES")
}
# enable axis
record(longin, "$(P)$(M):Enable_RBV") {
field(DTYP, "asynInt32")
field(INP, "@asyn($(PORT),$(N),1) AXIS_ENABLED")
field(PINI, "YES")
field(SCAN, "1 second")
}

View File

@ -181,21 +181,21 @@ asynStatus EL734Controller::transactController(int axisNo,char command[COMLEN],
}
if(strstr(myReply,"?cmd") != NULL){
snprintf(errTxt,sizeof(errTxt), "Bad command %s at axis %d", command, axisNo);
errlogSevPrintf(errlogMajor, errTxt);
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, errTxt);
if(axis!= NULL){
axis->updateMsgTxtFromDriver(errTxt);
}
return asynError;
} else if(strstr(myReply,"?par") != NULL){
snprintf(errTxt,sizeof(errTxt), "Bad parameter in command %s", command);
errlogSevPrintf(errlogMajor, errTxt);
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, errTxt);
if(axis!= NULL){
axis->updateMsgTxtFromDriver(errTxt);
}
return asynError;
} else if(strstr(myReply,"?rng") != NULL){
snprintf(errTxt,sizeof(errTxt), "Parameter out of range in command %s", command);
errlogSevPrintf(errlogMajor, errTxt);
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, errTxt);
if(axis!= NULL){
axis->updateMsgTxtFromDriver(errTxt);
}
@ -233,10 +233,12 @@ EL734Axis::EL734Axis(EL734Controller *pC, int axisNo)
pC_->setDoubleParam(axisNo_,pC_->motorHighLimit_,high);
callParamCallbacks();
} else {
errlogPrintf("Bad response - %s - requesting limits at axis %d", reply, axisNo_);
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Bad response - %s - requesting limits at axis %d", reply, axisNo_);
}
} else {
errlogPrintf("Failed to read limits at axis %d", axisNo_);
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Failed to read limits at axis %d", axisNo_);
}
}
@ -282,7 +284,8 @@ asynStatus EL734Axis::move(double position, int relative, double minVelocity, do
oredMSR = 0;
homing = 0;
errorReported = 0;
errlogPrintf("Starting axis %d with destination %f", axisNo_,position/1000);
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Starting axis %d with destination %f", axisNo_,position/1000);
sprintf(command, "p %d %.3f", axisNo_, position/1000.);
status = pC_->transactController(axisNo_,command,reply);
setIntegerParam(pC_->motorStatusProblem_, false);
@ -347,7 +350,7 @@ asynStatus EL734Axis::stop(double acceleration )
if(moving && errorReported == 0){
sprintf(command, "S %d", axisNo_);
status = pC_->transactController(axisNo_,command,reply);
errlogPrintf("Sent STOP on Axis %d\n", axisNo_);
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR, "Sent STOP on Axis %d\n", axisNo_);
updateMsgTxtFromDriver("Axis interrupted");
errorReported = 1;
}
@ -443,7 +446,8 @@ asynStatus EL734Axis::poll(bool *moving)
goto skip;
}
} else {
errlogPrintf("Axis %d, reply %s, position %lf\n", axisNo_, reply, position);
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"Axis %d, reply %s, position %lf\n", axisNo_, reply, position);
setDoubleParam(pC_->motorPosition_, position*1000);
//setDoubleParam(pC_->motorEncoderPosition_, position);
}
@ -492,7 +496,7 @@ asynStatus EL734Axis::poll(bool *moving)
if(oredMSR & 0x1000){
setIntegerParam(pC_->motorStatusProblem_, true);
// errlogPrintf("Detected air cushion error on %d", axisNo_);
errlogSevPrintf(errlogMajor, "Air cushion problem on %d", axisNo_);
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR, "Air cushion problem on %d", axisNo_);
updateMsgTxtFromDriver("Air cushion error");
errorReported = 1;
comStatus = asynError;
@ -500,7 +504,7 @@ asynStatus EL734Axis::poll(bool *moving)
}
if(oredMSR & 0x100){
setIntegerParam(pC_->motorStatusProblem_, true);
errlogSevPrintf(errlogMajor, "Run failure at %d", axisNo_);
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR, "Run failure at %d", axisNo_);
updateMsgTxtFromDriver("Run failure");
comStatus = asynError;
errorReported = 1;
@ -508,14 +512,14 @@ asynStatus EL734Axis::poll(bool *moving)
}
if(oredMSR & 0x400){
setIntegerParam(pC_->motorStatusProblem_, true);
errlogSevPrintf(errlogMajor, "Positioning failure at %d", axisNo_);
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR, "Positioning failure at %d", axisNo_);
updateMsgTxtFromDriver("Positioning failure");
comStatus = asynError;
errorReported = 1;
goto skip;
}
if(oredMSR & 0x200 || oredMSR & 0x80) {
errlogSevPrintf(errlogMinor, "Positioning fault at %d", axisNo_);
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_WARNING, "Positioning fault at %d", axisNo_);
}
setIntegerParam(pC_->motorStatusProblem_, false);
} else {

View File

@ -269,15 +269,18 @@ asynStatus
* overwritten when we read back the status at the end, but that's OK */
pAxis->setIntegerParam(function, value);
if(function == motorStop_){
errlogPrintf("Stop called with value %d\n", value);
double accel;
getDoubleParam(pAxis->axisNo_, motorAccel_, &accel);
status = pAxis->stop(accel);
return status;
}
if (function == enableAxis_) {
/*
* Read the status in order to prevent execssive commands
*/
devStatus = pAxis->readStatus();
if(devStatus < 900){
errlogPrintf("MMACS: Motor %d not ready to switch on\n", pAxis->axisNo_);
return asynError;
}
if (value == 1 && !pAxis->isOn(devStatus) ) {
/* download parameters, does not work as of now */
/*
@ -309,6 +312,7 @@ asynStatus
if(pAxis->isOn(devStatus) == value){
pAxis->active = true;
pAxis->poll(&moving); // to update the Enable_RBV field
pAxis->active = false;
return asynSuccess;
}
usleep(200);
@ -388,12 +392,11 @@ asynStatus
MasterMACSAxis::move(double position, int relative, double minVelocity,
double maxVelocity, double acceleration)
{
asynStatus status;
asynStatus status = asynSuccess;
char command[COMLEN], reply[COMLEN];
int devStatus;
errlogPrintf("minVelocity = %f, maxVelocity = %f\n", minVelocity,
maxVelocity);
//errlogPrintf("minVelocity = %f, maxVelocity = %f\n", minVelocity, maxVelocity);
memset(command, 0, COMLEN * sizeof(char));
/* clear motor error message */
@ -409,18 +412,9 @@ asynStatus
}
/*
* test if the thing is On
* only start if the thing is On
*/
devStatus = readStatus();
if(devStatus < 900) {
return asynError;
}
if (!isOn(devStatus)) {
setIntegerParam(pC_->motorStatusProblem_, true);
updateMsgTxtFromDriver("Motor disabled");
errlogPrintf("ERROR: trying to start disabled axis %d\n", axisNo_);
return asynError;
}
/*
* set speed
@ -433,14 +427,17 @@ asynStatus
if (relative) {
position += this->position;
}
errlogPrintf("Starting axis %d with destination %f", axisNo_,
if(isOn(devStatus) && active == false) {
errlogPrintf("Starting axis %d with destination %f\n", axisNo_,
position / 1000.);
/* send target position */
sprintf(command, "%dS02= %.3f", axisNo_, position / 1000.);
status = pC_->transactController(axisNo_, command, reply);
if (status == asynError) {
setIntegerParam(pC_->motorStatusProblem_, true);
errlogPrintf("MMACS: failed to set target on %d\n", axisNo_);
updateMsgTxtFromDriver("Failed to send target position");
return status;
}
@ -448,13 +445,18 @@ asynStatus
sprintf(command, "%dS00=1", axisNo_);
status = pC_->transactController(axisNo_, command, reply);
if (status == asynError) {
setIntegerParam(pC_->motorStatusProblem_, true);
errlogPrintf("MMACS: failed to start axis %d\n", axisNo_);
updateMsgTxtFromDriver("Failed to start axis");
return status;
}
hasStarted = true;
homing = 0;
active = true;
usleep(500);
lastPositionUpdate = time(NULL);
} else {
errlogPrintf("MMACS: axis %d disabled, cannot start\n", axisNo_);
}
return status;
}
@ -472,26 +474,20 @@ asynStatus
* test if the thing is On
*/
devStatus = readStatus();
if(devStatus < 900) {
return asynError;
}
if (!isOn(devStatus)) {
setIntegerParam(pC_->motorStatusProblem_, true);
updateMsgTxtFromDriver("Motor disabled");
errlogPrintf("ERROR: trying to home disabled axis %d\n", axisNo_);
return asynError;
}
setIntegerParam(pC_->motorStatusProblem_, false);
updateMsgTxtFromDriver("");
if(isOn(devStatus)){
sprintf(command, "%dS00=9", axisNo_);
homing = 1;
status = pC_->transactController(axisNo_, command, reply);
hasStarted = true;
active = true;
lastPositionUpdate = time(NULL);
return status;
} else {
errlogPrintf("MMACS: cannot home disabled axis %d\n", axisNo_);
return asynError;
}
}
asynStatus
@ -552,9 +548,8 @@ asynStatus MasterMACSAxis::poll(bool * moving)
{
asynStatus comStatus = asynSuccess;
char command[COMLEN], reply[COMLEN], *pPtr, buffer[80];
float errStatus;
unsigned int errCode, derCode, devStatus;
float errStatus;
struct tm* tm_info;
time_t timer;
@ -574,6 +569,7 @@ asynStatus MasterMACSAxis::poll(bool * moving)
strftime(buffer, 26, "%Y-%m-%d %H:%M:%S", tm_info);
errlogPrintf("poll called at %s on axis %d \n",
buffer, axisNo_ );
lastPoll = time(NULL);
setIntegerParam(pC_->motorStatusProblem_, false);
memset(command, 0, COMLEN * sizeof(char));
@ -581,23 +577,12 @@ asynStatus MasterMACSAxis::poll(bool * moving)
// Read the current motor position
sprintf(command, "%dR12", axisNo_);
comStatus = pC_->transactController(axisNo_, command, reply);
if (comStatus == asynError) {
setIntegerParam(pC_->motorStatusProblem_, true);
goto skip;
}
if(comStatus != asynError) {
pPtr = strstr(reply, "=");
if (pPtr) {
if(pPtr) {
sscanf(pPtr + 1, "%lf", &position);
} else {
errlogPrintf("Received malformed reply: Axis %d, reply %s\n",
axisNo_, reply + 4);
comStatus = asynError;
goto skip;
}
setDoubleParam(pC_->motorPosition_, position * 1000.);
setDoubleParam(pC_->motorEncoderPosition_, position * 1000.);
/*
* keep track of position in order to check for a stuck motor later
*/
@ -605,24 +590,38 @@ asynStatus MasterMACSAxis::poll(bool * moving)
oldPosition = position;
lastPositionUpdate = time(NULL);
}
} else {
errlogPrintf("MMACS: Invalid response asking position on %d\n", axisNo_);
}
} else {
errlogPrintf("MMACS: communication problem reading axis %d position\n", axisNo_);
}
// Read the overall status of this motor */
devStatus = readStatus();
if(devStatus < 900) {
setIntegerParam(pC_->motorStatusProblem_, true);
goto skip;
}
if(debug) {
errlogPrintf("Axis %d, position %lf, devStatus %d\n", axisNo_,
position, devStatus);
}
setIntegerParam(pC_->axisEnabled_, isOn(devStatus));
if (!isOn(devStatus)) {
setIntegerParam(pC_->motorStatusProblem_, true);
updateMsgTxtFromDriver("Motor disabled");
// Check for the thing being in a bad state
if(CHECK_BIT(devStatus, 6)) {
*moving = false;
active = false;
setIntegerParam(pC_->motorStatusDone_, true);
updateMsgTxtFromDriver("AXIS dead");
goto skip;
}
setIntegerParam(pC_->enableAxis_, isOn(devStatus));
setIntegerParam(pC_->axisEnabled_, isOn(devStatus));
// Check if the motor is disabled
if (!isOn(devStatus)) {
updateMsgTxtFromDriver("Axis disabled");
*moving = false;
active = false;
setIntegerParam(pC_->motorStatusDone_, true);
goto skip;
}
@ -633,6 +632,7 @@ asynStatus MasterMACSAxis::poll(bool * moving)
if (!hasStarted) {
*moving = false;
setIntegerParam(pC_->motorStatusDone_, true);
active = false;
goto skip;
}
@ -643,11 +643,13 @@ asynStatus MasterMACSAxis::poll(bool * moving)
/* we are still creeping along .... */
*moving = true;
setIntegerParam(pC_->motorStatusDone_, false);
if(time(NULL) > lastPositionUpdate + 60) {
if(time(NULL) > lastPositionUpdate + 120) {
// we are detecting a stuck motor
errlogPrintf("MMACS: axis %d is STUCK!!\n", axisNo_);
updateMsgTxtFromDriver("Axis STUCK!!");
setIntegerParam(pC_->motorStatusProblem_, true);
setIntegerParam(pC_->motorStatusDone_, true);
*moving = false;
active = false;
}
goto skip;
}
@ -657,6 +659,7 @@ asynStatus MasterMACSAxis::poll(bool * moving)
*moving = false;
active = false;
setIntegerParam(pC_->motorStatusDone_, true);
updateMsgTxtFromDriver("");
/* when homing, set the proper flag */
if (homing) {
@ -667,19 +670,14 @@ asynStatus MasterMACSAxis::poll(bool * moving)
setIntegerParam(pC_->motorStatusLowLimit_, false);
setIntegerParam(pC_->motorStatusHighLimit_, false);
if (CHECK_BIT(devStatus, 11)) {
setIntegerParam(pC_->motorStatusProblem_, true);
errlogSevPrintf(errlogMajor,
"Limit bit in status code %d",
axisNo_);
errlogSevPrintf(errlogMajor, "Limit bit in status code %d", axisNo_);
/* guessing which limit has been hit ... */
if (position > 0) {
updateMsgTxtFromDriver("Hit positive limit switch");
setIntegerParam(pC_->motorStatusHighLimit_, true);
setIntegerParam(pC_->motorStatusProblem_, false);
} else {
updateMsgTxtFromDriver("Hit negative limit switch");
setIntegerParam(pC_->motorStatusLowLimit_, true);
setIntegerParam(pC_->motorStatusProblem_, false);
}
goto skip;
}
@ -689,26 +687,25 @@ asynStatus MasterMACSAxis::poll(bool * moving)
/* read error codes */
sprintf(command, "%dR11", axisNo_);
comStatus = pC_->transactController(axisNo_, command, reply);
if (comStatus == asynError) {
setIntegerParam(pC_->motorStatusProblem_, true);
goto skip;
}
if (comStatus != asynError) {
pPtr = strstr(reply, "=");
if(pPtr) {
sscanf(pPtr + 1, "%f", &errStatus);
errCode = (unsigned int) errStatus;
} else {
errlogPrintf("MMACS: axis %d received invalid reply asking for error code \n", axisNo_);
updateMsgTxtFromDriver("Invalid reply asking error code R11");
errCode = 0;
goto skip;
}
sprintf(command, "%dR18", axisNo_);
comStatus = pC_->transactController(axisNo_, command, reply);
if (comStatus == asynError) {
setIntegerParam(pC_->motorStatusProblem_, true);
} else {
errlogPrintf("MMACS: axis %d failed reading error code \n", axisNo_);
goto skip;
}
sprintf(command, "%dR18", axisNo_);
comStatus = pC_->transactController(axisNo_, command, reply);
if (comStatus != asynError) {
pPtr = strstr(reply, "=");
if(pPtr) {
sscanf(pPtr + 1, "%f", &errStatus);
@ -716,7 +713,11 @@ asynStatus MasterMACSAxis::poll(bool * moving)
} else {
errlogPrintf("MMACS: malformed reply for R18: %s, on axis %d\n", reply, axisNo_);
derCode = 0;
updateMsgTxtFromDriver("Invalid reply asking error code R18");
goto skip;
}
} else {
errlogPrintf("MMACS: axis %d failed reading extended error code R18 \n", axisNo_);
goto skip;
}
if(debug) {
@ -724,9 +725,7 @@ asynStatus MasterMACSAxis::poll(bool * moving)
errCode, derCode);
}
setIntegerParam(pC_->motorStatusProblem_, true);
if (errCode == 0) {
setIntegerParam(pC_->motorStatusProblem_, true);
errlogSevPrintf(errlogMajor,
"Fault bit in status code, but no error code on %d\n", axisNo_);
updateMsgTxtFromDriver ("Fault bit in status code without error code");

View File

@ -7,7 +7,7 @@
drvAsynMMACSPort.c. The driver will not work with a standard asyn IPPort,
only with the special one.
Mark Koennecke, March 2023
Mark Koennecke, March, August, 2023
*/
#include "SINQController.h"

View File

@ -41,6 +41,7 @@
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <asynOctetSyncIO.h>
#include <epicsEvent.h>
#include <epicsThread.h>
@ -484,9 +485,7 @@ static void runEvents(EL737priv *priv)
// errlogPrintf("EL737: Starting preset timer\n");
}
status = el737_transactCommand(priv,command,reply);
if(status == asynSuccess){
priv->counting = 1;
}
} else {
if(priv->counting) {
/* Stop */
@ -569,6 +568,7 @@ static void el737Thread(void *param)
runEvents(priv);
if(priv->counting == 1){
timeout = .2;
usleep(500);
}
} else {
/*

View File

@ -287,7 +287,7 @@ asynStatus pmacAxis::setPosition(double position) {
}
asynStatus pmacAxis::stop(double acceleration) {
asynStatus status = asynError;
asynStatus status = asynSuccess;
static const char *functionName = "pmacAxis::stopAxis";
bool moving = false;
@ -489,7 +489,6 @@ asynStatus pmacAxis::getAxisStatus(bool *moving) {
*moving = false;
setIntegerParam(pC_->motorStatusMoving_, false);
setIntegerParam(pC_->motorStatusDone_, true);
setIntegerParam(pC_->motorStatusProblem_, true);
errlogPrintf("Axis %d did not start within 10 seconds!! BROKEN\n", axisNo_);
updateMsgTxtFromDriver("Axis did not start within 10 seconds");
starting = 0;
@ -614,7 +613,6 @@ asynStatus pmacHRPTAxis::getAxisStatus(bool *moving) {
*moving = false;
setIntegerParam(pC_->motorStatusMoving_, false);
setIntegerParam(pC_->motorStatusDone_, true);
setIntegerParam(pC_->motorStatusProblem_, true);
}
return result;
}
@ -955,7 +953,8 @@ asynStatus pmacV3Axis::getAxisStatus(bool *moving) {
pmacV3Controller *p3C_ = (pmacV3Controller *)pC_;
IsEnable = axStat != -3;
asynStatus st = setIntegerParam(p3C_->axisEnabled_, IsEnable);
setIntegerParam(p3C_->axisEnabled_, IsEnable);
asynStatus st = setIntegerParam(p3C_->enableAxis_, IsEnable);
cmdStatus = cmdStatus > st ? cmdStatus : st;
int direction = 0;
@ -993,7 +992,7 @@ asynStatus pmacV3Axis::getAxisStatus(bool *moving) {
// /*
// code to test against too long status 5 or 6
// */
int EstimatedTimeOfArrival = 60;
int EstimatedTimeOfArrival = 120;
if (axStat == 5 || axStat == 6) {
if (status6Time == 0) {
status6Time = time(NULL);
@ -1472,7 +1471,6 @@ asynStatus AmorDetectorAxis::poll(bool *moving)
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"AmorDetectorAxis::poll: %s", errorMessage);
updateMsgTxtFromDriver(errorMessage);
setIntegerParam(pC_->motorStatusProblem_, true);
status = asynError;
}
}

11
testel737.cmd Executable file
View File

@ -0,0 +1,11 @@
#!/usr/local/bin/iocsh
require sinq,koennecke
epicsEnvSet("TOP","/afs/psi.ch/project/sinqdev/sinqepicsapp")
#--------- load EL737 counter box
drvAsynIPPortConfigure("cter1","localhost:62000",0,0,0)
dbLoadRecords("$(TOP)/db/asynRecord.db","P=KM36:,R=cter1,PORT=cter1,ADDR=0,OMAX=80,IMAX=80")
dbLoadRecords("${TOP}/db/el737Record.db","P=KM36:counter,PORT=cter1,DESC=SANSCounter")

View File

@ -59,7 +59,7 @@ def scan_substitution_file(filename):
# import pdb; pdb.set_trace()
with open(filename, 'r') as fin:
rawline = fin.readline()
import pdb; pdb.set_trace()
# import pdb; pdb.set_trace()
while rawline:
line = rawline.replace(' ','')
line = line.strip('{}')