diff --git a/dsmApp/src/MD90Driver.cpp b/dsmApp/src/MD90Driver.cpp index a0e5976..b043323 100644 --- a/dsmApp/src/MD90Driver.cpp +++ b/dsmApp/src/MD90Driver.cpp @@ -140,29 +140,26 @@ void MD90Axis::report(FILE *fp, int level) asynMotorAxis::report(fp, level); } +/** Acceleration currently unsupported with MD-90 controller + * \param[in] acceleration The accelerations to ramp up to max velocity + * \param[in] velocity Motor velocity in steps / sec + */ asynStatus MD90Axis::sendAccelAndVelocity(double acceleration, double velocity) { asynStatus status; - int ival; + int freq; // static const char *functionName = "MD90::sendAccelAndVelocity"; // Send the velocity - ival = NINT(fabs(115200./velocity)); - if (ival < 2) ival=2; - if (ival > 255) ival = 255; - sprintf(pC_->outString_, "#%02dV=%d", axisNo_, ival); + // Velocity provided in steps/sec + // Our unit step size of the encoder is 10 nm, but the motor moves in steps approx. 5 micrometers. + // Motor controller accepts step frequency in Hz. + freq = NINT(fabs(velocity / 500.)); + if (freq < 5) freq=5; + if (freq > 125) freq = 125; + sprintf(pC_->outString_, "SSF %d", freq); status = pC_->writeReadController(); - // Send the acceleration - // acceleration is in steps/sec/sec - // MD-90 is programmed with Ramp Index (R) where: - // dval (steps/sec/sec) = 720,000/(256-R) */ - // or R=256-(720,000/dval) */ - ival = NINT(256-(720000./acceleration)); - if (ival < 1) ival=1; - if (ival > 255) ival=255; - sprintf(pC_->outString_, "#%02dR=%d", axisNo_, ival); - status = pC_->writeReadController(); return status; } @@ -208,13 +205,15 @@ asynStatus MD90Axis::moveVelocity(double minVelocity, double maxVelocity, double status = sendAccelAndVelocity(acceleration, maxVelocity); - /* MD-90 does not have jog command. Move 1 million steps */ + /* MD-90 does not have jog command. Move max 6000 steps */ + sprintf(pC_->outString_, "SNS 6000"); + status = pC_->writeReadController(); if (maxVelocity > 0.) { /* This is a positive move in MD90 coordinates */ - sprintf(pC_->outString_, "#%02dI+1000000", axisNo_); + sprintf(pC_->outString_, "ESF"); } else { - /* This is a negative move in MD90 coordinates */ - sprintf(pC_->outString_, "#%02dI-1000000", axisNo_); + /* This is a negative move in MD90 coordinates */ + sprintf(pC_->outString_, "ESB"); } status = pC_->writeReadController(); return status; @@ -230,22 +229,46 @@ asynStatus MD90Axis::stop(double acceleration ) return status; } -asynStatus MD90Axis::setPosition(double position) -{ - asynStatus status; - //static const char *functionName = "MD90Axis::setPosition"; - - sprintf(pC_->outString_, "#%02dP=%+d", axisNo_, NINT(position)); - status = pC_->writeReadController(); - return status; -} - +/** The ACS driver used this to turn on/off the motor winding current, so + * we'll use this for enabling/disabling the persistent move state. + */ asynStatus MD90Axis::setClosedLoop(bool closedLoop) { asynStatus status; //static const char *functionName = "MD90Axis::setClosedLoop"; - sprintf(pC_->outString_, "#%02dW=%d", axisNo_, closedLoop ? 1:0); + if (closedLoop == 1) { + sprintf(pC_->outString_, "EPM"); + } else { + sprintf(pC_->outString_, "DPM"); + } + status = pC_->writeReadController(); + return status; +} + +/** Set the I Gain of the motor control loop. The motor is an I- controller + * and has no P or D terms. + * \param[in] iGain The current I gain in the control loop + */ +asynStatus MD90Axis::setIGain(double iGain) +{ + asynStatus status; + //static const char *functionName = "MD90Axis::setIGain"; + + iGain = iGain * 100; + if (iGain < 1) iGain = 1.0; + if (iGain > 100) iGain = 100.0; + sprintf(pC_->outString_, "SGN %d", NINT(iGain)); + status = pC_->writeReadController(); + return status; +} + +asynStatus MD90Axis::doMoveToHome() +{ + asynStatus status; + //static const char *functionName = "MD90Axis::doMoveToHome"; + + sprintf(pC_->outString_, "CLM 0"); status = pC_->writeReadController(); return status; } @@ -255,7 +278,8 @@ asynStatus MD90Axis::setClosedLoop(bool closedLoop) * and the drive power-on status. * It calls setIntegerParam() and setDoubleParam() for each item that it polls, * and then calls callParamCallbacks() at the end. - * \param[out] moving A flag that is set indicating that the axis is moving (true) or done (false). */ + * \param[out] moving A flag that is set indicating that the axis is moving (true) or done (false). + */ asynStatus MD90Axis::poll(bool *moving) { int replyStatus; @@ -263,7 +287,7 @@ asynStatus MD90Axis::poll(bool *moving) int replyValue; int done; int driveOn; - int home; + int homed; double position; asynStatus comStatus; @@ -332,8 +356,8 @@ asynStatus MD90Axis::poll(bool *moving) if (comStatus) goto skip; // The response string is of the form "0: Home status: 1" sscanf (pC_->inString_, "%d: %[^:]: %d", &replyStatus, replyString, &replyValue); - home = (replyValue == '1') ? 1:0; - setIntegerParam(pC_->motorStatusAtHome_, home); + homed = (replyValue == '1') ? 1:0; + setIntegerParam(pC_->motorStatusHomed_, homed); // Read the drive power on status sprintf(pC_->outString_, "GPS"); diff --git a/dsmApp/src/MD90Driver.h b/dsmApp/src/MD90Driver.h index f98f3c2..12795ec 100644 --- a/dsmApp/src/MD90Driver.h +++ b/dsmApp/src/MD90Driver.h @@ -26,8 +26,9 @@ public: asynStatus home(double min_velocity, double max_velocity, double acceleration, int forwards); asynStatus stop(double acceleration); asynStatus poll(bool *moving); - asynStatus setPosition(double position); asynStatus setClosedLoop(bool closedLoop); + asynStatus setIGain(double iGain); + asynStatus doMoveToHome(); private: MD90Controller *pC_; /**< Pointer to the asynMotorController to which this axis belongs. diff --git a/iocs/dsmIOC/iocBoot/iocDsm/motor.substitutions.md90 b/iocs/dsmIOC/iocBoot/iocDsm/motor.substitutions.md90 index 40e4e4a..6c21e47 100644 --- a/iocs/dsmIOC/iocBoot/iocDsm/motor.substitutions.md90 +++ b/iocs/dsmIOC/iocBoot/iocDsm/motor.substitutions.md90 @@ -14,9 +14,9 @@ pattern # DESC Description # EGU Engineering units # DIR Direction -# VELO Velocity (EGU / s) +# VELO Velocity (EGU / s) (note: jog velocity set separately by JVEL) # VBAS Minimum velocity (EGU / s) -# VMAX Maximum velocity (EGU / s) (not getting set here with basic_asyn_motor.db) +# VMAX Maximum velocity (EGU / s) (note: not getting set here with basic_asyn_motor.db) # ACCL Acceleration (time in seconds until VELO) # BDST Backlash distance # MRES Motor step size (EGU)