Files
motorBase/motorApp/PIGCS2Src/PIasynAxis.cpp
T

326 lines
10 KiB
C++

/*
FILENAME... PIasynController.cpp
USAGE...
*************************************************************************
* Copyright (c) 2011-2013 Physik Instrumente (PI) GmbH & Co. KG
* This file is distributed subject to the EPICS Open License Agreement
* found in the file LICENSE that is included with this distribution.
*************************************************************************
Original Author: Steffen Rau
Based on drvMotorSim.c, Mark Rivers, December 13, 2009
*/
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <epicsTime.h>
#include <epicsThread.h>
#include <epicsString.h>
#include <epicsMutex.h>
#include <ellLib.h>
#include <iocsh.h>
#include <motor_interface.h>
#include "PIasynAxis.h"
#include "PIasynController.h"
#include "PIGCSController.h"
#include "PIInterface.h"
#include <epicsExport.h>
//#undef asynPrint
//#define asynPrint(user,reason,format...) 0
static const char *driverName = "PIasynAxis";
PIasynAxis::PIasynAxis(PIasynController *pController, PIGCSController* pGCSController, int axis, const char* szName )
: asynMotorAxis((asynMotorController*)pController, axis)
, pController_(pController)
, m_szAxisName(NULL)
, m_isHoming(0)
, m_homed(0)
, m_acceleration(0.0)
, m_maxAcceleration(-1.0)
, m_lastDirection(0)
, m_CPUnumerator(1000)
, m_CPUdenominator(1)
, m_pasynUser(NULL)
, m_bHasLimitSwitches(false)
, m_bHasReference(false)
, m_bProblem(false)
, m_bServoControl(false)
, m_bMoving(false)
, m_pGCSController(pGCSController)
{
if (szName != NULL)
{
m_szAxisName = new char[strlen(szName)+1];
strcpy(m_szAxisName, szName);
}
printf("PIasynAxis::PIasynAxis() %d: %s\n",
axis, m_szAxisName);
}
void PIasynAxis::Init(const char *portName)
{
asynUser* logSink = pasynManager->createAsynUser(0,0);
asynStatus status = pasynManager->connectDevice(logSink, portName, getAxisNo());
if (status != asynSuccess)
{
asynPrint(logSink, ASYN_TRACE_FLOW|ASYN_TRACE_ERROR,
"PIasynController::configAxis() - connectDevice() failed\n");
return;
}
m_pGCSController->m_pInterface->m_pCurrentLogSink = logSink;
setIntegerParam(pController_->motorStatusGainSupport_, 1);
m_pGCSController->initAxis(this);
double resolution;
m_pGCSController->getResolution(this, resolution);
m_pGCSController->getAxisVelocity(this);
m_pGCSController->getAxisPositionCts(this);
setDoubleParam(pController_->motorPosition_, m_positionCts);
setDoubleParam(pController_->motorMoveAbs_, m_positionCts);
m_pGCSController->getTravelLimits(this, negLimit_, posLimit_);
setDoubleParam(pController_->motorLowLimit_, negLimit_);
setDoubleParam(pController_->motorHighLimit_, posLimit_);
m_pGCSController->getReferencedState(this);
setIntegerParam( pController_->motorStatusHomed_, m_homed );
callParamCallbacks();
pasynManager->freeAsynUser(logSink);
}
PIasynAxis::~PIasynAxis()
{
if (m_szAxisName != NULL)
{
delete [] m_szAxisName;
}
}
asynStatus PIasynAxis::poll(bool *returnMoving)
{
int done = 0;
int moving, negLimit, posLimit, servoControl;
int oldHoming = m_isHoming;
m_pGCSController->getStatus(this, m_isHoming, moving, negLimit, posLimit, servoControl);
if (moving == 0 && m_isHoming == 0)
done = 1;
m_bMoving = (done!=1);
if (!m_isHoming || m_pGCSController->CanCommunicateWhileHoming())
{
if (oldHoming && oldHoming != m_isHoming)
{
m_pGCSController->getReferencedState(this);
asynPrint(pasynUser_, ASYN_TRACE_ERROR, //FIXME: ASYN_TRACE_FLOW,
"PIasynAxis::poll() axis %d referencing state changed, homed = %d\n",
axisNo_, m_homed );
}
if (m_bServoControl && servoControl == 0) // servo changed without user interaction!
{
m_bProblem = true;
}
if (!m_isHoming || m_pGCSController->IsGCS2())
{
m_bServoControl = (servoControl == 1);
m_pGCSController->getAxisPositionCts(this);
double realPosition;
m_pGCSController->getAxisPosition(this, realPosition);
setDoubleParam(pController_->PI_SUP_POSITION, realPosition );
}
}
if (m_isHoming)
{
asynPrint(pasynUser_, ASYN_TRACE_FLOW,
"PIasynAxis::poll() axis %d referencing ...\n", axisNo_ );
}
setDoubleParam(pController_->motorPosition_, m_positionCts );
setDoubleParam(pController_->motorEncoderPosition_, m_positionCts);
setIntegerParam(pController_->motorStatusDirection_, m_lastDirection);
setIntegerParam(pController_->motorStatusDone_, done );
setIntegerParam(pController_->motorStatusHighLimit_, posLimit);
setIntegerParam(pController_->motorStatusHomed_, m_homed );
setIntegerParam(pController_->motorStatusMoving_, !done );
setIntegerParam(pController_->motorStatusLowLimit_, negLimit);
setIntegerParam(pController_->motorStatusGainSupport_, true);
setIntegerParam(pController_->motorStatusProblem_, m_bProblem);
setIntegerParam(pController_->motorStatusPowerOn_, m_bServoControl);
setIntegerParam(pController_->PI_SUP_SERVO, m_bServoControl );
callParamCallbacks();
*returnMoving = m_bMoving;
return asynSuccess;
}
asynStatus PIasynAxis::move(double position, int relative, double minVelocity, double maxVelocity, double acceleration)
{
m_pGCSController->m_pInterface->m_pCurrentLogSink = pasynUser_;
asynStatus status = asynError;
static const char *functionName = "moveAxis";
if (!m_pGCSController->AcceptsNewTarget())
{
asynPrint(pasynUser_, ASYN_TRACE_ERROR|ASYN_TRACE_FLOW,
"%s:%s: Set port %s, axis %d - controller does not accept new target (busy?)\n",
driverName, functionName, pC_->portName, axisNo_ );
printf("%s:%s: Set port %s, axis %d - controller does not accept new target (busy?)\n",
driverName, functionName, pC_->portName, axisNo_ );
return status;
}
if (relative)
{
//TODO: MVR oder letztes target!
//TODO: when is this used?
}
if (pController_->movesDeferred != 0)
{ /*Deferred moves.*/
deferred_position = position;
deferred_move = 1;
deferred_relative = relative;
setIntegerParam(pController_->motorStatusDone_, 0);
callParamCallbacks();
return asynSuccess;
}
else
{
if (maxVelocity != 0)
{
status = m_pGCSController->setVelocityCts(this, maxVelocity);
if (asynSuccess != status)
{
return status;
}
}
if (acceleration != 0)
{
status = m_pGCSController->setAccelerationCts(this, acceleration);
if (asynSuccess != status)
{
return status;
}
}
setIntegerParam(pController_->motorStatusDone_, 0);
callParamCallbacks();
status = m_pGCSController->moveCts(this, position);
}
epicsEventSignal(pController_->pollEventId_);
asynPrint(pasynUser_, ASYN_TRACE_FLOW,
"%s:%s: Set driver %s, axis %d move to %f, min vel=%f, max_vel=%f, accel=%f, deffered=%d - status=%d\n",
driverName, functionName, pC_->portName, axisNo_, position, minVelocity, maxVelocity, acceleration, pController_->movesDeferred, int(status) );
return status;
}
asynStatus PIasynAxis::moveVelocity(double minVelocity, double maxVelocity, double acceleration)
{
m_pGCSController->m_pInterface->m_pCurrentLogSink = pasynUser_;
asynStatus status = asynError;
static const char *functionName = "moveVelocityAxis";
if (!m_pGCSController->AcceptsNewTarget())
{
asynPrint(pasynUser_, ASYN_TRACE_ERROR|ASYN_TRACE_FLOW,
"%s:%s: Set port %s, axis %d - controller does not accept new target (busy?)",
driverName, functionName, pController_->portName, axisNo_ );
return status;
}
setIntegerParam(pController_->motorStatusDone_, 0);
callParamCallbacks();
double target = maxVelocity > 0 ? posLimit_ : negLimit_;
asynPrint(pasynUser_, ASYN_TRACE_FLOW,
"%s:%s: Set port %s, axis %d move with velocity of %f, accel=%f / target %f - BEFORE MOV\n",
driverName, functionName, pController_->portName, axisNo_, maxVelocity, acceleration, target );
m_pGCSController->setVelocityCts(this, maxVelocity);
m_pGCSController->move(this, target);
epicsEventSignal(pController_->pollEventId_);
asynPrint(pasynUser_, ASYN_TRACE_FLOW,
"%s:%s: Set port %s, axis %d move with velocity of %f, accel=%f / target %f - AFTER MOV\n",
driverName, functionName, pController_->portName, axisNo_, maxVelocity, acceleration, target );
return status;
}
asynStatus PIasynAxis::stop(double acceleration)
{
m_pGCSController->m_pInterface->m_pCurrentLogSink = pasynUser_;
static const char *functionName = "stopAxis";
deferred_move = 0;
m_pGCSController->haltAxis(this);
epicsEventSignal(pController_->pollEventId_);
asynPrint(pasynUser_, ASYN_TRACE_FLOW,
"%s:%s: Set axis %d to stop with accel=%f",
driverName, functionName, axisNo_, acceleration );
return asynSuccess;
}
asynStatus PIasynAxis::home(double minVelocity, double maxVelocity, double acceleration, int forwards)
{
m_pGCSController->m_pInterface->m_pCurrentLogSink = pasynUser_;
asynStatus status = asynError;
static const char *functionName = "homeAxis";
m_isHoming = 1;
setIntegerParam(pController_->motorStatusDone_, 0 );
callParamCallbacks();
status = m_pGCSController->referenceVelCts(this, maxVelocity, forwards);
if (asynSuccess != status)
{
return status;
}
setIntegerParam(pController_->motorStatusHomed_, m_homed );
epicsEventSignal(pController_->pollEventId_);
asynPrint(pasynUser_, ASYN_TRACE_FLOW,
"%s:%s: Set driver %s, axis %d to home %s, min vel=%f, max_vel=%f, accel=%f",
driverName, functionName, pController_->portName, axisNo_, (forwards?"FORWARDS":"REVERSE"), minVelocity, maxVelocity, acceleration );
return status;
}
asynStatus PIasynAxis::setPosition(double position)
{
m_pGCSController->m_pInterface->m_pCurrentLogSink = pasynUser_;
asynStatus status = asynError;
status = m_pGCSController->setAxisPositionCts(this, position);
epicsEventSignal(pController_->pollEventId_);
asynPrint(pasynUser_, ASYN_TRACE_FLOW,
"%s:%s: Set driver %s, axis %d set position to %f - status=%d\n",
driverName, "setPositionAxis", pC_->portName, axisNo_, position, int(status) );
return status;
}