forked from epics_driver_modules/motorBase
New model 3 driver
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
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
@@ -0,0 +1,4 @@
|
||||
# Database Definition
|
||||
registrar(Hytec8601Register)
|
||||
|
||||
|
||||
@@ -0,0 +1,222 @@
|
||||
/********************************************************************************/
|
||||
/* 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;
|
||||
};
|
||||
@@ -0,0 +1,415 @@
|
||||
***********************************************************************************
|
||||
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: 05/MAY/2011
|
||||
|
||||
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. 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 if
|
||||
1MB memory space is specified or 2~15 if 2MB memory space is specified
|
||||
i defines the interrupt level. Valid number is 0 ~ 7.
|
||||
IPMEM=d defines the maximum memory size of the IP module. The value d has to be 1, 2,
|
||||
4 or 8 that represent 1MB, 2MB, 4MB or 8MB respectively. Default is 1.
|
||||
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 is used to define the A32 memory space base address when geographic
|
||||
addressing is not preferred. The value of MEMOFFS defines A16 ~ A31 of
|
||||
the base address as shown below. It is derived from the VME slot number
|
||||
of the carrier card plus the VME_A32_MSTR_LOCAL defined in the config.h
|
||||
file of the BSP.
|
||||
|
||||
D15 D14 D13 D12 D11 D10 D09 D08 D07 D06 D05 D04 D03 D02 D01 D00
|
||||
A31 A30 A29 A28 A27 A26 A25 A24 A23 A22 x x x x x x
|
||||
|
||||
X= don't care, normally 0. So the actual meaningful bit starts from A22.
|
||||
|
||||
The reason it starts from A22 is that the minimum VME carrier memory assignment is
|
||||
4MB, i.e. each IP card has 1MB as defined by the IPMEM=1. As such, a carrier in
|
||||
slot 1 would have base address 0x00400000 plus the VME_A32_MSTR_LOCAL define.
|
||||
Of course slot 1 is occupied by processor. So for slot 2, the base address is 0x00800000
|
||||
and for slot 3, the base address is 0x00C00000 and so forth.
|
||||
|
||||
If the VME_A32_MSTR_LOCAL is defined as 0x20000000, then for slot 3, the derived base
|
||||
address is 0x00C00000 + 0x20000000 = 0x200C00000. Hence the MEMOFFS = 8204 (decimal, i.e. 0x200C).
|
||||
For slot 5, the derived base address will be 0x01400000 + 0x20000000 = 0x21400000.
|
||||
Hence the MEMOFFS = 8512 (decimal, i.e. 0x2140). 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=192 ")
|
||||
|
||||
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 192 which means its
|
||||
base address is 0x00C00000 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 cardnum,
|
||||
epicsUInt16 movingPollPeriod,
|
||||
epicsUInt16 idlePollPeriod,
|
||||
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) cardnum Arbitrary card number to assign to this controller
|
||||
(4) movingPollPeriod status polling time period when motor is moving in ms
|
||||
(5) idlePollPeriod status polling time period when motor is stopped in ms
|
||||
(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, 0, 500, 1000, IPAC0, 0, 70, 15, 0.25, 0.25, 0.25, 0.25)
|
||||
|
||||
This configures the 8601 card with
|
||||
port name: Hy8601
|
||||
4 axes
|
||||
card number = 0
|
||||
poll status every 500ms when moving
|
||||
poll status every 1000ms when stopped
|
||||
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
|
||||
|
||||
|
||||
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.
|
||||
|
||||
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 cardnum,
|
||||
# epicsUInt16 movingPollPeriod,
|
||||
# epicsUInt16 idlePollPeriod,
|
||||
# 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) cardnum Arbitrary card number to assign to this controller
|
||||
# (4) movingPollPeriod status polling time period when motor is moving in ms
|
||||
# (5) idlePollPeriod status polling time period when motor is stopped in ms
|
||||
# (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, 0, IPAC0, 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()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user