|
|
|
@ -14,6 +14,7 @@ GPIB or USB. The controller is fairly simple. It can control quite a number of m
|
|
|
|
|
#include <math.h>
|
|
|
|
|
#include <ctype.h>
|
|
|
|
|
#include <time.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
|
|
#include <iocsh.h>
|
|
|
|
|
#include <epicsThread.h>
|
|
|
|
@ -192,6 +193,44 @@ asynStatus EuroMoveController::transactController(int axisNo,char command[COMLEN
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
asynStatus EuroMoveController::writeFloat64(asynUser *pasynUser, epicsFloat64 value)
|
|
|
|
|
{
|
|
|
|
|
int function = pasynUser->reason;
|
|
|
|
|
asynStatus status = asynError;
|
|
|
|
|
EuroMoveAxis *pAxis = NULL;
|
|
|
|
|
|
|
|
|
|
static const char *functionName = "EuroMoveController::writeFloat64";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pAxis = (EuroMoveAxis *)this->getAxis(pasynUser);
|
|
|
|
|
if (!pAxis) {
|
|
|
|
|
return asynError;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Set the parameter and readback in the parameter library. */
|
|
|
|
|
status = pAxis->setDoubleParam(function, value);
|
|
|
|
|
|
|
|
|
|
errlogPrintf("%s, reason %d, value %f\n", functionName, function, value);
|
|
|
|
|
|
|
|
|
|
// TODO: somethign is really shitty here: lowLimit and highLimit cannot be on the command
|
|
|
|
|
if (function == motorResolution_) {
|
|
|
|
|
if(value > .0){
|
|
|
|
|
pAxis->resolution = (int)(1./value);
|
|
|
|
|
} else {
|
|
|
|
|
pAxis->resolution = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Call base class method
|
|
|
|
|
//This will handle callCallbacks even if the function was handled here.
|
|
|
|
|
status = asynMotorController::writeFloat64(pasynUser, value);
|
|
|
|
|
|
|
|
|
|
return status;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// These are the EuroMoveAxis methods
|
|
|
|
|
|
|
|
|
|
/** Creates a new EuroMoveAxis object.
|
|
|
|
@ -236,7 +275,7 @@ asynStatus EuroMoveAxis::move(double position, int relative, double minVelocity,
|
|
|
|
|
if (relative) {
|
|
|
|
|
position += this->position;
|
|
|
|
|
}
|
|
|
|
|
homing = 0;
|
|
|
|
|
homingStatus = HomeIdle;
|
|
|
|
|
sprintf(command,"G%d=%d", motNo, (int)position);
|
|
|
|
|
status = pC_->transactController(motNo,command,reply);
|
|
|
|
|
next_poll = -1;
|
|
|
|
@ -247,10 +286,29 @@ asynStatus EuroMoveAxis::home(double minVelocity, double maxVelocity, double acc
|
|
|
|
|
{
|
|
|
|
|
asynStatus status = asynSuccess;
|
|
|
|
|
//static const char *functionName = "EuroMoveAxis::home";
|
|
|
|
|
char command[COMLEN], reply[COMLEN];
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
I do not know if this controller actually can do homing
|
|
|
|
|
The EuroMove controller does not have a built in homing mechanism. We simulate it by:
|
|
|
|
|
|
|
|
|
|
1). Running the motor in the appropriate end swicth at high speed
|
|
|
|
|
2) Stepping back three units
|
|
|
|
|
3) Run the motor again in the end switch at low speed for better accuracy
|
|
|
|
|
4) Set the limit position with the <I> command
|
|
|
|
|
|
|
|
|
|
The state of this operation is maintained in the homingStatus variable
|
|
|
|
|
*/
|
|
|
|
|
homingDirection = forwards;
|
|
|
|
|
homingStatus = HomeFastRun;
|
|
|
|
|
if(homingDirection){
|
|
|
|
|
sprintf(command,"H%d=03", motNo);
|
|
|
|
|
} else {
|
|
|
|
|
sprintf(command,"H%d=07", motNo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
status = pC_->transactController(motNo,command,reply);
|
|
|
|
|
next_poll = -1;
|
|
|
|
|
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -339,6 +397,7 @@ asynStatus EuroMoveAxis::poll(bool *moving)
|
|
|
|
|
asynStatus comStatus = asynSuccess;
|
|
|
|
|
char command[COMLEN], reply[COMLEN];
|
|
|
|
|
unsigned int axStatus;
|
|
|
|
|
double backStep, backPos, limit;
|
|
|
|
|
|
|
|
|
|
// protect against excessive polling
|
|
|
|
|
if(time(NULL) < next_poll){
|
|
|
|
@ -371,47 +430,135 @@ asynStatus EuroMoveAxis::poll(bool *moving)
|
|
|
|
|
/* errlogPrintf("Axis %d, status reply %s, position %d\n", axisNo_, reply, position); */
|
|
|
|
|
sscanf(reply, "%x", &axStatus);
|
|
|
|
|
|
|
|
|
|
if((axStatus & 128) > 0) { // test bit 8
|
|
|
|
|
*moving = true;
|
|
|
|
|
if(homingStatus == HomeIdle){
|
|
|
|
|
if((axStatus & 128) > 0) { // test bit 8
|
|
|
|
|
*moving = true;
|
|
|
|
|
next_poll = -1;
|
|
|
|
|
setIntegerParam(pC_->motorStatusDone_, false);
|
|
|
|
|
} else {
|
|
|
|
|
*moving = false;
|
|
|
|
|
next_poll = time(NULL)+IDLEPOLL;
|
|
|
|
|
setIntegerParam(pC_->motorStatusDone_, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Testing limit switches */
|
|
|
|
|
if((axStatus & 2) > 0){ // bit 2
|
|
|
|
|
setIntegerParam(pC_->motorStatusHighLimit_, true);
|
|
|
|
|
errlogPrintf("HighLimit detected on %d\n", motNo);
|
|
|
|
|
sendStop();
|
|
|
|
|
} else {
|
|
|
|
|
setIntegerParam(pC_->motorStatusHighLimit_, false);
|
|
|
|
|
}
|
|
|
|
|
if((axStatus & 1) > 0){ // bit 1
|
|
|
|
|
setIntegerParam(pC_->motorStatusLowLimit_, true);
|
|
|
|
|
errlogPrintf("LowLimit detected on %d\n", motNo);
|
|
|
|
|
sendStop();
|
|
|
|
|
} else {
|
|
|
|
|
setIntegerParam(pC_->motorStatusLowLimit_, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* there could be errors reported in the motor status */
|
|
|
|
|
if((axStatus & 8) > 0){ // bit 4
|
|
|
|
|
setIntegerParam(pC_->motorStatusProblem_, true);
|
|
|
|
|
updateMsgTxtFromDriver("Internal timeout detected");
|
|
|
|
|
errlogPrintf("Internal timeout detected on %d\n", motNo);
|
|
|
|
|
comStatus = asynError;
|
|
|
|
|
}
|
|
|
|
|
if((axStatus & 4) > 0){ // bit 3
|
|
|
|
|
setIntegerParam(pC_->motorStatusProblem_, true);
|
|
|
|
|
updateMsgTxtFromDriver("Encoding anomaly");
|
|
|
|
|
errlogPrintf("Encoding anomaly on %d\n", motNo);
|
|
|
|
|
comStatus = asynError;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
next_poll = -1;
|
|
|
|
|
setIntegerParam(pC_->motorStatusDone_, false);
|
|
|
|
|
} else {
|
|
|
|
|
*moving = false;
|
|
|
|
|
next_poll = time(NULL)+IDLEPOLL;
|
|
|
|
|
setIntegerParam(pC_->motorStatusDone_, true);
|
|
|
|
|
*moving = true;
|
|
|
|
|
switch(homingStatus){
|
|
|
|
|
case HomeIdle:
|
|
|
|
|
// handled above: this is here to silence the compiler
|
|
|
|
|
break;
|
|
|
|
|
case HomeFastRun:
|
|
|
|
|
// errlogPrintf("HomeFastRun\n");
|
|
|
|
|
if(axStatus & 2 || axStatus & 1){
|
|
|
|
|
sendStop();
|
|
|
|
|
homingStatus = HomeFastStop;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case HomeFastStop:
|
|
|
|
|
// errlogPrintf("HomeFastStop\n");
|
|
|
|
|
if((axStatus & 128) == 0){
|
|
|
|
|
backStep = 3 * resolution;
|
|
|
|
|
if(homingDirection){
|
|
|
|
|
backPos = position - backStep;
|
|
|
|
|
} else {
|
|
|
|
|
backPos = position + backStep;
|
|
|
|
|
}
|
|
|
|
|
sprintf(command,"G%d=%d", motNo, (int)backPos);
|
|
|
|
|
comStatus = pC_->transactController(motNo,command,reply);
|
|
|
|
|
if(comStatus == asynError){
|
|
|
|
|
setIntegerParam(pC_->motorStatusProblem_, true);
|
|
|
|
|
updateMsgTxtFromDriver("Homing problem when back stepping");
|
|
|
|
|
errlogPrintf("Homing problem when back stepping: %s not accepted\n", command);
|
|
|
|
|
*moving = false;
|
|
|
|
|
setIntegerParam(pC_->motorStatusAtHome_, true);
|
|
|
|
|
homingStatus = HomeIdle;
|
|
|
|
|
setIntegerParam(pC_->motorStatusDone_, true);
|
|
|
|
|
goto skip;
|
|
|
|
|
}
|
|
|
|
|
usleep(200);
|
|
|
|
|
homingStatus = HomeBackStep;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case HomeBackStep:
|
|
|
|
|
//errlogPrintf("HomeBackStep\n");
|
|
|
|
|
if((axStatus & 128) == 0){
|
|
|
|
|
homingStatus = HomeSlowRun;
|
|
|
|
|
if(homingDirection){
|
|
|
|
|
sprintf(command,"H%d=01", motNo);
|
|
|
|
|
} else {
|
|
|
|
|
sprintf(command,"H%d=05", motNo);
|
|
|
|
|
}
|
|
|
|
|
comStatus = pC_->transactController(motNo,command,reply);
|
|
|
|
|
if(comStatus == asynError){
|
|
|
|
|
setIntegerParam(pC_->motorStatusProblem_, true);
|
|
|
|
|
updateMsgTxtFromDriver("Homing problem slow running");
|
|
|
|
|
errlogPrintf("Homing problem when slow running: %s not accepted\n", command);
|
|
|
|
|
*moving = false;
|
|
|
|
|
setIntegerParam(pC_->motorStatusAtHome_, true);
|
|
|
|
|
homingStatus = HomeIdle;
|
|
|
|
|
setIntegerParam(pC_->motorStatusDone_, true);
|
|
|
|
|
goto skip;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case HomeSlowRun:
|
|
|
|
|
//errlogPrintf("HomeSlowRun\n");
|
|
|
|
|
if(axStatus & 2 || axStatus & 1){
|
|
|
|
|
sendStop();
|
|
|
|
|
homingStatus = HomeSlowStop;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case HomeSlowStop:
|
|
|
|
|
//errlogPrintf("HomeSlowStop\n");
|
|
|
|
|
if((axStatus & 128) == 0) {
|
|
|
|
|
if(homingDirection) {
|
|
|
|
|
pC_->getDoubleParam(axisNo_,pC_->motorHighLimit_,&limit);
|
|
|
|
|
} else {
|
|
|
|
|
pC_->getDoubleParam(axisNo_,pC_->motorLowLimit_,&limit);
|
|
|
|
|
}
|
|
|
|
|
setPosition(limit);
|
|
|
|
|
*moving = false;
|
|
|
|
|
setIntegerParam(pC_->motorStatusDone_, true);
|
|
|
|
|
next_poll = time(NULL)+IDLEPOLL;
|
|
|
|
|
setIntegerParam(pC_->motorStatusDone_, true);
|
|
|
|
|
setIntegerParam(pC_->motorStatusAtHome_, true);
|
|
|
|
|
homingStatus = HomeIdle;
|
|
|
|
|
setDoubleParam(pC_->motorPosition_,(double)limit);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Testing limit switches */
|
|
|
|
|
if((axStatus & 2) > 0){ // bit 2
|
|
|
|
|
setIntegerParam(pC_->motorStatusHighLimit_, true);
|
|
|
|
|
errlogPrintf("HighLimit detected on %d\n", motNo);
|
|
|
|
|
sendStop();
|
|
|
|
|
} else {
|
|
|
|
|
setIntegerParam(pC_->motorStatusHighLimit_, false);
|
|
|
|
|
}
|
|
|
|
|
if((axStatus & 1) > 0){ // bit 1
|
|
|
|
|
setIntegerParam(pC_->motorStatusLowLimit_, true);
|
|
|
|
|
errlogPrintf("LowLimit detected on %d\n", motNo);
|
|
|
|
|
sendStop();
|
|
|
|
|
} else {
|
|
|
|
|
setIntegerParam(pC_->motorStatusLowLimit_, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* there could be errors reported in the motor status */
|
|
|
|
|
if((axStatus & 8) > 0){ // bit 4
|
|
|
|
|
setIntegerParam(pC_->motorStatusProblem_, true);
|
|
|
|
|
updateMsgTxtFromDriver("Internal timeout detected");
|
|
|
|
|
errlogPrintf("Internal timeout detected on %d\n", motNo);
|
|
|
|
|
comStatus = asynError;
|
|
|
|
|
}
|
|
|
|
|
if((axStatus & 4) > 0){ // bit 3
|
|
|
|
|
setIntegerParam(pC_->motorStatusProblem_, true);
|
|
|
|
|
updateMsgTxtFromDriver("Encoding anomaly");
|
|
|
|
|
errlogPrintf("Encoding anomaly on %d\n", motNo);
|
|
|
|
|
comStatus = asynError;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
skip:
|
|
|
|
|
callParamCallbacks();
|
|
|
|
|
return comStatus;
|
|
|
|
|