diff --git a/iocBoot/iocsinqEPICS/motor.substitutions.phytron b/iocBoot/iocsinqEPICS/motor.substitutions.phytron index 14c774e..a94780b 100644 --- a/iocBoot/iocsinqEPICS/motor.substitutions.phytron +++ b/iocBoot/iocsinqEPICS/motor.substitutions.phytron @@ -5,3 +5,11 @@ pattern {KM36:phytron:, 1, "m$(N)", "asynMotor", phy, 1, "m1", mm, Pos, 2.0, 0.1, .2, 0, 1, .2, .001, 3, 100, -100, "1"} {KM36:phytron:, 2, "m$(N)", "asynMotor", phy, 2, "m2", mm, Pos, 2.0, 0.1, .2, 0, 1, .2, .001, 3, 100, -100, "10"} } + +file "$(SINQ)/Db/motorMessage.db" +{ +pattern +{P,N, M,PORT} +{KM36:phytron:, 1, "m$(N)",phy} +{KM36:phytron:, 2, "m$(N)",phy} +} \ No newline at end of file diff --git a/iocBoot/iocsinqEPICS/phytrontest.cmd b/iocBoot/iocsinqEPICS/phytrontest.cmd index 138ce5a..db9ebb3 100755 --- a/iocBoot/iocsinqEPICS/phytrontest.cmd +++ b/iocBoot/iocsinqEPICS/phytrontest.cmd @@ -30,7 +30,7 @@ sinqEPICS_registerRecordDeviceDriver pdbbase #drvAsynIPPortConfigure("serial1", "narziss-ts:3002",0,0,0) #drvAsynIPPortConfigure("serial1", "localhost:5050",0,0,0) drvAsynIPPortConfigure("serial1", "localhost:8080",0,0,0) -PhytronCreateController("phy","serial1",1,1); +PhytronCreateController("phy","serial1","0",1,1); ### Motors diff --git a/sinqEPICSApp/src/PhytronDriver.cpp b/sinqEPICSApp/src/PhytronDriver.cpp index 598b3bf..2b2d5f1 100644 --- a/sinqEPICSApp/src/PhytronDriver.cpp +++ b/sinqEPICSApp/src/PhytronDriver.cpp @@ -23,6 +23,12 @@ Though this driver has been written in 2016, the MCC-2 version used is probably Mark Koennecke September 2016 +Updated to use the new MsgTxt field through SINQAxis +Added a selector to support multiple phytrons on a connection + +Mark Koennecke +January 2019 + */ @@ -49,19 +55,17 @@ September 2016 * \param[in] PhytronPortName The name of the drvAsynSerialPort that was created previously to connect to the Phytron controller * \param[in] numAxes The number of axes that this controller supports */ -PhytronController::PhytronController(const char *portName, const char *PhytronPortName, int encX, int encY) - : asynMotorController(portName, 3, 0, - 0, // No additional interfaces beyond those in base class - 0, // No additional callback interfaces beyond those in base class - ASYN_CANBLOCK | ASYN_MULTIDEVICE, - 1, // autoconnect - 0, 0) // Default priority and stack size +PhytronController::PhytronController(const char *portName, const char *PhytronPortName, const char *sel , + int encX, int encY) + : SINQController(portName, PhytronPortName,2) { asynStatus status; PhytronAxis *pAxis; static const char *functionName = "PhytronController::PhytronController"; char etx[2]; + selector = strdup(sel); + /* Connect to Phytron controller */ status = pasynOctetSyncIO->connect(PhytronPortName, 0, &pasynUserController_, NULL); if (status) { @@ -87,10 +91,11 @@ PhytronController::PhytronController(const char *portName, const char *PhytronPo * \param[in] PhytronPortName The name of the drvAsynIPPPort that was created previously to connect to the Phytron controller * \param[in] numAxes The number of axes that this controller supports */ -extern "C" int PhytronCreateController(const char *portName, const char *PhytronPortName, int encX, int encY) +extern "C" int PhytronCreateController(const char *portName, const char *PhytronPortName, const char *selector, + int encX, int encY) { PhytronController *pPhytronController - = new PhytronController(portName, PhytronPortName, encX, encY); + = new PhytronController(portName, PhytronPortName,selector, encX, encY); pPhytronController = NULL; return(asynSuccess); } @@ -176,7 +181,7 @@ asynStatus PhytronController::transactController(char command[COMLEN], char repl I may need to replace the ETX. But I am not sure if asyn did not remove it for me. */ - strncat(reply,pPtr,sizeof(reply)); + strncat(reply,pPtr,COMLEN-1); return status; @@ -191,7 +196,7 @@ asynStatus PhytronController::transactController(char command[COMLEN], char repl * Initializes register numbers, etc. */ PhytronAxis::PhytronAxis(PhytronController *pC, int axisNo, int enc) - : asynMotorAxis(pC, axisNo), + : SINQAxis(pC, axisNo), pC_(pC) { encoder = enc; @@ -229,15 +234,17 @@ asynStatus PhytronAxis::move(double position, int relative, double minVelocity, //static const char *functionName = "PhytronAxis::move"; char command[COMLEN], reply[COMLEN]; + updateMsgTxtFromDriver(""); if (relative) { position += this->position; } homing = 0; - sprintf(command, "0%cA%f", phytronChar,position/1000.); + sprintf(command, "%s%cA%f", pC_->selector,phytronChar,position/1000.); status = pC_->transactController(command,reply); if(strstr(reply,"NACK") != NULL){ errlogSevPrintf(errlogMajor, "Drive command not acknowledged on %d", axisNo_); + updateMsgTxtFromDriver("Drive command not acknowledged"); setIntegerParam(pC_->motorStatusProblem_, true); return asynError; } @@ -251,13 +258,16 @@ asynStatus PhytronAxis::home(double minVelocity, double maxVelocity, double acce //static const char *functionName = "PhytronAxis::home"; char command[COMLEN], reply[COMLEN]; - sprintf(command, "0%cO-",phytronChar); + updateMsgTxtFromDriver(""); + + sprintf(command, "%s%cO-",pC_->selector,phytronChar); homing = 1; next_poll= -1; status = pC_->transactController(command,reply); if(strstr(reply,"NACK") != NULL){ errlogSevPrintf(errlogMajor, "Home command not acknowledged on %d", axisNo_); setIntegerParam(pC_->motorStatusProblem_, true); + updateMsgTxtFromDriver("Home command not acknowledged"); return asynError; } return status; @@ -274,6 +284,7 @@ asynStatus PhytronAxis::moveVelocity(double minVelocity, double maxVelocity, dou // "%s: minVelocity=%f, maxVelocity=%f, acceleration=%f\n", // functionName, minVelocity, maxVelocity, acceleration); + updateMsgTxtFromDriver(""); if (maxVelocity > 0.) { @@ -294,9 +305,10 @@ asynStatus PhytronAxis::stop(double acceleration ) //static const char *functionName = "PhytronAxis::stop"; char command[COMLEN], reply[COMLEN]; - sprintf(command, "0%cSN", phytronChar); + sprintf(command, "%s%cSN", pC_->selector,phytronChar); status = pC_->transactController(command,reply); errlogPrintf("Sent STOP on Axis %d\n", axisNo_); + updateMsgTxtFromDriver("Axis interrupted"); return status; } @@ -307,9 +319,9 @@ asynStatus PhytronAxis::setPosition(double position) //static const char *functionName = "PhytronAxis::setPosition"; char command[COMLEN], reply[COMLEN]; - sprintf(command, "0%cP22S%f", phytronChar, position/1000.); + sprintf(command, "%s%cP22S%f", pC_->selector,phytronChar, position/1000.); status = pC_->transactController(command,reply); - sprintf(command, "0%cP20S%f", phytronChar, position/1000.); + sprintf(command, "%s%cP20S%f", pC_->selector,phytronChar, position/1000.); status = pC_->transactController(command,reply); next_poll = -1; @@ -349,9 +361,9 @@ asynStatus PhytronAxis::poll(bool *moving) // Read the current motor position if(encoder) { - sprintf(command,"0%cP22R",phytronChar); + sprintf(command,"%s%cP22R",pC_->selector,phytronChar); } else { - sprintf(command,"0%cP20R",phytronChar); + sprintf(command,"%s%cP20R",pC_->selector,phytronChar); } comStatus = pC_->transactController(command,reply); @@ -360,7 +372,8 @@ asynStatus PhytronAxis::poll(bool *moving) if(strstr(reply,"NACK") != NULL){ setIntegerParam(pC_->motorStatusProblem_, true); errlogSevPrintf(errlogMajor, "Bad reply for position on %d", axisNo_); - goto skip; + updateMsgTxtFromDriver("Bad reply reading position"); + goto skip; } /* read over the ACK @@ -372,7 +385,7 @@ asynStatus PhytronAxis::poll(bool *moving) // Read the moving status of this motor - sprintf(command,"0%c=H",phytronChar); + sprintf(command,"%s%c=H",pC_->selector,phytronChar); comStatus = pC_->transactController(command,reply); if(comStatus) goto skip; /* errlogPrintf("Axis %d, status reply %s, position %lf\n", axisNo_, reply, position); */ @@ -396,11 +409,12 @@ asynStatus PhytronAxis::poll(bool *moving) /* check limits and errors, upper */ - sprintf(command,"0%c=I+",phytronChar); + sprintf(command,"%s%c=I+",pC_->selector,phytronChar); comStatus = pC_->transactController(command,reply); if(comStatus) goto skip; if(strstr(reply,"ACKE") != NULL){ setIntegerParam(pC_->motorStatusHighLimit_, true); + updateMsgTxtFromDriver("High Limit Hit"); } else { setIntegerParam(pC_->motorStatusHighLimit_, false); } @@ -408,11 +422,12 @@ asynStatus PhytronAxis::poll(bool *moving) /* lower limit */ - sprintf(command,"0%c=I-",phytronChar); + sprintf(command,"%s%c=I-",pC_->selector,phytronChar); comStatus = pC_->transactController(command,reply); if(comStatus) goto skip; if(strstr(reply,"ACKE") != NULL){ setIntegerParam(pC_->motorStatusLowLimit_, true); + updateMsgTxtFromDriver("Low Limit Hit"); } else { setIntegerParam(pC_->motorStatusLowLimit_, false); } @@ -420,12 +435,13 @@ asynStatus PhytronAxis::poll(bool *moving) /* error */ - sprintf(command,"0%c=E",phytronChar); + sprintf(command,"%s%c=E",pC_->selector,phytronChar); comStatus = pC_->transactController(command,reply); if(comStatus) goto skip; if(strstr(reply,"ACKE") != NULL){ setIntegerParam(pC_->motorStatusProblem_, true); errlogSevPrintf(errlogMajor, "Electronics on %d", axisNo_); + updateMsgTxtFromDriver("Electronics error"); } else { setIntegerParam(pC_->motorStatusProblem_, false); } @@ -442,16 +458,18 @@ asynStatus PhytronAxis::poll(bool *moving) /** Code for iocsh registration */ static const iocshArg PhytronCreateControllerArg0 = {"Port name", iocshArgString}; static const iocshArg PhytronCreateControllerArg1 = {"Phytron port name", iocshArgString}; -static const iocshArg PhytronCreateControllerArg2 = {"EnoderX", iocshArgInt}; -static const iocshArg PhytronCreateControllerArg3 = {"EnoderY", iocshArgInt}; +static const iocshArg PhytronCreateControllerArg2 = {"Phytron Selector", iocshArgString}; +static const iocshArg PhytronCreateControllerArg3 = {"EnoderX", iocshArgInt}; +static const iocshArg PhytronCreateControllerArg4 = {"EnoderY", iocshArgInt}; static const iocshArg * const PhytronCreateControllerArgs[] = {&PhytronCreateControllerArg0, &PhytronCreateControllerArg1, &PhytronCreateControllerArg2, - &PhytronCreateControllerArg3}; -static const iocshFuncDef PhytronCreateControllerDef = {"PhytronCreateController", 4, PhytronCreateControllerArgs}; + &PhytronCreateControllerArg3, + &PhytronCreateControllerArg4}; +static const iocshFuncDef PhytronCreateControllerDef = {"PhytronCreateController", 5, PhytronCreateControllerArgs}; static void PhytronCreateContollerCallFunc(const iocshArgBuf *args) { - PhytronCreateController(args[0].sval, args[1].sval, args[2].ival,args[3].ival); + PhytronCreateController(args[0].sval, args[1].sval, args[2].sval, args[3].ival,args[4].ival); } static void PhytronRegister(void) diff --git a/sinqEPICSApp/src/PhytronDriver.h b/sinqEPICSApp/src/PhytronDriver.h index 4538f01..7934694 100644 --- a/sinqEPICSApp/src/PhytronDriver.h +++ b/sinqEPICSApp/src/PhytronDriver.h @@ -5,14 +5,19 @@ USAGE... Motor driver support for the Phytron MCC-2 motor controller. Mark Koennecke September 2016 + +Updated to go through SINQAxis for -MsgTxt support +Added a selector to support multiple phytrons on a connection + +Mark Koennecke, January 2019 */ -#include "asynMotorController.h" -#include "asynMotorAxis.h" +#include "SINQController.h" +#include "SINQAxis.h" #define COMLEN 80 -class PhytronAxis : public asynMotorAxis +class PhytronAxis : public SINQAxis { public: /* These are the methods we override from the base class */ @@ -38,9 +43,10 @@ private: friend class PhytronController; }; -class PhytronController : public asynMotorController { +class PhytronController : public SINQController { public: - PhytronController(const char *portName, const char *PhytronPortName, int encX, int encY); + PhytronController(const char *portName, const char *PhytronPortName, const char *selector, + int encX, int encY); void report(FILE *fp, int level); PhytronAxis* getAxis(asynUser *pasynUser); @@ -52,5 +58,6 @@ friend class PhytronAxis; asynStatus transactController(char command[COMLEN], char reply[COMLEN]); + const char *selector; };