diff --git a/.gitmodules b/.gitmodules index 76b30afe..9f5d04bd 100644 --- a/.gitmodules +++ b/.gitmodules @@ -76,3 +76,6 @@ [submodule "modules/motorPI"] path = modules/motorPI url = https://github.com/epics-motor/motorPI.git +[submodule "modules/motorAMCI"] + path = modules/motorAMCI + url = https://github.com/epics-motor/motorAMCI.git diff --git a/iocBoot/iocWithAsyn/motor.cmd.ANF2 b/iocBoot/iocWithAsyn/motor.cmd.ANF2 deleted file mode 100644 index f501ae27..00000000 --- a/iocBoot/iocWithAsyn/motor.cmd.ANF2 +++ /dev/null @@ -1,107 +0,0 @@ -# ANF2 motors command file example (run in iocsh) -# -### Note: Modbus support (the EPICS modbus module) is required to be included in the -### EPICS application where the ANF2 support will be loaded. This file is an -### example of how to load the ANF2 support, in an ioc that is built with the -### EPICS modbus module. - -epicsEnvSet("PORT1", "ANF2_C1") -epicsEnvSet("PORT2", "ANF2_C2") - -# drvAsynIPPortConfigure("portName", "hostInfo", priority, noAutoConnect, noProcessEos); -drvAsynIPPortConfigure("$(PORT1)_IP","192.168.0.50:502",0,0,1) -drvAsynIPPortConfigure("$(PORT2)_IP","192.168.0.51:502",0,0,1) - -# modbusInterposeConfig("portName", linkType, timeoutMsec, writeDelayMsec) -modbusInterposeConfig("$(PORT1)_IP",0,2000,0) -modbusInterposeConfig("$(PORT2)_IP",0,2000,0) - -# NOTE: modbusLength = 10 * number of axes -# drvModbusAsynConfigure("portName", "tcpPortName", slaveAddress, modbusFunction, -# modbusStartAddress, modbusLength, dataType, pollMsec, "plcType") -drvModbusAsynConfigure("$(PORT1)_In", "$(PORT1)_IP", 0, 4, 0, 120, 0, 100, "ANF2_stepper") -drvModbusAsynConfigure("$(PORT2)_In", "$(PORT2)_IP", 0, 4, 0, 60, 0, 100, "ANF2_stepper") - -# NOTE: modbusLength = 10 * number of axes -# drvModbusAsynConfigure("portName", "tcpPortName", slaveAddress, modbusFunction, -# modbusStartAddress, modbusLength, dataType, pollMsec, "plcType") -drvModbusAsynConfigure("$(PORT1)_Out", "$(PORT1)_IP", 0, 16, 1024, 120, 6, 1, "ANF2_stepper") -drvModbusAsynConfigure("$(PORT2)_Out", "$(PORT2)_IP", 0, 16, 1024, 60, 6, 1, "ANF2_stepper") - -# Asyn traces for debugging -#!asynSetTraceIOMask "$(PORT1)_In",0,4 -#!asynSetTraceMask "$(PORT1)_In",0,9 -#!asynSetTraceIOMask "$(PORT1)_Out",0,4 -#!asynSetTraceMask "$(PORT1)_Out",0,9 -#!asynSetTraceInfoMask "$(PORT1)_Out",0,15 - -# Asyn records for debugging -#!dbLoadRecords("$(ASYN)/db/asynRecord.db","P=IOC:,R=asyn:c1ip,PORT=$(PORT1)_IP,ADDR=0,OMAX=256,IMAX=256") -#!dbLoadRecords("$(ASYN)/db/asynRecord.db","P=IOC:,R=asyn:c1in,PORT=$(PORT1)_In,ADDR=0,OMAX=256,IMAX=256") -#!dbLoadRecords("$(ASYN)/db/asynRecord.db","P=IOC:,R=asyn:c1out,PORT=$(PORT1)_Out,ADDR=0,OMAX=256,IMAX=256") -#!dbLoadRecords("$(ASYN)/db/asynRecord.db","P=IOC:,R=asyn:c1,PORT=$(PORT1),ADDR=0,OMAX=256,IMAX=256") - -# Load the motor records -dbLoadTemplate("templates/motor.substitutions.ANF2") - -# AMCI ANF2 stepper controller driver support -# -# ANF2CreateController( -# portName, The name of the asyn port that will be created by this driver -# ANF2InPortName, The name of the In drvAsynIPPPort to read from the ANF2 controller -# ANF2OutPortName, The name of the Out drvAsynIPPPort to write to the ANF2 controller -# numAxes) The number of axes in the stack (max=12) -# -# ANF2CreateAxis( -# ANF2Name, The controller's asyn port -# axis, The axis to be configured (zero-based numbering) -# hexConfig, The desired hex configuration (see manual & AMCI Net Configurator for details) -# baseSpeed, The base speed (steps/second; min=1, max=1,000,000) -# homingTimeout) The homing timeout (integer number of seconds; min=0, max=300) -# -# Note: The base speed can't be changed using the VBAS field of the motor record, but the driver -# does correct the acceleration sent by the motor record to give the desired acceleration time. - -# Controller 1 (One ANF2E, Five ANF2's) -ANF2CreateController("$(PORT1)", "$(PORT1)_In", "$(PORT1)_Out", 12) -# Axes for Controller 1 -ANF2CreateAxis("$(PORT1)", 0, "0x86280000", 100, 0) -ANF2CreateAxis("$(PORT1)", 1, "0x86000000", 100, 0) -ANF2CreateAxis("$(PORT1)", 2, "0x84000000", 100, 0) -ANF2CreateAxis("$(PORT1)", 3, "0x84000000", 100, 0) -ANF2CreateAxis("$(PORT1)", 4, "0x84000000", 100, 0) -ANF2CreateAxis("$(PORT1)", 5, "0x84000000", 100, 0) -ANF2CreateAxis("$(PORT1)", 6, "0x84000000", 100, 0) -ANF2CreateAxis("$(PORT1)", 7, "0x84000000", 100, 0) -ANF2CreateAxis("$(PORT1)", 8, "0x84000000", 100, 0) -ANF2CreateAxis("$(PORT1)", 9, "0x84000000", 100, 0) -ANF2CreateAxis("$(PORT1)", 10, "0x84000000", 100, 0) -ANF2CreateAxis("$(PORT1)", 11, "0x84000000", 100, 0) - -# Controller 2 (One ANF1E, Five ANF1's) -ANF2CreateController("$(PORT2)", "$(PORT2)_In", "$(PORT2)_Out", 6) -# Axes for Controller 2 -ANF2CreateAxis("$(PORT2)", 0, "0x84000000", 100, 0) -ANF2CreateAxis("$(PORT2)", 1, "0x84000000", 100, 0) -ANF2CreateAxis("$(PORT2)", 2, "0x84000000", 100, 0) -ANF2CreateAxis("$(PORT2)", 3, "0x84000000", 100, 0) -ANF2CreateAxis("$(PORT2)", 4, "0x84000000", 100, 0) -ANF2CreateAxis("$(PORT2)", 5, "0x84000000", 100, 0) - -# NOTE: the poller needs to be started after iocInit - - - -########## -# iocInit -########## - - - -# ANF2StartPoller( -# portName, The controller's asyn port -# movingPollPeriod, The time in ms between polls when any axis is moving -# idlePollPeriod) The time in ms between polls when no axis is moving -# -ANF2StartPoller("$(PORT1)", 200, 1000) -ANF2StartPoller("$(PORT2)", 200, 1000) diff --git a/iocBoot/iocWithAsyn/motor.substitutions.ANF2 b/iocBoot/iocWithAsyn/motor.substitutions.ANF2 deleted file mode 100644 index a29a9eb5..00000000 --- a/iocBoot/iocWithAsyn/motor.substitutions.ANF2 +++ /dev/null @@ -1,54 +0,0 @@ -file "$(MOTOR)/motorApp/Db/asyn_motor.db" -{ -pattern -{P, M, DTYP, PORT, ADDR, DESC, EGU, DIR, VELO, VBAS, ACCL, BDST, BVEL, BACC, MRES, PREC, DHLM, DLLM, INIT, RTRY} - -{IOC:, "m1", "asynMotor", "ANF2_C1", 0, "ANF2 C1 M1", steps, Pos, 100, 0, .2, 0, 50, .2, 1, 5, 1e9, -1e9, ""} -{IOC:, "m2", "asynMotor", "ANF2_C1", 1, "ANF2 C1 M2", steps, Pos, 100, 0, .2, 0, 50, .2, 1, 5, 1e9, -1e9, ""} -{IOC:, "m3", "asynMotor", "ANF2_C1", 2, "ANF2 C1 M3", steps, Pos, 100, 0, .2, 0, 50, .2, 1, 5, 1e9, -1e9, ""} -{IOC:, "m4", "asynMotor", "ANF2_C1", 3, "ANF2 C1 M4", steps, Pos, 100, 0, .2, 0, 50, .2, 1, 5, 1e9, -1e9, ""} -{IOC:, "m5", "asynMotor", "ANF2_C1", 4, "ANF2 C1 M5", steps, Pos, 100, 0, .2, 0, 50, .2, 1, 5, 1e9, -1e9, ""} -{IOC:, "m6", "asynMotor", "ANF2_C1", 5, "ANF2 C1 M6", steps, Pos, 100, 0, .2, 0, 50, .2, 1, 5, 1e9, -1e9, ""} -{IOC:, "m7", "asynMotor", "ANF2_C1", 6, "ANF2 C1 M7", steps, Pos, 100, 0, .2, 0, 50, .2, 1, 5, 1e9, -1e9, ""} -{IOC:, "m8", "asynMotor", "ANF2_C1", 7, "ANF2 C1 M8", steps, Pos, 100, 0, .2, 0, 50, .2, 1, 5, 1e9, -1e9, ""} -{IOC:, "m9", "asynMotor", "ANF2_C1", 8, "ANF2 C1 M9", steps, Pos, 100, 0, .2, 0, 50, .2, 1, 5, 1e9, -1e9, ""} -{IOC:, "m10", "asynMotor", "ANF2_C1", 9, "ANF2 C1 M10", steps, Pos, 100, 0, .2, 0, 50, .2, 1, 5, 1e9, -1e9, ""} -{IOC:, "m11", "asynMotor", "ANF2_C1", 10, "ANF2 C1 M11", steps, Pos, 100, 0, .2, 0, 50, .2, 1, 5, 1e9, -1e9, ""} -{IOC:, "m12", "asynMotor", "ANF2_C1", 11, "ANF2 C1 M12", steps, Pos, 100, 0, .2, 0, 50, .2, 1, 5, 1e9, -1e9, ""} - -{IOC:, "m13", "asynMotor", "ANF2_C2", 0, "ANF2 C2 M1", steps, Pos, 100, 0, .2, 0, 50, .2, 1, 5, 1e9, -1e9, ""} -{IOC:, "m14", "asynMotor", "ANF2_C2", 1, "ANF2 C2 M2", steps, Pos, 100, 0, .2, 0, 50, .2, 1, 5, 1e9, -1e9, ""} -{IOC:, "m15", "asynMotor", "ANF2_C2", 2, "ANF2 C2 M3", steps, Pos, 100, 0, .2, 0, 50, .2, 1, 5, 1e9, -1e9, ""} -{IOC:, "m16", "asynMotor", "ANF2_C2", 3, "ANF2 C2 M4", steps, Pos, 100, 0, .2, 0, 50, .2, 1, 5, 1e9, -1e9, ""} -{IOC:, "m17", "asynMotor", "ANF2_C2", 4, "ANF2 C2 M5", steps, Pos, 100, 0, .2, 0, 50, .2, 1, 5, 1e9, -1e9, ""} -{IOC:, "m18", "asynMotor", "ANF2_C2", 5, "ANF2 C2 M6", steps, Pos, 100, 0, .2, 0, 50, .2, 1, 5, 1e9, -1e9, ""} - -} - -file "$(MOTOR)/motorApp/Db/ANF2Aux.template" -{ -pattern -{P, R, PORT, ADDR} - -{IOC:, m1:, "ANF2_C1", 0} -{IOC:, m2:, "ANF2_C1", 1} -{IOC:, m3:, "ANF2_C1", 2} -{IOC:, m4:, "ANF2_C1", 3} -{IOC:, m5:, "ANF2_C1", 4} -{IOC:, m6:, "ANF2_C1", 5} -{IOC:, m7:, "ANF2_C1", 6} -{IOC:, m8:, "ANF2_C1", 7} -{IOC:, m9:, "ANF2_C1", 8} -{IOC:, m10:, "ANF2_C1", 9} -{IOC:, m11:, "ANF2_C1", 10} -{IOC:, m12:, "ANF2_C1", 11} - -{IOC:, m13:, "ANF2_C2", 0} -{IOC:, m14:, "ANF2_C2", 1} -{IOC:, m15:, "ANF2_C2", 2} -{IOC:, m16:, "ANF2_C2", 3} -{IOC:, m17:, "ANF2_C2", 4} -{IOC:, m18:, "ANF2_C2", 5} - -} - diff --git a/iocBoot/iocWithAsyn/motor.substitutions.ANG1 b/iocBoot/iocWithAsyn/motor.substitutions.ANG1 deleted file mode 100644 index 069accf7..00000000 --- a/iocBoot/iocWithAsyn/motor.substitutions.ANG1 +++ /dev/null @@ -1,17 +0,0 @@ -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 deleted file mode 100644 index 8e9a5dcb..00000000 --- a/iocBoot/iocWithAsyn/st.cmd.ANG1 +++ /dev/null @@ -1,74 +0,0 @@ -# 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, -# 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) diff --git a/modules/Makefile b/modules/Makefile index ac4a5b2f..1db87298 100644 --- a/modules/Makefile +++ b/modules/Makefile @@ -5,6 +5,7 @@ include $(TOP)/configure/CONFIG #SUBMODULES += motorVendor SUBMODULES += motorOms SUBMODULES += motorNewport +SUBMODULES += motorAMCI SUBMODULES += motorACR SUBMODULES += motorAcs SUBMODULES += motorAcsTech80 diff --git a/modules/motorAMCI b/modules/motorAMCI new file mode 160000 index 00000000..0bbd957f --- /dev/null +++ b/modules/motorAMCI @@ -0,0 +1 @@ +Subproject commit 0bbd957f21cb3a6aa48182b4295b111fc7aec24e diff --git a/motorApp/AMCISrc/AMCISupport.dbd b/motorApp/AMCISrc/AMCISupport.dbd deleted file mode 100644 index 48132bba..00000000 --- a/motorApp/AMCISrc/AMCISupport.dbd +++ /dev/null @@ -1,2 +0,0 @@ -include "ANG1Support.dbd" -include "ANF2Support.dbd" diff --git a/motorApp/AMCISrc/ANF2Driver.cpp b/motorApp/AMCISrc/ANF2Driver.cpp deleted file mode 100644 index 993a0a46..00000000 --- a/motorApp/AMCISrc/ANF2Driver.cpp +++ /dev/null @@ -1,1088 +0,0 @@ -/* -FILENAME... ANF2Driver.cpp -USAGE... Motor record driver support for the AMCI ANF2 stepper motor controller over Modbus/TCP. - -Kevin Peterson - -Based on the AMCI ANG1 Model 3 device driver written by Kurt Goetze - -*/ - - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include "ANF2Driver.h" -#include - -#define NINT(f) (int)((f)>0 ? (f)+0.5 : (f)-0.5) - -static const char *driverName = "ANF2MotorDriver"; - -/** Constructor, Creates a new ANF2Controller object. - * \param[in] portName The name of the asyn port that will be created for this driver - * \param[in] ANF2InPortName The name of the drvAsynSerialPort that was created previously to connect to the ANF2 controller - * \param[in] ANF2OutPortName The name of the drvAsynSerialPort that was created previously to connect to the ANF2 controller - * \param[in] numAxes The number of axes on the controller stack - */ -ANF2Controller::ANF2Controller(const char *portName, const char *ANF2InPortName, const char *ANF2OutPortName, - int numAxes) - : asynMotorController(portName, numAxes, NUM_ANF2_PARAMS, - asynInt32ArrayMask, // One additional interface beyond those in base class - asynInt32ArrayMask, // One additional callback interface beyond those in base class - ASYN_CANBLOCK | ASYN_MULTIDEVICE, - 1, // autoconnect - 0, 0) // Default priority and stack size -{ - int i, j; - asynStatus status = asynSuccess; - static const char *functionName = "ANF2Controller::ANF2Controller"; - - // Keep track of the number of axes created, so the poller can wait for all the axes to be created before starting - axesCreated_ = 0; - - inputDriver_ = epicsStrDup(ANF2InPortName); // Set this before calls to create Axis objects - - // Create controller-specific parameters - createParam(ANF2ResetErrorsString, asynParamInt32, &ANF2ResetErrors_); - createParam(ANF2GetInfoString, asynParamInt32, &ANF2GetInfo_); - //createParam(ANF2ReconfigString, asynParamInt32, &ANF2Reconfig_); - - numAxes_ = numAxes; - - for (j=0; jconnect(ANF2InPortName, i+j*AXIS_REG_OFFSET, &pasynUserInReg_[j][i], NULL); - } - status = pasynInt32ArraySyncIO->connect(ANF2OutPortName, j*AXIS_REG_OFFSET, &pasynUserOutReg_[j], NULL); - } - if (status) { - asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, - "%s: cannot connect to ANF2 controller\n", - functionName); - } - - /* Create the poller thread for this controller (do 2 forced-fast polls) - * NOTE: at this point the axis objects don't yet exist, but the poller tolerates this */ - //startPoller(movingPollPeriod, idlePollPeriod, 2); -} - - -/** Creates a new ANF2Controller object. - * Configuration command, called directly or from iocsh - * \param[in] portName The name of the asyn port that will be created for this driver - * \param[in] ANF2InPortName The name of the drvAsynIPPPort that was created previously to connect to the ANF2 controller - * \param[in] ANF2OutPortName The name of the drvAsynIPPPort that was created previously to connect to the ANF2 controller - * \param[in] numAxes The number of axes on the controller stack - */ -extern "C" int ANF2CreateController(const char *portName, const char *ANF2InPortName, const char *ANF2OutPortName, int numAxes) -{ - // Enforce max values - if (numAxes > MAX_AXES) { - numAxes = MAX_AXES; - } - - new ANF2Controller(portName, ANF2InPortName, ANF2OutPortName, numAxes); - return(asynSuccess); -} - -/** Starts the poller for a given controller - * \param[in] ANF2Name The name of the asyn port that for the controller - * \param[in] movingPollPeriod The time in ms between polls when any axis is moving - * \param[in] idlePollPeriod The time in ms between polls when no axis is moving - */ -extern "C" asynStatus ANF2StartPoller(const char *ANF2Name, int movingPollPeriod, int idlePollPeriod) -{ - ANF2Controller *pC; - static const char *functionName = "ANF2StartPoller"; - - pC = (ANF2Controller*) findAsynPortDriver(ANF2Name); - if (!pC) { - printf("%s:%s: Error port %s not found\n", - driverName, functionName, ANF2Name); - return asynError; - } - - pC->lock(); - pC->doStartPoller(movingPollPeriod/1000.0, idlePollPeriod/1000.0); - pC->unlock(); - return asynSuccess; -} - -void ANF2Controller::doStartPoller(double movingPollPeriod, double idlePollPeriod) -{ - // - movingPollPeriod_ = movingPollPeriod; - idlePollPeriod_ = idlePollPeriod; - - // - startPoller(movingPollPeriod_, idlePollPeriod_, 2); -} - - -/** 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 ANF2Controller::report(FILE *fp, int level) -{ - int i, j; - ANF2Axis* pAxis[MAX_AXES]; - - fprintf(fp, "====================================\n"); - fprintf(fp, "ANF2 motor driver:\n"); - fprintf(fp, " asyn port: %s\n", this->portName); - fprintf(fp, " num axes: %i\n", numAxes_); - fprintf(fp, " axes created: %i\n", axesCreated_); - fprintf(fp, " moving poll period: %lf\n", movingPollPeriod_); - fprintf(fp, " idle poll period: %lf\n", idlePollPeriod_); - fprintf(fp, "\n"); - fprintf(fp, "Input registers:\n\n"); - - for (j=0; jgetInfo(); - } - - fprintf(fp, " Reg\t"); - for (j=0; jinputReg_[i]); - - } - fprintf(fp, "\n"); - } - - fprintf(fp, "\n"); - /*for (i=0; i(asynMotorController::getAxis(pANF2Axis methodsasynUser)); - return static_cast(asynMotorController::getAxis(pasynUser)); -} - -/** Returns a pointer to an ANF2Axis object. - * Returns NULL if the axis number encoded in pasynUser is invalid. - * \param[in] No Axis index number. */ -ANF2Axis* ANF2Controller::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 ANF2Jerk_ 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 ANF2Controller::writeInt32(asynUser *pasynUser, epicsInt32 value) -{ - int function = pasynUser->reason; - asynStatus status = asynSuccess; - ANF2Axis *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 == ANF2ResetErrors_) - { - // Only reset errors when value is 1 - if (value == 1) { - printf("ANF2Controller:writeInt32: Resetting errors for axis = %d\n", pAxis->axisNo_); - pAxis->resetErrors(); - - } - } else if (function == ANF2GetInfo_) - { - // Only get info when value is 1 - if (value == 1) { - printf("ANF2Controller:writeInt32: Getting info for axis = %d\n", pAxis->axisNo_); - pAxis->getInfo(); - - } - /* - } else if (function == ANF2Reconfig_) - { - // reconfig regardless of the value - pAxis->reconfig(value); - */ - } 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 ANF2Controller::writeReg32Array(int axisNo, epicsInt32* output, int nElements, double timeout) -{ - asynStatus status; - ANF2Axis *pAxis = getAxis(axisNo); - static const char *functionName = "ANF2Controller::writeReg32Array"; - - // This message isn't very helpful. Print something better in the future. - asynPrint(pAxis->pasynUser_, ASYN_TRACEIO_DRIVER, - "%s: axisNo=%i, nElements=%d\n", - functionName, axisNo, nElements); - status = pasynInt32ArraySyncIO->write(pasynUserOutReg_[axisNo], output, nElements, timeout); - - return status; -} - -asynStatus ANF2Controller::readReg16(int axisNo, int axisReg, epicsInt32 *input, double timeout) -{ - asynStatus status; - - //printf("axisReg = %d\n", axisReg); - //asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER,"readReg16 reg = %d\n", axisReg); - status = pasynInt32SyncIO->read(pasynUserInReg_[axisNo][axisReg], input, timeout); - - return status ; -} - -asynStatus ANF2Controller::readReg32(int axisNo, int axisReg, epicsInt32 *combo, double timeout) -{ - asynStatus status; - epicsInt32 lowerWord32, upperWord32; // only have pasynInt32SyncIO, not pasynInt16SyncIO , - - //printf("calling readReg16\n"); - status = readReg16(axisNo, axisReg, &upperWord32, timeout); //get Upper Word - - axisReg++; - status = readReg16(axisNo, axisReg, &lowerWord32, timeout); //get Lower Word - - *combo = NINT((upperWord32 << 16) | lowerWord32); - - return status ; -} - - -// ANF2Axis methods Here -// These are the ANF2Axis methods - -/** Creates a new ANF2Axis object. - * \param[in] pC Pointer to the ANF2Controller to which this axis belongs. - * \param[in] axisNo Index number of this axis, range 0 to pC->numAxes_-1. - * - * Initializes register numbers, etc. - */ -ANF2Axis::ANF2Axis(ANF2Controller *pC, int axisNo, epicsInt32 config, epicsInt32 baseSpeed, epicsInt32 homingTimeout) - : asynMotorAxis(pC, axisNo), - pC_(pC) -{ - int status; - - axisNo_ = axisNo; - config_ = config; - baseSpeed_ = baseSpeed; - homingTimeout_ = homingTimeout; - - // These registers will always be zero - zeroRegisters(zeroReg_); - - status = pasynInt32SyncIO->connect(pC_->inputDriver_, axisNo_*AXIS_REG_OFFSET, &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_); - } - - /* TODO: - * reduce the sleeps to see which ones are necessary - * make reconfig useful? - */ - - epicsThreadSleep(0.1); - - // Clear the command/configuration register (a good thing to do but doesn't appear to be necessary) - //status = pC_->writeReg32Array(axisNo_, zeroReg_, 5, DEFAULT_CONTROLLER_TIMEOUT); - - // Delay - //epicsThreadSleep(0.05); - - // These registers will always have the last config that was sent to the controller - zeroRegisters(confReg_); - - // Send the configuration (array) - // assemble the configuration bits; set the start speed to a non-zero value (100), which is required for the configuration to be accepted - confReg_[CONFIGURATION] = config; - confReg_[BASE_SPEED] = baseSpeed; - confReg_[HOME_TIMEOUT] = homingTimeout << 16; - - // Write all the registers - status = pC_->writeReg32Array(axisNo_, confReg_, 5, DEFAULT_CONTROLLER_TIMEOUT); - - // Delay - epicsThreadSleep(0.05); - - // Parse the configuration (mostly for asynReport purposes) - // MSW - CaptInput_ = (config & (0x1 << 16)) >> 16; - ExtInput_ = (config & (0x2 << 16)) >> 17; - HomeInput_ = (config & (0x4 << 16)) >> 18; - CWInput_ = (config & (0x18 << 16)) >> 19; - CCWInput_ = (config & (0x60 << 16)) >> 21; - BHPO_ = (config & (0x80 << 16)) >> 23; - QuadEnc_ = (config & (0x100 << 16)) >> 24; - DiagFbk_ = (config & (0x200 << 16)) >> 25; - OutPulse_ = (config & (0x400 << 16)) >> 26; - HomeOp_ = (config & (0x800 << 16)) >> 27; - CardAxis_ = (config & (0x4000 << 16)) >> 30; - OpMode_ = (epicsUInt32)(config & (0x8000 << 16)) >> 31; - // LSW - CaptInputAS_ = config & 0x1; - ExtInputAS_ = (config & 0x2) >> 1; - HomeInputAS_ = (config & 0x4) >> 2; - CWInputAS_ = (config & 0x8) >> 3; - CCWInputAS_ = (config & 0x10) >> 4; - - // Only allow UEIP to be used if the axis is configured to have a quadrature encoder - if ((QuadEnc_ != 0x0) || (DiagFbk_ != 0x0)) { - setIntegerParam(pC_->motorStatusHasEncoder_, 1); - } else { - setIntegerParam(pC_->motorStatusHasEncoder_, 0); - } - - // set position to 0 to clear the "position invalid" status that results from configuring the axis - setPosition(0); - // Tell asynMotor device support the position is zero so that autosave will restore the saved position (doesn't appear to be necessary) - //setDoubleParam(pC_->motorPosition_, 0.0); - - // Delay - //epicsThreadSleep(1.0); - - // Initialize parameters to avoid ASYN_TRACE_FLOW errors - setIntegerParam(pC_->motorStatusDirection_, 1); - // The following are necessary after this commit: - // https://github.com/epics-modules/motor/commit/36dfab4a78725866fab5bd212c4c128a86e9f044 - setIntegerParam(pC_->motorPowerAutoOnOff_, 0); - setDoubleParam(pC_->motorPowerOnDelay_, 0.0); - setDoubleParam(pC_->motorPowerOffDelay_, 0.0); - - // Tell the driver the axis has been created - pC_->axesCreated_ += 1; - - //epicsThreadSleep(1.0); -} - -/* - Configuration Bits: - 0x1 - Caputure Input (0 = Disabled, 1 = Enabled) - 0x2 - External Input (0 = Disabled, 1 = Enabled) - 0x4 - Home Input (0 = Disabled, 1 = Enabled) - 0x8 - - - */ - -extern "C" asynStatus ANF2CreateAxis(const char *ANF2Name, /* specify which controller by port name */ - int axis, /* axis number 0-1 */ - const char *hexConfig, /* desired configuration in hex */ - epicsInt32 baseSpeed, /* base speed */ - epicsInt32 homingTimeout) /* homing timeout */ -{ - ANF2Controller *pC; - epicsInt32 config; - static const char *functionName = "ANF2CreateAxis"; - - pC = (ANF2Controller*) findAsynPortDriver(ANF2Name); - if (!pC) { - printf("%s:%s: Error port %s not found\n", - driverName, functionName, ANF2Name); - return asynError; - } - - errno = 0; - config = strtoul(hexConfig, NULL, 16); - if (errno != 0) { - printf("%s:%s: Error invalid config=%s\n", - driverName, functionName, hexConfig); - return asynError; - } else { - printf("%s:%s: Config=0x%x\n", - driverName, functionName, config); - } - - // baseSpeed is steps/second (1-1,000,000) - if (baseSpeed < 1) { - baseSpeed = 1; - } - if (baseSpeed > 1000000) { - baseSpeed = 1000000; - } - - // homingTimeout is seconds (0-300) - if (homingTimeout < 0) { - homingTimeout = 0; - } - if (homingTimeout > 300) { - homingTimeout = 300; - } - - pC->lock(); - new ANF2Axis(pC, axis, config, baseSpeed, homingTimeout); - pC->unlock(); - return asynSuccess; -} - -void ANF2Axis::zeroRegisters(epicsInt32 *reg) -{ - int i; - - for(i=0; i<5; i++) - { - reg[i] = 0x0; - } -} - -asynStatus ANF2Axis::resetErrors() -{ - asynStatus status; - epicsInt32 errorReg[5]; - static const char *functionName = "ANF2Axis::resetErrors"; - - asynPrint(pasynUser_, ASYN_TRACEIO_DRIVER, "%s: axisNo=%i\n", functionName, axisNo_); - - zeroRegisters(errorReg); - - errorReg[COMMAND] = 0x800 << 16; - - // Send the reset error command - status = pC_->writeReg32Array(axisNo_, errorReg, 5, DEFAULT_CONTROLLER_TIMEOUT); - - return status; -} - -void ANF2Axis::getInfo() -{ - asynStatus status; - int i; - - // For a read (not sure why this is necessary) - status = pasynInt32SyncIO->write(pasynUserForceRead_, 1, DEFAULT_CONTROLLER_TIMEOUT); - - //printf("Registers for axis %i:\n", axisNo_); - - for( i=0; ireadReg16(axisNo_, i, &inputReg_[i], DEFAULT_CONTROLLER_TIMEOUT); - //printf(" status=%d, register=%i, val=0x%x\n", status, i, inputReg_[i]); - } -} - -/* -// reconfig was used during development. It won't be generally useful without effort. -// It isn't obvious that this is a feature that should exist on-the-fly -void ANF2Axis::reconfig(epicsInt32 value) -{ - asynStatus status; - epicsInt32 confReg[5]; - - // TODO: modify this to use the base speed from the parameter, and instead accept a string for a new config - - printf("Reconfiguring axis %i\n", axisNo_); - - // Clear the command/configuration register - status = pC_->writeReg32Array(axisNo_, zeroReg_, 5, DEFAULT_CONTROLLER_TIMEOUT); - - // Construct the new config - zeroRegisters(confReg); - confReg[CONFIGURATION] = 0x86000000; - confReg[BASE_SPEED] = 0x00000064; - //confReg[HOME_TIMEOUT] = 0x0; - //confReg[CONFIG_REG_3] = 0x0; - //confReg[CONFIG_REG_4] = 0x0; - - epicsThreadSleep(0.05); - - // Send the new config - status = pC_->writeReg32Array(axisNo_, confReg_, 5, DEFAULT_CONTROLLER_TIMEOUT); - - epicsThreadSleep(0.05); - - // Set the position to clear the invalid position error - setPosition(value); - - epicsThreadSleep(0.05); -} -*/ - -/** 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 ANF2Axis::report(FILE *fp, int level) -{ - // TODO: make this more useful - - if (level > 0) { - fprintf(fp, "Configuration for axis %i [0x%x]:\n", axisNo_, config_); - fprintf(fp, " Base Speed: %i\n", baseSpeed_); - fprintf(fp, " Homing Timeout: %i\n", homingTimeout_); - fprintf(fp, " Capture Input: %i (Active State: %i)\n", CaptInput_, CaptInputAS_); - fprintf(fp, " External Input: %i (Active State: %i)\n", ExtInput_, ExtInputAS_); - fprintf(fp, " Home Input: %i (Active State: %i)\n", HomeInput_, HomeInputAS_); - fprintf(fp, " CW Input: %i (Active State: %i)\n", CWInput_, CWInputAS_); - fprintf(fp, " CCW Input: %i (Active State: %i)\n", CCWInput_, CCWInputAS_); - fprintf(fp, " Backplane Home Proximity Operation: %i\n", BHPO_); - fprintf(fp, " Quadrature Encoder: %i\n", QuadEnc_); - fprintf(fp, " Diagnostic Feedback: %i\n", DiagFbk_); - fprintf(fp, " Output Pulse Type: %i\n", OutPulse_); - fprintf(fp, " Home Operation: %i\n", HomeOp_); - fprintf(fp, " Card Axis: %i\n", CardAxis_); - fprintf(fp, " Operation Mode for Axis: %i\n", OpMode_); - fprintf(fp, "\n"); - } - - //printf("ANF2Axis::report -> BEFORE asynMotorAxis::report!!\n"); - - // Call the base class method - asynMotorAxis::report(fp, level); - - //printf("ANF2Axis::report -> AFTER asynMotorAxis::report!!\n"); - -} - -// SET VEL & ACCEL -asynStatus ANF2Axis::sendAccelAndVelocity(double acceleration, double velocity) -{ - // static const char *functionName = "ANF2Axis::sendAccelAndVelocity"; - - // ANF2 speed range is 1 to 1,000,000 steps/sec - if (velocity > 1000000.0) { - velocity = 1000000.0; - } - if (velocity < 1.0) { - velocity = 1.0; - } - - // Set the velocity register - motionReg_[SPEED] = NINT(velocity); - - // ANF2 acceleration range 1 to 2000 steps/ms/sec - // Therefore need to limit range received by motor record from 1000 to 2e6 steps/sec/sec - if (acceleration < 1000.0) { - //printf("Acceleration is < 1000: %lf\n", acceleration); - acceleration = 1000.0; - } - if (acceleration > 2000000.0) { - //printf("Acceleration is > 2000: %lf\n", acceleration); - acceleration = 2000000.0; - } - - // Set the accel/decel register - motionReg_[ACCEL_DECEL] = (NINT(acceleration/1000.0) << 16) | (NINT(acceleration/1000.0)); - - return asynSuccess; -} - -/* - * This driver only sets the base speed at initialization when the configuration is sent. - * It is possible that the base speed (VBAS) in the motor record is inconsistent with the - * base speed set at initialization, since there is no way for an asyn motor driver to force - * the base speed to be reset when a user changes it. The resulting acceleration calculated - * by the motor record is likely to be incorrect. The following method calculates the - * acceleration that will give the correct acceleration time (ACCL) for the base speed that - * was specified at initialization. - */ -double ANF2Axis::correctAccel(double minVelocity, double maxVelocity, double acceleration) -{ - double accelTime; - double newAccel; - static const char *functionName = "ANF2Axis::correctAccel"; - - accelTime = (maxVelocity - minVelocity) / acceleration; - newAccel = (maxVelocity - (double)baseSpeed_) / accelTime; - - asynPrint(pasynUser_, ASYN_TRACEIO_DRIVER, - "%s: axisNo=%i, old acceleration=%lf, new acceleration=%lf\n", - functionName, axisNo_, acceleration, newAccel); - - return newAccel; -} - - -// MOVE -asynStatus ANF2Axis::move(double position, int relative, double minVelocity, double maxVelocity, double acceleration) -{ - asynStatus status; - epicsInt32 posInt; - static const char *functionName = "ANF2Axis::move"; - - asynPrint(pasynUser_, ASYN_TRACEIO_DRIVER, - "%s: axisNo=%i, relative=%i, minVelocity=%f, maxVelocity=%f, acceleration=%f\n", - functionName, axisNo_, relative, minVelocity, maxVelocity, acceleration); - - // Clear the command/configuration register - status = pC_->writeReg32Array(axisNo_, zeroReg_, 5, DEFAULT_CONTROLLER_TIMEOUT); - - epicsThreadSleep(0.05); - - // Clear the motition registers - zeroRegisters(motionReg_); - - // Correct the acceleration - acceleration = correctAccel(minVelocity, maxVelocity, acceleration); - - // This sets indices 2 & 3 of motionReg_ - status = sendAccelAndVelocity(acceleration, maxVelocity); - - posInt = NINT(position); - - if (relative) { - //printf(" ** relative move called\n"); - - // Set position and cmd registers - motionReg_[COMMAND] = 0x2 << 16; - motionReg_[POSITION] = posInt; - - } else { - //printf(" ** absolute move called\n"); - - // Set position and cmd registers - motionReg_[COMMAND] = 0x1 << 16; - motionReg_[POSITION] = posInt; - } - - //printf(" ** position = %d\n", posInt); - - // The final registers are zero for absolute and relative moves (this shouldn't be necessary--DELETEME) - motionReg_[CMD_REG_4] = 0x0; - - // Write all the registers atomically - // The number of elements refers to the number of epicsInt32s registers_ - status = pC_->writeReg32Array(axisNo_, motionReg_, 5, 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 ANF2Axis::home(double minVelocity, double maxVelocity, double acceleration, int forwards) -{ - asynStatus status; - static const char *functionName = "ANF2Axis::home"; - - asynPrint(pasynUser_, ASYN_TRACEIO_DRIVER, - "%s: axisNo=%i, forwards=%i, minVelocity=%f, maxVelocity=%f, acceleration=%f\n", - functionName, axisNo_, forwards, minVelocity, maxVelocity, acceleration); - - // Clear the command/configuration register - status = pC_->writeReg32Array(axisNo_, zeroReg_, 5, DEFAULT_CONTROLLER_TIMEOUT); - - epicsThreadSleep(0.05); - - // Clear the motition registers - zeroRegisters(motionReg_); - - // Correct the acceleration - acceleration = correctAccel(minVelocity, maxVelocity, acceleration); - - // This sets indices 2 & 3 of motionReg_ - status = sendAccelAndVelocity(acceleration, maxVelocity); - - // Note: if the home input is active when the home command is sent, the axis will appear to move in the wrong direction - if (forwards) { - printf(" ** HOMING FORWARDS **\n"); - // The +Find Home (CW) command - motionReg_[COMMAND] = 0x20 << 16; - } else { - printf(" ** HOMING REVERSE **\n"); - // The -Find Home (CCW) command - motionReg_[COMMAND] = 0x40 << 16; - } - - // Write all the registers atomically - status = pC_->writeReg32Array(axisNo_, motionReg_, 5, DEFAULT_CONTROLLER_TIMEOUT); - - return status; -} - -// JOG -asynStatus ANF2Axis::moveVelocity(double minVelocity, double maxVelocity, double acceleration) -{ - asynStatus status; - //int velo, distance; - static const char *functionName = "ANF2Axis::moveVelocity"; - - asynPrint(pasynUser_, ASYN_TRACEIO_DRIVER, - "%s: axisNo=%d, minVelocity=%f, maxVelocity=%f, acceleration=%f\n", - functionName, axisNo_, minVelocity, maxVelocity, acceleration); - - // - // The jog command requires a different stop than a move command - - // Set a jogging flag - jogging_ = true; - - // Clear the command/configuration register - status = pC_->writeReg32Array(axisNo_, zeroReg_, 5, DEFAULT_CONTROLLER_TIMEOUT); - - epicsThreadSleep(0.05); - - // Clear the motition registers - zeroRegisters(motionReg_); - - // Note: the jog acceleration doesn't need to be corrected; the JAR field has units of egu/s/s - - if (maxVelocity > 0.0) { - //printf(" ** positive jog called\n"); - - // Set cmd register - motionReg_[COMMAND] = 0x80 << 16; - - // Do nothing to the velocity - - } else { - //printf(" ** negative jog called\n"); - - // Set cmd register - motionReg_[COMMAND] = 0x100 << 16; - - // ANF2 only accepts speeds > 0 - maxVelocity = fabs(maxVelocity); - } - - // This sets indices 2 & 3 of motionReg_ - status = sendAccelAndVelocity(acceleration, maxVelocity); - - // Write all the registers atomically - status = pC_->writeReg32Array(axisNo_, motionReg_, 5, DEFAULT_CONTROLLER_TIMEOUT); - // - - /* - velo = NINT(fabs(maxVelocity)); - - // Simulate a jog like the ANG1 driver does. Move 1 million steps - distance = 1000000; - if (maxVelocity > 0.) { - // This is a positive move in ANF2 coordinates - //printf(" ** relative move (JOG pos) called\n"); - status = move(distance, 0, minVelocity, velo, acceleration); - } else { - // This is a negative move in ANF2 coordinates - //printf(" ** relative move (JOG neg) called\n"); - status = move((distance * -1.0), 0, minVelocity, velo, acceleration); - } - */ - - // Delay the first status read, give the controller some time to return moving status - epicsThreadSleep(0.05); - return status; -} - - -// STOP -asynStatus ANF2Axis::stop(double acceleration) -{ - asynStatus status; - epicsInt32 stopReg; - static const char *functionName = "ANF2Axis::stop"; - - asynPrint(pasynUser_, ASYN_TRACEIO_DRIVER, "%s: axisNo=%i\n", functionName, axisNo_); - - //printf("\n STOP \n\n"); - - // The stop commands ignore all 32-bit registers beyond the first - - // Clear the command/configuration register (this causes a jog to stop) - status = pC_->writeReg32Array(axisNo_, zeroReg_, 1, DEFAULT_CONTROLLER_TIMEOUT); - - if (jogging_ == false) - { - //printf("stopping a normal move\n"); - // The immediate stop command cuts the pulses off without any deceleration and causes the position to become invalid - //stopReg = 0x10 << 16; // Immediate stop - // Hold move works very well with normal moves - stopReg = 0x4 << 16; // Hold move - - // This causes a normal move to stop - status = pC_->writeReg32Array(axisNo_, &stopReg, 1, DEFAULT_CONTROLLER_TIMEOUT); - - // Clear the command/configuration register - //status = pC_->writeReg32Array(axisNo_, zeroReg_, 5, DEFAULT_CONTROLLER_TIMEOUT); - } else { - // Reset the jogging flag (assume the stop was successful) - //printf("resetting the jog flag\n"); - jogging_ = false; - } - - return status; -} - -// SET -asynStatus ANF2Axis::setPosition(double position) -{ - asynStatus status; - epicsInt32 set_position; - epicsInt32 posReg[5]; - static const char *functionName = "ANF2Axis::setPosition"; - - asynPrint(pasynUser_, ASYN_TRACEIO_DRIVER, "%s: axisNo=%i, position=%lf\n", functionName, axisNo_, position); - - // Clear the command/configuration register - status = pC_->writeReg32Array(axisNo_, zeroReg_, 5, DEFAULT_CONTROLLER_TIMEOUT); - - epicsThreadSleep(0.1); - - set_position = NINT(position); - - zeroRegisters(posReg); - posReg[COMMAND] = 0x200 << 16; - posReg[POSITION] = set_position; - - // Write all the registers atomically - status = pC_->writeReg32Array(axisNo_, posReg, 5, DEFAULT_CONTROLLER_TIMEOUT); - - // Can this delay be shorter? - epicsThreadSleep(0.2); - - // The ANG1 driver does this; do we need to? - // Clear the command/configuration register - //status = pC_->writeReg32Array(axisNo_, zeroReg_, 5, DEFAULT_CONTROLLER_TIMEOUT); - - return status; -} - -// ENABLE TORQUE -asynStatus ANF2Axis::setClosedLoop(bool closedLoop) -{ - //asynStatus status; - //epicsInt32 clReg[5]; - //static const char *functionName = "ANF2Axis::setClosedLoop"; - - // The ANF2 doesn't have a closed-loop enable/disable command, so do nothing. - // The configuration of an axis: - // * can be changed so that an axis is disabled, but that doesn't disable torque - // * can be changed to disable the use of encoder inputs, but that isn't currently allowed on-the-fly - - /*printf(" ** setClosedLoop called \n"); - if (closedLoop) { - printf("setting enable true\n"); - - setIntegerParam(pC_->motorStatusPowerOn_, 1); - } else { - printf("setting disable false\n"); - setIntegerParam(pC_->motorStatusPowerOn_, 0); - } - return status;*/ - - return asynSuccess; -} - -// 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 ANF2Axis::poll(bool *moving) -{ - int done; - int lowLimit; - int highLimit; - int enabled; - int cmdError; - int direction; - double position; - double encPosition; - asynStatus status; - epicsInt32 read_val; // don't use a pointer here. The _address_ of read_val should be passed to the read function. - - // Don't do any polling until ALL the axes have been created; this ensures that we don't interpret the configuration values as command values - // This is probably not necessary now that the poller can be started after iocInit - if (pC_->axesCreated_ != pC_->numAxes_) { - *moving = false; - return asynSuccess; - } - - // 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 - status = pC_->readReg32(axisNo_, POS_RD_UPR, &read_val, DEFAULT_CONTROLLER_TIMEOUT); - //printf("ANF2Axis::poll: Motor position raw: %d\n", read_val); - position = (double) read_val; - setDoubleParam(pC_->motorPosition_, position); - //printf("ANF2Axis::poll: Motor #%i position: %f\n", axisNo_, position); - - // Read encoder position - status = pC_->readReg32(axisNo_, EN_POS_UPR, &read_val, DEFAULT_CONTROLLER_TIMEOUT); - //printf("ANF2Axis::poll: Motor encoder position raw: %d\n", read_val); - encPosition = (double) read_val; - setDoubleParam(pC_->motorEncoderPosition_, encPosition); - //printf("ANF2Axis::poll: Motor #%i encoder position: %f\n", axisNo_, encPosition); - - // Read the moving status of this motor - // - status = pC_->readReg16(axisNo_, 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); - - // Initialize the direction bit to the last value - status = pC_->getIntegerParam(pC_->motorStatusDirection_, &direction); - - // Direction (only set the direction of the controller is moving) - if (!done) { - if (read_val & 0x1) { - direction = 1; - } - if ((read_val & 0x2) >> 1) { - direction = 0; - } - setIntegerParam(pC_->motorStatusDirection_, direction); - } - - // Check for command errors - cmdError = (read_val & 0x1000) ? 1 : 0; - - // Check for enable/disable (not actually the torque status) and set accordingly. - // Enable/disable is determined by the configuration and it isn't obvious why one would disable an axis. - enabled = (read_val & 0x4000); - if (enabled) - setIntegerParam(pC_->motorStatusPowerOn_, 1); - else - setIntegerParam(pC_->motorStatusPowerOn_, 0); - - // Read the limit status - // - status = pC_->readReg16(axisNo_, STATUS_2, &read_val, DEFAULT_CONTROLLER_TIMEOUT); - //printf("status 2 is 0x%X\n", read_val); - - // Set the high limit only when moving in the positive direction - highLimit = (read_val & 0x8) ? (direction & 1) : 0; // a cw limit has been reached - setIntegerParam(pC_->motorStatusHighLimit_, highLimit); - //printf("+limit %d\n", highLimit); - - // Set the low limit only when moving in the negative direction - lowLimit = (read_val & 0x10) ? (!direction & 1) : 0; // a ccw limit has been reached - setIntegerParam(pC_->motorStatusLowLimit_, lowLimit); - //printf("-limit %d\n", lowLimit); - - // Clear command errors so we can attempt to move again - if (cmdError) { - printf("poll: resetting errors\n"); - resetErrors(); - } - - // Should be in init routine? Allows CNEN to be used. - setIntegerParam(pC_->motorStatusGainSupport_, 1); - - // Notify asynMotorController polling routine that we're ready - callParamCallbacks(); - - return status; -} - -/** Code for iocsh registration */ - -/* ANF2CreateController */ -static const iocshArg ANF2CreateControllerArg0 = {"Port name", iocshArgString}; -static const iocshArg ANF2CreateControllerArg1 = {"ANF2 In port name", iocshArgString}; -static const iocshArg ANF2CreateControllerArg2 = {"ANF2 Out port name", iocshArgString}; -static const iocshArg ANF2CreateControllerArg3 = {"Number of axes", iocshArgInt}; -static const iocshArg * const ANF2CreateControllerArgs[] = {&ANF2CreateControllerArg0, - &ANF2CreateControllerArg1, - &ANF2CreateControllerArg2, - &ANF2CreateControllerArg3}; -static const iocshFuncDef ANF2CreateControllerDef = {"ANF2CreateController", 4, ANF2CreateControllerArgs}; -static void ANF2CreateControllerCallFunc(const iocshArgBuf *args) -{ - ANF2CreateController(args[0].sval, args[1].sval, args[2].sval, args[3].ival); -} - -/* ANF2StartPoller */ -static const iocshArg ANF2StartPollerArg0 = {"Port name", iocshArgString}; -static const iocshArg ANF2StartPollerArg1 = {"Moving poll period (ms)", iocshArgInt}; -static const iocshArg ANF2StartPollerArg2 = {"Idle poll period (ms)", iocshArgInt}; -static const iocshArg * const ANF2StartPollerArgs[] = {&ANF2StartPollerArg0, - &ANF2StartPollerArg1, - &ANF2StartPollerArg2}; -static const iocshFuncDef ANF2StartPollerDef = {"ANF2StartPoller", 3, ANF2StartPollerArgs}; -static void ANF2StartPollerCallFunc(const iocshArgBuf *args) -{ - ANF2StartPoller(args[0].sval, args[1].ival, args[2].ival); -} - -/* ANF2CreateAxis */ -static const iocshArg ANF2CreateAxisArg0 = {"Port name", iocshArgString}; -static const iocshArg ANF2CreateAxisArg1 = {"Axis number", iocshArgInt}; -static const iocshArg ANF2CreateAxisArg2 = {"Hex config", iocshArgString}; -static const iocshArg ANF2CreateAxisArg3 = {"Base speed", iocshArgInt}; -static const iocshArg ANF2CreateAxisArg4 = {"Homing timeout", iocshArgInt}; -static const iocshArg * const ANF2CreateAxisArgs[] = {&ANF2CreateAxisArg0, - &ANF2CreateAxisArg1, - &ANF2CreateAxisArg2, - &ANF2CreateAxisArg3, - &ANF2CreateAxisArg4}; -static const iocshFuncDef ANF2CreateAxisDef = {"ANF2CreateAxis", 5, ANF2CreateAxisArgs}; -static void ANF2CreateAxisCallFunc(const iocshArgBuf *args) -{ - ANF2CreateAxis(args[0].sval, args[1].ival, args[2].sval, args[3].ival, args[4].ival); -} - - -static void ANF2Register(void) -{ - iocshRegister(&ANF2CreateControllerDef, ANF2CreateControllerCallFunc); - iocshRegister(&ANF2StartPollerDef, ANF2StartPollerCallFunc); - iocshRegister(&ANF2CreateAxisDef, ANF2CreateAxisCallFunc); -} - -extern "C" { -epicsExportRegistrar(ANF2Register); -} diff --git a/motorApp/AMCISrc/ANF2Driver.h b/motorApp/AMCISrc/ANF2Driver.h deleted file mode 100644 index 97e7d841..00000000 --- a/motorApp/AMCISrc/ANF2Driver.h +++ /dev/null @@ -1,151 +0,0 @@ -/* -FILENAME... ANF2Driver.h -USAGE... Motor driver support for the AMCI ANF2 controller. - -Kevin Peterson - -Based on the AMCI ANG1 Model 3 device driver written by Kurt Goetze - -*/ - -#include "asynMotorController.h" -#include "asynMotorAxis.h" -//#include -#include - -#define MAX_AXES 12 - -#define MAX_INPUT_REGS 10 -#define MAX_OUTPUT_REGS 10 - -#define AXIS_REG_OFFSET 10 - -/*** Input CMD Registers (16-bit) ***/ -#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 -// Not used must equal zero #define RESERVED 8 -#define NET_CONN 9 - -/*** Output Command Registers (32-bit) ***/ -#define COMMAND 0 -#define POSITION 1 -#define SPEED 2 -#define ACCEL_DECEL 3 -#define CMD_REG_4 4 - -/*** Output Configuration Registers (32-bit) ***/ -#define CONFIGURATION 0 -#define BASE_SPEED 1 -#define HOME_TIMEOUT 2 -#define CONFIG_REG_3 3 -#define CONFIG_REG_4 4 - -// No. of controller-specific parameters -#define NUM_ANF2_PARAMS 2 - -/** drvInfo strings for extra parameters that the ACR controller supports */ -#define ANF2ResetErrorsString "ANF2_RESET_ERRORS" -#define ANF2GetInfoString "ANF2_GET_INFO" -//#define ANF2ReconfigString "ANF2_RECONFIG" - -class ANF2Axis : public asynMotorAxis -{ -public: - /* These are the methods we override from the base class */ - ANF2Axis(class ANF2Controller *pC, int axisNo, epicsInt32 config, epicsInt32 baseSpeed, epicsInt32 homingTimeout); - 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: - ANF2Controller *pC_; /**< Pointer to the asynMotorController to which this axis belongs. - * Abbreviated because it is used very frequently */ - asynStatus sendAccelAndVelocity(double accel, double velocity); - double correctAccel(double minVelocity, double maxVelocity, double acceleration); - asynStatus resetErrors(); - void getInfo(); - epicsInt32 inputReg_[10]; - //void reconfig(epicsInt32 value); - void zeroRegisters(epicsInt32 *reg); - asynUser *pasynUserForceRead_; - int axisNo_; - epicsInt32 baseSpeed_; - epicsInt32 homingTimeout_; - epicsInt32 config_; - epicsInt32 motionReg_[5]; - epicsInt32 confReg_[5]; - epicsInt32 zeroReg_[5]; - bool jogging_; - // Configuration bits - short CaptInput_; - short ExtInput_; - short HomeInput_; - short CWInput_; - short CCWInput_; - short BHPO_; - short QuadEnc_; - short DiagFbk_; - short OutPulse_; - short HomeOp_; - short CardAxis_; - short OpMode_; - // LSW - short CaptInputAS_; - short ExtInputAS_; - short HomeInputAS_; - short CWInputAS_; - short CCWInputAS_; - -friend class ANF2Controller; -}; - -class ANF2Controller : public asynMotorController { -public: - ANF2Controller(const char *portName, const char *ANF2InPortName, const char *ANF2OutPortName, int numAxes); - void doStartPoller(double movingPollPeriod, double idlePollPeriod); - - void report(FILE *fp, int level); - ANF2Axis* getAxis(asynUser *pasynUser); - ANF2Axis* getAxis(int axisNo); - asynUser *pasynUserInReg_[MAX_AXES][MAX_INPUT_REGS]; - asynUser *pasynUserOutReg_[MAX_AXES]; - - /* 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); - - /* These are the methods that are new to this class */ - -protected: - int ANF2ResetErrors_; /** Reset Errors parameter index */ - int ANF2GetInfo_; /**< Get Info parameter index */ - //int ANF2Reconfig_; /**< Reconfig parameter index */ - -private: - asynStatus writeReg16(int, int, int, double); - asynStatus writeReg32(int, int, int, double); - asynStatus writeReg32Array(int, epicsInt32*, int, double); - asynStatus readReg16(int, int, epicsInt32*, double); - asynStatus readReg32(int, int, epicsInt32*, double); - char *inputDriver_; - int numAxes_; - int numModules_; - int axesPerModule_; - double movingPollPeriod_; - double idlePollPeriod_; - int axesCreated_; - -friend class ANF2Axis; -}; diff --git a/motorApp/AMCISrc/ANF2Support.dbd b/motorApp/AMCISrc/ANF2Support.dbd deleted file mode 100644 index 73678200..00000000 --- a/motorApp/AMCISrc/ANF2Support.dbd +++ /dev/null @@ -1,2 +0,0 @@ -#registrar(ANF2MotorRegister) -registrar(ANF2Register) diff --git a/motorApp/AMCISrc/ANG1Driver.cpp b/motorApp/AMCISrc/ANG1Driver.cpp deleted file mode 100644 index 9b16ed9c..00000000 --- a/motorApp/AMCISrc/ANG1Driver.cpp +++ /dev/null @@ -1,640 +0,0 @@ -/* -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 deleted file mode 100644 index 09160f37..00000000 --- a/motorApp/AMCISrc/ANG1Driver.h +++ /dev/null @@ -1,88 +0,0 @@ -/* -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 deleted file mode 100644 index ab5549c5..00000000 --- a/motorApp/AMCISrc/ANG1Support.dbd +++ /dev/null @@ -1,2 +0,0 @@ -#registrar(ANG1MotorRegister) -registrar(ANG1Register) diff --git a/motorApp/AMCISrc/Makefile b/motorApp/AMCISrc/Makefile deleted file mode 100644 index ac94d326..00000000 --- a/motorApp/AMCISrc/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -TOP=../.. - -include $(TOP)/configure/CONFIG -#---------------------------------------- -# ADD MACRO DEFINITIONS AFTER THIS LINE -#============================= - -#================================================== -# Build an IOC support library - -LIBRARY_IOC += AMCI - -# motorRecord.h will be created from motorRecord.dbd -# install devMotorSoft.dbd into /dbd -DBD += AMCISupport.dbd -DBD += ANG1Support.dbd -DBD += ANF2Support.dbd - -# The following are compiled and added to the Support library -AMCI_SRCS += ANG1Driver.cpp -AMCI_SRCS += ANF2Driver.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 deleted file mode 100644 index 57dc4991..00000000 --- a/motorApp/AMCISrc/README +++ /dev/null @@ -1,49 +0,0 @@ -AMCI ANG1 -========= - -Asyn model 3 driver support for the AMCI ANG1 stepper motor -controller/driver. - -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. -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 (ANG1-E). - - - -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. - diff --git a/motorApp/AMCISrc/README_ANF2.md b/motorApp/AMCISrc/README_ANF2.md deleted file mode 100644 index f72ca191..00000000 --- a/motorApp/AMCISrc/README_ANF2.md +++ /dev/null @@ -1,70 +0,0 @@ -# AMCI ANF2 - -Asyn model 3 driver support for the AMCI ANF2 stepper motor controller - -Modbus/TCP communication, using Mark Rivers' modbus module - -## Supported Controller Models - -The following ANF controller versions are supported: -``` -ANF1E: 1-axis stepper controller, modbus tcp/ip -ANF1: 1-axis stepper controller, no network interface -ANF2E: 2-axis stepper controller, modbus tcp/ip -ANF2: 2-axis stepper controller, no network interface -``` -A stack of controller 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. - -## Vendor Software - -ANF2 configuration software is available from AMCI's website: - -www.amci.com/product-software.asp - -Note: The AMCI Net Configurator only works (allows a motor to be moved) if -the controller is configured for EtherNet/IP, however, the EPICS support -requires the device to be configured for Modbus-TCP. - -## Controller Quirks - -* The controller doesn't allow absolute moves when a limit is active; -The only way to move a motor off of a limit is by **jogging**. - -* The base speed is set when an axis is configured. This driver corrects -the acceleration sent by the motor record (VBAS isn't guaranteed to match -the base speed) and sends the acceleration necessary to achieve the desired -acceleration time. - -* The controller doesn't remember its configuration after it is power-cycled. - -* Sending the configuration to the controller invalidates the position -requiring either a home search or the redefinition of the current position. - -* The configuration can't be read after a configuration is accepted by the -controller, after which it automatically switches into command mode. - -* The command to stop an abosolute move generates an error if a jog is in -progress. The command to stop a jog doesn't stop an absolute move. - -## Controller Configuration - -The AMCI Net Configurator can be used to: - -* Change the ip address from the default (192.168.0.50) - -* Change the protocol to Modbus-TCP - -* Determine hex config strings for each axis - -### Example axis configuration - -``` -0x86000000 - Step & Direction pulses, Diagnostic Feedback, No home switch, No limits -0x86280000 - Step & Direction pulses, Diagnostic Feedback, No home switch, Active-low CW/CCW limits -0x84000000 - Step & Direction pulses, No Feedback, No home switch, No Limits -0x84280000 - Step & Direction pulses, No Feedback, No home switch, Active-low CW/CCW limits -0x842C0004 - Step & Direction pulses, No Feedback, Active-high home switch, Active-low CW/CCW limits -0x85280000 - Step & Direction pulses, Quadrature Feedback, No home switch, Active-low CW/CCW limits -``` diff --git a/motorApp/Db/ANF2Aux.template b/motorApp/Db/ANF2Aux.template deleted file mode 100644 index 93a255d7..00000000 --- a/motorApp/Db/ANF2Aux.template +++ /dev/null @@ -1,28 +0,0 @@ -# Database for extra PVs for AMCI ANG1 controllers - -record(bo,"$(P)$(R)ResetErrors") { - field(DESC,"Reset Errors") - field(PINI, "0") - field(VAL,"0") - field(DTYP, "asynInt32") - field(OUT,"@asyn($(PORT),$(ADDR))ANF2_RESET_ERRORS") - field(ZNAM, "Done") - field(ONAM, "Reset") -} - -record(bo,"$(P)$(R)GetInfo") { - field(DESC,"Get Info") - field(PINI, "0") - field(VAL,"0") - field(DTYP, "asynInt32") - field(OUT,"@asyn($(PORT),$(ADDR))ANF2_GET_INFO") -} - -# Reconfig isn't yet implemented in a generally-useful way -#record(longout,"$(P)$(R)Reconfig") { -# field(DESC,"Reconfig") -# field(PINI, "0") -# field(VAL,"0") -# field(DTYP, "asynInt32") -# field(OUT,"@asyn($(PORT),$(ADDR))ANF2_RECONFIG") -#} diff --git a/motorApp/Makefile b/motorApp/Makefile index f182a8f6..a0fe4d94 100644 --- a/motorApp/Makefile +++ b/motorApp/Makefile @@ -27,9 +27,6 @@ PC6KSrc_DEPEND_DIRS = MotorSrc DIRS += SmarActMCSSrc SmarActMCSSrc_DEPEND_DIRS = MotorSrc -DIRS += AMCISrc -AMCISrc_DEPEND_DIRS = MotorSrc - endif # Install the edl files