Removed HytecSrc; Added motorHytec submodule

This commit is contained in:
kpetersn
2019-04-04 16:52:17 -05:00
parent 2b77267562
commit 64dafb7498
11 changed files with 7 additions and 1955 deletions
+3
View File
@@ -16,3 +16,6 @@
[submodule "modules/motorFaulhaber"]
path = modules/motorFaulhaber
url = https://github.com/epics-motor/motorFaulhaber.git
[submodule "modules/motorHytec"]
path = modules/motorHytec
url = https://github.com/epics-motor/motorHytec.git
+3
View File
@@ -9,6 +9,9 @@ SUBMODULES += motorAcsTech80
SUBMODULES += motorAttocube
SUBMODULES += motorDeltaTau
SUBMODULES += motorFaulhaber
ifdef IPAC
SUBMODULES += motorHytec
endif
# Allow sites to add extra submodules
-include Makefile.local
Submodule modules/motorHytec added at 17b57f757a
Binary file not shown.
-72
View File
@@ -1,72 +0,0 @@
record(bo,"$(dev):$(area):$(locn):POWER") {
field(DTYP,"asynInt32")
field(OUT,"@asyn($(PORT) 0)HYTEC_POWER")
field(VAL, "1")
field(ZNAM, "On")
field(ONAM, "Off")
}
record(bo,"$(dev):$(area):$(locn):BRAKE") {
field(DTYP,"asynInt32")
field(OUT,"@asyn($(PORT) 0)HYTEC_BRAKE")
field(VAL, "1")
field(ZNAM, "Set")
field(ONAM, "Rls")
}
record(ai,"$(dev):$(area):$(locn):POSN") {
field(PINI, "YES")
field(DTYP,"asynInt32")
field(INP,"@asyn($(PORT) 0)MOTOR_POSITION")
field(SCAN, "1 second")
}
record(ai,"$(dev):$(area):$(locn):FIRMWARE_VERSION") {
field(PINI, "YES")
field(DTYP,"asynInt32")
field(INP,"@asyn($(PORT) 0)HYTEC_FWVERSION")
field(SCAN, "1 second")
}
record(ai,"$(dev):$(area):$(locn):EN_POSN") {
field(PINI, "YES")
field(DTYP,"asynInt32")
field(INP,"@asyn($(PORT) 0)MOTOR_ENCODER_POSITION")
field(SCAN, "1 second")
}
record(ai, "$(dev):$(area):$(locn):LOWLMT") {
field(SCAN, "I/O Intr")
field(DTYP, "asynInt32")
field(INP, "@asyn($(PORT) 0) MOTOR_STATUS_LOW_LIMIT")
}
record(ai, "$(dev):$(area):$(locn):HIGHLMT") {
field(SCAN, "I/O Intr")
field(DTYP, "asynInt32")
field(INP, "@asyn($(PORT) 0) MOTOR_STATUS_HIGH_LIMIT")
}
record(ai, "$(dev):$(area):$(locn):DONE") {
field(SCAN, "I/O Intr")
field(DTYP, "asynInt32")
field(INP, "@asyn($(PORT) 0) MOTOR_STATUS_DONE")
}
record(ai, "$(dev):$(area):$(locn):HOMELMT") {
field(SCAN, "I/O Intr")
field(DTYP, "asynInt32")
field(INP, "@asyn($(PORT) 0) MOTOR_STATUS_AT_HOME")
}
record(ai, "$(dev):$(area):$(locn):FAULT") {
field(SCAN, "I/O Intr")
field(DTYP, "asynInt32")
field(INP, "@asyn($(PORT) 0) MOTOR_STATUS_PROBLEM")
}
record(ai, "$(dev):$(area):$(locn):HASENCODER") {
field(SCAN, "I/O Intr")
field(DTYP, "asynInt32")
field(INP, "@asyn($(PORT) 0) MOTOR_STATUS_HAS_ENCODER")
}
File diff suppressed because it is too large Load Diff
-4
View File
@@ -1,4 +0,0 @@
# Database Definition
registrar(Hytec8601Register)
-222
View File
@@ -1,222 +0,0 @@
/********************************************************************************/
/* H H Y Y TTTTT EEEEE CCC HYTEC ELECTRONICS LTD */
/* H H Y Y T E C 5 Cradock Road, */
/* HHHHH Y T EEE C Reading, Berks. Tel: 0118 9757770 */
/* H H Y T E C RG2 0JT Fax: 0118 9757566 */
/* H H Y T EEEEE CCC Web: www.hytec-electronics.co.uk */
/********************************************************************************/
/********************************************************************************/
/* _____________________________________________________________________ */
/* | H Y T E C 8 6 0 1 S T E P M O T E R A s y n D r i v e r | */
/* --------------------------------------------------------------------- */
/* */
/* Source file name :- HytecMotorDriver.c */
/* */
/* Initial creation date :- 29-Mar-2011 */
/* */
/* Original Developers :- Jim Chen. Hytec Electronics Ltd */
/* */
/********************************************************************************/
/* */
/* Description :- This is the "model 3" asyn motor driver for Hytec 8601 */
/* Stepper Motor IP module. The code is based on original */
/* Hytec drvHy8601asyn.c driver and also Mark Rivers' */
/* ACRMotorDriver. */
/* */
/* */
/* (C)2011 Hytec Electronics Ltd. */
/* */
/********************************************************************************/
/* */
/* Revision history: (comment and initial revisions) */
/* */
/* vers. revised modified by date */
/* ----- ----------- ---------------- --------------- */
/* 2.0 Continued version Jim Chen 29/03/2011 */
/* The main contents of this driver are the same as the original */
/* Hytec drvHy8601asyn.c driver but in "model 3" form as defined */
/* by Mark Rivers. Hence it starts from version 2.0. */
/* 2.1 New interfaces Jim Chen 04/04/2011 */
/* This version follows the asyn motor model 3 latest interface */
/* changes that include: */
/* a).New asynMotorAxis base class */
/* b).Moves the axis specific functions from the motor controller */
/* class to individual axis class */
/* c).Changes asynMotorDriver.cpp to asynMotorController.cpp. */
/* 2.2 Bugs fix Jim Chen 14/04/2011 */
/* Fixed setPosition bug */
/* Added firmware version parameter */
/* */
/********************************************************************************/
#include "asynMotorController.h"
#include "asynMotorAxis.h"
static const char *driverName = "HytecMotorDriver";
/* CSR Register bit definitions */
#define CSR_HOMESTOP 0x8000
#define CSR_INTEN 0x4000
#define CSR_DONE 0x2000
#define CSR_CRASHSTOP 0x1000
#define CSR_DIRECTION 0x0800
#define CSR_AUX2 0x0400
#define CSR_AUX1 0x0200
#define CSR_ENCODUSE 0x0100
#define CSR_ENCODDET 0x0080
#define CSR_JOG 0x0040
#define CSR_GO 0x0020
#define CSR_DRVSTAT 0x0010
#define CSR_HOMELMT 0x0008
#define CSR_MAXLMT 0x0004
#define CSR_MINLMT 0x0002
#define CSR_RESET 0x0001
/* New Hardware Register Map */
#define REG_STEPCNTLO 0x00
#define REG_STEPCNTHI 0x02
#define REG_CURRPOSLO 0x04
#define REG_CURRPOSHI 0x06
#define REG_STARTSTOPSPD 0x08
#define REG_HIGHSPD 0x0A
#define REG_RAMPRATE 0x0C
#define REG_CSR 0x0E
#define REG_INTMASK 0x10
#define REG_INTVECTOR 0x12
#define REG_INTREQUEST 0x14
#define REG_CURRENTSPD 0x16
#define REG_SPARE1 0x18
#define REG_SPARE2 0x1A
#define REG_SPARE3 0x1C
#define REG_SPARE4 0x1E
#define PROM_MODEL 0x8601
#define PROM_OFFS 0x80
#define REG_BANK_OFFS 0x00
#define REG_BANK_SZ 0x20
#define INT_LMT (CSR_MINLMT | CSR_MAXLMT | CSR_HOMELMT)
#define INT_SRCS (CSR_RESET | INT_LMT | CSR_DRVSTAT | CSR_DONE)
/* define a mask to enable all sources of interrupts */
#define ALL_INTS (INT_SRCS | CSR_INTEN)
#define DONE_INT (CSR_DONE) /* the only interrupt suggested to use. JC 12-Nov-2009 */
#define HY8601_NUM_AXES 4
#define IP_DETECT_STR "VITA4 "
#define GET_REG(base,reg) (*(volatile epicsUInt16 *)((base)+(reg)))
#define SET_REG(base,reg,val) do { *(volatile epicsUInt16 *)((base)+(reg)) = (val);} while(0)
#define CSR_SET(base,bit) do { *(volatile epicsUInt16 *)((base)+REG_CSR) |= (bit);} while(0)
/* Please NOTE, The DONE bit is cleared by either ORing an "1" or ANDing an "1" (if it is already "1") to it.
* Yet neither ORing nor ANDing it with "0" would affect it. As such, clearing any other bit in the CSR with
* the AND operation need to be very careful so that it doesn't knock down the DONE bit. This is why in the
* following macro after inverting the bit in the CSR, we clear the DONE bit to the inversion result in order
* not to affect the DONE bit. */
#define CSR_CLR(base,bit) do { *(volatile epicsUInt16 *)((base)+REG_CSR) &= ((~(bit)) & 0xDFFF);} while(0)
#define HytecPowerControlString "HYTEC_POWER"
#define HytecBrakeControlString "HYTEC_BRAKE"
#define HytecFirmwareString "HYTEC_FWVERSION"
#define HytecMoveAllString "HYTEC_MOVEALL"
class HytecMotorAxis : public asynMotorAxis
{
public:
HytecMotorAxis(class HytecMotorController *pC, int axis, double ratio, int vector);
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);
int getVector();
volatile char * getChanbase();
//the following are called from non-member function so they are here
private:
asynStatus InitialiseAxis();
HytecMotorController *pC_;
volatile char *chanbase;
int vector;
int useencoder;
double encoderRatio; /**< (double) Number of encoder counts in one motor count (encoder counts/motor counts) */
double resolution; /**< (double) Number of motor units per engineering unit */
double softLowLimit; /**< (double) Low soft limit in motor units ???? Shouldn't these two in engineering unit? */
double softHighLimit; /**< (double) High soft limit in motor units ???? */
double absPosition;
double desiredMove;
int times; /* to remember the the done bit set the first time */
int absAskingPosition;
friend class HytecMotorController;
};
class HytecMotorController : asynMotorController
{
public:
HytecMotorController(const char *portName, int numAxes, double movingPollPeriod,
double idlePollPeriod, int cardnum, int ip_carrier, int ipslot,
int vector, int useencoder, double encoderRatio0, double encoderRatio1,
double encoderRatio2, double encoderRatio3);
// These are the methods that we override from asynMotorDriver
asynStatus readInt32(asynUser *pasynUser, epicsInt32 *value);
asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value);
asynStatus writeFloat64(asynUser *pasynUser, epicsFloat64 value);
void report(FILE *fp, int level);
HytecMotorAxis* getAxis(asynUser *pasynUser);
HytecMotorAxis* getAxis(int axisNo);
//the following are called from non-member function so they are here
void drvHy8601GetAxisStatus( HytecMotorAxis *pAxis, int csr_data );
int getNumAxes();
int getIPCarrier();
int getIPSlot();
epicsMessageQueueId getINTMsgQID();
void increaseMsgSent();
void increaseMsgFail();
protected:
// New function codes
int HytecPowerControl_;
#define FIRST_HYTEC_PARAM HytecPowerControl_
int HytecBrakeControl_;
int HytecFWVersion_;
int HytecMoveAll_;
#define LAST_HYTEC_PARAM HytecMoveAll_
#define NUM_HYTEC_PARAMS (&LAST_HYTEC_PARAM - &FIRST_HYTEC_PARAM + 1)
private:
asynStatus SetupCard();
int checkprom(char *pr,int expmodel);
int numAxes;
epicsMessageQueueId intMsgQId;
int messagesSent; // for report
int messagesFailed; // for report
int ip_carrier;
int ipslot;
asynUser *pasynUser;
int card;
int vector;
int useencoder;
volatile char *regbase;
epicsThreadId motorThread;
friend class HytecMotorAxis;
};
-25
View File
@@ -1,25 +0,0 @@
TOP=../..
include $(TOP)/configure/CONFIG
# -------------------------------
# Build HytecMotor Module Library
# -------------------------------
LIBRARY_IOC += HytecMotor
DBD += HytecMotorDriver.dbd
# The following are compiled and added to the support library
HytecMotor_SRCS += HytecMotorDriver.cpp
INC += HytecMotorDriver.h
# We need to link this IOC Application against the EPICS Base libraries
HytecMotor_LIBS += motor
HytecMotor_LIBS += asyn Ipac
HytecMotor_LIBS += $(EPICS_BASE_IOC_LIBS)
# ---------------------------------------------------
include $(TOP)/configure/RULES
-510
View File
@@ -1,510 +0,0 @@
***********************************************************************************
Hytec 8601 Step Motor Controller Asyn Driver Notes
Author: Jim Chen, Hytec Electronics Ltd
jim.chen@hytec-electronics.co.uk
First Initial: 12/NOV/2010
Last updated: 29/FEB/2012
Modification note:
22/FEB/2012 - corrected memory offset calculation errors reported by Ernest Williams SLAC.
29/FEB/2012 - added coverage for all cases when setting up the MEMOFFS for 8002 carrier.
This driver is based on "model 3" motor asyn driver defined by Mark Rivers.
***********************************************************************************
Support modules
===============
1). asyn driver version asyn4-13-1 or later.
2). ipac module version ipac-2.11 plus one of the Hytec carrier card drivers such as
drvHy8002.c for VxWorks or RTEMS under VME64x with 8002/8003/8004 carriers,
drvHyLinuxCarrier.c for Linux with IOC9010/PCIe6335/uTCA7002 carriers,
drvHyRTEMSCarrier.c for RTEMS with IOC9010 blade.
3). devLib2 version 2.1 or later if using RTEMS on IOC9010 blade.
4). motor module version later than motorR6-5-1. Currently the 'model 3' version can be
downloaded from subversion https://subversion.xor.aps.anl.gov/synApps/motor/trunk.
This will be formally released some stage on the official EPICS website.
5). EPICS core R3.14.8.2 or later.
6). RTEMS R4.9.4 or later.
Hytec 8002/8003/8004 carrier card configuration
===============================================
This board is a 6U VME64x carrier card. It provides four single size IP slots and
is configurable for many parameters. It supports interrupt level from 0 to 7. Any
IP cards can be enabled/disabled interrupt. The clock can be set to either 8MHz or
32MHz. For IPAC Memory space if required, the base address can be defined automatically
by geographical addressing when VME64x crate is used. For other type of crates,
the base address can be set by configuring a series of jumpers on the board or by
passing parameter to the memory offset register in the ipacAddCarrier call.
The IPAC Carrier Driver for this board is found in the file drvHy8002.c which
implements two commands ipacAddHy8002 and Hy8002CarrierInfo. The ipacAddHy8002
command is used to add a Hytec 8002/8003 board to the system. The Hy8002CarrierInfo
reports hardware information for a specified board or all boards in the system if
the parameter passed down is 0xFFFF. These commands are registered by the registrar
routine Hy8002Registrar to add them to the iocsh and link the driver into a final
IOC executable, for which it must be listed in the IOC's .dbd file thus:
registrar(Hy8002Registrar)
1). Configuration Command and Parameter
--------------------------------------
- int ipacAddHYy8002(const char *cardParams);
The parameter string should comprise two (2) to six (6) parameters which are comma
separated. The first two are mandate and have to be separated only by one comma.
The others are key/value pairs and are optional as per the conditions of the operating
system used. The format is defined as
s,i,IPMEM=d,IPCLCK=d,ROAK=d,MEMOFFS=d
where d is a decimal integer number.
s defines the VME slot number of the carrier card. Valid number is 2 ~ 21.
this number MUST be the same as the VME slot number where the carrier
card is plugged in.
i defines the interrupt level. Valid number is 0 ~ 7.
IPMEM=d defines the maximum memory size of the IP module. The valid values are 1, 2,
4 or 8 that represent 1MB, 2MB, 4MB or 8MB respectively. Default is 1. For
majority Hytec ADCs, DACs such as 8401, 8414, 8417, 8402 and 8415 etc, they
all have 2MB on board. The user can choose to use either 1MB or 2MB. None of
the Hytec IPs has more than 2MB on board memory. Other vendors might have.
IPCLCK=d defines the clock that its value has to be either 8 for 8MHz or 32 for
32Mhz. Default is 8.
ROAK=d if d =1, it defines carrier card to release the interrupt upon the
acknowledgment. If d=0, the interrupt is released by user interrupt
service routine. Default is 0.
MEMOFFS=d this parameter defines the A32 memory access base address. "d" is a decimal
number that represents the offset (the upper WORD) of the A32 base address.
It is needed when any of the two statements below is true:
A. The operating system either VxWorks or RTEMS has defined a non-zero
VME_A32_MSTR_LOCAL macro in the system config.h file.
B. The VME crate is not geographical addressing facilitated. In such a system,
user must use this to set up base address for A32.
For a VME crate that is geographical addressing facilitated, and the system
defines a non-zero VME_A32_MSTR_LOCAL macro, then it is needed. But if
VME_A32_MSTR_LOCAL macro is defined as 0, then this is optional. Setting this
the driver will turn off the carrier card geographical addressing by setting
a bit in the CSR.
Note: MEMOFFS has nothing to do with A16 base address formation. A16 base address
is determined either by geographical addressing or by carrier board on board
jumpers settings. For VME crate that is not geographical addressing facilitated,
both 8002 and 8004 carriers need to use on board jumpers (J6~J10) to set up
(On 8004 carrier, moving the jumpers to "manual" positions). When the VME
crate is geographical addressing facilitated, for 8002 carrier, A16 base
address is determined by the crate geographical addressing facility, i.e.
determined automatically by the slot number where the carrier is plugged in
(the actually A16 base address is determined as vmeslotnumber << 11). But for
8004 carrier, user can have a choice to either use the on board jumpers to
manually set up (moving jumpers J6~J10 away from "auto" to "manual" positions)
or let the the geographical addressing to determine it (keep all J6 ~ J10 to
"auto" position).
Calcualtion of MEMOFFS:
As mentioned above, MEMOFFS setting represents the upper WORD of A32 VME address. Two
things need to be considered when doing the calculation: IPMEM setting and the the
VME_A32_MSTR_LOCAL macro definition in the config.h file of the BSP.
IPMEM defines the memory size per IP card. Either 8002 or 8004 has up to 4 IPs so
the carrier memory size is 4 times of the IP memory. The minimum size of an IP, which
is also the default setting (if IPMEM is not defined), is 1MB. Hence the MEMOFFS
should start from address line A22 as shown below
MEMOFFS BIT 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
A31 A30 A29 A28 A27 A26 A25 A24 A23 A22 0 0 0 0 0 0
The MEMOFFS must be defined such that any two carriers in the same crate shuoldn't
have overlapped memory area. So when IPMEM changes, the starting address line for
calculating MEMOFFS changes as well as illustrated below:
IPMEM memory per IP carrier memory size starting address line
1 1MB 4MB A22
2 2MB 8MB A23
4 4MB 16MB A24
8 8MB 32MB A25
all address lines below this starting address must be 0.
VME_A32_MSTR_LOCAL macro is the system base and it just needs to be added on to the
calculation.
In principle, calculating MEMOFFS doesn't have to correspond it to VME slot number
that the carrier is plugged in. The only thing matters is as said that any two MEMOFFS
settings for any two carriers in the same crate should not overlap. Yet associating
the VME slot number in the calculation just makes better logical sense and fits the
natual of human being's thinking. Some examples are shown below.
Let's assume IPMEM=1 (the default setting), this gives 4MB memory space for a 8002
carrier so starting address line is A22. The remaining must be 0.
MEMOFFS BIT 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
A31 A30 A29 A28 A27 A26 A25 A24 A23 A22 0 0 0 0 0 0
For a carrier in VME slot 2, we can define its A32 base address as 0x00400000,
plus VME_A32_MSTR_LOCAL. For VME slot 3, it could be 0x00800000 plus VME_A32_MSTR_LOCAL
and for VME slot 4, it could be 0x00C00000 plus VME_A32_MSTR_LOCAL and so forth.
Assuming VME_A32_MSTR_LOCAL is 0x20000000, then for VME slot 4, the calculated base
address should be 0x00C00000 + 0x20000000 = 0x20C000000. Hence the MEMOFFS = 8384
(decimal, i.e. 0x20C0). For slot 5, the derived base address could be 0x01000000 +
0x20000000 = 0x21000000. Hence the MEMOFFS = 8448 (decimal, i.e. 0x2100) and so forth.
Now if IPMEM=2, this gives 8MB memory space for each 8002 carrier so the starting address
line is A23. The remaining must be 0.
MEMOFFS BIT 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
A31 A30 A29 A28 A27 A26 A25 A24 A23 0 0 0 0 0 0 0
For a carrier in VME slot 2, we could define its A32 base address as 0x00800000
plus VME_A32_MSTR_LOCAL. For VME slot 3, the base address could be 0x01000000 plus
VME_A32_MSTR_LOCAL and for VME slot 4, the base address could be 0x01800000 plus
VME_A32_MSTR_LOCALand so forth.
Assuming VME_A32_MSTR_LOCAL is still 0x20000000, then for VME slot 4, the calculated
base address should be 0x01800000 + 0x20000000 = 0x218000000. Hence the MEMOFFS = 8576
(decimal, i.e. 0x2180). For slot 5, the derived base address could be 0x02000000 +
0x20000000 = 0x22000000. Hence the MEMOFFS = 8704 (decimal, i.e. 0x2200) and so forth.
- int Hy8002CarrierInfo(int carrier);
where 'carrier' is the registered carrier number in the system. If it is specified,
this function prints out the specified carrier hardware information. If carrier = 0xFFFF,
then all carriers' hardware information will be printed out.
2). Configuration Examples
-------------------------
ipacAddHy8002("3,2")
This indicates that the carrier is in slot 3 and the interrupt level is set to 2.
IP memory uses default 1MB. Clock uses default 8MHz. RORA as default. use geographical
addressing etc.
ipacAddHy8002("5,4,IPMEM=1,IPCLCK=8,ROAK=1,MEMOFFS=256 ")
Here the slot is 5, interrupt level is 4. IP memory size is 1MB, clock uses 8MHz.
Use ROAK but not using geographic addressing. The memory offset is 256 which means its
base address is 0x01000000 assuming the VME_A32_MSTR_LOCAL is set to 0x00000000.
3). Interrupt Commands Supported
-------------------------------
The interrupt level can be set by the second parameter of the ipacAddHy8002 routine.
Individual IP module can be set to generate interrupt or not. The commands supported
for ipmIrqCmd are illustrated below.
cmd Value Returned
ipac_irqGetLevel Carrier interrupt level (0 ~ 7)
ipac_irqEnable 0 = OK
ipac_irqDisable 0 = OK
ipac_irqPoll >0 if the interrupt line is active, else 0
(other commands) S_IPAC_notImplemented
Hy8601 IP Asyn Driver Usage
============================
1). Configuration shell command
-------------------------------
The configuration ioc shell command takes the form below.
int Hytec8601Configure(char *portName,
epicsUInt16 numAxes,
epicsUInt16 movingPollPeriod,
epicsUInt16 idlePollPeriod,
epicsUInt16 cardnum,
epicsUInt16 ip_carrier,
epicsUInt16 ipslot,
epicsUInt16 vector,
epicsUInt16 useencoder,
epicsDouble encoderRatio0,
epicsDouble encoderRatio1,
epicsDouble encoderRatio2,
epicsDouble encoderRatio3)
Where:
(1) portName asyn port name
(2) numAxes number of axes
(3) movingPollPeriod status polling time period when motor is moving in ms
(4) idlePollPeriod status polling time period when motor is stopped in ms
(5) cardnum Arbitrary card number to assign to this controller (currently not used)
(6) ip_carrier which previously configured IP carrier in the IOC
(7) ipslot which IP Slot on carrier card (0=A etc.)
(8) vector which Interrupt Vector (0 - Find One ?)
(9) useencoder - bit0 for axis0, bit1 for axis1, bit2 for axis2 and bit3 for axis3.
Other bits not used. 1=use encoder, 0=don't use encoder !
(10) encoderRatio0 - axis0 hardware encoder ratio
(11) encoderRatio1 - axis1 hardware encoder ratio
(12) encoderRatio2 - axis2 hardware encoder ratio
(13) encoderRatio3 - axis3 hardware encoder ratio
Example:
Hytec8601Configure("Hy8601", 4, 500, 1000, 0, IPAC0, 0, 70, 15, 0.25, 0.25, 0.25, 0.25)
This configures the 8601 card with
port name: Hy8601
4 axes
poll status every 500ms when moving
poll status every 1000ms when stopped
card number = 0
carrier serial number = 0
ipslot = site A
interrupt vector = 70
all 4 axes use encoder
all 4 axes have quardrature encoder hence their ratios are 0.25
Please note, since the parameters in the function is more than 10, in VxWorks, the start up
script loading will complain about " too many parameters..." In this case, adding
iocsh()
before this routine in start up script will solve the problem.
2). Database definition file
----------------------------
Database definition file is: HytecMotorDriver.dbd.
3). Databases
-------------
Two databases can be loaded:
dbLoadRecords("db/basic_asyn_motor.db")
dbLoadRecords("db/HytecMotorControl.db", "dev=IP8601,area=TEST,locn=LAB,PORT=Hy8601")
Where:
basic_asyn_motor.db is the motor record database. It initialises 4 axes.
HytecMotorControl.db is the special controls for Hy8601 motor controller. It contains few extra asyn records
including POWER, BRAKE controls, synchronous read of absolute position and enocder position and firmware
version etc as below.
record(bo,"$(dev):$(area):$(locn):POWER") {
field(DTYP,"asynInt32")
field(OUT,"@asyn($(PORT) 0)HYTEC_POWER")
field(VAL, "1")
field(ONAM, "On")
field(ZNAM, "Off")
}
record(bo,"$(dev):$(area):$(locn):BRAKE") {
field(DTYP,"asynInt32")
field(OUT,"@asyn($(PORT) 0)HYTEC_BRAKE")
field(VAL, "1")
field(ZNAM, "Set")
field(ONAM, "Rls")
}
record(ai,"$(dev):$(area):$(locn):POSN") {
field(PINI, "YES")
field(DTYP,"asynInt32")
field(INP,"@asyn($(PORT) 0)MOTOR_POSITION")
field(SCAN, "1 second")
}
record(ai,"$(dev):$(area):$(locn):EN_POSN") {
field(PINI, "YES")
field(DTYP,"asynInt32")
field(INP,"@asyn($(PORT) 0)MOTOR_ENCODER_POSITION")
field(SCAN, "1 second")
}
record(ai,"$(dev):$(area):$(locn):FIRMWARE_VERSION") {
field(PINI, "YES")
field(DTYP,"asynInt32")
field(INP,"@asyn($(PORT) 0)HYTEC_FWVERSION")
field(SCAN, "1 second")
}
There are other records in the HytecMotorControl.db which can return the positions synchronously etc.
These positions are raw values in terms of the "counts". These records can be read by "ai" records
and can be converted to engineering values by EGUF, EGUL etc.
Notes:
- The power control uses AUX1 of the 8601 CSR. As it indicates in the record above, command
caput $(dev):$(area):$(locn):POWER 1
means power "On" and it sets the AUX1 bit, i.e. AUX1 output high (1).
caput $(dev):$(area):$(locn):POWER 0
means power "Off" so it clears AUX1 bit, i.e. AUX1 output low (0). Command
- The brake control uses AUX2 of the 8601 CSR. As it indicates in the record above, command
caput $(dev):$(area):$(locn):BRAKE 1
means to release the brake. It clears AUX2 bit, i.e. AUX2 output low (0). Command
caput $(dev):$(area):$(locn):BRAKE 0
means set the brake. It sets the AUX2 bit, i.e. AUX2 output high (1).
- The firmware version record returns the IP card PCB board issue number and the firmware version
caget $(dev):$(area):$(locn):FIRMWARE_VERSION
will return something like '2210' for example, whereas the first 2 is the PCB issue number and
210 is the firmware version.
4). To build an example application
-----------------------------------
To build an example to test the 8601 asyn driver, use EPICS makeBaseApp.pl script to create
the example as usual. Then modify the following files to include the driver module(s).
- <TOP>/configure/RELEASE
Change the EPICS_BASE and SUPPORT to the proper directories.
Add ASYN, IPAC and MOTOR moudles:
ASYN=$(SUPPORT)/asyn/asyn4-14
IPAC=$(SUPPORT)/ipac/ipac-2.11
MOTOR=<the motor module dir>/motorR6-5-2
- <TOP>xxxApp/src/Makefile
In the Makefile of the example src, add following lines:
example_DBD += asyn.dbd
example_DBD += motorSupport.dbd
example_DBD += motorRecord.dbd
example_DBD += drvIpac.dbd
example_DBD += HytecMotorDriver.dbd
example_LIBS += HytecMotor
example_LIBS += motor
example_LIBS += Ipac
example_LIBS += asyn
- <TOP>/xxxApp/Db/Makefile
Copy HytecMotorControl.db to the Db directory and add the following lines in the Makefile of
the Db directory:
DB += basic_asyn_motor.db
DB += HytecMotorControl.db
- Build the application from <TOP>
- Modify st.cmd in iocBoot/iocexample as per next section and run the start up script from here.
5). Start up script example
---------------------------
The following example is for an IOC that uses RTEMS R4.9.4, MVME5500 processor board.
# Change directory to TOP of application
cd("../..")
iocBoot=pwd()
ld( "bin/RTEMS-mvme5500/MotionControl.obj")
#ld < bin/vxWorks-ppc604_long/MotionControl.munch #for VxWorks
## Set common environment variables
#< all/pre_st.cmd
epicsEnvSet("IOC_NAME", "MC02")
epicsEnvSet("LOCA_NAME", "B025")
epicsEnvSet("ENGINEER", "Condamoor, Shantha")
epicsEnvSet( "EPICS_CA_MAX_ARRAY_BYTES", "30000")
# Register all support components
dbLoadDatabase( "dbd/MotionControl.dbd")
MotionControl_registerRecordDeviceDriver( pdbbase)
bspExtVerbosity=0
###########################################################
# Configure Hytec 8002 carriers
# 8002 carrier VME slot: 3
# INT level: 5
# Memory per IP: 1MB
# Memory mapping offset: 8384
# ===================================================================
#The typical output on beatnik looks like this:
# Cexp@till35>BSP_VMEOutboundPortsShow()
# Tsi148 Outbound Ports:
# Port VME-Addr Size PCI-Adrs Mode:
# 0: 0x20000000 0x0e000000 0x90000000 A32, SUP, D32, SCT
# 1: 0x00000000 0x00ff0000 0x9f000000 A24, SUP, D32, SCT
# 2: 0x00000000 0x00010000 0x9fff0000 A16, SUP, D32, SCT
# 7: 0x00000000 0x01000000 0x9e000000 CSR, SUP, D32, SCT
# ===================================================================
# A32 space configured to start here: 0x20000000
# Tell the carrier not to use geographic addressing
IPAC0=ipacAddHy8002("3,5,IPMEM=1,MEMOFFS=8384")
#
# Hytec MDS-8 8601 driver setup parameters:
# int Hytec8601Configure(char *portName,
# epicsUInt16 numAxes,
# epicsUInt16 movingPollPeriod,
# epicsUInt16 idlePollPeriod,
# epicsUInt16 cardnum,
# epicsUInt16 ip_carrier,
# epicsUInt16 ipslot,
# epicsUInt16 vector,
# epicsUInt16 useencoder,
# epicsDouble encoderRatio0,
# epicsDouble encoderRatio1,
# epicsDouble encoderRatio2,
# epicsDouble encoderRatio3)
# (1) portName asyn port name
# (2) numAxes number of axes
# (3) movingPollPeriod status polling time period when motor is moving in ms
# (4) idlePollPeriod status polling time period when motor is stopped in ms
# (5) cardnum Arbitrary card number to assign to this controller, not used
# (6) ip_carrier which previously configured IP carrier in the IOC
# (7) ipslot which IP Slot on carrier card (0=A etc.)
# (8) vector which Interrupt Vector (0 - Find One ?)
# (9) useencoder - bit0 for axis0, bit1 for axis1, bit2 for axis2 and bit3 for axis3.
# Other bits not used. 1=use encoder, 0=don't use encoder !
# (10) encoderRatio0 - axis0 hardware encoder ratio
# (11) encoderRatio1 - axis1 hardware encoder ratio
# (12) encoderRatio2 - axis2 hardware encoder ratio
# (13) encoderRatio3 - axis3 hardware encoder ratio
Hytec8601Configure("Hy8601", 4, IPAC0, 0, 0, 70, 0, 0.25, 0.25, 0.25, 0.25)
# ========================================================
# New Hytec Motor Databases
# =======================================================
dbLoadRecords("db/basic_asyn_motor.db")
dbLoadRecords("db/HytecMotorControl.db", "dev=IP8601,area=TEST,locn=LAB,PORT=Hy8601")
# ========================================================
iocInit()
-6
View File
@@ -66,12 +66,6 @@ KohzuSrc_DEPEND_DIRS = MotorSrc
DIRS += AerotechSrc
AerotechSrc_DEPEND_DIRS = MotorSrc
# The Hytec support requires ipac
ifdef IPAC
DIRS += HytecSrc
HytecSrc_DEPEND_DIRS = MotorSrc
endif
DIRS += ACRSrc
ACRSrc_DEPEND_DIRS = MotorSrc