From b867f013efa0eaebb45635a1215f891071b3b935 Mon Sep 17 00:00:00 2001 From: Keenan Lang Date: Tue, 20 Sep 2016 16:48:12 -0500 Subject: [PATCH 01/27] Issue/feature reporting link Added links that will bring up issue reporting with a built-in response template. --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 7e3d9d82..25912443 100644 --- a/README.md +++ b/README.md @@ -6,4 +6,8 @@ For more information, see: * [motor wiki](https://github.com/epics-modules/motor/wiki) * http://www.aps.anl.gov/bcda/synApps +[Report an issue with Motor](https://github.com/epics-modules/motor/issues/new?title=%20ISSUE%20NAME%20HERE&body=**Describe%20the%20issue**%0A%0A**Steps%20to%20reproduce**%0A1.%20Step%20one%0A2.%20Step%20two%0A3.%20Step%20three%0A%0A**Expected%20behaivour**%0A%0A**Actual%20behaviour**%0A%0A**Build%20Environment**%0AArchitecture:%0AEpics%20Base%20Version:%0ADependent%20Module%20Versions:&labels=bug) +[Request a feature](https://github.com/epics-modules/motor/issues/new?title=%20FEATURE%20SHORT%20DESCRIPTION&body=**Feature Long Description**%0A%0A**Why%20should%20this%20be%20added?**%0A&labels=enhancement) + + converted from APS SVN repository: Fri Oct 16 12:31:41 CDT 2015 From c970afbfe71521d1587c51b0c7f3a634b03f5833 Mon Sep 17 00:00:00 2001 From: sluiter Date: Wed, 28 Sep 2016 16:07:59 -0500 Subject: [PATCH 02/27] Reverted FLNK change. Except for the condition that DMOV == FALSE, FLNK processing was standard. --- motorApp/MotorSrc/motorRecord.cc | 11 ++++++----- motorApp/MotorSrc/motorRecord.dbd | 5 ----- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/motorApp/MotorSrc/motorRecord.cc b/motorApp/MotorSrc/motorRecord.cc index e1f29575..64b6fa58 100644 --- a/motorApp/MotorSrc/motorRecord.cc +++ b/motorApp/MotorSrc/motorRecord.cc @@ -183,6 +183,9 @@ USAGE... Motor Record Support. * .72 03-13-15 rls - Changed RDBL to set RRBV rather than DRBV. * .73 02-15-16 rls - JOGF/R soft limit error check was using the wrong coordinate sytem limits. * Changed error checks from dial to user limits. + * .74 09-28-16 rls - Reverted .71 FLNK change. Except for the condition that DMOV == FALSE, FLNK + * processing was standard. If processing is needed on a DMOV false to true + * transition, a new motor record field should be added. */ #define VERSION 6.10 @@ -1163,10 +1166,10 @@ Exit: Update record timestamp, call recGblGetTimeStamp(). Process alarms, call alarm_sub(). Monitor changes to record fields, call monitor(). - IF Done Moving field (DMOV) is TRUE, AND, Last Done Moving (LDMV) was False. + + IF Done Moving field (DMOV) is TRUE Process the forward-scan-link record, call recGblFwdLink(). ENDIF - Update Last Done Moving (LDMV). Set Processing Active indicator field (PACT) false. Exit. @@ -1406,9 +1409,8 @@ process_exit: alarm_sub(pmr); /* If we've violated alarm limits, yell. */ monitor(pmr); /* If values have changed, broadcast them. */ - if (pmr->dmov != 0 && pmr->ldmv == 0) /* Test for False to True transition. */ + if (pmr->dmov != 0) recGblFwdLink(pmr); /* Process the forward-scan-link record. */ - pmr->ldmv = pmr->dmov; pmr->pact = 0; Debug(4, "process:---------------------- end; motor \"%s\"\n", pmr->name); @@ -2450,7 +2452,6 @@ static long special(DBADDR *paddr, int after) if (pmr->dmov == TRUE) { pmr->dmov = FALSE; - pmr->ldmv = pmr->dmov; db_post_events(pmr, &pmr->dmov, DBE_VAL_LOG); } return(OK); diff --git a/motorApp/MotorSrc/motorRecord.dbd b/motorApp/MotorSrc/motorRecord.dbd index 3417521e..674c6a34 100644 --- a/motorApp/MotorSrc/motorRecord.dbd +++ b/motorApp/MotorSrc/motorRecord.dbd @@ -586,11 +586,6 @@ recordtype(motor) { special(SPC_NOMOD) initial("1") } - field(LDMV,DBF_SHORT) { - prompt("Last Done moving value") - special(SPC_NOMOD) - initial("1") - } field(MOVN,DBF_SHORT) { prompt("Motor is moving") special(SPC_NOMOD) From 548c1188ae150aae0ea8b393e7c98172ccb42a9c Mon Sep 17 00:00:00 2001 From: PI-SRau Date: Thu, 20 Oct 2016 17:36:09 +0200 Subject: [PATCH 03/27] Support controller that do not know "VEL(?)" command --- motorApp/PIGCS2Src/PIGCSController.cpp | 45 +++++++++++++++++++------- motorApp/PIGCS2Src/PIGCSController.h | 2 ++ 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/motorApp/PIGCS2Src/PIGCSController.cpp b/motorApp/PIGCS2Src/PIGCSController.cpp index c153844e..5364865a 100644 --- a/motorApp/PIGCS2Src/PIGCSController.cpp +++ b/motorApp/PIGCS2Src/PIGCSController.cpp @@ -111,6 +111,10 @@ bool PIGCSController::IsGCS2(PIInterface* pInterface) asynStatus PIGCSController::setVelocityCts( PIasynAxis* pAxis, double velocity ) { + if (!m_KnowsVELcommand) + { + return asynSuccess; + } char cmd[100]; velocity = fabs(velocity) * pAxis->m_CPUdenominator / pAxis->m_CPUnumerator; sprintf(cmd,"VEL %s %f", pAxis->m_szAxisName, velocity); @@ -247,17 +251,21 @@ int PIGCSController::getGCSError() 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); + if (m_pInterface->m_pCurrentLogSink) + { + 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; } @@ -308,6 +316,10 @@ asynStatus PIGCSController::getAxisPosition(PIasynAxis* pAxis, double& position) */ asynStatus PIGCSController::getAxisVelocity(PIasynAxis* pAxis) { + if (!m_KnowsVELcommand) + { + return asynSuccess; + } char cmd[100]; char buf[255]; sprintf(cmd, "VEL? %s", pAxis->m_szAxisName); @@ -443,7 +455,7 @@ asynStatus PIGCSController::getAxisPositionCts(PIasynAxis* pAxis) pAxis->m_position = pos; if (pAxis->m_CPUdenominator==0 || pAxis->m_CPUnumerator==0) { - pAxis->m_positionCts = pos; + pAxis->m_positionCts = int(pos); return status; } @@ -577,7 +589,7 @@ asynStatus PIGCSController::initAxis(PIasynAxis* pAxis) asynPrint(m_pInterface->m_pCurrentLogSink, ASYN_TRACE_FLOW, "PIGCSController::initAxis() stage configuration: %s\n", buf); } - pAxis->m_movingStateMask = pow(2.0, pAxis->getAxisNo()); + pAxis->m_movingStateMask = int (pow(2.0, pAxis->getAxisNo()) ); return setServo(pAxis, 1); } @@ -585,6 +597,15 @@ asynStatus PIGCSController::initAxis(PIasynAxis* pAxis) asynStatus PIGCSController::init(void) { asynStatus status; + char buffer [1024]; + status = m_pInterface->sendAndReceive("VEL?", buffer, 1023); + m_KnowsVELcommand = ( asynSuccess == status); + if (!m_KnowsVELcommand) + { + (void) getGCSError (); + } + + status = findConnectedAxes(); return status; } diff --git a/motorApp/PIGCS2Src/PIGCSController.h b/motorApp/PIGCS2Src/PIGCSController.h index 722eedc9..29db5fb8 100644 --- a/motorApp/PIGCS2Src/PIGCSController.h +++ b/motorApp/PIGCS2Src/PIGCSController.h @@ -109,6 +109,8 @@ protected: size_t m_nrFoundAxes; char m_allAxesIDs[255]; int m_LastError; + + bool m_KnowsVELcommand; }; #endif /* PIGCSCONTROLLER_H_ */ From cbea70e429189fffbc5de9d2623bc3a44f1cdbac Mon Sep 17 00:00:00 2001 From: PI-SRau Date: Thu, 20 Oct 2016 17:39:45 +0200 Subject: [PATCH 04/27] add support for E-871 and E-873 as "motor" controllers --- motorApp/PIGCS2Src/PIGCSController.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/motorApp/PIGCS2Src/PIGCSController.cpp b/motorApp/PIGCS2Src/PIGCSController.cpp index c153844e..592934f9 100644 --- a/motorApp/PIGCS2Src/PIGCSController.cpp +++ b/motorApp/PIGCS2Src/PIGCSController.cpp @@ -46,6 +46,8 @@ PIGCSController* PIGCSController::CreateGCSController(PIInterface* pInterface, c || strstr(szIDN, "C-867") != NULL || strstr(szIDN, "C-884") != NULL || strstr(szIDN, "E-861") != NULL + || strstr(szIDN, "E-871") != NULL + || strstr(szIDN, "E-873") != NULL ) { return new PIGCSMotorController(pInterface, szIDN); From e269064b2712661681a1f8d7b447221ec86b3137 Mon Sep 17 00:00:00 2001 From: PI-SRau Date: Thu, 20 Oct 2016 17:42:12 +0200 Subject: [PATCH 05/27] add .gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index a0755961..fae3cabb 100644 --- a/.gitignore +++ b/.gitignore @@ -14,4 +14,4 @@ envPaths dllPath.bat auto_settings.sav* auto_positions.sav* - +.ccfxprepdir/ From 28f4a8f2ed0cab43bc4430e9327a46be59a83863 Mon Sep 17 00:00:00 2001 From: Pete R Jemian Date: Wed, 9 Nov 2016 14:52:29 -0600 Subject: [PATCH 06/27] display each HTML file --- documentation/README.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 documentation/README.md diff --git a/documentation/README.md b/documentation/README.md new file mode 100644 index 00000000..2a2dd045 --- /dev/null +++ b/documentation/README.md @@ -0,0 +1,8 @@ +# HTML documentation + +* [motor.html](http://htmlpreview.github.com/?https://github.com/epics-modules/utils/blob/master/documentation/motor.html) +* [motorDeviceDriver.html](http://htmlpreview.github.com/?https://github.com/epics-modules/utils/blob/master/documentation/motorDeviceDriver.html) +* [motorRecord.html](http://htmlpreview.github.com/?https://github.com/epics-modules/utils/blob/master/documentation/motorRecord.html) +* [motor_files.html](http://htmlpreview.github.com/?https://github.com/epics-modules/utils/blob/master/documentation/motor_files.html) +* [motor_release.html](http://htmlpreview.github.com/?https://github.com/epics-modules/utils/blob/master/documentation/motor_release.html) +* [trajectoryScan.html](http://htmlpreview.github.com/?https://github.com/epics-modules/utils/blob/master/documentation/trajectoryScan.html) From e23721fb0c6fe62a077218319cc4ed009a978ae9 Mon Sep 17 00:00:00 2001 From: Pete R Jemian Date: Wed, 9 Nov 2016 14:55:07 -0600 Subject: [PATCH 07/27] the module name --- documentation/README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/documentation/README.md b/documentation/README.md index 2a2dd045..9a4b7e91 100644 --- a/documentation/README.md +++ b/documentation/README.md @@ -1,8 +1,8 @@ # HTML documentation -* [motor.html](http://htmlpreview.github.com/?https://github.com/epics-modules/utils/blob/master/documentation/motor.html) -* [motorDeviceDriver.html](http://htmlpreview.github.com/?https://github.com/epics-modules/utils/blob/master/documentation/motorDeviceDriver.html) -* [motorRecord.html](http://htmlpreview.github.com/?https://github.com/epics-modules/utils/blob/master/documentation/motorRecord.html) -* [motor_files.html](http://htmlpreview.github.com/?https://github.com/epics-modules/utils/blob/master/documentation/motor_files.html) -* [motor_release.html](http://htmlpreview.github.com/?https://github.com/epics-modules/utils/blob/master/documentation/motor_release.html) -* [trajectoryScan.html](http://htmlpreview.github.com/?https://github.com/epics-modules/utils/blob/master/documentation/trajectoryScan.html) +* [motor.html](http://htmlpreview.github.com/?https://github.com/epics-modules/motor/blob/master/documentation/motor.html) +* [motorDeviceDriver.html](http://htmlpreview.github.com/?https://github.com/epics-modules/motor/blob/master/documentation/motorDeviceDriver.html) +* [motorRecord.html](http://htmlpreview.github.com/?https://github.com/epics-modules/motor/blob/master/documentation/motorRecord.html) +* [motor_files.html](http://htmlpreview.github.com/?https://github.com/epics-modules/motor/blob/master/documentation/motor_files.html) +* [motor_release.html](http://htmlpreview.github.com/?https://github.com/epics-modules/motor/blob/master/documentation/motor_release.html) +* [trajectoryScan.html](http://htmlpreview.github.com/?https://github.com/epics-modules/motor/blob/master/documentation/trajectoryScan.html) From f718aaa3bab1f15e4973cea7b25a8ae935774345 Mon Sep 17 00:00:00 2001 From: Pete R Jemian Date: Wed, 9 Nov 2016 14:55:54 -0600 Subject: [PATCH 08/27] link to all HTML docs --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 25912443..fae0d79e 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ For more information, see: * [main page](http://htmlpreview.github.io/?https://github.com/epics-modules/motor/blob/master/documentation/motor.html) * [motor wiki](https://github.com/epics-modules/motor/wiki) * http://www.aps.anl.gov/bcda/synApps +* [HTML documentation](https://github.com/epics-modules/motor/blob/master/documentation/README.md) [Report an issue with Motor](https://github.com/epics-modules/motor/issues/new?title=%20ISSUE%20NAME%20HERE&body=**Describe%20the%20issue**%0A%0A**Steps%20to%20reproduce**%0A1.%20Step%20one%0A2.%20Step%20two%0A3.%20Step%20three%0A%0A**Expected%20behaivour**%0A%0A**Actual%20behaviour**%0A%0A**Build%20Environment**%0AArchitecture:%0AEpics%20Base%20Version:%0ADependent%20Module%20Versions:&labels=bug) [Request a feature](https://github.com/epics-modules/motor/issues/new?title=%20FEATURE%20SHORT%20DESCRIPTION&body=**Feature Long Description**%0A%0A**Why%20should%20this%20be%20added?**%0A&labels=enhancement) From bc3811835f72d3336a834e1d4e9b07274296a96a Mon Sep 17 00:00:00 2001 From: PI-SRau Date: Wed, 11 Jan 2017 16:41:13 +0100 Subject: [PATCH 09/27] if controller does not know how to set velocity, setting acceleration and deceleration must be disabled also --- motorApp/PIGCS2Src/PIGCSMotorController.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/motorApp/PIGCS2Src/PIGCSMotorController.cpp b/motorApp/PIGCS2Src/PIGCSMotorController.cpp index e62d0bbd..b763716b 100644 --- a/motorApp/PIGCS2Src/PIGCSMotorController.cpp +++ b/motorApp/PIGCS2Src/PIGCSMotorController.cpp @@ -163,6 +163,10 @@ asynStatus PIGCSMotorController::getStatus(PIasynAxis* pAxis, int& homing, int& asynStatus PIGCSMotorController::getMaxAcceleration(PIasynAxis* pAxis) { + if (!m_KnowsVELcommand) + { + return asynSuccess; + } double maxAcc, maxDec; asynStatus status = getGCSParameter(pAxis, PI_PARA_MOT_MAX_ACCEL, maxAcc); if (asynSuccess != status) @@ -184,6 +188,10 @@ asynStatus PIGCSMotorController::getMaxAcceleration(PIasynAxis* pAxis) asynStatus PIGCSMotorController::setAcceleration( PIasynAxis* pAxis, double acceleration) { + if (!m_KnowsVELcommand) + { + return asynSuccess; + } asynStatus status = setGCSParameter(pAxis, PI_PARA_MOT_CURR_ACCEL, acceleration); if (asynSuccess != status) return status; From 5cad105357739d603218502eb38be20ee736b4ee Mon Sep 17 00:00:00 2001 From: timmmooney Date: Thu, 12 Jan 2017 11:09:55 -0600 Subject: [PATCH 10/27] ignore SET field, so a database can do it instead --- motorApp/MotorSrc/motorRecord.cc | 8 ++++---- motorApp/MotorSrc/motorRecord.dbd | 4 ++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/motorApp/MotorSrc/motorRecord.cc b/motorApp/MotorSrc/motorRecord.cc index 64b6fa58..919831c1 100644 --- a/motorApp/MotorSrc/motorRecord.cc +++ b/motorApp/MotorSrc/motorRecord.cc @@ -1378,7 +1378,7 @@ enter_do_work: if (pmr->lvio != old_lvio) { MARK(M_LVIO); - if (pmr->lvio && !pmr->set) + if (pmr->lvio && (!pmr->set && !pmr->igset)) { pmr->stop = 1; MARK(M_STOP); @@ -1868,7 +1868,7 @@ static RTN_STATUS do_work(motorRecord * pmr, CALLBACK_VALUE proc_ind) WRITE_MSG(SET_ENC_RATIO, ep_mp); SEND_MSG(); } - if (pmr->set) + if (pmr->set && !pmr->igset) { pmr->pp = TRUE; INIT_MSG(); @@ -2082,7 +2082,7 @@ static RTN_STATUS do_work(motorRecord * pmr, CALLBACK_VALUE proc_ind) if (pmr->val != pmr->lval) { MARK(M_VAL); - if (set && !pmr->foff) + if ((set && !pmr->igset) && !pmr->foff) { /* * Act directly on .val. and return. User wants to redefine .val @@ -2132,7 +2132,7 @@ static RTN_STATUS do_work(motorRecord * pmr, CALLBACK_VALUE proc_ind) pmr->rdif = NINT(pmr->diff / pmr->mres); MARK(M_RDIF); - if (set) + if (set && !pmr->igset) { if ((pmr->mip & MIP_LOAD_P) == 0) /* Test for LOAD_POS completion. */ load_pos(pmr); diff --git a/motorApp/MotorSrc/motorRecord.dbd b/motorApp/MotorSrc/motorRecord.dbd index 674c6a34..aa455cba 100644 --- a/motorApp/MotorSrc/motorRecord.dbd +++ b/motorApp/MotorSrc/motorRecord.dbd @@ -788,4 +788,8 @@ recordtype(motor) { pp(TRUE) interest(1) } + field(IGSET,DBF_SHORT) { + prompt("Ignore SET field") + interest(2) + } } From 5bd92b2e58b001d4a153093a790a14afea68638b Mon Sep 17 00:00:00 2001 From: PI-SRau Date: Mon, 16 Jan 2017 08:44:30 +0100 Subject: [PATCH 11/27] replaces tabs with spaces --- motorApp/PIGCS2Src/PIGCSMotorController.cpp | 196 ++++++++++---------- 1 file changed, 98 insertions(+), 98 deletions(-) diff --git a/motorApp/PIGCS2Src/PIGCSMotorController.cpp b/motorApp/PIGCS2Src/PIGCSMotorController.cpp index b763716b..78e320f1 100644 --- a/motorApp/PIGCS2Src/PIGCSMotorController.cpp +++ b/motorApp/PIGCS2Src/PIGCSMotorController.cpp @@ -24,87 +24,87 @@ Created: 15.12.2010 asynStatus PIGCSMotorController::initAxis(PIasynAxis* pAxis) { - asynStatus status = hasLimitSwitches(pAxis); - if (asynSuccess != status) - { - return status; - } - status = hasReferenceSensor(pAxis); - if (asynSuccess != status) - { - return status; - } - return PIGCSController::initAxis(pAxis); + asynStatus status = hasLimitSwitches(pAxis); + if (asynSuccess != status) + { + return status; + } + status = hasReferenceSensor(pAxis); + if (asynSuccess != status) + { + return status; + } + return PIGCSController::initAxis(pAxis); } asynStatus PIGCSMotorController::setAccelerationCts( PIasynAxis* pAxis, double accelerationCts) { - double acceleration = fabs(accelerationCts) * pAxis->m_CPUdenominator / pAxis->m_CPUnumerator; - if (acceleration == pAxis->m_acceleration) - return asynSuccess; - if (pAxis->m_maxAcceleration < 0) - { - getMaxAcceleration(pAxis); - } - if (acceleration > pAxis->m_maxAcceleration) - acceleration = pAxis->m_maxAcceleration; + double acceleration = fabs(accelerationCts) * pAxis->m_CPUdenominator / pAxis->m_CPUnumerator; + if (acceleration == pAxis->m_acceleration) + return asynSuccess; + if (pAxis->m_maxAcceleration < 0) + { + getMaxAcceleration(pAxis); + } + if (acceleration > pAxis->m_maxAcceleration) + acceleration = pAxis->m_maxAcceleration; - return setAcceleration(pAxis, acceleration); + return setAcceleration(pAxis, acceleration); } asynStatus PIGCSMotorController::referenceVelCts( PIasynAxis* pAxis, double velocity, int forwards) { - asynStatus status = setServo(pAxis, 1); + asynStatus status = setServo(pAxis, 1); if (asynSuccess != status) - return status; + return status; - char cmd[100]; - if (velocity != 0) - { - velocity = fabs(velocity) * pAxis->m_CPUdenominator / pAxis->m_CPUnumerator; - sprintf(cmd,"SPA %s 0x50 %f", pAxis->m_szAxisName, velocity); - m_pInterface->sendOnly(cmd); - } + char cmd[100]; + if (velocity != 0) + { + velocity = fabs(velocity) * pAxis->m_CPUdenominator / pAxis->m_CPUnumerator; + sprintf(cmd,"SPA %s 0x50 %f", pAxis->m_szAxisName, velocity); + m_pInterface->sendOnly(cmd); + } - if (pAxis->m_bHasReference) - { - // call FRF - find reference - sprintf(cmd,"FRF %s", pAxis->m_szAxisName); - } - else if (pAxis->m_bHasLimitSwitches) - { - if (forwards) - { - // call FPL - find positive limit switch - sprintf(cmd,"FPL %s", pAxis->m_szAxisName); - } - else - { - // call FNL - find negative limit switch - sprintf(cmd,"FNL %s", pAxis->m_szAxisName); - } - } - else - { - asynPrint(m_pInterface->m_pCurrentLogSink, ASYN_TRACE_ERROR, - "PIGCSMotorController::referenceVelCts() failed - axis has no reference/limit switch\n"); - epicsSnprintf(pAxis->m_pasynUser->errorMessage,pAxis->m_pasynUser->errorMessageSize, - "PIGCSMotorController::referenceVelCts() failed - axis has no reference/limit switch\n"); - return asynError; - } - status = m_pInterface->sendOnly(cmd); - if (asynSuccess != status) - return status; - int errorCode = getGCSError(); - if (errorCode == 0) - { - return asynSuccess; - } + if (pAxis->m_bHasReference) + { + // call FRF - find reference + sprintf(cmd,"FRF %s", pAxis->m_szAxisName); + } + else if (pAxis->m_bHasLimitSwitches) + { + if (forwards) + { + // call FPL - find positive limit switch + sprintf(cmd,"FPL %s", pAxis->m_szAxisName); + } + else + { + // call FNL - find negative limit switch + sprintf(cmd,"FNL %s", pAxis->m_szAxisName); + } + } + else + { + asynPrint(m_pInterface->m_pCurrentLogSink, ASYN_TRACE_ERROR, + "PIGCSMotorController::referenceVelCts() failed - axis has no reference/limit switch\n"); + epicsSnprintf(pAxis->m_pasynUser->errorMessage,pAxis->m_pasynUser->errorMessageSize, + "PIGCSMotorController::referenceVelCts() failed - axis has no reference/limit switch\n"); + return asynError; + } + 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_ERROR, - "PIGCSMotorController::referenceVelCts() failed\n"); - epicsSnprintf(pAxis->m_pasynUser->errorMessage,pAxis->m_pasynUser->errorMessageSize, - "PIGCSMotorController::referenceVelCts() failed - GCS Error %d\n",errorCode); - return asynError; + "PIGCSMotorController::referenceVelCts() failed\n"); + epicsSnprintf(pAxis->m_pasynUser->errorMessage,pAxis->m_pasynUser->errorMessageSize, + "PIGCSMotorController::referenceVelCts() failed - GCS Error %d\n",errorCode); + return asynError; } @@ -113,18 +113,18 @@ asynStatus PIGCSMotorController::referenceVelCts( PIasynAxis* pAxis, double velo */ asynStatus PIGCSMotorController::getResolution(PIasynAxis* pAxis, double& resolution ) { - // CPU is "Counts Per Unit" - // this is stored as two integers in the controller + // CPU is "Counts Per Unit" + // this is stored as two integers in the controller double num, denom; asynStatus status = getGCSParameter(pAxis, PI_PARA_MOT_CPU_Z, num); if (status != asynSuccess) { - return status; + return status; } status = getGCSParameter(pAxis, PI_PARA_MOT_CPU_N, denom); if (status != asynSuccess) { - return status; + return status; } pAxis->m_CPUnumerator = num; pAxis->m_CPUdenominator = denom; @@ -135,11 +135,11 @@ asynStatus PIGCSMotorController::getResolution(PIasynAxis* pAxis, double& resolu asynStatus PIGCSMotorController::getStatus(PIasynAxis* pAxis, int& homing, int& moving, int& negLimit, int& posLimit, int& servoControl) { - char buf[255]; + char buf[255]; asynStatus status = m_pInterface->sendAndReceive(char(4), buf, 99); if (status != asynSuccess) { - return status; + return status; } // TODO this is for a single axis C-863/867 controller!!!! // TODO a) change it to multi-axis code. @@ -167,23 +167,23 @@ asynStatus PIGCSMotorController::getMaxAcceleration(PIasynAxis* pAxis) { return asynSuccess; } - double maxAcc, maxDec; - asynStatus status = getGCSParameter(pAxis, PI_PARA_MOT_MAX_ACCEL, maxAcc); - if (asynSuccess != status) - return status; - status = getGCSParameter(pAxis, PI_PARA_MOT_MAX_DECEL, maxDec); - if (asynSuccess != status) - return status; + double maxAcc, maxDec; + asynStatus status = getGCSParameter(pAxis, PI_PARA_MOT_MAX_ACCEL, maxAcc); + if (asynSuccess != status) + return status; + status = getGCSParameter(pAxis, PI_PARA_MOT_MAX_DECEL, maxDec); + if (asynSuccess != status) + return status; - if (maxAcc < maxDec) - { - pAxis->m_maxAcceleration = maxAcc; - } - else - { - pAxis->m_maxAcceleration = maxDec; - } - return status; + if (maxAcc < maxDec) + { + pAxis->m_maxAcceleration = maxAcc; + } + else + { + pAxis->m_maxAcceleration = maxDec; + } + return status; } asynStatus PIGCSMotorController::setAcceleration( PIasynAxis* pAxis, double acceleration) @@ -192,14 +192,14 @@ asynStatus PIGCSMotorController::setAcceleration( PIasynAxis* pAxis, double acce { return asynSuccess; } - asynStatus status = setGCSParameter(pAxis, PI_PARA_MOT_CURR_ACCEL, acceleration); - if (asynSuccess != status) - return status; - status = setGCSParameter(pAxis, PI_PARA_MOT_CURR_DECEL, acceleration); - if (asynSuccess != status) - return status; - pAxis->m_acceleration = acceleration; - return status; + asynStatus status = setGCSParameter(pAxis, PI_PARA_MOT_CURR_ACCEL, acceleration); + if (asynSuccess != status) + return status; + status = setGCSParameter(pAxis, PI_PARA_MOT_CURR_DECEL, acceleration); + if (asynSuccess != status) + return status; + pAxis->m_acceleration = acceleration; + return status; } From 02e28d602cdc03f55d61bc48ded92a59e64044fc Mon Sep 17 00:00:00 2001 From: Pete R Jemian Date: Mon, 13 Feb 2017 13:07:56 -0600 Subject: [PATCH 12/27] supports *positioning* motors --- documentation/motorRecord.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/motorRecord.html b/documentation/motorRecord.html index 3cfad59f..95301a19 100644 --- a/documentation/motorRecord.html +++ b/documentation/motorRecord.html @@ -39,7 +39,7 @@ record, and related EPICS software required to build and use it.  Version R6-9 of the motor record is compatible with EPICS base R3.14.12.2 and above.

-The motor record is intended to support motors of all kinds, but currently +The motor record is intended to support positioning motors of all kinds, but currently supports only the following variety of motor controllers (in addition to Soft Channel support):

From 4f54eb502bb1e4157db9a0587cfdbabd66de0c95 Mon Sep 17 00:00:00 2001 From: sluiter Date: Wed, 22 Feb 2017 08:26:35 -0600 Subject: [PATCH 13/27] Optional test for VME58 failure mode where board reboots after the 1st motion related command. --- motorApp/OmsSrc/drvOms58.cc | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/motorApp/OmsSrc/drvOms58.cc b/motorApp/OmsSrc/drvOms58.cc index 6e4459c7..2643ef61 100644 --- a/motorApp/OmsSrc/drvOms58.cc +++ b/motorApp/OmsSrc/drvOms58.cc @@ -111,6 +111,13 @@ USAGE... Motor record driver level support for OMS model VME58. * .41 10-20-11 rls - Added counter in send_mess() to prevent endless loop * after VME58 reboot. * .42 07-26-12 rls - Added reboot test to send_mess(). + * .43 02-21-16 rls - Added code to send_mess() that test for a VME58 reboot + * after a motion related (ST, MA, MR) command. Found new + * VME58 failure mode where board reboots after the 1st + * motion related command. Since delay between motion + * command and reboot test must be long enough to avoid a + * VMEbus error, delay is excessive for normal operation. + * Hence, the oms58_reboot_test external variable. * */ @@ -167,6 +174,7 @@ static inline void Debug(int level, const char *format, ...) { /* Global data. */ int oms58_num_cards = 0; +int oms58_reboot_test = 0; /* Local data required for every driver; see "motordrvComCode.h" */ #include "motordrvComCode.h" @@ -720,7 +728,20 @@ static RTN_STATUS send_mess(int card, char const *com, char *name) Debug(4, "send_mess: sent card %d message:", card); Debug(4, "%s\n", outbuf); - pmotor->outPutIndex = putIndex; /* Message Sent */ + pmotor->outPutIndex = putIndex; /* Send message. */ + + if (oms58_reboot_test != 0) /* Test if board has rebooted after sending message. */ + { + epicsThreadSleep(0.300); + if (pmotor->rebootind != 0x4321) + { + errlogPrintf(rebootmsg, card); + /* Disable board. */ + motor_state[card] = (struct controller *)NULL; + epicsThreadSleep(1.0); + return (ERROR); + } + } for (count = 0; (putIndex != pmotor->outGetIndex) && (count < 1000); count++) { From 38cfa6aedfa6fb375d9306a0e2f5f86674af25ce Mon Sep 17 00:00:00 2001 From: Mark Rivers Date: Tue, 7 Mar 2017 13:41:32 -0600 Subject: [PATCH 14/27] Minor corrections --- motorApp/MotorSrc/README | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/motorApp/MotorSrc/README b/motorApp/MotorSrc/README index 99781856..f4eabee2 100644 --- a/motorApp/MotorSrc/README +++ b/motorApp/MotorSrc/README @@ -1,5 +1,3 @@ -Here's my best guess at what all this stuff is. TMM - Model 3 (asyn, C++) driver base classes -------------------------------- asynMotorAxis.cpp @@ -10,17 +8,20 @@ asynMotorController.h Model 2 and Model 3 device support -------------------------------- devMotorAsyn.c +motor_interface.h Model 2 (asyn, C) -------------- drvMotorAsyn.c -motor_interface.h paramLib.c paramLib.h +Definitions used in record, device support, and utilities +--------------------------------------------------------- +motor.h + motor record ------------ -motor.h motorRecord.cc motorRecord.dbd From 02612bad41d75ac772648b04cb5130d02c354706 Mon Sep 17 00:00:00 2001 From: "J. Lewis Muir" Date: Wed, 8 Mar 2017 07:05:27 -0600 Subject: [PATCH 15/27] Fix motorApp/MotorSrc/README header dash lines Make motorApp/MotorSrc/README header dash lines match length of header text. --- motorApp/MotorSrc/README | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/motorApp/MotorSrc/README b/motorApp/MotorSrc/README index f4eabee2..034c35a0 100644 --- a/motorApp/MotorSrc/README +++ b/motorApp/MotorSrc/README @@ -1,17 +1,17 @@ Model 3 (asyn, C++) driver base classes --------------------------------- +--------------------------------------- asynMotorAxis.cpp asynMotorAxis.h asynMotorController.cpp asynMotorController.h Model 2 and Model 3 device support --------------------------------- +---------------------------------- devMotorAsyn.c motor_interface.h Model 2 (asyn, C) --------------- +----------------- drvMotorAsyn.c paramLib.c paramLib.h @@ -26,7 +26,7 @@ motorRecord.cc motorRecord.dbd Model 1 (non-asyn) device/driver support ------------------------------- +---------------------------------------- motordevCom.cc motordevCom.h motordrvCom.cc From 66b211adee4d965b96ad7eddf63b5261c9c4a4b4 Mon Sep 17 00:00:00 2001 From: sluiter Date: Thu, 6 Apr 2017 16:02:31 -0500 Subject: [PATCH 16/27] Remove 'MAXv_axis[]' related compiler warnings and unused variables 'got_encoder'. --- motorApp/OmsSrc/drvMAXv.cc | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/motorApp/OmsSrc/drvMAXv.cc b/motorApp/OmsSrc/drvMAXv.cc index 2bf305e5..7134c603 100644 --- a/motorApp/OmsSrc/drvMAXv.cc +++ b/motorApp/OmsSrc/drvMAXv.cc @@ -93,7 +93,7 @@ USAGE... Motor record driver level support for OMS model MAXv. * command into two commands. * - Fix for intermittent wrong command displayed from Command Error message. motorIsr() saves the * message in a separate static buffer. - * 26 11-05-13 rls - Valid IRQ levels are 2 thru 6. + * 26 02-08-16 rls - Valid IRQ levels are 2 thru 6. * */ @@ -167,7 +167,7 @@ static epicsAddressType MAXv_ADDRS_TYPE; static volatile unsigned MAXvInterruptVector = 0; static volatile epicsUInt8 omsInterruptLevel = OMS_INT_LEVEL; static volatile int motionTO = 10; -static char *MAXv_axis[] = {"X", "Y", "Z", "T", "U", "V", "R", "S"}; +static const char *MAXv_axis[] = {"X", "Y", "Z", "T", "U", "V", "R", "S"}; static double quantum; static char **initstring = 0; static epicsUInt32 MAXv_brd_size; /* card address boundary */ @@ -254,7 +254,7 @@ struct driver_table MAXv_access = query_done, NULL, &initialized, - MAXv_axis + (char **) MAXv_axis }; struct drvMAXv_drvet @@ -308,10 +308,10 @@ static void query_done(int card, int axis, struct mess_node *nodeptr) { char buffer[MAX_IDENT_LEN]; - send_recv_mess(card, DONE_QUERY, MAXv_axis[axis], buffer, 1); + send_recv_mess(card, DONE_QUERY, (char *) MAXv_axis[axis], buffer, 1); if (nodeptr->status.Bits.RA_PROBLEM) - send_mess(card, AXIS_STOP, MAXv_axis[axis]); + send_mess(card, AXIS_STOP, (char *) MAXv_axis[axis]); } @@ -372,7 +372,6 @@ static int set_status(int card, int signal) char q_buf[MAX_IDENT_LEN], outbuf[50]; int index; bool ls_active = false; - bool got_encoder; msta_field status; int absoluteAxis = (configurationFlags[card] & (1 << signal)); @@ -406,16 +405,14 @@ static int set_status(int card, int signal) if (motor_info->encoder_present == YES) { /* get 4 pieces of info from axis */ - send_recv_mess(card, "QA", MAXv_axis[signal], &q_buf[0], 1); + send_recv_mess(card, "QA", (char *) MAXv_axis[signal], &q_buf[0], 1); q_buf[4] = ','; - send_recv_mess(card, "EA", MAXv_axis[signal], &q_buf[5], 1); - got_encoder = true; + send_recv_mess(card, "EA", (char *) MAXv_axis[signal], &q_buf[5], 1); } else { /* get 2 pieces of info from axis */ - send_recv_mess(card, AXIS_INFO, MAXv_axis[signal], q_buf, 1); - got_encoder = false; + send_recv_mess(card, AXIS_INFO, (char *) MAXv_axis[signal], q_buf, 1); } for (index = 0, p = epicsStrtok_r(q_buf, ",", &tok_save); p; @@ -477,7 +474,7 @@ static int set_status(int card, int signal) if (motor_info->no_motion_count > motionTO) { status.Bits.RA_PROBLEM = 1; - send_mess(card, AXIS_STOP, MAXv_axis[signal]); + send_mess(card, AXIS_STOP, (char *) MAXv_axis[signal]); motor_info->no_motion_count = 0; errlogSevPrintf(errlogMinor, "Motor motion timeout ERROR on card: %d, signal: %d\n", card, signal); @@ -491,7 +488,7 @@ static int set_status(int card, int signal) status.Bits.RA_PROBLEM = 0; /* get command velocity */ - send_recv_mess(card, "RV", MAXv_axis[signal], q_buf, 1); + send_recv_mess(card, "RV", (char *) MAXv_axis[signal], q_buf, 1); motor_info->velocity = atoi(q_buf); /* Get encoder position */ @@ -584,7 +581,7 @@ errorexit: errMessage(-1, "Invalid device directive"); strcpy(buffer, nodeptr->postmsgptr); strcpy(outbuf, buffer); - send_mess(card, outbuf, MAXv_axis[signal]); + send_mess(card, outbuf, (char *) MAXv_axis[signal]); nodeptr->postmsgptr = NULL; } @@ -1308,7 +1305,7 @@ static int motor_init() STATUS1 flag1; /* Test if motor has an encoder. */ - send_mess(card_index, ENCODER_QUERY, MAXv_axis[motor_index]); + send_mess(card_index, ENCODER_QUERY, (char *) MAXv_axis[motor_index]); while (!pmotor->status1_flag.Bits.done) /* Wait for command to complete. */ epicsThreadSleep(quantum); @@ -1327,7 +1324,7 @@ static int motor_init() } /* Test if motor has PID parameters. */ - send_mess(card_index, PID_QUERY, MAXv_axis[motor_index]); + send_mess(card_index, PID_QUERY, (char *) MAXv_axis[motor_index]); while (!pmotor->status1_flag.Bits.done) /* Wait for command to complete. */ epicsThreadSleep(quantum); if (pmotor->status1_flag.Bits.cmndError) @@ -1354,9 +1351,9 @@ static int motor_init() if (pvtdata->fwver >= 1.30) { - send_recv_mess(card_index, "LM?", MAXv_axis[motor_index], axis_pos, 1); + send_recv_mess(card_index, "LM?", (char *) MAXv_axis[motor_index], axis_pos, 1); if (strcmp(axis_pos, "=f") == 0) /* If limit mode is set to "Off". */ - send_mess(card_index, "LMH", MAXv_axis[motor_index]); /* Set limit mode to "Hard". */ + send_mess(card_index, "LMH", (char *) MAXv_axis[motor_index]); /* Set limit mode to "Hard". */ } } @@ -1383,7 +1380,7 @@ static int motor_init() set_status(card_index, motor_index); /* Is this needed??? */ - send_recv_mess(card_index, DONE_QUERY, MAXv_axis[motor_index], axis_pos, 1); + send_recv_mess(card_index, DONE_QUERY, (char *) MAXv_axis[motor_index], axis_pos, 1); } Debug(2, "motor_init: Init Address=%p\n", localaddr); From e604c9588a087228dc6c0333818e00113df841ea Mon Sep 17 00:00:00 2001 From: sluiter Date: Thu, 6 Apr 2017 16:29:41 -0500 Subject: [PATCH 17/27] Error check for new failure mode where board reboots after 1st command with response. --- motorApp/OmsSrc/drvMAXv.cc | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/motorApp/OmsSrc/drvMAXv.cc b/motorApp/OmsSrc/drvMAXv.cc index 7134c603..c895d3b5 100644 --- a/motorApp/OmsSrc/drvMAXv.cc +++ b/motorApp/OmsSrc/drvMAXv.cc @@ -94,6 +94,7 @@ USAGE... Motor record driver level support for OMS model MAXv. * - Fix for intermittent wrong command displayed from Command Error message. motorIsr() saves the * message in a separate static buffer. * 26 02-08-16 rls - Valid IRQ levels are 2 thru 6. + * 27 04-04-17 rls - Added error check for new failure mode where board reboots after 1st command with response. * */ @@ -1190,6 +1191,7 @@ static int motor_init() epicsInt8 *startAddr; epicsInt8 *endAddr; bool wdtrip; + int rtn_code; Debug(2, "motor_init: card %d\n", card_index); @@ -1262,7 +1264,13 @@ static int motor_init() send_mess(card_index, ERROR_CLEAR, (char) NULL); send_mess(card_index, STOP_ALL, (char) NULL); - send_recv_mess(card_index, GET_IDENT, (char) NULL, (char *) pmotorState->ident, 1); + rtn_code = send_recv_mess(card_index, GET_IDENT, (char) NULL, (char *) pmotorState->ident, 1); + if (rtn_code != 0) + { + errlogPrintf("\n***MAXv card #%d Disabled*** not responding to commands!\n\n", card_index); + motor_state[card_index] = (struct controller *) NULL; + goto loopend; + } Debug(3, "Identification = %s\n", pmotorState->ident); /* Save firmware version. */ From 2b853366f48230356c869a46691acbd8c7391810 Mon Sep 17 00:00:00 2001 From: Mark Rivers Date: Tue, 18 Apr 2017 12:51:16 -0500 Subject: [PATCH 18/27] Added support for CONEX-PP --- motorApp/NewportSrc/AG_CONEX.cpp | 157 ++++++++++++++++++++----------- motorApp/NewportSrc/AG_CONEX.h | 5 +- 2 files changed, 104 insertions(+), 58 deletions(-) diff --git a/motorApp/NewportSrc/AG_CONEX.cpp b/motorApp/NewportSrc/AG_CONEX.cpp index d6baebc2..04af446f 100644 --- a/motorApp/NewportSrc/AG_CONEX.cpp +++ b/motorApp/NewportSrc/AG_CONEX.cpp @@ -1,6 +1,6 @@ /* FILENAME... AG_CONEX.cpp -USAGE... Motor driver support for the Newport CONEX-AGP and CONEX-CC series controllers. +USAGE... Motor driver support for the Newport CONEX-AGP, CONEX-CC and CONEX-PP series controllers. Mark Rivers April 11, 2013 @@ -29,6 +29,9 @@ April 11, 2013 #define CONEX_TIMEOUT 2.0 #define LINUX_WRITE_DELAY 0.1 +// We force minus end-of-run home type for Conex-PP for now +#define HOME_TYPE_MINUS_EOR 4 + /** Creates a new AG_CONEXController object. * \param[in] portName The name of the asyn port that will be created for this driver * \param[in] serialPortName The name of the drvAsynSerialPort that was created previously to connect to the CONEX controller @@ -186,6 +189,9 @@ AG_CONEXAxis::AG_CONEXAxis(AG_CONEXController *pC) KIMax_ = 1.e6; KDMax_ = 1.e6; } + else if (strstr(pC->controllerVersion_, "Conex PP")) { + conexModel_ = ModelConexPP; + } else { asynPrint(pC->pasynUserSelf, ASYN_TRACE_ERROR, "%s: unknown model, firmware string=%s\n", @@ -196,12 +202,16 @@ AG_CONEXAxis::AG_CONEXAxis(AG_CONEXController *pC) // Read the stage ID sprintf(pC_->outString_, "%dID?", pC->controllerID_); pC_->writeReadController(); - strcpy(stageID_, &pC_->inString_[4]); + strcpy(stageID_, &pC_->inString_[3]); - // Read the encoder increment - sprintf(pC_->outString_, "%dSU?", pC->controllerID_); - pC_->writeReadController(); - encoderIncrement_ = atof(&pC_->inString_[3]); + // Read the encoder increment (CC and AGP only) + if ((conexModel_ == ModelConexAGP) || (conexModel_ == ModelConexCC)) { + sprintf(pC_->outString_, "%dSU?", pC->controllerID_); + pC_->writeReadController(); + encoderIncrement_ = atof(&pC_->inString_[3]); + } else { + encoderIncrement_ = 1.; + } // Read the interpolation factor (AGP only) if (conexModel_ == ModelConexAGP) { @@ -212,8 +222,21 @@ AG_CONEXAxis::AG_CONEXAxis(AG_CONEXController *pC) interpolationFactor_ = 1.; } + if (conexModel_ == ModelConexPP) { + sprintf(pC_->outString_, "%dFRM?", pC->controllerID_); + pC_->writeReadController(); + microStepsPerFullStep_ = atoi(&pC_->inString_[4]); + sprintf(pC_->outString_, "%dFRS?", pC->controllerID_); + pC_->writeReadController(); + fullStepSize_ = atof(&pC_->inString_[4]); + } + // Compute the minimum step size - stepSize_ = encoderIncrement_ / interpolationFactor_; + if ((conexModel_ == ModelConexAGP) || (conexModel_ == ModelConexCC)) { + stepSize_ = encoderIncrement_ / interpolationFactor_; + } else { + stepSize_ = fullStepSize_ / microStepsPerFullStep_ / 1000.; + } // Read the low and high software limits sprintf(pC_->outString_, "%dSL?", pC->controllerID_); @@ -223,8 +246,10 @@ AG_CONEXAxis::AG_CONEXAxis(AG_CONEXController *pC) pC_->writeReadController(); highLimit_ = atof(&pC_->inString_[3]); - // Tell the motor record that we have an gain supprt - setIntegerParam(pC_->motorStatusGainSupport_, 1); + // Tell the motor record that we have an gain support (CC and AGP only) + if ((conexModel_ == ModelConexAGP) || (conexModel_ == ModelConexCC)) { + setIntegerParam(pC_->motorStatusGainSupport_, 1); + } } /** Reports on status of the axis @@ -236,32 +261,36 @@ AG_CONEXAxis::AG_CONEXAxis(AG_CONEXController *pC) void AG_CONEXAxis::report(FILE *fp, int level) { if (level > 0) { - // Read KOP, KI, LF - sprintf(pC_->outString_, "%dKP?", pC_->controllerID_); - pC_->writeReadController(); - KP_ = atof(&pC_->inString_[3]); - sprintf(pC_->outString_, "%dKI?", pC_->controllerID_); - pC_->writeReadController(); - KI_ = atof(&pC_->inString_[3]); - if (conexModel_ == ModelConexAGP) { - sprintf(pC_->outString_, "%dLF?", pC_->controllerID_); + // Read KOP, KI, LF (CC and AGP only) + if ((conexModel_ == ModelConexAGP) || (conexModel_ == ModelConexCC)) { + sprintf(pC_->outString_, "%dKP?", pC_->controllerID_); pC_->writeReadController(); - LF_ = atof(&pC_->inString_[3]); - } else if (conexModel_ == ModelConexCC) { - sprintf(pC_->outString_, "%dKD?", pC_->controllerID_); + KP_ = atof(&pC_->inString_[3]); + sprintf(pC_->outString_, "%dKI?", pC_->controllerID_); pC_->writeReadController(); - KD_ = atof(&pC_->inString_[3]); - LF_ = KD_; // For printout below + KI_ = atof(&pC_->inString_[3]); + if (conexModel_ == ModelConexAGP) { + sprintf(pC_->outString_, "%dLF?", pC_->controllerID_); + pC_->writeReadController(); + LF_ = atof(&pC_->inString_[3]); + } else if (conexModel_ == ModelConexCC) { + sprintf(pC_->outString_, "%dKD?", pC_->controllerID_); + pC_->writeReadController(); + KD_ = atof(&pC_->inString_[3]); + LF_ = KD_; // For printout below + } } fprintf(fp, " stageID=%s\n" " currentPosition=%f, encoderIncrement=%f\n" " interpolationFactor=%f, stepSize=%f, lowLimit=%f, highLimit=%f\n" - " KP=%f, KI=%f, KD/LF=%f\n", + " KP=%f, KI=%f, KD/LF=%f\n" + " fullStepSize=%f, microStepsPerFullStep=%d\n", stageID_, currentPosition_, encoderIncrement_, interpolationFactor_, stepSize_, lowLimit_, highLimit_, - KP_, KI_, LF_); + KP_, KI_, LF_, + fullStepSize_, microStepsPerFullStep_); } // Call the base class method @@ -273,8 +302,8 @@ asynStatus AG_CONEXAxis::move(double position, int relative, double minVelocity, asynStatus status; // static const char *functionName = "AG_CONEXAxis::move"; - // The CONEX-CC supports velocity and acceleration, the CONEX-AGP does not - if (conexModel_ == ModelConexCC) { + // The CONEX-CC and CONEX-PP support velocity and acceleration, the CONEX-AGP does not + if ((conexModel_ == ModelConexCC) || (conexModel_ == ModelConexPP)) { sprintf(pC_->outString_, "%dAC%f", pC_->controllerID_, acceleration*stepSize_); status = pC_->writeCONEX(); sprintf(pC_->outString_, "%dVA%f", pC_->controllerID_, maxVelocity*stepSize_); @@ -304,6 +333,14 @@ asynStatus AG_CONEXAxis::home(double minVelocity, double maxVelocity, double acc // and writing to non-volatile memory with the OH command. // This is time-consuming and can only be done a limited number of times so we don't do it here. + // The CONEX-PP supports home velocity and home type. We force negative limit switch home type. + if (conexModel_ == ModelConexPP) { + sprintf(pC_->outString_, "%dOH%f", pC_->controllerID_, maxVelocity); + status = pC_->writeCONEX(); + sprintf(pC_->outString_, "%dHT%d", pC_->controllerID_, HOME_TYPE_MINUS_EOR); + status = pC_->writeCONEX(); + } + sprintf(pC_->outString_, "%dOR", pC_->controllerID_); status = pC_->writeCONEX(); return status; @@ -367,52 +404,58 @@ asynStatus AG_CONEXAxis::getClosedLoop(bool *closedLoop) asynStatus AG_CONEXAxis::setPGain(double pGain) { - asynStatus status; + asynStatus status = asynSuccess; bool closedLoop; //static const char *functionName = "AG_CONEXAxis::setPGain"; - getClosedLoop(&closedLoop); - setClosedLoop(false); - // The pGain value from the motor record is between 0 and 1. - sprintf(pC_->outString_, "%dKP%f", pC_->controllerID_, pGain*KPMax_); - status = pC_->writeCONEX(); - if (closedLoop) setClosedLoop(true); + if ((conexModel_ == ModelConexAGP) || (conexModel_ == ModelConexCC)) { + getClosedLoop(&closedLoop); + setClosedLoop(false); + // The pGain value from the motor record is between 0 and 1. + sprintf(pC_->outString_, "%dKP%f", pC_->controllerID_, pGain*KPMax_); + status = pC_->writeCONEX(); + if (closedLoop) setClosedLoop(true); + } return status; } asynStatus AG_CONEXAxis::setIGain(double iGain) { - asynStatus status; + asynStatus status = asynSuccess; bool closedLoop; //static const char *functionName = "AG_CONEXAxis::setIGain"; - getClosedLoop(&closedLoop); - setClosedLoop(false); - // The iGain value from the motor record is between 0 and 1. - sprintf(pC_->outString_, "%dKI%f", pC_->controllerID_, iGain*KIMax_); - status = pC_->writeCONEX(); - if (closedLoop) setClosedLoop(true); + if ((conexModel_ == ModelConexAGP) || (conexModel_ == ModelConexCC)) { + getClosedLoop(&closedLoop); + setClosedLoop(false); + // The iGain value from the motor record is between 0 and 1. + sprintf(pC_->outString_, "%dKI%f", pC_->controllerID_, iGain*KIMax_); + status = pC_->writeCONEX(); + if (closedLoop) setClosedLoop(true); + } return status; } asynStatus AG_CONEXAxis::setDGain(double dGain) { - asynStatus status; + asynStatus status = asynSuccess; bool closedLoop; //static const char *functionName = "AG_CONEXAxis::setPGain"; - getClosedLoop(&closedLoop); - setClosedLoop(false); - if (conexModel_ == ModelConexCC) { - // The dGain value from the motor record is between 0 and 1. - sprintf(pC_->outString_, "%dKI%f", pC_->controllerID_, dGain*KDMax_); - } else if (conexModel_ == ModelConexAGP) { - // We are using the DGain for the Low pass filter frequency. - // DGain value is between 0 and 1 - sprintf(pC_->outString_, "%dLF%f", pC_->controllerID_, dGain*LFMax_); + if ((conexModel_ == ModelConexAGP) || (conexModel_ == ModelConexCC)) { + getClosedLoop(&closedLoop); + setClosedLoop(false); + if (conexModel_ == ModelConexCC) { + // The dGain value from the motor record is between 0 and 1. + sprintf(pC_->outString_, "%dKI%f", pC_->controllerID_, dGain*KDMax_); + } else if (conexModel_ == ModelConexAGP) { + // We are using the DGain for the Low pass filter frequency. + // DGain value is between 0 and 1 + sprintf(pC_->outString_, "%dLF%f", pC_->controllerID_, dGain*LFMax_); + } + status = pC_->writeCONEX(); + if (closedLoop) setClosedLoop(true); } - status = pC_->writeCONEX(); - if (closedLoop) setClosedLoop(true); return status; } @@ -455,10 +498,10 @@ asynStatus AG_CONEXAxis::poll(bool *moving) setIntegerParam(pC_->motorStatusDone_, done); *moving = done ? false:true; - // The meaning of the error bits is different for the CC and AGP - if (conexModel_ == ModelConexCC) { - if (status & 0x100) lowLimit = 1; - if (status & 0x200) highLimit = 1; + // The meaning of the error bits is different for the CC, AGP, and PP + if ((conexModel_ == ModelConexCC) || (conexModel_ == ModelConexPP)) { + if (status & 0x100) lowLimit = 1; + if (status & 0x200) highLimit = 1; } setIntegerParam(pC_->motorStatusLowLimit_, lowLimit); diff --git a/motorApp/NewportSrc/AG_CONEX.h b/motorApp/NewportSrc/AG_CONEX.h index 5191c45a..f5ffbdf8 100644 --- a/motorApp/NewportSrc/AG_CONEX.h +++ b/motorApp/NewportSrc/AG_CONEX.h @@ -12,7 +12,8 @@ April 11, 2013 typedef enum { ModelConexAGP, - ModelConexCC + ModelConexCC, + ModelConexPP } ConexModel_t; // No controller-specific parameters yet @@ -43,6 +44,8 @@ private: double encoderIncrement_; double interpolationFactor_; double stepSize_; + double fullStepSize_; + int microStepsPerFullStep_; double highLimit_; double lowLimit_; double KP_; From 4afa9424488feffb388b6646d7ad2fa1a4766f01 Mon Sep 17 00:00:00 2001 From: Mark Rivers Date: Tue, 18 Apr 2017 12:58:20 -0500 Subject: [PATCH 19/27] New file --- .../iocWithAsyn/motor.substitutions.CONEX-PP | 9 ++++ iocBoot/iocWithAsyn/st.cmd.CONEX-PP | 45 +++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 iocBoot/iocWithAsyn/motor.substitutions.CONEX-PP create mode 100644 iocBoot/iocWithAsyn/st.cmd.CONEX-PP diff --git a/iocBoot/iocWithAsyn/motor.substitutions.CONEX-PP b/iocBoot/iocWithAsyn/motor.substitutions.CONEX-PP new file mode 100644 index 00000000..78df4c27 --- /dev/null +++ b/iocBoot/iocWithAsyn/motor.substitutions.CONEX-PP @@ -0,0 +1,9 @@ +file "$(TOP)/db/basic_asyn_motor.db" +{ +pattern +{P, N, M, DTYP, PORT, ADDR, DESC, EGU, DIR, VELO, VBAS, ACCL, BDST, BVEL, BACC, MRES, PREC, DHLM, DLLM, INIT} +# Newport NSA12 stage, 6.35 microns/full step, 128 micro-steps/s +{IOC:, 1, "m$(N)", "asynMotor", CONEX1, 0, "X", mm, Pos, 1., 0.1, .25, 0, 1, .2, 4.9609375e-5, 4, 28, -1, ""} +{IOC:, 2, "m$(N)", "asynMotor", CONEX2, 0, "Y", mm, Pos, 1., 0.1, .25, 0, 1, .2, 4.9609375e-5, 4, 28, -1, ""} +{IOC:, 3, "m$(N)", "asynMotor", CONEX3, 0, "Z", mm, Pos, 1., 0.1, .25, 0, 1, .2, 4.9609375e-5, 4, 28, -1, ""} +} diff --git a/iocBoot/iocWithAsyn/st.cmd.CONEX-PP b/iocBoot/iocWithAsyn/st.cmd.CONEX-PP new file mode 100644 index 00000000..4447b287 --- /dev/null +++ b/iocBoot/iocWithAsyn/st.cmd.CONEX-PP @@ -0,0 +1,45 @@ +#errlogInit(5000) +< envPaths +# Tell EPICS all about the record types, device-support modules, drivers, +# etc. +dbLoadDatabase("../../dbd/WithAsyn.dbd") +WithAsyn_registerRecordDeviceDriver(pdbbase) + +### Motors +dbLoadTemplate "motor.substitutions.CONEX-PP" + +# For Windows +drvAsynSerialPortConfigure("serial1", "COM8", 0, 0, 0) +# For Linux +#drvAsynSerialPortConfigure("serial1", "/dev/ttyUSB0", 0, 0, 0) +asynOctetSetInputEos("serial1",0,"\r\n") +asynOctetSetOutputEos("serial1",0,"\r\n") +asynSetOption("serial1",0,"baud","115200") +asynSetOption("serial1",0,"bits","8") +asynSetOption("serial1",0,"stop","1") +asynSetOption("serial1",0,"parity","none") +asynSetOption("serial1",0,"clocal","Y") +asynSetOption("serial1",0,"crtscts","N") + +asynSetTraceIOMask("serial1", 0, 2) +#asynSetTraceMask("serial1", 0, 9) + +# Load asyn record +dbLoadRecords("$(ASYN)/db/asynRecord.db", "P=IOC:,R=serial1,PORT=serial1, ADDR=0,OMAX=256,IMAX=256") + +# AG_CONEXCreateController(asyn port, serial port, controllerID, +# active poll period (ms), idle poll period (ms)) +AG_CONEXCreateController("CONEX1", "serial1", 1, 50, 500) +asynSetTraceIOMask("CONEX1", 0, 2) +#asynSetTraceMask("CONEX1", 0, 255) +AG_CONEXCreateController("CONEX2", "serial1", 2, 50, 500) +asynSetTraceIOMask("CONEX2", 0, 2) +#asynSetTraceMask("CONEX2", 0, 255) +AG_CONEXCreateController("CONEX3", "serial1", 3, 50, 500) +asynSetTraceIOMask("CONEX3", 0, 2) +#asynSetTraceMask("CONEX3", 0, 255) + +iocInit + +dbpf IOC:m1.RTRY 0 +dbpf IOC:m1.NTM 0 From d10c31ff2e7a72603947169f4b6b473510129f06 Mon Sep 17 00:00:00 2001 From: Keenan Lang Date: Wed, 19 Apr 2017 16:01:07 -0500 Subject: [PATCH 20/27] Fixed Formatting --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fae0d79e..10ca1150 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ For more information, see: * [HTML documentation](https://github.com/epics-modules/motor/blob/master/documentation/README.md) [Report an issue with Motor](https://github.com/epics-modules/motor/issues/new?title=%20ISSUE%20NAME%20HERE&body=**Describe%20the%20issue**%0A%0A**Steps%20to%20reproduce**%0A1.%20Step%20one%0A2.%20Step%20two%0A3.%20Step%20three%0A%0A**Expected%20behaivour**%0A%0A**Actual%20behaviour**%0A%0A**Build%20Environment**%0AArchitecture:%0AEpics%20Base%20Version:%0ADependent%20Module%20Versions:&labels=bug) -[Request a feature](https://github.com/epics-modules/motor/issues/new?title=%20FEATURE%20SHORT%20DESCRIPTION&body=**Feature Long Description**%0A%0A**Why%20should%20this%20be%20added?**%0A&labels=enhancement) +[Request a feature](https://github.com/epics-modules/motor/issues/new?title=%20FEATURE%20SHORT%20DESCRIPTION&body=**Feature%20Long%20Description**%0A%0A**Why%20should%20this%20be%20added?**%0A&labels=enhancement) converted from APS SVN repository: Fri Oct 16 12:31:41 CDT 2015 From 4125a39c4026f4729c70e0700e78c5d01a16d034 Mon Sep 17 00:00:00 2001 From: Keenan Lang Date: Wed, 3 May 2017 10:15:20 -0500 Subject: [PATCH 21/27] Add iocsh bindings for oms58Setup command --- motorApp/OmsSrc/devOms.dbd | 1 + motorApp/OmsSrc/drvOms58.cc | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/motorApp/OmsSrc/devOms.dbd b/motorApp/OmsSrc/devOms.dbd index d0b4f55e..569232b4 100644 --- a/motorApp/OmsSrc/devOms.dbd +++ b/motorApp/OmsSrc/devOms.dbd @@ -5,6 +5,7 @@ driver(drvOms) # Oregon Micro Systems VME58 driver support. device(motor,VME_IO,devOms58,"OMS VME58") driver(drvOms58) +registrar(oms58Registrar) # Oregon Micro Systems MAXv driver support. device(motor,VME_IO,devMAXv,"OMS MAXv") diff --git a/motorApp/OmsSrc/drvOms58.cc b/motorApp/OmsSrc/drvOms58.cc index 2643ef61..38511374 100644 --- a/motorApp/OmsSrc/drvOms58.cc +++ b/motorApp/OmsSrc/drvOms58.cc @@ -141,6 +141,7 @@ USAGE... Motor record driver level support for OMS model VME58. #include "drvOms58.h" #include "epicsExport.h" +#include "iocsh.h" #define PRIVATE_FUNCTIONS 1 /* normal:1, debug:0 */ @@ -1357,4 +1358,28 @@ static void oms_reset(void *arg) } +/* Epics iocsh bindings */ + +static const iocshArg oms58Arg0 = {"num_card", iocshArgInt}; +static const iocshArg oms58Arg1 = {"addrs", iocshArgInt}; +static const iocshArg oms58Arg2 = {"vector", iocshArgInt}; +static const iocshArg oms58Arg3 = {"int_level", iocshArgInt}; +static const iocshArg oms58Arg4 = {"scan_rate", iocshArgInt}; + +static const iocshArg* const oms58Args[5] = {&oms58Arg0, &oms58Arg1, &oms58Arg2, &oms58Arg3, &oms58Arg4}; + +static const iocshFuncDef oms58FuncDef = {"oms58Setup", 5, oms58Args}; + +static void oms58CallFunc(const iocshArgBuf* args) +{ + oms58Setup(args[0].ival, (void*) args[1].ival, (unsigned) args[2].ival, args[3].ival, args[4].ival); +} + +void oms58Registrar(void) +{ + iocshRegister(&oms58FuncDef, &oms58CallFunc); +} + +epicsExportRegistrar(oms58Registrar); + /*---------------------------------------------------------------------*/ From b9002b745d950df7b9daf56e2a4614dc2014210d Mon Sep 17 00:00:00 2001 From: "Kurt A. Goetze" Date: Fri, 14 Jul 2017 16:42:36 -0500 Subject: [PATCH 22/27] add AMCISrc dir --- motorApp/AMCISrc/AMCIRegister.cc | 52 +++ motorApp/AMCISrc/AMCIRegister.h | 44 +++ motorApp/AMCISrc/ANG1Driver.cpp | 640 +++++++++++++++++++++++++++++++ motorApp/AMCISrc/ANG1Driver.h | 88 +++++ motorApp/AMCISrc/ANG1Support.dbd | 2 + motorApp/AMCISrc/Makefile | 29 ++ motorApp/AMCISrc/README | 49 +++ 7 files changed, 904 insertions(+) create mode 100644 motorApp/AMCISrc/AMCIRegister.cc create mode 100644 motorApp/AMCISrc/AMCIRegister.h create mode 100644 motorApp/AMCISrc/ANG1Driver.cpp create mode 100644 motorApp/AMCISrc/ANG1Driver.h create mode 100644 motorApp/AMCISrc/ANG1Support.dbd create mode 100644 motorApp/AMCISrc/Makefile create mode 100644 motorApp/AMCISrc/README diff --git a/motorApp/AMCISrc/AMCIRegister.cc b/motorApp/AMCISrc/AMCIRegister.cc new file mode 100644 index 00000000..ce0afdf5 --- /dev/null +++ b/motorApp/AMCISrc/AMCIRegister.cc @@ -0,0 +1,52 @@ +/* +FILENAME... AMCIRegister.cc +USAGE... Register AMCI motor device driver shell commands. + +Version: $Revision: 1.4 $ +Modified By: $Author: sluiter $ +Last Modified: $Date: 2004-07-16 19:06:58 $ +*/ + +/***************************************************************** + COPYRIGHT NOTIFICATION +***************************************************************** + +(C) COPYRIGHT 1993 UNIVERSITY OF CHICAGO + +This software was developed under a United States Government license +described on the COPYRIGHT_UniversityOfChicago file included as part +of this distribution. +**********************************************************************/ + +#include +#include "AMCIRegister.h" +#include "epicsExport.h" + +extern "C" +{ + +// AMCI ANG1 Setup arguments +static const iocshArg setupArg0 = {"asyn port name", iocshArgString}; +static const iocshArg setupArg1 = {"Input port name", iocshArgString}; +static const iocshArg setupArg2 = {"Output port name", iocshArgString}; +static const iocshArg setupArg3 = {"Number of axes", iocshArgInt}; +static const iocshArg setupArg4 = {"Polling rate moving", iocshArgInt}; +static const iocshArg setupArg5 = {"Polling rate idle", iocshArgInt}; + +static const iocshArg * const ANG1SetupArgs[6] = {&setupArg0, &setupArg1, &setupArg2, &setupArg3, &setupArg4, &setupArg5}; + +static const iocshFuncDef setupANG1 = {"ANG1Setup", 6, ANG1SetupArgs}; + +static void setupANG1CallFunc(const iocshArgBuf *args) +{ + ANG1Setup(args[0].sval, args[1].sval, args[2].sval, args[3].ival, args[4].ival, args[5].ival); +} + +static void AMCIRegister(void) +{ + iocshRegister(&setupANG1, setupANG1CallFunc); +} + +epicsExportRegistrar(AMCIRegister); + +} // extern "C" diff --git a/motorApp/AMCISrc/AMCIRegister.h b/motorApp/AMCISrc/AMCIRegister.h new file mode 100644 index 00000000..98511177 --- /dev/null +++ b/motorApp/AMCISrc/AMCIRegister.h @@ -0,0 +1,44 @@ +/* +FILENAME... AMCIRegister.h +USAGE... This file contains function prototypes for AMCI IOC shell commands. + +Version: $Revision: 1.3 $ +Modified By: $Author: sluiter $ +Last Modified: $Date: 2004-07-16 19:06:58 $ +*/ + +/* + * Original Author: Ron Sluiter + * Date: 05/19/03 + * + * Experimental Physics and Industrial Control System (EPICS) + * + * Copyright 1991, the Regents of the University of California, + * and the University of Chicago Board of Governors. + * + * This software was produced under U.S. Government contracts: + * (W-7405-ENG-36) at the Los Alamos National Laboratory, + * and (W-31-109-ENG-38) at Argonne National Laboratory. + * + * Initial development by: + * The Controls and Automation Group (AT-8) + * Ground Test Accelerator + * Accelerator Technology Division + * Los Alamos National Laboratory + * + * Co-developed with + * The Controls and Computing Group + * Accelerator Systems Division + * Advanced Photon Source + * Argonne National Laboratory + * + * Modification Log: + * ----------------- + */ + +#include "motor.h" +#include "motordrvCom.h" + +/* Function prototypes. */ +extern RTN_STATUS ANG1Setup(const char *, const char *, const char *, int, int, int); + diff --git a/motorApp/AMCISrc/ANG1Driver.cpp b/motorApp/AMCISrc/ANG1Driver.cpp new file mode 100644 index 00000000..9b16ed9c --- /dev/null +++ b/motorApp/AMCISrc/ANG1Driver.cpp @@ -0,0 +1,640 @@ +/* +FILENAME... ANG1Driver.cpp +USAGE... Motor record driver support for the AMCI ANG1 stepper motor controller over Modbus/TCP. + +Kurt Goetze + +Based on the ACS MCB-4B Model 3 device driver written by Mark Rivers + +*/ + + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "ANG1Driver.h" +#include + +#define NINT(f) (int)((f)>0 ? (f)+0.5 : (f)-0.5) + +static const char *driverName = "ANG1MotorDriver"; + +/*** Input Registers ***/ +#define STATUS_1 0 +#define STATUS_2 1 +#define POS_RD_UPR 2 +#define POS_RD_LWR 3 +#define EN_POS_UPR 4 +#define EN_POS_LWR 5 +#define EN_CAP_UPR 6 +#define EN_CAP_LWR 7 +#define MOT_CUR 8 // programmed motor current (x10) +#define JERK_RD 9 + +/*** Output Registers ***/ +#define CMD_MSW 0 // module 0 starts at register address 1024. This is set in drvModbusAsynConfigure. +#define CMD_LSW 1 +#define POS_WR_UPR 2 +#define POS_WR_LWR 3 +#define SPD_UPR 4 +#define SPD_LWR 5 +#define ACCEL 6 +#define DECEL 7 +// Not used must equal zero #define RESERVED 8 +#define JERK 9 + +/** Constructor, Creates a new ANG1Controller object. + * \param[in] portName The name of the asyn port that will be created for this driver + * \param[in] ANG1InPortName The name of the drvAsynSerialPort that was created previously to connect to the ANG1 controller + * \param[in] ANG1OutPortName The name of the drvAsynSerialPort that was created previously to connect to the ANG1 controller + * \param[in] numAxes The number of axes that this controller supports + * \param[in] movingPollPeriod The time between polls when any axis is moving + * \param[in] idlePollPeriod The time between polls when no axis is moving + */ +ANG1Controller::ANG1Controller(const char *portName, const char *ANG1InPortName, const char *ANG1OutPortName, int numAxes, + double movingPollPeriod, double idlePollPeriod) + : asynMotorController(portName, numAxes, NUM_ANG1_PARAMS, + 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 +{ + int axis, i; + asynStatus status; + ANG1Axis *pAxis; + static const char *functionName = "ANG1Controller::ANG1Controller"; + + inputDriver_ = epicsStrDup(ANG1InPortName); // Set this before calls to create Axis objects + + // Create controller-specific parameters + createParam(ANG1JerkString, asynParamInt32, &ANG1Jerk_); + + /* Connect to ANG1 controller */ + for (i=0; iconnect(ANG1InPortName, i, &pasynUserInReg_[i], NULL); + } + for (i=0; iconnect(ANG1OutPortName, i, &pasynUserOutReg_[i], NULL); + } + if (status) { + asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, + "%s: cannot connect to ANG1 controller\n", + functionName); + } + for (axis=0; axis 0 then information is printed about each axis. + * After printing controller-specific information it calls asynMotorController::report() + */ +void ANG1Controller::report(FILE *fp, int level) +{ + fprintf(fp, "ANG1 motor driver %s, numAxes=%d, moving poll period=%f, idle poll period=%f\n", + this->portName, numAxes_, movingPollPeriod_, idlePollPeriod_); + + // Call the base class method + asynMotorController::report(fp, level); +} + +/** Returns a pointer to an ANG1Axis object. + * Returns NULL if the axis number encoded in pasynUser is invalid. + * \param[in] pasynUser asynUser structure that encodes the axis index number. */ +ANG1Axis* ANG1Controller::getAxis(asynUser *pasynUser) +{ +// ? return static_cast(asynMotorController::getAxis(pANG1Axis methodsasynUser)); + return static_cast(asynMotorController::getAxis(pasynUser)); +} + +/** Returns a pointer to an ANG1Axis object. + * Returns NULL if the axis number encoded in pasynUser is invalid. + * \param[in] No Axis index number. */ +ANG1Axis* ANG1Controller::getAxis(int axisNo) +{ + return static_cast(asynMotorController::getAxis(axisNo)); +} + +/** Called when asyn clients call pasynInt32->write(). + * Extracts the function and axis number from pasynUser. + * Sets the value in the parameter library (?) + * If the function is ANG1Jerk_ it sets the jerk value in the controller. + * Calls any registered callbacks for this pasynUser->reason and address. + * For all other functions it calls asynMotorController::writeInt32. + * \param[in] pasynUser asynUser structure that encodes the reason and address. + * \param[in] value Value to write. */ +asynStatus ANG1Controller::writeInt32(asynUser *pasynUser, epicsInt32 value) +{ + int function = pasynUser->reason; + asynStatus status = asynSuccess; + ANG1Axis *pAxis = getAxis(pasynUser); + static const char *functionName = "writeInt32"; + + /* Set the parameter and readback in the parameter library. */ + status = setIntegerParam(pAxis->axisNo_, function, value); + + if (function == ANG1Jerk_) + { + // Jerk in units steps/sec/sec/sec (0 - 5000) + printf("Jerk = %d\n", value); + status = writeReg16(JERK, value, DEFAULT_CONTROLLER_TIMEOUT); + +// sprintf(outString_, "%s JOG JRK %f", pAxis->axisName_, value); +// status = writeController(); + + } else { + /* Call base class method */ + status = asynMotorController::writeInt32(pasynUser, value); + } + + /* Do callbacks so higher layers see any changes */ + pAxis->callParamCallbacks(); + if (status) + asynPrint(pasynUser, ASYN_TRACE_ERROR, + "%s:%s: error, status=%d function=%d, value=%d\n", + driverName, functionName, status, function, value); + else + asynPrint(pasynUser, ASYN_TRACEIO_DRIVER, + "%s:%s: function=%d, value=%d\n", + driverName, functionName, function, value); + return status; +} + +asynStatus ANG1Controller::writeReg16(int reg, int output, double timeout) +{ + asynStatus status; + + //printf("writeReg16: writing %d to register %d\n", output, reg); + asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER,"writeReg16: writing %d to register %d\n", output, reg); + status = pasynInt32SyncIO->write(pasynUserOutReg_[reg], output, timeout); + epicsThreadSleep(0.01); + + return status ; +} + +asynStatus ANG1Controller::writeReg32(int reg, int output, double timeout) +{ +//.. break 32-bit integer into 2 pieces +//.. write the pieces into ANG1 registers + + asynStatus status; + float fnum; + int lower,upper; + + fnum = (output / 1000.0); + upper = (int)fnum; + fnum = fnum - upper; + fnum = NINT(fnum * 1000); + lower = (int)fnum; + +//could write the words this way +// status = pasynInt32SyncIO->write(pasynUserOutReg_[reg], upper, timeout); +// status = pasynInt32SyncIO->write(pasynUserOutReg_[reg+1], lower, timeout); + +//or this way +// writeReg16(piece1 ie MSW ... + status = writeReg16(reg, upper, DEFAULT_CONTROLLER_TIMEOUT); + +// writeReg16(piece2 ie LSW ... + reg++; + status = writeReg16(reg, lower, DEFAULT_CONTROLLER_TIMEOUT); + + return status ; +} + +asynStatus ANG1Controller::readReg16(int reg, epicsInt32 *input, double timeout) +{ + asynStatus status; + + //printf("reg = %d\n", reg); + asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER,"readReg16 reg = %d\n", reg); + status = pasynInt32SyncIO->read(pasynUserInReg_[reg], input, timeout); + + return status ; +} + +asynStatus ANG1Controller::readReg32(int reg, epicsInt32 *combo, double timeout) +{ +//.. read 2 16-bit words from ANG1 registers +//.. assemble 2 16-bit pieces into 1 32-bit integer + + asynStatus status; +// float fnum; + epicsInt32 lowerWord32, upperWord32; // only have pasynInt32SyncIO, not pasynInt16SyncIO , + epicsInt16 lowerWord16, upperWord16; // so we need to get 32-bits and cast to 16-bit integer + + //printf("calling readReg16\n"); + status = readReg16(reg, &upperWord32, timeout); //get Upper Word + upperWord16 = (epicsInt16)upperWord32; + //printf("upperWord16: %d\n", upperWord16); + asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER,"readReg32 upperWord16: %d\n", upperWord16); + + // if status != 1 : + reg++; + status = readReg16(reg, &lowerWord32, timeout); //get Lower Word + lowerWord16 = (epicsInt16)lowerWord32; + //printf("lowerWord16: %d\n", lowerWord16); + asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER,"readReg32 lowerWord16: %d\n", lowerWord16); + + *combo = NINT((upperWord16 * 1000) + lowerWord16); + + return status ; +} + + +// ANG1Axis methods Here +// These are the ANG1Axis methods + +/** Creates a new ANG1Axis object. + * \param[in] pC Pointer to the ANG1Controller to which this axis belongs. + * \param[in] axisNo Index number of this axis, range 0 to pC->numAxes_-1. + * + * Initializes register numbers, etc. + */ +ANG1Axis::ANG1Axis(ANG1Controller *pC, int axisNo) + : asynMotorAxis(pC, axisNo), + pC_(pC) +{ + int status; + + //status = pasynInt32SyncIO->connect(myModbusInputDriver, 0, &pasynUserForceRead_, "MODBUS_READ"); + status = pasynInt32SyncIO->connect(pC_->inputDriver_, 0, &pasynUserForceRead_, "MODBUS_READ"); + if (status) { + //printf("%s:%s: Error, unable to connect pasynUserForceRead_ to Modbus input driver %s\n", pC_->inputDriver_, pC_->functionName, myModbusInputDriver); + printf("%s: Error, unable to connect pasynUserForceRead_ to Modbus input driver\n", pC_->inputDriver_); + } + printf("ANG1Axis::ANG1Axis : pasynUserForceRead_->reason=%d\n", pasynUserForceRead_->reason); + + // set position to 0 + setPosition(0); +} + +/** Reports on status of the axis + * \param[in] fp The file pointer on which report information will be written + * \param[in] level The level of report detail desired + * + * After printing device-specific information calls asynMotorAxis::report() + */ +void ANG1Axis::report(FILE *fp, int level) +{ + if (level > 0) { + fprintf(fp, " axis %d\n", + axisNo_); + } + + // Call the base class method + asynMotorAxis::report(fp, level); +} + +// SET VEL & ACCEL +asynStatus ANG1Axis::sendAccelAndVelocity(double acceleration, double velocity) +{ + asynStatus status; + // static const char *functionName = "ANG1::sendAccelAndVelocity"; + + // Send the velocity in egus + //sprintf(pC_->outString_, "%1dVA%f", axisNo_ + 1, (velocity*stepSize_)); + //status = pC_->writeController(); + status = pC_->writeReg32(SPD_UPR, NINT(velocity), DEFAULT_CONTROLLER_TIMEOUT); + + // Send the acceleration in egus/sec/sec + //printf(" velocity: %f\n", velocity); + //printf(" acceleration: %f\n", acceleration); + // ANG1 acceleration range 1 to 5000 steps/ms/sec + // Therefore need to limit range received by motor record from 1000 to 5e6 steps/sec/sec + if (acceleration < 1000) { + // print message noting that accel has been capped low + acceleration = 1000; + } + if (acceleration > 5000000) { + // print message noting that accel has been capped high + acceleration = 5000000; + } + // ANG1 acceleration units are steps/millisecond/second, so we divide by 1000 here + status = pC_->writeReg16(ACCEL, NINT(acceleration/1000.0), DEFAULT_CONTROLLER_TIMEOUT); + status = pC_->writeReg16(DECEL, NINT(acceleration/1000.0), DEFAULT_CONTROLLER_TIMEOUT); + return status; +} + +// MOVE +asynStatus ANG1Axis::move(double position, int relative, double minVelocity, double maxVelocity, double acceleration) +{ + asynStatus status; + int velo, distance, move_bit; + + printf(" ** ANG1Axis::move called, relative = %d\n", relative); + + status = sendAccelAndVelocity(acceleration, maxVelocity); + + //velo = maxVelocity * SOME_SCALE_FACTOR + velo = NINT(maxVelocity); + if (relative) { + printf(" ** relative move called\n"); + //status = pC_->writeReg32(SPD_UPR, velo, DEFAULT_CONTROLLER_TIMEOUT); + //distance = position * SOM_OTHER_SCALE_FACTOR; + distance = NINT(position); + status = pC_->writeReg32(POS_WR_UPR, distance, DEFAULT_CONTROLLER_TIMEOUT); + move_bit = 0x0; + status = pC_->writeReg16(CMD_MSW, move_bit, DEFAULT_CONTROLLER_TIMEOUT); + move_bit = 0x2; + status = pC_->writeReg16(CMD_MSW, move_bit, DEFAULT_CONTROLLER_TIMEOUT); + } else { + // absolute + printf(" ** absolute move called\n"); + //status = pC_->writeReg32(SPD_UPR, velo, DEFAULT_CONTROLLER_TIMEOUT); + //distance = position * SOM_OTHER_SCALE_FACTOR; + distance = NINT(position); + printf(" ** distance = %d\n", distance); + status = pC_->writeReg32(POS_WR_UPR, distance, DEFAULT_CONTROLLER_TIMEOUT); + move_bit = 0x0; + status = pC_->writeReg16(CMD_MSW, move_bit, DEFAULT_CONTROLLER_TIMEOUT); + move_bit = 0x1; + status = pC_->writeReg16(CMD_MSW, move_bit, DEFAULT_CONTROLLER_TIMEOUT); + } + // Delay the first status read, give the controller some time to return moving status + epicsThreadSleep(0.05); + return status; +} + +// HOME (needs work) +asynStatus ANG1Axis::home(double minVelocity, double maxVelocity, double acceleration, int forwards) +{ + asynStatus status; + int home_bit; + // static const char *functionName = "ANG1Axis::home"; + + //status = sendAccelAndVelocity(acceleration, maxVelocity); + + if (forwards) { + printf(" ** HOMING FORWARDS **\n"); + home_bit = 0x20; + status = pC_->writeReg16(CMD_MSW, home_bit, DEFAULT_CONTROLLER_TIMEOUT); + } else { + home_bit = 0x40; + status = pC_->writeReg16(CMD_MSW, home_bit, DEFAULT_CONTROLLER_TIMEOUT); + } + return status; +} + +// JOG +asynStatus ANG1Axis::moveVelocity(double minVelocity, double maxVelocity, double acceleration) +{ + asynStatus status; + int velo, distance, move_bit; + static const char *functionName = "ANG1Axis::moveVelocity"; + + asynPrint(pasynUser_, ASYN_TRACE_FLOW, + "%s: minVelocity=%f, maxVelocity=%f, acceleration=%f\n", + functionName, minVelocity, maxVelocity, acceleration); + + velo = NINT(fabs(maxVelocity)); + + status = sendAccelAndVelocity(acceleration, velo); + + /* ANG1 does not have jog command. Move 1 million steps */ + if (maxVelocity > 0.) { + /* This is a positive move in ANG1 coordinates */ + //printf(" ** relative move (JOG pos) called\n"); + distance = 1000000; + status = pC_->writeReg32(POS_WR_UPR, distance, DEFAULT_CONTROLLER_TIMEOUT); + move_bit = 0x0; + status = pC_->writeReg16(CMD_MSW, move_bit, DEFAULT_CONTROLLER_TIMEOUT); + move_bit = 0x2; + status = pC_->writeReg16(CMD_MSW, move_bit, DEFAULT_CONTROLLER_TIMEOUT); + } else { + /* This is a negative move in ANG1 coordinates */ + //printf(" ** relative move (JOG neg) called\n"); + distance = -1000000; + status = pC_->writeReg32(POS_WR_UPR, distance, DEFAULT_CONTROLLER_TIMEOUT); + move_bit = 0x0; + status = pC_->writeReg16(CMD_MSW, move_bit, DEFAULT_CONTROLLER_TIMEOUT); + move_bit = 0x2; + status = pC_->writeReg16(CMD_MSW, move_bit, DEFAULT_CONTROLLER_TIMEOUT); + } + // Delay the first status read, give the controller some time to return moving status + epicsThreadSleep(0.05); + return status; +} + + +// STOP +asynStatus ANG1Axis::stop(double acceleration) +{ + asynStatus status; + int stop_bit; + //static const char *functionName = "ANG1Axis::stop"; + + printf("\n STOP \n\n"); + + stop_bit = 0x0; + status = pC_->writeReg16(CMD_MSW, stop_bit, DEFAULT_CONTROLLER_TIMEOUT); + +// stop_bit = 0x10; Immediate stop + stop_bit = 0x4; // Hold move + status = pC_->writeReg16(CMD_MSW, stop_bit, DEFAULT_CONTROLLER_TIMEOUT); + + return status; +} + +// SET +asynStatus ANG1Axis::setPosition(double position) +{ + asynStatus status; + int set_position, set_bit; + //static const char *functionName = "ANG1Axis::setPosition"; + + //status = writeReg32(SPD_UPR, velo, DEFAULT_CONTROLLER_TIMEOUT); + //distance = position * SOM_OTHER_SCALE_FACTOR; + set_position = NINT(position); + + status = pC_->writeReg32(POS_WR_UPR, set_position, DEFAULT_CONTROLLER_TIMEOUT); + + set_bit = 0x200; + status = pC_->writeReg16(CMD_MSW, set_bit, DEFAULT_CONTROLLER_TIMEOUT); + + set_bit = 0x0; + status = pC_->writeReg16(CMD_MSW, set_bit, DEFAULT_CONTROLLER_TIMEOUT); + + return status; +} + +// ENABLE TORQUE +asynStatus ANG1Axis::setClosedLoop(bool closedLoop) +{ + asynStatus status; + int enable = 0x8000; + int disable = 0x0000; + int cmd; + + printf(" ** setClosedLoop called \n"); + if (closedLoop) { + printf("setting enable %X\n", enable); + // Let's reset errors first + cmd = 0x0; + status = pC_->writeReg16(CMD_MSW, cmd, DEFAULT_CONTROLLER_TIMEOUT); + + cmd = 0x400; + status = pC_->writeReg16(CMD_MSW, cmd, DEFAULT_CONTROLLER_TIMEOUT); + + cmd = 0x0; + status = pC_->writeReg16(CMD_MSW, cmd, DEFAULT_CONTROLLER_TIMEOUT); + status = pC_->writeReg16(CMD_LSW, enable, DEFAULT_CONTROLLER_TIMEOUT); + setIntegerParam(pC_->motorStatusPowerOn_, 1); + + } else { + printf("setting disable %X\n", disable); + status = pC_->writeReg16(CMD_LSW, disable, DEFAULT_CONTROLLER_TIMEOUT); + setIntegerParam(pC_->motorStatusPowerOn_, 0); + } + + return status; +} + +// POLL +/** Polls the axis. + * This function reads motor position, limit status, home status, and moving 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). */ +asynStatus ANG1Axis::poll(bool *moving) +{ + int done; + int limit; + int enabled; + double position; + asynStatus status; + epicsInt32 read_val; // don't use a pointer here. The _address_ of read_val should be passed to the read function. + + // Force a read operation + //printf(" . . . . . Calling pasynInt32SyncIO->write\n"); + //printf("Calling pasynInt32SyncIO->write(pasynUserForceRead_, 1, TIMEOUT), pasynUserForceRead_->reason=%d\n", pasynUserForceRead_->reason); + status = pasynInt32SyncIO->write(pasynUserForceRead_, 1, DEFAULT_CONTROLLER_TIMEOUT); + //printf(" . . . . . status = %d\n", status); + // if status goto end + + // Read the current motor position + // + //readReg32(int reg, epicsInt32 *combo, double timeout) + status = pC_->readReg32(POS_RD_UPR, &read_val, DEFAULT_CONTROLLER_TIMEOUT); + printf("ANG1Axis::poll: Motor position raw: %d\n", read_val); + position = (double) read_val; + setDoubleParam(pC_->motorPosition_, position); + printf("ANG1Axis::poll: Motor position: %f\n", position); + + // Read the moving status of this motor + // + status = pC_->readReg16(STATUS_1, &read_val, DEFAULT_CONTROLLER_TIMEOUT); + //printf("status 1 is 0x%X\n", read_val); + + // Done logic + done = ((read_val & 0x8) >> 3); // status word 1 bit 3 set to 1 when the motor is not in motion. + setIntegerParam(pC_->motorStatusDone_, done); + *moving = done ? false:true; + printf("done is %d\n", done); + + // Read the limit status + // + status = pC_->readReg16(STATUS_2, &read_val, DEFAULT_CONTROLLER_TIMEOUT); + printf("status 2 is 0x%X\n", read_val); + + limit = (read_val & 0x1); // a cw limit has been reached + setIntegerParam(pC_->motorStatusHighLimit_, limit); + //printf("+limit %d\n", limit); + if (limit) { // reset error and set position so we can move off of the limit + // Reset error + setClosedLoop(1); + // Reset position + //printf(" Reset Position\n"); + setPosition(position); + } + + limit = (read_val & 0x2); // a ccw limit has been reached + setIntegerParam(pC_->motorStatusLowLimit_, limit); + //printf("-limit %d\n", limit); + if (limit) { // reset error and set position so we can move off of the limit + // Reset error + setClosedLoop(1); + // Reset position + setPosition(position); + } + + // test for home + + // Should be in init routine? Allows CNEN to be used. + setIntegerParam(pC_->motorStatusGainSupport_, 1); + + // Check for the torque status and set accordingly. + enabled = (read_val & 0x8000); + if (enabled) + setIntegerParam(pC_->motorStatusPowerOn_, 1); + else + setIntegerParam(pC_->motorStatusPowerOn_, 0); + + // Notify asynMotorController polling routine that we're ready + callParamCallbacks(); + + return status; +} + +/** Code for iocsh registration */ +static const iocshArg ANG1CreateControllerArg0 = {"Port name", iocshArgString}; +static const iocshArg ANG1CreateControllerArg1 = {"ANG1 In port name", iocshArgString}; +static const iocshArg ANG1CreateControllerArg2 = {"ANG1 Out port name", iocshArgString}; +static const iocshArg ANG1CreateControllerArg3 = {"Number of axes", iocshArgInt}; +static const iocshArg ANG1CreateControllerArg4 = {"Moving poll period (ms)", iocshArgInt}; +static const iocshArg ANG1CreateControllerArg5 = {"Idle poll period (ms)", iocshArgInt}; +static const iocshArg * const ANG1CreateControllerArgs[] = {&ANG1CreateControllerArg0, + &ANG1CreateControllerArg1, + &ANG1CreateControllerArg2, + &ANG1CreateControllerArg3, + &ANG1CreateControllerArg4, + &ANG1CreateControllerArg5,}; +static const iocshFuncDef ANG1CreateControllerDef = {"ANG1CreateController", 6, ANG1CreateControllerArgs}; +static void ANG1CreateContollerCallFunc(const iocshArgBuf *args) +{ + ANG1CreateController(args[0].sval, args[1].sval, args[2].sval, args[3].ival, args[4].ival, args[5].ival); +} + +static void ANG1Register(void) +{ + iocshRegister(&ANG1CreateControllerDef, ANG1CreateContollerCallFunc); +} + +extern "C" { +epicsExportRegistrar(ANG1Register); +} diff --git a/motorApp/AMCISrc/ANG1Driver.h b/motorApp/AMCISrc/ANG1Driver.h new file mode 100644 index 00000000..09160f37 --- /dev/null +++ b/motorApp/AMCISrc/ANG1Driver.h @@ -0,0 +1,88 @@ +/* +FILENAME... ANG1Driver.h +USAGE... Motor driver support for the AMCI ANG1 controller. + +Based on MCB-4B driver written by +Mark Rivers +March 1, 2012 + +K. Goetze 2014-03-24 + +*/ + +#include "asynMotorController.h" +#include "asynMotorAxis.h" + +#define MAX_ANG1_AXES 1 + +#define MAX_INPUT_REGS 10 +#define MAX_OUTPUT_REGS 10 + +// No. of controller-specific parameters +#define NUM_ANG1_PARAMS 1 + +/** drvInfo strings for extra parameters that the ACR controller supports */ +#define ANG1JerkString "ANG1_JERK" +//#define ACRReadBinaryIOString "ACR_READ_BINARY_IO" +//#define ACRBinaryInString "ACR_BINARY_IN" +//#define ACRBinaryOutString "ACR_BINARY_OUT" +//#define ACRBinaryOutRBVString "ACR_BINARY_OUT_RBV" + +class ANG1Axis : public asynMotorAxis +{ +public: + /* These are the methods we override from the base class */ + ANG1Axis(class ANG1Controller *pC, int axis); + void report(FILE *fp, int level); + asynStatus move(double position, int relative, double min_velocity, double max_velocity, double acceleration); + asynStatus moveVelocity(double min_velocity, double max_velocity, double acceleration); + 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); + +private: + ANG1Controller *pC_; /**< Pointer to the asynMotorController to which this axis belongs. + * Abbreviated because it is used very frequently */ + asynStatus sendAccelAndVelocity(double accel, double velocity); + asynUser *pasynUserForceRead_; + +friend class ANG1Controller; +}; + +class ANG1Controller : public asynMotorController { +public: + ANG1Controller(const char *portName, const char *ANG1InPortName, const char *ANG1OutPortName, int numAxes, double movingPollPeriod, double idlePollPeriod); + + void report(FILE *fp, int level); + ANG1Axis* getAxis(asynUser *pasynUser); + ANG1Axis* getAxis(int axisNo); + asynUser *pasynUserInReg_[MAX_INPUT_REGS]; + asynUser *pasynUserOutReg_[MAX_OUTPUT_REGS]; +// asynUser *pasynUserForceRead_; + + + /* These are the methods that we override from asynMotorDriver */ + asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value); + //asynStatus writeFloat64(asynUser *pasynUser, epicsFloat64 value); + //void report(FILE *fp, int level); + //ACRAxis* getAxis(asynUser *pasynUser); + //ACRAxis* getAxis(int axisNo); + + + /* These are the methods that are new to this class */ + +protected: + int ANG1Jerk_; /**< Jerk time parameter index */ + + +private: + asynStatus writeReg16(int, int, double); + asynStatus writeReg32(int, int, double); + asynStatus readReg16(int, epicsInt32*, double); + asynStatus readReg32(int, epicsInt32*, double); + char *inputDriver_; + +friend class ANG1Axis; +}; diff --git a/motorApp/AMCISrc/ANG1Support.dbd b/motorApp/AMCISrc/ANG1Support.dbd new file mode 100644 index 00000000..ab5549c5 --- /dev/null +++ b/motorApp/AMCISrc/ANG1Support.dbd @@ -0,0 +1,2 @@ +#registrar(ANG1MotorRegister) +registrar(ANG1Register) diff --git a/motorApp/AMCISrc/Makefile b/motorApp/AMCISrc/Makefile new file mode 100644 index 00000000..b1156cec --- /dev/null +++ b/motorApp/AMCISrc/Makefile @@ -0,0 +1,29 @@ +TOP=../.. + +include $(TOP)/configure/CONFIG +#---------------------------------------- +# ADD MACRO DEFINITIONS AFTER THIS LINE +#============================= + +#================================================== +# Build an IOC support library + +LIBRARY_IOC += AMCI + +SRCS += AMCIRegister.cc + +# motorRecord.h will be created from motorRecord.dbd +# install devMotorSoft.dbd into /dbd +DBD += ANG1Support.dbd + +# The following are compiled and added to the Support library +AMCI_SRCS += ANG1Driver.cpp + +AMCI_LIBS += motor +AMCI_LIBS += asyn +AMCI_LIBS += $(EPICS_BASE_IOC_LIBS) + +include $(TOP)/configure/RULES +#---------------------------------------- +# ADD RULES AFTER THIS LINE + diff --git a/motorApp/AMCISrc/README b/motorApp/AMCISrc/README new file mode 100644 index 00000000..c3bbc7a6 --- /dev/null +++ b/motorApp/AMCISrc/README @@ -0,0 +1,49 @@ +AMCI ANG1 +========= + +Asyn model 3 driver support for the AMCI ANG1 stepper motor +controller/driver. + +Modbus/TCP communication, using the synApps modbus module + +Currently some basic parameters, such as IP address, motor current, +etc., will need to be set up on the controller using AMCI's PC/Win software. +Limits and Home also need to be configured with this software: * + + Limit -> ANG1 Input 1 + - Limit -> ANG1 Input 2 + Home -> ANG1 Input 3 + +ANG1 configuration software is available from AMCI's website: + +www.amci.com/product-software.asp + +Eventually I would like to implement the "Configuration Mode" options +down in the driver, making the AMCI PC software necessary only for +initial comms (IP) setup. + +The ANG1 controller/driver is available with or without an ethernet +port. A group of controller/drivers can contain up to 6 modules, one of +which needs to have the ethernet option. A single-channel +implementation would need the module with ethernet. This software is +intended to support configurations of multiple groups of 1 to 6 modules. +Again, each group will need 1 ethernet enabled module. + + + +asyn model 3 driver files: +-------------------------- +ANG1Driver.cpp +ANG1Driver.h +ANG1Support.dbd + + +* Note: 1.) At some point I would like to add the capability to set these + parameters at boot-time, using the ANG1 "configuration mode". + + 2.) VBAS can only be set in configuration mode (which is not + currently supported) or by using the PC configuration software. + To use VBAS, set the desired value for the axis using the AMCI + PC configuration interface, then set the VBAS field in the + motor record accordingly. That way this value will be used by + the record to correctly calculate acceleration. + From 68463eca4f09eb347a31c5ac4ef48114eced7bbc Mon Sep 17 00:00:00 2001 From: "Kurt A. Goetze" Date: Mon, 17 Jul 2017 09:51:41 -0500 Subject: [PATCH 23/27] update --- motorApp/AMCISrc/README | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/motorApp/AMCISrc/README b/motorApp/AMCISrc/README index c3bbc7a6..57dc4991 100644 --- a/motorApp/AMCISrc/README +++ b/motorApp/AMCISrc/README @@ -4,7 +4,7 @@ AMCI ANG1 Asyn model 3 driver support for the AMCI ANG1 stepper motor controller/driver. -Modbus/TCP communication, using the synApps modbus module +Modbus/TCP communication, using Mark Rivers' modbus module Currently some basic parameters, such as IP address, motor current, etc., will need to be set up on the controller using AMCI's PC/Win software. @@ -26,7 +26,7 @@ port. A group of controller/drivers can contain up to 6 modules, one of which needs to have the ethernet option. A single-channel implementation would need the module with ethernet. This software is intended to support configurations of multiple groups of 1 to 6 modules. -Again, each group will need 1 ethernet enabled module. +Again, each group will need 1 ethernet enabled module (ANG1-E). From b60e8ee404b1685fab7e8b2218eabc70eb1d1206 Mon Sep 17 00:00:00 2001 From: "Kurt A. Goetze" Date: Mon, 17 Jul 2017 11:59:09 -0500 Subject: [PATCH 24/27] update Makefile --- motorApp/Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/motorApp/Makefile b/motorApp/Makefile index 36ce18e1..35d18e15 100644 --- a/motorApp/Makefile +++ b/motorApp/Makefile @@ -105,6 +105,9 @@ MicronixSrc_DEPEND_DIRS = MotorSrc DIRS += PhytronSrc PhytronSrc_DEPEND_DIRS = MotorSrc +DIRS += AMCISrc +AMCISrc_DEPEND_DIRS = MotorSrc + endif # Install the edl files From 2ff3d3a562cbf95fd63c43b491086385a1d2df51 Mon Sep 17 00:00:00 2001 From: "Kurt A. Goetze" Date: Tue, 18 Jul 2017 12:12:57 -0500 Subject: [PATCH 25/27] Add support files --- iocBoot/iocWithAsyn/motor.substitutions.ANG1 | 17 +++++ iocBoot/iocWithAsyn/st.cmd.ANG1 | 69 ++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 iocBoot/iocWithAsyn/motor.substitutions.ANG1 create mode 100644 iocBoot/iocWithAsyn/st.cmd.ANG1 diff --git a/iocBoot/iocWithAsyn/motor.substitutions.ANG1 b/iocBoot/iocWithAsyn/motor.substitutions.ANG1 new file mode 100644 index 00000000..069accf7 --- /dev/null +++ b/iocBoot/iocWithAsyn/motor.substitutions.ANG1 @@ -0,0 +1,17 @@ +file "$(MOTOR)/motorApp/Db/basic_asyn_motor.db" +{ +pattern +{P, N, M, DTYP, PORT, ADDR, DESC, EGU, DIR, VELO, VBAS, ACCL, BDST, BVEL, BACC, MRES, PREC, DHLM, DLLM, INIT, RTRY} + +{IOC:, 1, "m$(N)", "asynMotor", "ANG1_1_1", 0, "AMCI ANG1 1", steps, Pos, 100, 0, .2, 0, 50, .2, 1, 5, 1e9, -1e9, ""} +{IOC:, 2, "m$(N)", "asynMotor", "ANG1_1_2", 0, "AMCI ANG1 2", steps, Pos, 100, 0, .2, 0, 50, .2, 1, 5, 1e9, -1e9, ""} +} + +file "$(MOTOR)/motorApp/Db/ANG1Aux.template" +{ +pattern +{P, R, PORT, ADDR} +{IOC:, m1:, ANG1_1_1, 0} +{IOC:, m2:, ANG1_1_2, 0} +} + diff --git a/iocBoot/iocWithAsyn/st.cmd.ANG1 b/iocBoot/iocWithAsyn/st.cmd.ANG1 new file mode 100644 index 00000000..e4227c0e --- /dev/null +++ b/iocBoot/iocWithAsyn/st.cmd.ANG1 @@ -0,0 +1,69 @@ +# ANG1_motors.cmd +# + +# Use the following commands for TCP/IP +#drvAsynIPPortConfigure(const char *portName, +# const char *hostInfo, +# unsigned int priority, +# int noAutoConnect, +# int noProcessEos); +# One per controller. One controller can support up to six drivers. +drvAsynIPPortConfigure("ang1_1","164.54.53.107:502",0,0,1) +#drvAsynIPPortConfigure("ang1_2","164.54.53.23:502",0,0,1) +#drvAsynIPPortConfigure("ang1_3","164.54.xxx.xxx:502",0,0,1) + +#modbusInterposeConfig(const char *portName, +# modbusLinkType linkType, +# int timeoutMsec, +# int writeDelayMsec) +# One per controller. One controller can support up to six drivers. +modbusInterposeConfig("ang1_1",0,2000,0) +#modbusInterposeConfig("ang1_2",0,2000,0) + +# Word access at Modbus address 0 +# Access 1 words as inputs. +# Function code=3 +# default data type unsigned integer. +# drvModbusAsynConfigure("portName", "tcpPortName", slaveAddress, modbusFunction, modbusStartAddress, modbusLength, dataType, pollMsec, "plcType") +# One per axis. Note: "ANG1" is the AMCI model. "ANG1_1" is the controller. "ANG1_1_1" is the axis. +drvModbusAsynConfigure("ANG1_1_1_In_Word", "ang1_1", 0, 4, 0, 10, 0, 100, "ANG1_stepper") +drvModbusAsynConfigure("ANG1_1_2_In_Word", "ang1_1", 0, 4, 10, 10, 0, 100, "ANG1_stepper") +#drvModbusAsynConfigure("ANG1_1_3_In_Word", "ang1_1", 0, 3, 20, 10, 0, 100, "ANG1_stepper") +#drvModbusAsynConfigure("ANG1_1_4_In_Word", "ang1_1", 0, 3, 30, 10, 0, 100, "ANG1_stepper") +#drvModbusAsynConfigure("ANG1_1_5_In_Word", "ang1_1", 0, 3, 40, 10, 0, 100, "ANG1_stepper") +#drvModbusAsynConfigure("ANG1_1_6_In_Word", "ang1_1", 0, 3, 50, 10, 0, 100, "ANG1_stepper") + +# Access 1 words as outputs. +# Either function code=6 (single register) or 16 (multiple registers) can be used, but 16 +# is better because it is "atomic" when writing values longer than 16-bits. +# Default data type unsigned integer. +# drvModbusAsynConfigure("portName", "tcpPortName", slaveAddress, modbusFunction, modbusStartAddress, modbusLength, dataType, pollMsec, "plcType") +# Not sure why the outputs can't be configured for Modbus data type 4? +drvModbusAsynConfigure("ANG1_1_1_Out_Word", "ang1_1", 0, 6, 1024, 10, 0, 1, "ANG1_stepper") +drvModbusAsynConfigure("ANG1_1_2_Out_Word", "ang1_1", 0, 6, 1034, 10, 0, 1, "ANG1_stepper") +#drvModbusAsynConfigure("ANG1_1_3_Out_Word", "ang1_1", 0, 6, 1044, 10, 0, 1, "ANG1_stepper") +#drvModbusAsynConfigure("ANG1_1_4_Out_Word", "ang1_1", 0, 6, 1054, 10, 0, 1, "ANG1_stepper") +#drvModbusAsynConfigure("ANG1_1_5_Out_Word", "ang1_1", 0, 6, 1064, 10, 0, 1, "ANG1_stepper") +#drvModbusAsynConfigure("ANG1_1_6_Out_Word", "ang1_1", 0, 6, 1074, 10, 0, 1, "ANG1_stepper") + +# Second ANG1 controller... +#drvModbusAsynConfigure("ANG1_2_1_Out_Word_0", "ang1_2", 0, 6, 1024, 1, 0, 1, "ANG1_stepper") + +dbLoadTemplate("ANG1_motors.substitutions") + +# AMCI ANG1 stepper controller/driver support +# portName The name of the asyn port that will be created for this driver +# ANG1InPortName The name of the In drvAsynIPPPort that was created previously to connect to the ANG1 controller +# ANG1OutPortName The name of the Out drvAsynIPPPort that was created previously to connect to the ANG1 controller +# numAxes The number of axes that this controller supports +# movingPollPeriod The time in ms between polls when any axis is moving +# idlePollPeriod The time in ms between polls when no axis is moving +# +# One per axis. Note: "ANG1" is the AMCI model. "ANG1_1" is the controller. "ANG1_1_1" is the axis. +# Also, ANG1_1_1 is the port name needed for motor.substitutions. +ANG1CreateController(ANG1_1_1, ANG1_1_1_In_Word, ANG1_1_1_Out_Word, 1, 100, 0) +ANG1CreateController(ANG1_1_2, ANG1_1_2_In_Word, ANG1_1_2_Out_Word, 1, 100, 0) +#ANG1CreateController(ANG1_1, ANG1_1_3_In_Word, ANG1_1_3_Out_Word, 1, 100, 0) +#ANG1CreateController(ANG1_1, ANG1_1_4_In_Word, ANG1_1_4_Out_Word, 1, 100, 0) +#ANG1CreateController(ANG1_1, ANG1_1_5_In_Word, ANG1_1_5_Out_Word, 1, 100, 0) +#ANG1CreateController(ANG1_1, ANG1_1_6_In_Word, ANG1_1_6_Out_Word, 1, 100, 0) From f00dc933f78ddf199455e8a2dea00da5cb2845a1 Mon Sep 17 00:00:00 2001 From: "Kurt A. Goetze" Date: Wed, 19 Jul 2017 11:53:39 -0500 Subject: [PATCH 26/27] update comments --- iocBoot/iocWithAsyn/st.cmd.ANG1 | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/iocBoot/iocWithAsyn/st.cmd.ANG1 b/iocBoot/iocWithAsyn/st.cmd.ANG1 index e4227c0e..8e9a5dcb 100644 --- a/iocBoot/iocWithAsyn/st.cmd.ANG1 +++ b/iocBoot/iocWithAsyn/st.cmd.ANG1 @@ -1,5 +1,10 @@ -# ANG1_motors.cmd +# ANG1 motors Command file Example # +### Note: Modbus support (the EPICS modbus module) is required to be included in the +### EPICS application where the ANG1 support will be loaded. This file is an +### example of how to load the ANG1 support, in an ioc that is built with the +### EPICS modbus module. + # Use the following commands for TCP/IP #drvAsynIPPortConfigure(const char *portName, From a3cd81031a4ae91243071db5fecd039031e2f300 Mon Sep 17 00:00:00 2001 From: kpetersn Date: Wed, 23 Aug 2017 15:36:12 -0500 Subject: [PATCH 27/27] Revert "Merge branch 'master' into master" This reverts commit 3ec6ec433c57165393f6a93c28c139e554cd56a3, reversing changes made to 8966aeabf292874de8c78754e95e14cde1f1c776. --- configure/RELEASE | 3 - .../iocWithAsyn/motor.substitutions.script | 15 - iocBoot/iocWithAsyn/scripts/softMotor.lua | 67 -- iocBoot/iocWithAsyn/scripts/vmc.lua | 66 -- iocBoot/iocWithAsyn/st.cmd.script | 18 - motorApp/Db/Makefile | 1 - motorApp/Db/ScriptMotorReload.db | 9 - motorApp/Makefile | 6 - motorApp/ScriptMotorSrc/Makefile | 30 - motorApp/ScriptMotorSrc/ScriptMotorDriver.cpp | 859 ------------------ motorApp/ScriptMotorSrc/ScriptMotorDriver.dbd | 1 - motorApp/ScriptMotorSrc/ScriptMotorDriver.h | 76 -- motorApp/op/adl/ScriptMotorReload.adl | 140 --- motorExApp/WithAsyn/Makefile | 7 - 14 files changed, 1298 deletions(-) delete mode 100644 iocBoot/iocWithAsyn/motor.substitutions.script delete mode 100644 iocBoot/iocWithAsyn/scripts/softMotor.lua delete mode 100644 iocBoot/iocWithAsyn/scripts/vmc.lua delete mode 100644 iocBoot/iocWithAsyn/st.cmd.script delete mode 100644 motorApp/Db/ScriptMotorReload.db delete mode 100644 motorApp/ScriptMotorSrc/Makefile delete mode 100644 motorApp/ScriptMotorSrc/ScriptMotorDriver.cpp delete mode 100644 motorApp/ScriptMotorSrc/ScriptMotorDriver.dbd delete mode 100644 motorApp/ScriptMotorSrc/ScriptMotorDriver.h delete mode 100644 motorApp/op/adl/ScriptMotorReload.adl diff --git a/configure/RELEASE b/configure/RELEASE index d59ae099..003d8fd6 100644 --- a/configure/RELEASE +++ b/configure/RELEASE @@ -37,9 +37,6 @@ EPICS_BASE= # Recommended IPAC release: R2-12 IPAC=$(SUPPORT)/ipac/R2-12 -# Script module needed to build ScriptMotorController -#!SCRIPT=$(SUPPORT)/script - # The following is only needed for the motor examples in iocBoot. #!MOTOR=$(TOP) diff --git a/iocBoot/iocWithAsyn/motor.substitutions.script b/iocBoot/iocWithAsyn/motor.substitutions.script deleted file mode 100644 index c2f63ea9..00000000 --- a/iocBoot/iocWithAsyn/motor.substitutions.script +++ /dev/null @@ -1,15 +0,0 @@ -file "$(TOP)/db/asyn_motor.db" -{ - pattern - {P, M, DTYP, PORT, ADDR, DESC, EGU, DIR, VMAX, VELO, VBAS, ACCL, BDST, BVEL, BACC, MRES, PREC, DHLM, DLLM, INIT} - {IOC:, m1, "asynMotor", VMC_MOTOR, 0, "VMCMotor", mm, Pos, 15., 3., .05, .5, 0, 1.0, 2, .025, 5, 0, 0, ""} - {IOC:, m2, "asynMotor", SOFT_MOTOR, 0, "SoftMotor", mm, Pos, 15., 3., .05, .5, 0, 1.0, 2, .025, 5, 0, 0, ""} -} - -file "$(TOP)/db/ScriptMotorReload.db" -{ - pattern - {P, PORT} - {IOC:, SOFT_MOTOR} - {IOC:, VMC_MOTOR} -} diff --git a/iocBoot/iocWithAsyn/scripts/softMotor.lua b/iocBoot/iocWithAsyn/scripts/softMotor.lua deleted file mode 100644 index 0f6e8fd0..00000000 --- a/iocBoot/iocWithAsyn/scripts/softMotor.lua +++ /dev/null @@ -1,67 +0,0 @@ -IdlePollPeriod = 1.00 -MovingPollPeriod = 0.25 - -lastPos = 0 -targetPos = 0 - -function move(position, relative, minVel, maxVel, accel) - local MRES = asyn.getDoubleParam( DRIVER, AXIS, "MOTOR_REC_RESOLUTION") - - if (relative) then - local prev = asyn.getDoubleParam( DRIVER, AXIS, "MOTOR_POSITION") - targetPos = prev + (position * MRES) - else - targetPos = (position * MRES) - end - - epics.put(DRIVE_PV, targetPos) - - if (position > 0) then - asyn.setIntegerParam( DRIVER, AXIS, "MOTOR_STATUS_DIRECTION", 1) - else - asyn.setIntegerParam( DRIVER, AXIS, "MOTOR_STATUS_DIRECTION", 0) - end - - asyn.callParamCallbacks(DRIVER, AXIS) -end - - -function poll() - local MRES = asyn.getDoubleParam( DRIVER, AXIS, "MOTOR_REC_RESOLUTION") - - if (MRES == 0.0) then - return true - end - - local curr = epics.get(READBACK_PV) - - asyn.setDoubleParam( DRIVER, AXIS, "MOTOR_POSITION", curr / MRES) - - local done = 0 - local moving = 1 - - if (curr == targetPos) then - done = 1 - moving = 0 - elseif (math.abs(curr - targetPos) <= MRES and lastPos == curr) then - done = 1 - moving = 0 - end - - lastPos = curr - - asyn.setIntegerParam( DRIVER, AXIS, "MOTOR_STATUS_DONE", done) - asyn.setIntegerParam( DRIVER, AXIS, "MOTOR_STATUS_MOVING", moving) - - asyn.callParamCallbacks(DRIVER, AXIS) - - return (done ~= 1) -end - - -function stop(acceleration) - local curr = asyn.getDoubleParam( DRIVER, AXIS, "MOTOR_POSITION") - - epics.put(DRIVE_PV, curr) - targetPos = curr -end diff --git a/iocBoot/iocWithAsyn/scripts/vmc.lua b/iocBoot/iocWithAsyn/scripts/vmc.lua deleted file mode 100644 index 46ff05fe..00000000 --- a/iocBoot/iocWithAsyn/scripts/vmc.lua +++ /dev/null @@ -1,66 +0,0 @@ -IdlePollPeriod = 1.0 -MovingPollPeriod = 0.25 -ForcedFastPolls = 2 - -InTerminator = "\r\n" -OutTerminator = "\r\n" - -function sendAccelAndVelocity(minVel, maxVel, accel) - asyn.writeread( string.format( "%d BAS %f", AXIS + 1, minVel) , PORT); - asyn.writeread( string.format( "%d VEL %f", AXIS + 1, maxVel) , PORT); - asyn.writeread( string.format( "%d ACC %f", AXIS + 1, accel ) , PORT); -end - - -function move(position, relative, minVel, maxVel, accel) - sendAccelAndVelocity( minVel, maxVel, accel) - - if (relative) then - asyn.writeread( string.format( "%d MR %d", AXIS + 1, math.floor(position) ) , PORT) - else - asyn.writeread( string.format( "%d MV %d", AXIS + 1, math.floor(position) ) , PORT) - end -end - - -function moveVelocity(minVel, maxVel, accel) - sendAccelAndVelocity( minVel, maxVel, accel) - - asyn.writeread( string.format( "%d JOG %f", AXIS + 1, maxVel) , PORT); -end - - -function poll() - asyn.write( string.format( "%d POS?", AXIS + 1) , PORT) - - asyn.setDoubleParam( DRIVER, AXIS, "MOTOR_POSITION", tonumber( asyn.read(PORT) ) ) - - asyn.write( string.format( "%d ST?", AXIS + 1) , PORT) - - local status = tonumber( asyn.read(PORT) ) - - local direction = (status & 1) - local done = (status & 2) >> 1 - local limit_high = (status & 8) >> 3 - local limit_low = (status & 16) >> 4 - - asyn.setIntegerParam( DRIVER, AXIS, "MOTOR_STATUS_DIRECTION", direction) - asyn.setIntegerParam( DRIVER, AXIS, "MOTOR_STATUS_DONE", done) - asyn.setIntegerParam( DRIVER, AXIS, "MOTOR_STATUS_MOVING", done ~ 1) - asyn.setIntegerParam( DRIVER, AXIS, "MOTOR_STATUS_HIGH_LIMIT", limit_high) - asyn.setIntegerParam( DRIVER, AXIS, "MOTOR_STATUS_LOW_LIMIT", limit_low) - - asyn.callParamCallbacks(DRIVER, AXIS) - - return (done ~= 1) -end - - -function stop(acceleration) - asyn.writeread( string.format( "%d AB", AXIS + 1) , PORT); -end - - -function setPosition(position) - asyn.writeread( string.format( "%d POS %d", AXIS + 1, math.floor(position) ) , PORT); -end diff --git a/iocBoot/iocWithAsyn/st.cmd.script b/iocBoot/iocWithAsyn/st.cmd.script deleted file mode 100644 index a113cde0..00000000 --- a/iocBoot/iocWithAsyn/st.cmd.script +++ /dev/null @@ -1,18 +0,0 @@ -< envPaths - -dbLoadDatabase("$(TOP)/dbd/WithAsyn.dbd") -WithAsyn_registerRecordDeviceDriver(pdbbase) - -epicsEnvSet("LUA_SCRIPT_PATH", "./scripts") - -# Connect to virtual motor controller server -drvAsynIPPortConfigure("VMC","127.0.0.1:31337", 0, 0, 0) - -#ScriptControllerConfig( "PORT_NAME", num_axes, "lua_script", "PARAMS=") -ScriptControllerConfig("VMC_MOTOR", 1, "vmc.lua", "PORT=VMC") - -ScriptControllerConfig("SOFT_MOTOR", 1, "softMotor.lua", "DRIVE_PV='IOC:m1.VAL', READBACK_PV='IOC:m1.RBV'") - -dbLoadTemplate("motor.substitutions.script") - -iocInit diff --git a/motorApp/Db/Makefile b/motorApp/Db/Makefile index 2c539228..d36a1dca 100644 --- a/motorApp/Db/Makefile +++ b/motorApp/Db/Makefile @@ -46,7 +46,6 @@ DB += profileMoveAxisXPS.template DB += PI_Support.db PI_SupportCtrl.db DB += Phytron_motor.db Phytron_I1AM01.db Phytron_MCM01.db DB += asyn_auto_power.db -DB += ScriptMotorReload.db #---------------------------------------------------- # Declare template files which do not show up in DB diff --git a/motorApp/Db/ScriptMotorReload.db b/motorApp/Db/ScriptMotorReload.db deleted file mode 100644 index 63904454..00000000 --- a/motorApp/Db/ScriptMotorReload.db +++ /dev/null @@ -1,9 +0,0 @@ -record(bo, "$(P)$(PORT):ScriptReload") -{ - field(DESC, "$(PORT) Script Reload") - field(DTYP, "asynInt32") - field(OUT, "@asyn($(PORT), 0, 0)RELOAD_SCRIPT") - - field(ZNAM, "Loaded") - field(ONAM, "Reload") -} diff --git a/motorApp/Makefile b/motorApp/Makefile index 78fc0593..35d18e15 100644 --- a/motorApp/Makefile +++ b/motorApp/Makefile @@ -108,12 +108,6 @@ PhytronSrc_DEPEND_DIRS = MotorSrc DIRS += AMCISrc AMCISrc_DEPEND_DIRS = MotorSrc -# The Script motor support requires the lua scripting module -ifdef SCRIPT -DIRS += ScriptMotorSrc -ScriptMotorSrc_DEPEND_DIRS = MotorSrc -endif - endif # Install the edl files diff --git a/motorApp/ScriptMotorSrc/Makefile b/motorApp/ScriptMotorSrc/Makefile deleted file mode 100644 index e27e5fd6..00000000 --- a/motorApp/ScriptMotorSrc/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -# Makefile -TOP=../.. - -include $(TOP)/configure/CONFIG -#---------------------------------------- -# ADD MACRO DEFINITIONS AFTER THIS LINE -#============================= - -#================================================== -# Build an IOC support library -LIBRARY_IOC = ScriptMotor - -# motorRecord.h will be created from motorRecord.dbd -# install devMotorSoft.dbd into /dbd -DBD += ScriptMotorDriver.dbd - -INC += ScriptMotorDriver.h - -# The following are compiled and added to the Support library -ScriptMotor_SRCS += ScriptMotorDriver.cpp - -ScriptMotor_LIBS += motor -ScriptMotor_LIBS += asyn -ScriptMotor_LIBS += script -ScriptMotor_LIBS += $(EPICS_BASE_IOC_LIBS) - -include $(TOP)/configure/RULES -#---------------------------------------- -# ADD RULES AFTER THIS LINE - diff --git a/motorApp/ScriptMotorSrc/ScriptMotorDriver.cpp b/motorApp/ScriptMotorSrc/ScriptMotorDriver.cpp deleted file mode 100644 index 93b8e3d9..00000000 --- a/motorApp/ScriptMotorSrc/ScriptMotorDriver.cpp +++ /dev/null @@ -1,859 +0,0 @@ -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include "asynMotorController.h" -#include "asynMotorAxis.h" - -#include -#include "ScriptMotorDriver.h" - -#define NINT(f) (int)((f)>0 ? (f)+0.5 : (f)-0.5) - - -/************************************************ - * These are the ScriptMotorController methods * - ************************************************/ - - -/** Creates a new ScriptMotorController object. - * \param[in] asyn_port The name of the asyn port that will be created for this driver - * \param[in] serial_port The name of the drvAsynSerialPort that was created previously to connect to the VirtualMotor controller - * \param[in] max_axes The number of axes that this controller supports - * \param[in] script_file - * \param[in] params - */ -ScriptMotorController::ScriptMotorController(const char* asyn_port, - int max_axes, - const char* script_file, - const char* params) - : asynMotorController(asyn_port, - max_axes, - 1, // No. ScriptMotorController asyn parameters - 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, // Default priority - 0) // Default stack size -{ - this->script = std::string(script_file); - - if (params) { this->init_params = std::string(params); } - else { this->init_params = std::string(""); } - - this->createParam("RELOAD_SCRIPT", asynParamInt32, &this->ScriptMotorReload); - - for (int axis = 0; axis < max_axes; axis += 1) - { - new ScriptMotorAxis(this, axis, script_file, params); - } - - this->startPoller(this->movingPollPeriod_, this->idlePollPeriod_, this->forcedFastPolls_); -} - -void ScriptMotorController::reload() -{ - this->lock(); - for (int index = 0; index < this->numAxes_; index += 1) - { - ScriptMotorAxis* axis = this->getAxis(index); - axis->reload(this->script.c_str(), this->init_params.c_str()); - } - this->unlock(); - - printf("Controller %s reloaded %s.\n", this->portName, this->script.c_str()); -} - -/** Creates a new ScriptMotorController object. - * Configuration command, called directly or from iocsh - * \param[in] asyn_port The name of the asyn port that will be created for this driver - * \param[in] max_axes The number of axes that this controller supports - * \param[in] script_file - * \param[in] params - */ -extern "C" int ScriptControllerConfig(const char* asyn_port, - int max_axes, - const char* script_file, - const char* params) -{ - new ScriptMotorController(asyn_port, max_axes, script_file, params); - return(asynSuccess); -} - - -/** Reports on status of the driver - * \param[in] fp The file pointer on which report information will be written - * \param[in] level The level of report detail desired - * - * If details > 0 then information is printed about each axis. - * After printing controller-specific information it calls asynMotorController::report() - */ -void ScriptMotorController::report(FILE *fp, int level) -{ - fprintf(fp, "Script Motor Controller driver %s\n", this->portName); - fprintf(fp, " numAxes=%d\n", numAxes_); - fprintf(fp, " moving poll period=%f\n", movingPollPeriod_); - fprintf(fp, " idle poll period=%f\n", idlePollPeriod_); - - // Call the base class method - asynMotorController::report(fp, level); -} - -asynStatus ScriptMotorController::writeInt32(asynUser *pasynUser, epicsInt32 value) -{ - int function = pasynUser->reason; - - if (function == this->ScriptMotorReload) - { - if (value == 1) { this->reload(); } - return asynSuccess; - } - else - { - return asynMotorController::writeInt32(pasynUser, value); - } -} - -asynStatus ScriptMotorController::setIntegerParam(int list, int function, int value) -{ - if (function >= this->motorStatusDirection_ && function <= this->motorStatusHomed_) - { - ScriptMotorAxis* axis = (ScriptMotorAxis*) this->getAxis(list); - epicsUInt32 status = axis->setStatusParam(function, value); - asynMotorController::setIntegerParam(list, this->motorStatus_, status); - } - - return asynMotorController::setIntegerParam(list, function, value); -} - -asynStatus ScriptMotorController::setDoubleParam(int list, int function, double value) -{ - if (function == this->motorPosition_ || function == this->motorEncoderPosition_) - { - ScriptMotorAxis* axis = (ScriptMotorAxis*) this->getAxis(list); - axis->setPositionParam(function, value); - } - - return asynMotorController::setDoubleParam(list, function, value); -} - -void ScriptMotorController::configAxis(int axisNo, const char* params) -{ - ScriptMotorAxis* axis = this->getAxis(axisNo); - - if (params) { axis->params = std::string(params); } - else { axis->params = std::string(""); } - - axis->config(params); -} - -/** Returns a pointer to an ScriptMotorAxis object. - * Returns NULL if the axis number encoded in pasynUser is invalid. - * \param[in] pasynUser asynUser structure that encodes the axis index number. */ -ScriptMotorAxis* ScriptMotorController::getAxis(asynUser *pasynUser) -{ - return static_cast(asynMotorController::getAxis(pasynUser)); -} - - -/** Returns a pointer to an ScriptMotorAxis object. - * Returns NULL if the axis number encoded in pasynUser is invalid. - * \param[in] axisNo Axis index number. */ -ScriptMotorAxis* ScriptMotorController::getAxis(int axisNo) -{ - return static_cast(asynMotorController::getAxis(axisNo)); -} - - -/****************************************** - * These are the ScriptMotorAxis methods * - ******************************************/ - - -/** Creates a new ScriptMotorAxis object. - * \param[in] pC Pointer to the ScriptMotorController to which this axis belongs. - * \param[in] axisNo Index number of this axis, range 0 to pC->numAxes_-1. - * - * Initializes register numbers, etc. - */ -ScriptMotorAxis::ScriptMotorAxis(ScriptMotorController *pC, int axisNo, const char* script_file, const char* params) - : asynMotorAxis(pC, axisNo), - pC_(pC) -{ - this->initState(script_file); - this->config(params); - - int isnum; - - lua_getglobal(this->state, "MovingPollPeriod"); - double MovingPollPeriod = lua_tonumberx(this->state, -1, &isnum); - if (isnum) { pC->movingPollPeriod_ = MovingPollPeriod; } - lua_remove(this->state, -1); - - lua_getglobal(this->state, "IdlePollPeriod"); - double IdlePollPeriod = lua_tonumberx(this->state, -1, &isnum); - if (isnum) { pC->idlePollPeriod_ = IdlePollPeriod; } - lua_remove(this->state, -1); - - lua_getglobal(this->state, "ForcedFastPolls"); - double ForcedFastPolls = lua_tonumberx(this->state, -1, &isnum); - if (isnum) { pC->forcedFastPolls_ = ForcedFastPolls; } - lua_remove(this->state, -1); - - // Zero the encoder position (this only appears to be a problem on windows) - setDoubleParam(pC_->motorEncoderPosition_, 0.0); - - // Make the changed parameters take effect - callParamCallbacks(); -} - -void ScriptMotorAxis::initState(const char* script_file) -{ - this->state = luaL_newstate(); - int status = luaLoadScript(this->state, script_file); - - if (status) { printf("Error compiling script file: %s\n", script_file); } - - lua_pushstring(this->state, (const char*) this->pC_->portName); - lua_setglobal(this->state, "DRIVER"); - - lua_pushnumber(this->state, axisNo_); - lua_setglobal(this->state, "AXIS"); -} - -void ScriptMotorAxis::reload(const char* script_file, const char* controller_params) -{ - this->initState(script_file); - this->config(controller_params); - this->config(this->params.c_str()); -} - -epicsUInt32 ScriptMotorAxis::setStatusParam(int index, int value) -{ - if (index >= pC_->motorStatusDirection_ && index <= pC_->motorStatusHomed_) - { - epicsUInt32 status = status_.status; - int mask = 1 << (index - pC_->motorStatusDirection_); - - if (value) { status |= mask; } - else { status &= ~mask; } - - if (status != status_.status) - { - status_.status = status; - statusChanged_ = 1; - } - - return status; - } - - return 0; -} - -void ScriptMotorAxis::setPositionParam(int index, double value) -{ - if (index == pC_->motorPosition_) - { - if (value != status_.position) - { - statusChanged_ = 1; - status_.position = value; - } - } - else if (index == pC_->motorEncoderPosition_) - { - if (value != status_.encoderPosition) - { - statusChanged_ = 1; - status_.encoderPosition = value; - } - } -} - - -/* - * - */ -extern "C" int ScriptAxisConfig(const char* ScriptMotorName, int axisNo, const char* params) -{ - static const char *functionName = "VirtualMotorCreateAxis"; - - ScriptMotorController *pC = (ScriptMotorController*) findAsynPortDriver(ScriptMotorName); - if (!pC) - { - printf("Error port %s not found\n", ScriptMotorName); - return asynError; - } - - pC->lock(); - pC->configAxis(axisNo, params); - pC->unlock(); - - return asynSuccess; -} - - -/** Reports on status of the axis - * \param[in] fp The file pointer on which report information will be written - * \param[in] level The level of report detail desired - * - * After printing device-specific information calls asynMotorAxis::report() - */ -void ScriptMotorAxis::report(FILE *fp, int level) -{ - if (level > 0) { - fprintf(fp, " Axis #%d\n", axisNo_); - fprintf(fp, " axisIndex_=%d\n", axisIndex_); - } - - // Call the base class method - asynMotorAxis::report(fp, level); -} - - -/* - * move() is called by asynMotor device support when an absolute or a relative move is requested. - * It can be called multiple times if BDST > 0 or RTRY > 0. - * - * Arguments in terms of motor record fields: - * position (steps) = RVAL = DVAL / MRES - * baseVelocity (steps/s) = VBAS / abs(MRES) - * velocity (step/s) = VELO / abs(MRES) - * acceleration (step/s/s) = (velocity - baseVelocity) / ACCL - */ -asynStatus ScriptMotorAxis::move(double position, int relative, double minVelocity, double maxVelocity, double acceleration) -{ - asynStatus status; - // static const char *functionName = "ScriptMotorAxis::move"; - - int result = lua_getglobal(this->state, "move"); - if (result != LUA_TFUNCTION) - { - // No function in script - } - else - { - lua_pushnumber(this->state, position); - lua_pushboolean(this->state, relative); - lua_pushnumber(this->state, minVelocity); - lua_pushnumber(this->state, maxVelocity); - lua_pushnumber(this->state, acceleration); - - if (lua_pcall(this->state, 5, 1, 0)) - { - this->logError(); - return asynError; - } - - int rettype = lua_type(this->state, -1); - - // Do something with returned value - - lua_pop(this->state, 1); - } - - return asynSuccess; -} - - -/* - * home() is called by asynMotor device support when a home is requested. - * Note: forwards is set by device support, NOT by the motor record. - * - * Arguments in terms of motor record fields: - * minVelocity (steps/s) = VBAS / abs(MRES) - * maxVelocity (step/s) = HVEL / abs(MRES) - * acceleration (step/s/s) = (maxVelocity - minVelocity) / ACCL - * forwards = 1 if HOMF was pressed, 0 if HOMR was pressed - */ - -asynStatus ScriptMotorAxis::home(double minVelocity, double maxVelocity, double acceleration, int forwards) -{ - int result = lua_getglobal(this->state, "home"); - if (result != LUA_TFUNCTION) - { - // No function in script - } - else - { - lua_pushnumber(this->state, minVelocity); - lua_pushnumber(this->state, maxVelocity); - lua_pushnumber(this->state, acceleration); - lua_pushboolean(this->state, forwards); - - if (lua_pcall(this->state, 4, 1, 0)) - { - this->logError(); - return asynError; - } - - int rettype = lua_type(this->state, -1); - - // Do something with returned value - - lua_pop(this->state, 1); - } - - return asynSuccess; -} - - - -/* - * moveVelocity() is called by asynMotor device support when a jog is requested. - * If a controller doesn't have a jog command (or jog commands), this a jog can be simulated here. - * - * Arguments in terms of motor record fields: - * minVelocity (steps/s) = VBAS / abs(MRES) - * maxVelocity (step/s) = (jog_direction == forward) ? JVEL * DIR / MRES : -1 * JVEL * DIR / MRES - * acceleration (step/s/s) = JAR / abs(EGU) - */ -asynStatus ScriptMotorAxis::moveVelocity(double minVelocity, double maxVelocity, double acceleration) -{ - int result = lua_getglobal(this->state, "moveVelocity"); - if (result != LUA_TFUNCTION) - { - // No function in script - } - else - { - lua_pushnumber(this->state, minVelocity); - lua_pushnumber(this->state, maxVelocity); - lua_pushnumber(this->state, acceleration); - - if (lua_pcall(this->state, 3, 1, 0)) - { - this->logError(); - return asynError; - } - - int rettype = lua_type(this->state, -1); - - // Do something with returned value - - lua_pop(this->state, 1); - } - - return asynSuccess; -} - - -/* - * stop() is called by asynMotor device support whenever a user presses the stop button. - * It is also called when the jog button is released. - * - * Arguments in terms of motor record fields: - * acceleration = ??? - */ -asynStatus ScriptMotorAxis::stop(double acceleration) -{ - int result = lua_getglobal(this->state, "stop"); - if (result != LUA_TFUNCTION) - { - // No function in script - } - else - { - lua_pushnumber(this->state, acceleration); - - if (lua_pcall(this->state, 1, 1, 0)) - { - this->logError(); - return asynError; - } - - int rettype = lua_type(this->state, -1); - - // Do something with returned value - - lua_pop(this->state, 1); - } - - return asynSuccess; -} - - -/* - * setPosition() is called by asynMotor device support when a position is redefined. - * It is also required for autosave to restore a position to the controller at iocInit. - * - * Arguments in terms of motor record fields: - * position (steps) = DVAL / MRES = RVAL - */ -asynStatus ScriptMotorAxis::setPosition(double position) -{ - int result = lua_getglobal(this->state, "setPosition"); - if (result != LUA_TFUNCTION) - { - // No function in script - } - else - { - lua_pushnumber(this->state, position); - - if (lua_pcall(this->state, 1, 1, 0)) - { - this->logError(); - return asynError; - } - - int rettype = lua_type(this->state, -1); - - // Do something with returned value - - lua_pop(this->state, 1); - } - - return asynSuccess; -} - -asynStatus ScriptMotorAxis::setEncoderPosition(double position) -{ - int result = lua_getglobal(this->state, "setEncoderPosition"); - if (result != LUA_TFUNCTION) - { - // No function in script - } - else - { - lua_pushnumber(this->state, position); - - if (lua_pcall(this->state, 1, 1, 0)) - { - this->logError(); - return asynError; - } - - int rettype = lua_type(this->state, -1); - - // Do something with returned value - - lua_pop(this->state, 1); - } - - return asynSuccess; -} - -asynStatus ScriptMotorAxis::setHighLimit(double highLimit) -{ - int result = lua_getglobal(this->state, "setHighLimit"); - if (result != LUA_TFUNCTION) - { - // No function in script - } - else - { - lua_pushnumber(this->state, highLimit); - - if (lua_pcall(this->state, 1, 1, 0)) - { - this->logError(); - return asynError; - } - - int rettype = lua_type(this->state, -1); - - // Do something with returned value - - lua_pop(this->state, 1); - } - - return asynSuccess; -} - -asynStatus ScriptMotorAxis::setLowLimit(double lowLimit) -{ - int result = lua_getglobal(this->state, "setLowLimit"); - if (result != LUA_TFUNCTION) - { - // No function in script - } - else - { - lua_pushnumber(this->state, lowLimit); - - if (lua_pcall(this->state, 1, 1, 0)) - { - this->logError(); - return asynError; - } - - int rettype = lua_type(this->state, -1); - - // Do something with returned value - - lua_pop(this->state, 1); - } - - return asynSuccess; -} - - -asynStatus ScriptMotorAxis::setPGain(double PGain) -{ - int result = lua_getglobal(this->state, "setPGain"); - if (result != LUA_TFUNCTION) - { - // No function in script - } - else - { - lua_pushnumber(this->state, PGain); - - if (lua_pcall(this->state, 1, 1, 0)) - { - this->logError(); - return asynError; - } - - int rettype = lua_type(this->state, -1); - - // Do something with returned value - - lua_pop(this->state, 1); - } - - return asynSuccess; -} - -asynStatus ScriptMotorAxis::setIGain(double IGain) -{ - int result = lua_getglobal(this->state, "setIGain"); - if (result != LUA_TFUNCTION) - { - // No function in script - } - else - { - lua_pushnumber(this->state, IGain); - - if (lua_pcall(this->state, 1, 1, 0)) - { - this->logError(); - return asynError; - } - - int rettype = lua_type(this->state, -1); - - // Do something with returned value - - lua_pop(this->state, 1); - } - - return asynSuccess; -} - -asynStatus ScriptMotorAxis::setDGain(double DGain) -{ - int result = lua_getglobal(this->state, "setDGain"); - if (result != LUA_TFUNCTION) - { - // No function in script - } - else - { - lua_pushnumber(this->state, DGain); - - if (lua_pcall(this->state, 1, 1, 0)) - { - this->logError(); - return asynError; - } - - int rettype = lua_type(this->state, -1); - - // Do something with returned value - - lua_pop(this->state, 1); - } - - return asynSuccess; -} - -/* - * setClosedLoop() is called by asynMotor device support when a user enables or disables torque, - * usually from the motorx_all.adl, but only for drivers that set the following params to 1: - * pC->motorStatusGainSupport_ - * pC->motorStatusHasEncoder_ - * What is actually implemented here varies greatly based on the specfics of the controller. - * - * Arguments in terms of motor record fields: - * closedLoop = CNEN - */ - -asynStatus ScriptMotorAxis::setClosedLoop(bool closedLoop) -{ - int result = lua_getglobal(this->state, "setClosedLoop"); - if (result != LUA_TFUNCTION) - { - // No function in script - } - else - { - lua_pushboolean(this->state, (int) closedLoop); - - if (lua_pcall(this->state, 1, 1, 0)) - { - this->logError(); - return asynError; - } - - int rettype = lua_type(this->state, -1); - - // Do something with returned value - - lua_pop(this->state, 1); - } - - return asynSuccess; -} - -asynStatus ScriptMotorAxis::setEncoderRatio(double EncoderRatio) -{ - int result = lua_getglobal(this->state, "setEncoderRatio"); - if (result != LUA_TFUNCTION) - { - // No function in script - } - else - { - lua_pushnumber(this->state, EncoderRatio); - - if (lua_pcall(this->state, 1, 1, 0)) - { - this->logError(); - return asynError; - } - - int rettype = lua_type(this->state, -1); - - // Do something with returned value - - lua_pop(this->state, 1); - } - - return asynSuccess; -} - - - -/** Polls the axis. - * This function reads the motor position, the limit status, the home status, the moving status, - * 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). */ -asynStatus ScriptMotorAxis::poll(bool *moving) -{ - int result = lua_getglobal(this->state, "poll"); - if (result != LUA_TFUNCTION) - { - // No function in script - } - else - { - if (lua_pcall(this->state, 0, 1, 0)) - { - this->logError(); - return asynError; - } - - int rettype = lua_type(this->state, -1); - - if (rettype == LUA_TBOOLEAN) - { - if (lua_toboolean(this->state, -1)) { *moving = true; } - else { *moving = false; } - } - - lua_pop(this->state, 1); - } - - this->callParamCallbacks(); - return asynSuccess; -} - -void ScriptMotorAxis::config(const char* params) -{ - luaLoadMacros(this->state, params); -} - -void ScriptMotorAxis::logError() -{ - std::string err(lua_tostring(this->state, -1)); - lua_pop(this->state, 1); - - printf("%s\n", err.c_str()); -} - -void ScriptMotorReload(const char* port) -{ - ScriptMotorController* controller = (ScriptMotorController*) findAsynPortDriver(port); - - if (controller != NULL) { controller->reload(); } -} - - -/** Code for iocsh registration */ -static const iocshArg ScriptMotorReloadArg0 = {"Motor Port name", iocshArgString}; - -static const iocshArg* const ScriptMotorReloadArgs[] = {&ScriptMotorReloadArg0}; - -static const iocshFuncDef ScriptMotorReloadDef = {"ScriptMotorReload", 1, ScriptMotorReloadArgs}; - -static void ScriptMotorReloadCallFunc(const iocshArgBuf *args) -{ - ScriptMotorReload(args[0].sval); -} - - -static const iocshArg ScriptMotorCreateControllerArg0 = {"Motor Port name", iocshArgString}; -static const iocshArg ScriptMotorCreateControllerArg1 = {"Number of axes", iocshArgInt}; -static const iocshArg ScriptMotorCreateControllerArg2 = {"Control Script", iocshArgString}; -static const iocshArg ScriptMotorCreateControllerArg3 = {"Parameters", iocshArgString}; -static const iocshArg * const ScriptMotorCreateControllerArgs[] = {&ScriptMotorCreateControllerArg0, - &ScriptMotorCreateControllerArg1, - &ScriptMotorCreateControllerArg2, - &ScriptMotorCreateControllerArg3}; -static const iocshFuncDef ScriptMotorCreateControllerDef = {"ScriptControllerConfig", 4, ScriptMotorCreateControllerArgs}; -static void ScriptMotorCreateContollerCallFunc(const iocshArgBuf *args) -{ - ScriptControllerConfig(args[0].sval, args[1].ival, args[2].sval, args[3].sval); -} - - -static const iocshArg ScriptMotorCreateAxisArg0 = {"Controller port name", iocshArgString}; -static const iocshArg ScriptMotorCreateAxisArg1 = {"Axis number", iocshArgInt}; -static const iocshArg ScriptMotorCreateAxisArg2 = {"Parameters", iocshArgString}; - -static const iocshArg * const ScriptMotorCreateAxisArgs[] = {&ScriptMotorCreateAxisArg0, - &ScriptMotorCreateAxisArg1, - &ScriptMotorCreateAxisArg2}; - -static const iocshFuncDef ScriptMotorCreateAxisDef = {"ScriptAxisConfig", 3, ScriptMotorCreateAxisArgs}; -static void ScriptMotorCreateAxisCallFunc(const iocshArgBuf *args) -{ - ScriptAxisConfig(args[0].sval, args[1].ival, args[2].sval); -} - - - -static void ScriptMotorRegister(void) -{ - iocshRegister(&ScriptMotorReloadDef, ScriptMotorReloadCallFunc); - iocshRegister(&ScriptMotorCreateControllerDef, ScriptMotorCreateContollerCallFunc); - iocshRegister(&ScriptMotorCreateAxisDef, ScriptMotorCreateAxisCallFunc); -} - - -extern "C" { -epicsExportRegistrar(ScriptMotorRegister); -} diff --git a/motorApp/ScriptMotorSrc/ScriptMotorDriver.dbd b/motorApp/ScriptMotorSrc/ScriptMotorDriver.dbd deleted file mode 100644 index 8f5bbc23..00000000 --- a/motorApp/ScriptMotorSrc/ScriptMotorDriver.dbd +++ /dev/null @@ -1 +0,0 @@ -registrar(ScriptMotorRegister) diff --git a/motorApp/ScriptMotorSrc/ScriptMotorDriver.h b/motorApp/ScriptMotorSrc/ScriptMotorDriver.h deleted file mode 100644 index efa010cd..00000000 --- a/motorApp/ScriptMotorSrc/ScriptMotorDriver.h +++ /dev/null @@ -1,76 +0,0 @@ -#include "asynMotorController.h" -#include "asynMotorAxis.h" - -#include -#include "epicsScript.h" - -class epicsShareClass ScriptMotorAxis : public asynMotorAxis -{ -public: - /* These are the methods we override from the base class */ - ScriptMotorAxis(class ScriptMotorController *pC, int axisNo, const char* script_file, const char* params); - - void reload(const char* script, const char* params); - - void report(FILE *fp, int level); - - asynStatus move(double position, int relative, double min_velocity, double max_velocity, double acceleration); - asynStatus moveVelocity(double min_velocity, double max_velocity, double acceleration); - 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 setEncoderPosition(double position); - asynStatus setHighLimit(double highLimit); - asynStatus setLowLimit(double lowLimit); - asynStatus setPGain(double pGain); - asynStatus setIGain(double iGain); - asynStatus setDGain(double dGain); - asynStatus setClosedLoop(bool closedLoop); - asynStatus setEncoderRatio(double ratio); - - virtual epicsUInt32 setStatusParam(int index, int value); - virtual void setPositionParam(int index, double value); - -private: - ScriptMotorController *pC_; /**< Pointer to the asynMotorController to which this axis belongs. - * Abbreviated because it is used very frequently */ - int axisIndex_; - - std::string params; - - lua_State* state; - - void initState(const char* script_file); - void config(const char* params); - void logError(); - -friend class ScriptMotorController; -}; - -class epicsShareClass ScriptMotorController : public asynMotorController { -public: - ScriptMotorController(const char *asyn_port, int max_axes, const char* script_file, const char* params); - - virtual asynStatus setIntegerParam(int list, int function, int value); - virtual asynStatus setDoubleParam(int list, int function, double value); - - virtual asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value); - - void report(FILE *fp, int level); - ScriptMotorAxis* getAxis(asynUser *pasynUser); - ScriptMotorAxis* getAxis(int axisNo); - - void configAxis(int axisNo, const char* params); - - void reload(); - -protected: - int ScriptMotorReload; - -private: - std::string script; - std::string init_params; - -friend class ScriptMotorAxis; -}; diff --git a/motorApp/op/adl/ScriptMotorReload.adl b/motorApp/op/adl/ScriptMotorReload.adl deleted file mode 100644 index 6f76c4a8..00000000 --- a/motorApp/op/adl/ScriptMotorReload.adl +++ /dev/null @@ -1,140 +0,0 @@ - -file { - name="/home/oxygen40/KLANG/Documents/Projects/Repository/git/motor/motorApp/op/adl/ScriptMotorReload.adl" - version=030107 -} -display { - object { - x=663 - y=227 - width=220 - height=75 - } - clr=14 - bclr=4 - cmap="" - gridSpacing=5 - gridOn=0 - snapToGrid=0 -} -"color map" { - ncolors=65 - colors { - ffffff, - ececec, - dadada, - c8c8c8, - bbbbbb, - aeaeae, - 9e9e9e, - 919191, - 858585, - 787878, - 696969, - 5a5a5a, - 464646, - 2d2d2d, - 000000, - 00d800, - 1ebb00, - 339900, - 2d7f00, - 216c00, - fd0000, - de1309, - be190b, - a01207, - 820400, - 5893ff, - 597ee1, - 4b6ec7, - 3a5eab, - 27548d, - fbf34a, - f9da3c, - eeb62b, - e19015, - cd6100, - ffb0ff, - d67fe2, - ae4ebc, - 8b1a96, - 610a75, - a4aaff, - 8793e2, - 6a73c1, - 4d52a4, - 343386, - c7bb6d, - b79d5c, - a47e3c, - 7d5627, - 58340f, - 99ffff, - 73dfff, - 4ea5f9, - 2a63e4, - 0a00b8, - ebf1b5, - d4db9d, - bbc187, - a6a462, - 8b8239, - 73ff6b, - 52da3b, - 3cb420, - 289315, - 1a7309, - } -} -rectangle { - object { - x=0 - y=0 - width=250 - height=25 - } - "basic attribute" { - clr=29 - } -} -"message button" { - object { - x=10 - y=35 - width=200 - height=30 - } - control { - chan="$(P)$(PORT):ScriptReload" - clr=14 - bclr=62 - } - label="Reload $(PORT)" - press_msg="1" -} -rectangle { - object { - x=-7 - y=-7 - width=257 - height=32 - } - "basic attribute" { - clr=14 - fill="outline" - width=3 - } -} -text { - object { - x=5 - y=3 - width=200 - height=20 - } - "basic attribute" { - clr=0 - } - textix="Script Motor Reload" -} diff --git a/motorExApp/WithAsyn/Makefile b/motorExApp/WithAsyn/Makefile index f678e039..7be8e650 100644 --- a/motorExApp/WithAsyn/Makefile +++ b/motorExApp/WithAsyn/Makefile @@ -39,9 +39,6 @@ ifdef BUSY endif COMMONDBDS += PI_GCS2Support.dbd COMMONDBDS += phytron.dbd -ifdef SCRIPT -COMMONDBDS += ScriptMotorDriver.dbd -endif DBD += WithAsyn.dbd WithAsyn_DBD += $(COMMONDBDS) @@ -86,10 +83,6 @@ COMMONLIBS += ACRMotor COMMONLIBS += PI_GCS2Support COMMONLIBS += phytronAxisMotor COMMONLIBS += motor -ifdef SCRIPT -COMMONLIBS += ScriptMotor -COMMONLIBS += script -endif # Needed for Newport SNL programs WithAsyn_LIBS += $(COMMONLIBS)