/* FILENAME... PIGCSController.cpp ************************************************************************* * 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. ************************************************************************* Version: $Revision: 6$ Modified By: $Author: Steffen Rau$ Last Modified: $Date: 05.11.2013 17:38:32$ HeadURL: $URL$ Original Author: Steffen Rau Created: 15.12.2010 */ #include #include #include #include "PIGCSController.h" #include "PIasynAxis.h" #include "PIInterface.h" #include "PIGCSMotorController.h" #include "PIGCSPiezoController.h" #include "PIE517Controller.h" #include "PIE755Controller.h" #include "PIHexapodController.h" #include "PIGCS2_HexapodController.h" #include "PIC702Controller.h" //#undef asynPrint //#define asynPrint(user,reason,format...) 0 extern "C" { int TranslatePIError(const int error, char* szBuffer, const int maxlen); } /** * create instance of GCS controller depending on identification (\a szIDN) */ PIGCSController* PIGCSController::CreateGCSController(PIInterface* pInterface, const char* szIDN) { if ( strstr(szIDN, "C-663") != NULL || strstr(szIDN, "C-863") != NULL || strstr(szIDN, "C-867") != NULL ) { return new PIGCSMotorController(pInterface, szIDN); } else if ( strstr(szIDN, "E-517") != NULL) { return new PIE517Controller(pInterface, szIDN); } else if ( strstr(szIDN, "E-753") != NULL || strstr(szIDN, "E-709") != NULL || strstr(szIDN, "E-725") != NULL ) { return new PIGCSPiezoController(pInterface, szIDN); } else if ( strstr(szIDN, "E-755") != NULL) { return new PIE755Controller(pInterface, szIDN); } else if ( strstr(szIDN, "C-702") != NULL) { return new PIC702Controller(pInterface, szIDN); } else if ( strstr(szIDN, "HEXAPOD") != NULL || strstr(szIDN, "F-HEX") != NULL || strstr(szIDN, "F-206") != NULL || strstr(szIDN, "M-8") != NULL || strstr(szIDN, "C-887") != NULL ) { if (IsGCS2(pInterface)) { return new PIGCS2_HexapodController(pInterface, szIDN); } else { return new PIHexapodController(pInterface, szIDN); } } else { return NULL; } } bool PIGCSController::IsGCS2(PIInterface* pInterface) { char buf[256]; asynStatus status = pInterface->sendAndReceive("CSV?", buf, 255); if (asynTimeout == status) { return false; } else if (asynSuccess != status) { return false; } float csv = atof(buf); return (csv >= 2.0); } asynStatus PIGCSController::setVelocityCts( PIasynAxis* pAxis, double velocity ) { char cmd[100]; velocity = fabs(velocity) * pAxis->m_CPUdenominator / pAxis->m_CPUnumerator; sprintf(cmd,"VEL %s %f", pAxis->m_szAxisName, velocity); asynStatus status = m_pInterface->sendOnly(cmd); if (asynSuccess == status) { pAxis->m_velocity = velocity; } return status; } asynStatus PIGCSController::moveCts( PIasynAxis** pAxesArray, int* pTargetCtsArray, int numAxes) { //TODO: "Use MVE or set vel/acc so axes reach target at the same time"" asynStatus status; char cmd[1000] = "MOV"; char subCmd[100]; for (int axis = 0; axis m_CPUdenominator / pAxis->m_CPUnumerator; sprintf(subCmd," %s %f", pAxis->m_szAxisName, target); strcat(cmd, subCmd); pAxis->m_lastDirection = (pTargetCtsArray[axis] > pAxis->m_positionCts) ? 1 : 0; } status = m_pInterface->sendOnly(cmd); if (asynSuccess != status) { return status; } int errorCode = getGCSError(); if (errorCode == 0) return asynSuccess; asynPrint(m_pInterface->m_pCurrentLogSink, ASYN_TRACE_FLOW|ASYN_TRACE_ERROR, "PIGCSController::moveCts(array) failed, GCS error %d\n", errorCode); return asynError; } asynStatus PIGCSController::setAxisPositionCts(PIasynAxis* pAxis, double positionCts) { double position = double(positionCts) * pAxis->m_CPUdenominator / pAxis->m_CPUnumerator; asynPrint(m_pInterface->m_pCurrentLogSink, ASYN_TRACE_FLOW|ASYN_TRACE_ERROR, "PIGCSController::setAxisPositionCts(, %d) \n", positionCts); return setAxisPosition(pAxis, position); } asynStatus PIGCSController::setAxisPosition(PIasynAxis* pAxis, double position) { asynStatus status; char cmd[100]; sprintf(cmd,"RON %s 0", pAxis->m_szAxisName); status = m_pInterface->sendOnly(cmd); if (asynSuccess != status) { return status; } asynPrint(m_pInterface->m_pCurrentLogSink, ASYN_TRACE_FLOW|ASYN_TRACE_ERROR, "PIGCSController::setAxisPosition() sent \"%s\"\n", cmd); sprintf(cmd,"POS %s %f", pAxis->m_szAxisName, position); status = m_pInterface->sendOnly(cmd); if (asynSuccess != status) { return status; } asynPrint(m_pInterface->m_pCurrentLogSink, ASYN_TRACE_FLOW|ASYN_TRACE_ERROR, "PIGCSController::setAxisPosition() sent \"%s\"\n", cmd); sprintf(cmd,"RON %s 1", pAxis->m_szAxisName); status = m_pInterface->sendOnly(cmd); if (asynSuccess != status) { return status; } asynPrint(m_pInterface->m_pCurrentLogSink, ASYN_TRACE_FLOW|ASYN_TRACE_ERROR, "PIGCSController::setAxisPosition() sent \"%s\"\n", cmd); int errorCode = getGCSError(); if (errorCode == 0) return asynSuccess; asynPrint(m_pInterface->m_pCurrentLogSink, ASYN_TRACE_FLOW|ASYN_TRACE_ERROR, "PIGCSController::setAxisPosition() failed, GCS error %d\n", errorCode); return asynError; } asynStatus PIGCSController::moveCts( PIasynAxis* pAxis, int targetCts ) { double target = double(targetCts) * pAxis->m_CPUdenominator / pAxis->m_CPUnumerator; asynPrint(m_pInterface->m_pCurrentLogSink, ASYN_TRACE_FLOW|ASYN_TRACE_ERROR, "PIGCSController::moveCts(, %d) \n", targetCts); return move(pAxis, target); } asynStatus PIGCSController::move( PIasynAxis* pAxis, double target ) { asynStatus status; char cmd[100]; sprintf(cmd,"MOV %s %f", pAxis->m_szAxisName, target); status = m_pInterface->sendOnly(cmd); if (asynSuccess != status) { return status; } asynPrint(m_pInterface->m_pCurrentLogSink, ASYN_TRACE_FLOW|ASYN_TRACE_ERROR, "PIGCSController::move() sent \"%s\"\n", cmd); pAxis->m_lastDirection = (target > pAxis->m_position) ? 1 : 0; int errorCode = getGCSError(); if (errorCode == 0) return asynSuccess; asynPrint(m_pInterface->m_pCurrentLogSink, ASYN_TRACE_FLOW|ASYN_TRACE_ERROR, "PIGCSController::move() failed, GCS error %d\n", errorCode); return asynError; } int PIGCSController::getGCSError() { char buf[256]; asynStatus status = m_pInterface->sendAndReceive("ERR?", buf, 255); if (asynTimeout == status) { return COM_TIMEOUT; } else if (asynSuccess != status) { return COM_ERROR; } int errorCode = atoi(buf); if (0 != errorCode) { m_LastError = errorCode; asynPrint(m_pInterface->m_pCurrentLogSink, ASYN_TRACE_ERROR|ASYN_TRACE_FLOW, "PIGCSController::getGCSError() GCS error code = %d\n", errorCode); char szErrorMsg[1024]; if (TranslatePIError(errorCode, szErrorMsg, 1024)) { asynPrint(m_pInterface->m_pCurrentLogSink, ASYN_TRACE_ERROR|ASYN_TRACE_FLOW, "PIGCSController::getGCSError() GCS error, %s\n", szErrorMsg); } } return errorCode; } asynStatus PIGCSController::haltAxis(PIasynAxis* pAxis) { char cmd[100]; sprintf(cmd,"HLT %s", pAxis->m_szAxisName); asynStatus status = m_pInterface->sendOnly(cmd); if (status != asynSuccess) { return status; } int err = getGCSError(); // controller will set error code to PI_CNTR_STOP (10) if (err != PI_CNTR_STOP) { asynPrint(m_pInterface->m_pCurrentLogSink, ASYN_TRACE_FLOW|ASYN_TRACE_ERROR, "PIGCSController::haltAxis() failed, GCS error %d", err); return asynError; } return status; } /** * get position of axis in physical units (EGU) as defined on the controller */ asynStatus PIGCSController::getAxisPosition(PIasynAxis* pAxis, double& position) { char cmd[100]; char buf[255]; sprintf(cmd, "POS? %s", pAxis->m_szAxisName); asynStatus status = m_pInterface->sendAndReceive(cmd, buf, 99); if (status != asynSuccess) { return status; } if (!getValue(buf, position)) { status = asynError; } return status; } /** * get velocity of axis in physical units (EGU) as defined on the controller * and set PIasynAxis::m_velocity */ asynStatus PIGCSController::getAxisVelocity(PIasynAxis* pAxis) { char cmd[100]; char buf[255]; sprintf(cmd, "VEL? %s", pAxis->m_szAxisName); asynStatus status = m_pInterface->sendAndReceive(cmd, buf, 99); if (status != asynSuccess) { return status; } if (!getValue(buf, pAxis->m_velocity)) { status = asynError; } return status; } /** * Find travel range for axis. */ asynStatus PIGCSController::getTravelLimits(PIasynAxis* pAxis, double& negLimit, double& posLimit) { char cmd[100]; char buf[255]; sprintf(cmd, "TMN? %s", pAxis->m_szAxisName); asynStatus status = m_pInterface->sendAndReceive(cmd, buf, 99); if (status != asynSuccess) { return status; } if (!getValue(buf, negLimit)) { return asynError; } sprintf(cmd, "TMX? %s", pAxis->m_szAxisName); status = m_pInterface->sendAndReceive(cmd, buf, 99); if (status != asynSuccess) { return status; } if (!getValue(buf, posLimit)) { return asynError; } return status; } asynStatus PIGCSController::hasLimitSwitches(PIasynAxis* pAxis) { char cmd[100]; char buf[255]; sprintf(cmd, "LIM? %s", pAxis->m_szAxisName); asynStatus status = m_pInterface->sendAndReceive(cmd, buf, 99); if (status != asynSuccess) { return status; } if (!getValue(buf, pAxis->m_bHasLimitSwitches)) { return asynError; } if (!pAxis->m_bHasLimitSwitches) { sprintf(cmd, "HAR? %s", pAxis->m_szAxisName); asynStatus status = m_pInterface->sendAndReceive(cmd, buf, 99); if (status == asynSuccess) { if (!getValue(buf, pAxis->m_bHasLimitSwitches)) { return asynError; } } else if (status == asynTimeout) { int err = getGCSError(); if (err == PI_CNTR_UNKNOWN_COMMAND) { // "HAR?" not known pAxis->m_bHasLimitSwitches = false; } else { return status; } } else { return status; } } asynPrint(m_pInterface->m_pCurrentLogSink, ASYN_TRACE_FLOW, "PIGCSController::hasLimitSwitches() axis has %slimit switches\n", pAxis->m_bHasLimitSwitches?"":"no "); return status; } asynStatus PIGCSController::hasReferenceSensor(PIasynAxis* pAxis) { char cmd[100]; char buf[255]; sprintf(cmd, "TRS? %s", pAxis->m_szAxisName); asynStatus status = m_pInterface->sendAndReceive(cmd, buf, 99); if (status != asynSuccess) { return status; } if (!getValue(buf, pAxis->m_bHasReference)) { return asynError; } asynPrint(m_pInterface->m_pCurrentLogSink, ASYN_TRACE_FLOW, "PIGCSController::hasReferenceSwitch() axis has %sreference sensor\n", pAxis->m_bHasReference?"":"no "); return status; } /** * get position of axis in counts as used in EPICS. * getAxisPosition() is called and position is covnerted to counts using the * counts-per-unit (CPU) fraction of the axis. */ asynStatus PIGCSController::getAxisPositionCts(PIasynAxis* pAxis) { double pos; asynStatus status = getAxisPosition(pAxis, pos); if (status != asynSuccess) { return status; } pAxis->m_position = pos; if (pAxis->m_CPUdenominator==0 || pAxis->m_CPUnumerator==0) { pAxis->m_positionCts = pos; return status; } pAxis->m_positionCts = int( (pos * double(pAxis->m_CPUnumerator) / double(pAxis->m_CPUdenominator))+0.5); if (m_pInterface->m_pCurrentLogSink != NULL) { asynPrint(m_pInterface->m_pCurrentLogSink, ASYN_TRACE_FLOW, "PIGCSController::getAxisPositionCts() pos:%d\n", pAxis->m_positionCts); } return status; } //void PIGCSController::calcAxisPositionCts(); asynStatus PIGCSController::setServo(PIasynAxis* pAxis, int servoState) { char cmd[100]; sprintf(cmd, "SVO %s %d", pAxis->m_szAxisName, servoState); asynStatus status = m_pInterface->sendOnly(cmd); if (status != asynSuccess) { return status; } int err = getGCSError(); if (COM_NO_ERROR == err) { pAxis->m_bServoControl = (servoState == 1); if (pAxis->m_bProblem && pAxis->m_bServoControl) { pAxis->m_bProblem = false; } return asynSuccess; } asynPrint(m_pInterface->m_pCurrentLogSink, ASYN_TRACE_ERROR|ASYN_TRACE_FLOW, "Could not set servo state!\n"); return asynError; } asynStatus PIGCSController::getMoving(PIasynAxis* pAxis, int& moving) { char buf[255]; asynStatus status = m_pInterface->sendAndReceive(char(5), buf, 99);; if (status != asynSuccess) { //printf("PIGCSController::getMoving() failed, status %d", status); return status; } char* pStr; long movingState = strtol(buf, &pStr, 16); moving = (movingState & pAxis->m_movingStateMask) != 0 ? 1 : 0; return status; } asynStatus PIGCSController::getBusy(PIasynAxis* pAxis, int& busy) { char buf[255]; asynStatus status = m_pInterface->sendAndReceive(char(7), buf, 99);; if (status != asynSuccess) { return status; } unsigned char c = (unsigned char)buf[0]; busy = (c==0xB0); return status; } asynStatus PIGCSController::setGCSParameter(PIasynAxis* pAxis, unsigned int paramID, double value) { char cmd[100]; sprintf(cmd, "SPA %s %d %.12g", pAxis->m_szAxisName, paramID, value); asynStatus status = m_pInterface->sendOnly(cmd); return status; } asynStatus PIGCSController::getGCSParameter(PIasynAxis* pAxis, unsigned int paramID, double& value) { char cmd[100]; char buf[255]; sprintf(cmd, "SPA? %s %d", pAxis->m_szAxisName, paramID); asynStatus status = m_pInterface->sendAndReceive(cmd, buf, 99); if (status != asynSuccess) { return status; } if (!getValue(buf, value)) { return asynError; } return status; } PIGCSController::PIGCSController(PIInterface* pInterface, const char* szIDN) : m_pInterface(pInterface) , m_bAnyAxisMoving(false) , m_nrFoundAxes(0) , m_LastError(0) { strncpy(szIdentification, szIDN, 199); } PIGCSController::~PIGCSController() { if (NULL != m_pInterface) { delete m_pInterface; } } asynStatus PIGCSController::initAxis(PIasynAxis* pAxis) { // read stage name - to have it in logfile and find // problems because of mis/non-configured controllers char cmd[100]; char buf[255]; sprintf(cmd, "CST? %s", pAxis->m_szAxisName); asynStatus status = m_pInterface->sendAndReceive(cmd, buf, 99);; if (status != asynSuccess) { return status; } if (NULL != m_pInterface->m_pCurrentLogSink) { asynPrint(m_pInterface->m_pCurrentLogSink, ASYN_TRACE_FLOW, "PIGCSController::initAxis() stage configuration: %s\n", buf); } pAxis->m_movingStateMask = pow(2.0, pAxis->getAxisNo()); return setServo(pAxis, 1); } asynStatus PIGCSController::init(void) { asynStatus status; status = findConnectedAxes(); return status; } asynStatus PIGCSController::findConnectedAxes() { m_nrFoundAxes = 0; for (size_t i=0; isendAndReceive("SAI?", m_allAxesIDs, 255); if (asynSuccess != status) { return status; } char* szAxis = strtok(m_allAxesIDs, "\n"); while (szAxis != NULL) { int i=strlen(szAxis)-1; while (szAxis[i] == ' ') { szAxis[i] = '\0'; i--; } if (MAX_NR_AXES <= m_nrFoundAxes) { return asynError; } m_axesIDs[m_nrFoundAxes] = szAxis; m_nrFoundAxes++; szAxis = strtok(NULL, "\n"); } return status; } asynStatus PIGCSController::getReferencedState(PIasynAxis* pAxis) { char cmd[100]; char buf[255]; sprintf(cmd, "FRF? %s", pAxis->m_szAxisName); asynStatus status = m_pInterface->sendAndReceive(cmd, buf, 99);; if (status != asynSuccess) { return status; } if (getValue(buf, pAxis->m_homed)) { return asynError; } return status; } asynStatus PIGCSController::getResolution(PIasynAxis* pAxis, double& resolution ) { resolution = 0.0001; pAxis->m_CPUnumerator = 10000; pAxis->m_CPUdenominator = 1; return asynSuccess; } asynStatus PIGCSController::SetPivotX(double value) { if (NULL != m_pInterface->m_pCurrentLogSink) { asynPrint(m_pInterface->m_pCurrentLogSink, ASYN_TRACE_FLOW, "PIGCSController::SetPivotX() ignored"); } return asynSuccess; } asynStatus PIGCSController::SetPivotY(double value) { if (NULL != m_pInterface->m_pCurrentLogSink) { asynPrint(m_pInterface->m_pCurrentLogSink, ASYN_TRACE_FLOW, "PIGCSController::SetPivotY() ignored"); } return asynSuccess; } asynStatus PIGCSController::SetPivotZ(double value) { if (NULL != m_pInterface->m_pCurrentLogSink) { asynPrint(m_pInterface->m_pCurrentLogSink, ASYN_TRACE_FLOW, "PIGCSController::SetPivotZ() ignored"); } return asynSuccess; } bool PIGCSController::getValue(const char* szMsg, double& value) { const char* p = strstr(szMsg, "="); if (p==NULL || *p == '\0') { return false; } value = atof(p+1); return true; } bool PIGCSController::getValue(const char* szMsg, int& value) { const char* p = strstr(szMsg, "="); if (p==NULL || *p == '\0') { return false; } value = atoi(p+1); return true; } bool PIGCSController::getValue(const char* szMsg, bool& value) { const char* p = strstr(szMsg, "="); if (p==NULL || *p == '\0') { return false; } int ivalue = atoi(p+1); value = (ivalue =! 0); return true; }