add PIE710 support files to repository

This commit is contained in:
jsullivan-anl
2006-10-06 18:18:22 +00:00
parent 2496700f7d
commit 5cf02a6c71
5 changed files with 1194 additions and 0 deletions
+68
View File
@@ -0,0 +1,68 @@
/*
FILENAME... PIE710Register.cc
USAGE... Register PI motor device driver shell commands.
Version: $Revision: 1.1 $
Modified By: $Author: sullivan $
Last Modified: $Date: 2006-10-06 18:18:21 $
*/
/*****************************************************************
COPYRIGHT NOTIFICATION
*****************************************************************
(C) COPYRIGHT 1993 UNIVERSITY OF CHICAGO
This software was developed under a United States Government license
described on the COPYRIGHT_UniversityOfChicago file included as part
of this distribution.
**********************************************************************/
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include <iocsh.h>
#include "motor.h"
#include "drvPIE710.h"
#include "epicsExport.h"
extern "C"
{
// Pi Setup arguments
static const iocshArg setupArg0 = {"Max. controller count", iocshArgInt};
static const iocshArg setupArg1 = {"Polling rate", iocshArgInt};
// Pi Config arguments
static const iocshArg configArg0 = {"Card being configured", iocshArgInt};
static const iocshArg configArg1 = {"asyn port name", iocshArgString};
static const iocshArg configArg2 = {"asyn address (GPIB)", iocshArgInt};
static const iocshArg * const PIE710SetupArgs[2] = {&setupArg0, &setupArg1};
static const iocshArg * const PIE710ConfigArgs[3] = {&configArg0, &configArg1,
&configArg2};
static const iocshFuncDef setupPIE710 = {"PIE710Setup", 2, PIE710SetupArgs};
static const iocshFuncDef configPIE710 = {"PIE710Config", 3, PIE710ConfigArgs};
static void setupPIE710CallFunc(const iocshArgBuf *args)
{
PIE710Setup(args[0].ival, args[1].ival);
}
static void configPIE710CallFunc(const iocshArgBuf *args)
{
PIE710Config(args[0].ival, args[1].sval, args[2].ival);
}
static void PIE710motorRegister(void)
{
iocshRegister(&setupPIE710, setupPIE710CallFunc);
iocshRegister(&configPIE710, configPIE710CallFunc);
}
epicsExportRegistrar(PIE710motorRegister);
} // extern "C"
+108
View File
@@ -0,0 +1,108 @@
Digital Piezo Controller
(c) 2003 Physik Instrumente GmbH
Model: E-710
Version: V5.023
RS232:
9600,8,1,N (default)
Commands:
<axis#><command>[<arg>]</n>
Where axis# starts at 1.
* NO reply from motion commands
* Multiple command delimiter = ","
Reply: <reply string></n>
Position Resolution: 0.0001 micrometers
Effective Resolution: 0.01 (holding position)
Setup:
Position Error Tolerance Setting (Memory address 64)
This parameter controls the "On Target" flag (GI8) that is
used to determine DONE. If the tolerance is too large the
motorRecord will see DONE before the drive has reached
it target position.
Set the tolerance parameter to the retry deadband.
<axis>DP0,64DR<#.###> - sets RAM
<axis>DP-1,64DR<#.###> - sets EERAM <used on power cycle>
example:
1DP0,64DR0.01 - set tolerance to 0.01 um
1DP-1,64DR0.01
=================== MOTION =================
ENABLE Servo
<axis#>SL[0/1]
MOVE Absolute
<axis#>MA<position>
MOVE Relative
<axis#>MR<position>
GO HOME
<axis#>GH
SET VELOCITY
<axis#>SV<velocity>
Units: um/ms or urad/ms (float or int)
SET P-Term (Proportional Gain)
<axis#>SP<p>
STOP MOTION ?
<axis#>MR0 /* Zero relative move */
<axis#>SV0 /* Zero velocity */
=================== STATUS =================
READ Version Info
GI
Return:
Digital Piezo Controller V5.023<\n>
(c) 2003 Physik Instrumente GmbH<\n>
READ Commanded position
<axis#>MA
Response: +0000.0000
READ Feedback position
<axis#>TP - tell position
Response: +0000.0000
Units: micrometer or microradian
<axis#>TS - tell sensor
READ Velocity (programmed)
<axis#>TV
Response: 0.000000e+1
READ Status:
<axis#>GI8
Status Byte:
Bit 0: 0 = Servo on, 1 = Servo off
Bit 1: 0 = Piezo voltage inside limits,1 = Piezo voltage at limit
Bit 2: 0 = On Target: Position error smaller than tolerance 1 = Position error too large
Bit 3: 0 = Target position higher than low limit, 1 = Target Position at low limit
Bit 4: 0 = Target position smaller than high limit, 1 = Target position at high limit.
Bit 5: 0 = AutoZero is not running 1 = AutoZero is running
Bit 6: not used
Bit 7: 0 = no error, 1 = last sent command not accepted, error during command processing.
[The bit is reset by this command.]
+307
View File
@@ -0,0 +1,307 @@
/*
FILENAME... devPIE710.cc
USAGE... Motor record device level support for Physik Instrumente (PI)
GmbH & Co. E-710 motor controller.
Version: $Revision: 1.1 $
Modified By: $Author: sullivan $
Last Modified: $Date: 2006-10-06 18:18:21 $
*/
/*
* Original Author: Ron Sluiter
* Date: 12/17/03
* Current Author: Joe Sullivan
*
* Experimental Physics and Industrial Control System (EPICS)
*
* Copyright 1991, the Regents of the University of California,
* and the University of Chicago Board of Governors.
*
* This software was produced under U.S. Government contracts:
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
* and (W-31-109-ENG-38) at Argonne National Laboratory.
*
* Initial development by:
* The Controls and Automation Group (AT-8)
* Ground Test Accelerator
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Co-developed with
* The Controls and Computing Group
* Accelerator Systems Division
* Advanced Photon Source
* Argonne National Laboratory
*
* Modification Log:
* -----------------
* .01 09/13/06 jps - copied from devPIC848.cc
*/
#include <string.h>
#include "motorRecord.h"
#include "motor.h"
#include "motordevCom.h"
#include "drvPIE710.h"
#include "epicsExport.h"
extern struct driver_table PIE710_access;
/* ----------------Create the dsets for devPIE710----------------- */
static struct driver_table *drvtabptr;
static long PIE710_init(void *);
static long PIE710_init_record(void *);
static long PIE710_start_trans(struct motorRecord *);
static RTN_STATUS PIE710_build_trans(motor_cmnd, double *, struct motorRecord *);
static RTN_STATUS PIE710_end_trans(struct motorRecord *);
struct motor_dset devPIE710 =
{
{8, NULL, (DEVSUPFUN) PIE710_init, (DEVSUPFUN) PIE710_init_record, NULL},
motor_update_values,
PIE710_start_trans,
PIE710_build_trans,
PIE710_end_trans
};
extern "C" {epicsExportAddress(dset,devPIE710);}
/* --------------------------- program data --------------------- */
/* This table is used to define the command types */
/* WARNING! this must match "motor_cmnd" in motor.h */
static msg_types PIE710_table[] = {
MOTION, /* MOVE_ABS */
MOTION, /* MOVE_REL */
MOTION, /* HOME_FOR */
MOTION, /* HOME_REV */
IMMEDIATE, /* LOAD_POS */
IMMEDIATE, /* SET_VEL_BASE */
IMMEDIATE, /* SET_VELOCITY */
IMMEDIATE, /* SET_ACCEL */
IMMEDIATE, /* GO */
IMMEDIATE, /* SET_ENC_RATIO */
INFO, /* GET_INFO */
MOVE_TERM, /* STOP_AXIS */
VELOCITY, /* JOG */
IMMEDIATE, /* SET_PGAIN */
IMMEDIATE, /* SET_IGAIN */
IMMEDIATE, /* SET_DGAIN */
IMMEDIATE, /* ENABLE_TORQUE */
IMMEDIATE, /* DISABL_TORQUE */
IMMEDIATE, /* PRIMITIVE */
IMMEDIATE, /* SET_HIGH_LIMIT */
IMMEDIATE, /* SET_LOW_LIMIT */
VELOCITY /* JOG_VELOCITY */
};
static struct board_stat **PIE710_cards;
/* --------------------------- program data --------------------- */
/* initialize device support for PIE710 stepper motor */
static long PIE710_init(void *arg)
{
long rtnval;
int after = (int) arg;
if (after == 0)
{
drvtabptr = &PIE710_access;
(drvtabptr->init)();
}
rtnval = motor_init_com(after, *drvtabptr->cardcnt_ptr, drvtabptr, &PIE710_cards);
return(rtnval);
}
/* initialize a record instance */
static long PIE710_init_record(void *arg)
{
struct motorRecord *mr = (struct motorRecord *) arg;
return(motor_init_record_com(mr, *drvtabptr->cardcnt_ptr, drvtabptr, PIE710_cards));
}
/* start building a transaction */
static long PIE710_start_trans(struct motorRecord *mr)
{
motor_start_trans_com(mr, PIE710_cards);
return(OK);
}
/* end building a transaction */
static RTN_STATUS PIE710_end_trans(struct motorRecord *mr)
{
motor_end_trans_com(mr, drvtabptr);
return(OK);
}
/* add a part to the transaction */
static RTN_STATUS PIE710_build_trans(motor_cmnd command, double *parms, struct motorRecord *mr)
{
struct motor_trans *trans = (struct motor_trans *) mr->dpvt;
struct mess_node *motor_call;
struct controller *brdptr;
struct PIE710controller *cntrl;
char buff[110];
int card, maxdigits;
unsigned int size;
double dval, cntrl_units, res;
RTN_STATUS rtnval;
bool send;
send = true; /* Default to send motor command. */
rtnval = OK;
buff[0] = '\0';
/* Protect against NULL pointer with WRTITE_MSG(GO/STOP_AXIS/GET_INFO, NULL). */
dval = (parms == NULL) ? 0.0 : *parms;
rtnval = (RTN_STATUS) motor_start_trans_com(mr, PIE710_cards);
motor_call = &(trans->motor_call);
card = motor_call->card;
brdptr = (*trans->tabptr->card_array)[card];
if (brdptr == NULL)
return(rtnval = ERROR);
cntrl = (struct PIE710controller *) brdptr->DevicePrivate;
res = cntrl->drive_resolution[motor_call->signal];
cntrl_units = dval;
maxdigits = 5;
if (PIE710_table[command] > motor_call->type)
motor_call->type = PIE710_table[command];
if (trans->state != BUILD_STATE)
return(rtnval = ERROR);
if (command == PRIMITIVE && mr->init != NULL && strlen(mr->init) != 0)
strcat(motor_call->message, mr->init);
switch (command)
{
case MOVE_ABS:
case MOVE_REL:
case HOME_FOR:
case HOME_REV:
case JOG:
if (strlen(mr->prem) != 0)
{
strcat(motor_call->message, mr->prem);
strcat(motor_call->message, ",");
}
if (strlen(mr->post) != 0)
motor_call->postmsgptr = (char *) &mr->post;
break;
default:
break;
}
switch (command)
{
case MOVE_ABS:
sprintf(buff, "#MA%.*f,", maxdigits, (cntrl_units * res));
break;
case MOVE_REL:
sprintf(buff, "#MR%+.*f,", maxdigits, (cntrl_units * res));
break;
case HOME_FOR:
sprintf(buff, "#GH,");
break;
case HOME_REV:
sprintf(buff, "#GH,");
break;
case LOAD_POS:
rtnval = ERROR;
break;
case SET_VEL_BASE:
send = false; /* DC motor; not base velocity. */
break;
case SET_VELOCITY:
sprintf(buff, "#SV%.*f,", maxdigits, (cntrl_units * res));
break;
case ENABLE_TORQUE:
strcpy(buff, "#SL1,");
break;
case DISABL_TORQUE:
strcpy(buff, "#SL0,");
break;
case SET_ACCEL:
/* The PIE710 does not support acceleration commands. */
case GO:
/* The PIE710 starts moving immediately on move commands, GO command
* does nothing. */
send = false;
break;
case PRIMITIVE:
case GET_INFO:
/* These commands are not actually done by sending a message, but
rather they will indirectly cause the driver to read the status
of all motors */
break;
case STOP_AXIS:
/* No stop command available - use move relative 0 */
sprintf(buff, "#MR0,");
break;
case JOG_VELOCITY:
case JOG:
sprintf(buff, "#SV%.*f,", maxdigits, cntrl_units);
break;
case SET_PGAIN:
sprintf(buff, "#SP%.*f", maxdigits, cntrl_units);
break;
case SET_IGAIN:
send = false;
break;
case SET_DGAIN:
send = false;
break;
case SET_HIGH_LIMIT:
case SET_LOW_LIMIT:
case SET_ENC_RATIO:
trans->state = IDLE_STATE; /* No command sent to the controller. */
send = false;
break;
default:
send = false;
rtnval = ERROR;
}
size = strlen(buff);
if (send == false)
return(rtnval);
else if (size > sizeof(buff) || (strlen(motor_call->message) + size) > MAX_MSG_SIZE)
errlogMessage("PIE710_build_trans(): buffer overflow.\n");
else
{
strcat(motor_call->message, buff);
rtnval = motor_end_trans_com(mr, drvtabptr);
}
return(rtnval);
}
+639
View File
@@ -0,0 +1,639 @@
/*
FILENAME... drvPIE710.cc
USAGE... Motor record driver level support for Physik Instrumente (PI)
GmbH & Co. E-710 motor controller.
Version: $Revision: 1.1 $
Modified By: $Author: sullivan $
Last Modified: $Date: 2006-10-06 18:18:22 $
*/
/*
* Original Author: Ron Sluiter
* Date: 10/18/05
* Current Author: Joe Sullivan
*
* Experimental Physics and Industrial Control System (EPICS)
*
* Copyright 1991, the Regents of the University of California,
* and the University of Chicago Board of Governors.
*
* This software was produced under U.S. Government contracts:
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
* and (W-31-109-ENG-38) at Argonne National Laboratory.
*
* Initial development by:
* The Controls and Automation Group (AT-8)
* Ground Test Accelerator
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Co-developed with
* The Controls and Computing Group
* Accelerator Systems Division
* Advanced Photon Source
* Argonne National Laboratory
*
* Modification Log:
* -----------------
* .01 09/13/06 jps - copied from drvPIC848.cc
*/
/*
DESIGN LIMITATIONS...
1 - Like all controllers, the PIE710 must be powered-on when EPICS is first
booted up.
*/
#include <string.h>
#include <epicsThread.h>
#include <drvSup.h>
#include "motorRecord.h"
#include "motor.h"
#include "drvPIE710.h"
#include "epicsExport.h"
#define GET_IDENT "GI"
#define PIE710_NUM_CARDS 8
#define MAX_AXES 6
#define BUFF_SIZE 100 /* Maximum length of string to/from PIE710 */
/*----------------debugging-----------------*/
#ifdef __GNUG__
#ifdef DEBUG
#define Debug(l, f, args...) { if(l<=drvPIE710debug) printf(f,## args); }
#else
#define Debug(l, f, args...)
#endif
#else
#define Debug()
#endif
volatile int drvPIE710debug = 0;
extern "C" {epicsExportAddress(int, drvPIE710debug);}
/* --- Local data. --- */
int PIE710_num_cards = 0;
static char *PIE710_axis[] = {"1", "2", "3", "4", "5", "6"};
/* Local data required for every driver; see "motordrvComCode.h" */
#include "motordrvComCode.h"
/*----------------functions-----------------*/
static int recv_mess(int, char *, int);
static RTN_STATUS send_mess(int, char const *, char *);
static int set_status(int, int);
static long report(int);
static long init();
static int motor_init();
static void query_done(int, int, struct mess_node *);
/*----------------functions-----------------*/
struct driver_table PIE710_access =
{
motor_init,
motor_send,
motor_free,
motor_card_info,
motor_axis_info,
&mess_queue,
&queue_lock,
&free_list,
&freelist_lock,
&motor_sem,
&motor_state,
&total_cards,
&any_motor_in_motion,
send_mess,
recv_mess,
set_status,
query_done,
NULL,
&initialized,
PIE710_axis
};
struct
{
long number;
long (*report) (int);
long (*init) (void);
} drvPIE710 = {2, report, init};
extern "C" {epicsExportAddress(drvet, drvPIE710);}
static struct thread_args targs = {SCAN_RATE, &PIE710_access, 0.0};
/*********************************************************
* Print out driver status report
*********************************************************/
static long report(int level)
{
int card;
if (PIE710_num_cards <=0)
printf(" No PIE710 controllers configured.\n");
else
{
for (card = 0; card < PIE710_num_cards; card++)
{
struct controller *brdptr = motor_state[card];
if (brdptr == NULL)
printf(" PIE710 controller %d connection failed.\n", card);
else
{
struct PIE710controller *cntrl;
cntrl = (struct PIE710controller *) brdptr->DevicePrivate;
printf(" PIE710 controller #%d, port=%s, id: %s \n", card,
cntrl->asyn_port, brdptr->ident);
}
}
}
return(OK);
}
static long init()
{
/*
* We cannot call motor_init() here, because that function can do GPIB I/O,
* and hence requires that the drvGPIB have already been initialized.
* That cannot be guaranteed, so we need to call motor_init from device
* support
*/
/* Check for setup */
if (PIE710_num_cards <= 0)
{
Debug(1, "init(): PIE710 driver disabled. PIE710Setup() missing from startup script.\n");
}
return((long) 0);
}
static void query_done(int card, int axis, struct mess_node *nodeptr)
{
}
/********************************************************************************
* *
* FUNCTION NAME: set_status *
* *
* LOGIC: *
* Initialize. *
* Send "Moving Status" query. *
* Read response. *
* IF normal response to query. *
* Set communication status to NORMAL. *
* ELSE *
* IF communication status is NORMAL. *
* Set communication status to RETRY. *
* NORMAL EXIT. *
* ELSE *
* Set communication status error. *
* ERROR EXIT. *
* ENDIF *
* ENDIF *
* *
* IF "Moving Status" indicates any motion (i.e. status != 0). *
* Clear "Done Moving" status bit. *
* ELSE *
* Set "Done Moving" status bit. *
* ENDIF *
* *
* *
********************************************************************************/
static int set_status(int card, int signal)
{
struct PIE710controller *cntrl;
struct mess_node *nodeptr;
struct mess_info *motor_info;
struct motorRecord *mr;
/* Message parsing variables */
char buff[BUFF_SIZE];
char rtnBuff[BUFF_SIZE];
E710_Status_Reg mstat;
int rtn_state;
unsigned int convert_cnt, charcnt, statusInt;
epicsInt32 motorData;
bool plusdir, ls_active, plusLS, minusLS;
msta_field status;
cntrl = (struct PIE710controller *) motor_state[card]->DevicePrivate;
motor_info = &(motor_state[card]->motor_info[signal]);
nodeptr = motor_info->motor_motion;
if (nodeptr != NULL)
mr = (struct motorRecord *) nodeptr->mrecord;
else
mr = NULL;
status.All = motor_info->status.All;
if (cntrl->status != NORMAL)
charcnt = recv_mess(card, buff, FLUSH);
send_mess(card, "#GI8", PIE710_axis[signal]);
charcnt = recv_mess(card, buff, 1);
if (charcnt > 2)
convert_cnt = sscanf(buff, "%s %s %d\n", rtnBuff, rtnBuff, &statusInt);
else
convert_cnt = 0;
if (charcnt > 2 && convert_cnt == 3)
{
cntrl->status = NORMAL;
status.Bits.CNTRL_COMM_ERR = 0;
}
else
{
if (cntrl->status == NORMAL)
{
cntrl->status = RETRY;
rtn_state = OK;
goto exit;
}
else
{
cntrl->status = COMM_ERR;
status.Bits.CNTRL_COMM_ERR = 1;
status.Bits.RA_PROBLEM = 1;
rtn_state = 1;
goto exit;
}
}
/* Check for 1 byte status of earlier E710 revisions
* and shift into high byte */
if (cntrl->statusShift)
mstat.All = statusInt * (2^8);
else
mstat.All = statusInt;
/* Always DONE if torque disabled */
status.Bits.RA_DONE = (mstat.Bits.moving && !mstat.Bits.torque) ? 0 : 1;
status.Bits.RA_HOME = status.Bits.RA_DONE;
status.Bits.EA_POSITION = (mstat.Bits.torque) ? 0 : 1; /* Torgue disabled flag */
ls_active = plusLS = minusLS = false;
/* LS status may be true but servo is not within position error - keep updating */
if (status.Bits.RA_DONE)
{
plusLS = mstat.Bits.plus_ls ? true : false;
minusLS = mstat.Bits.minus_ls ? true : false;
}
send_mess(card, "#TP", PIE710_axis[signal]);
recv_mess(card, buff, 1);
motorData = NINT(atof(buff) / cntrl->drive_resolution[signal]);
if (motorData == motor_info->position)
{
if (nodeptr != 0) /* Increment counter only if motor is moving. */
motor_info->no_motion_count++;
}
else
{
status.Bits.RA_DIRECTION = (motorData >= motor_info->position) ? 1 : 0;
motor_info->position = motor_info->encoder_position = motorData;
motor_info->no_motion_count = 0;
}
plusdir = (status.Bits.RA_DIRECTION) ? true : false;
/* Set limit switch error indicators. */
if (plusLS == true)
{
status.Bits.RA_PLUS_LS = 1;
if (plusdir == true)
ls_active = true;
}
else
status.Bits.RA_PLUS_LS = 0;
if (minusLS == true)
{
status.Bits.RA_MINUS_LS = 1;
if (plusdir == false)
ls_active = true;
}
else
status.Bits.RA_MINUS_LS = 0;
/* encoder status */
status.Bits.EA_SLIP = 0;
status.Bits.EA_SLIP_STALL = 0;
status.Bits.EA_HOME = 0;
status.Bits.RA_PROBLEM = 0;
/* Parse motor velocity? */
/* NEEDS WORK */
motor_info->velocity = 0;
if (!status.Bits.RA_DIRECTION)
motor_info->velocity *= -1;
rtn_state = (!motor_info->no_motion_count || ls_active == true ||
status.Bits.RA_DONE | status.Bits.RA_PROBLEM) ? 1 : 0;
/* Test for post-move string. */
if ((status.Bits.RA_DONE || ls_active == true) && nodeptr != 0 &&
nodeptr->postmsgptr != 0)
{
strcpy(buff, nodeptr->postmsgptr);
send_mess(card, buff, (char) NULL);
nodeptr->postmsgptr = NULL;
}
exit:
motor_info->status.All = status.All;
return(rtn_state);
}
/*****************************************************/
/* send a message to the PIE710 board */
/* send_mess() */
/*****************************************************/
static RTN_STATUS send_mess(int card, char const *com, char *name)
{
char local_buff[MAX_MSG_SIZE];
struct PIE710controller *cntrl;
int comsize, namesize;
size_t nwrite;
comsize = (com == NULL) ? 0 : strlen(com);
namesize = (name == NULL) ? 0 : strlen(name);
if ((comsize + namesize) > MAX_MSG_SIZE)
{
errlogMessage("drvPIE710.cc:send_mess(); message size violation.\n");
return(ERROR);
}
else if (comsize == 0) /* Normal exit on empty input message. */
return(OK);
if (!motor_state[card])
{
errlogPrintf("drvPIE710.cc:send_mess() - invalid card #%d\n", card);
return(ERROR);
}
local_buff[0] = (char) NULL; /* Terminate local buffer. */
if (name == NULL)
strcat(local_buff, com); /* Make a local copy of the string. */
else
{
strcpy(local_buff, com);
local_buff[0] = *name; /* put in axis. */
}
Debug(2, "send_mess(): message = %s\n", local_buff);
cntrl = (struct PIE710controller *) motor_state[card]->DevicePrivate;
pasynOctetSyncIO->write(cntrl->pasynUser, local_buff, strlen(local_buff),
COMM_TIMEOUT, &nwrite);
return(OK);
}
/*****************************************************/
/* receive a message from the PIE710 board */
/* recv_mess() */
/*****************************************************/
static int recv_mess(int card, char *com, int flag)
{
struct PIE710controller *cntrl;
size_t nread = 0;
asynStatus status = asynError;
int eomReason;
/* Check that card exists */
if (!motor_state[card])
return(ERROR);
cntrl = (struct PIE710controller *) motor_state[card]->DevicePrivate;
if (flag == FLUSH)
pasynOctetSyncIO->flush(cntrl->pasynUser);
else
status = pasynOctetSyncIO->read(cntrl->pasynUser, com, BUFF_SIZE,
COMM_TIMEOUT, &nread, &eomReason);
if ((status != asynSuccess) || (nread <= 0))
{
com[0] = '\0';
nread = 0;
}
Debug(2, "recv_mess(): message = \"%s\"\n", com);
return(nread);
}
/*****************************************************/
/* Setup system configuration */
/* PIE710Setup() */
/*****************************************************/
RTN_STATUS
PIE710Setup(int num_cards, /* maximum number of controllers in system. */
int scan_rate) /* polling rate - 1/60 sec units. */
{
int itera;
if (num_cards < 1 || num_cards > PIE710_NUM_CARDS)
PIE710_num_cards = PIE710_NUM_CARDS;
else
PIE710_num_cards = num_cards;
/* Set motor polling task rate */
if (scan_rate >= 1 && scan_rate <= 60)
targs.motor_scan_rate = scan_rate;
else
targs.motor_scan_rate = SCAN_RATE;
/*
* Allocate space for motor_state structures. Note this must be done
* before PIE710Config is called, so it cannot be done in motor_init()
* This means that we must allocate space for a card without knowing
* if it really exists, which is not a serious problem
*/
motor_state = (struct controller **) malloc(PIE710_num_cards *
sizeof(struct controller *));
for (itera = 0; itera < PIE710_num_cards; itera++)
motor_state[itera] = (struct controller *) NULL;
return(OK);
}
/*****************************************************/
/* Configure a controller */
/* PIE710Config() */
/*****************************************************/
RTN_STATUS
PIE710Config(int card, /* card being configured */
const char *name, /* asyn port name */
int addr) /* asyn address (GPIB) */
{
struct PIE710controller *cntrl;
if (card < 0 || card >= PIE710_num_cards)
return(ERROR);
motor_state[card] = (struct controller *) malloc(sizeof(struct controller));
motor_state[card]->DevicePrivate = malloc(sizeof(struct PIE710controller));
cntrl = (struct PIE710controller *) motor_state[card]->DevicePrivate;
strcpy(cntrl->asyn_port, name);
cntrl->asyn_address = addr;
return(OK);
}
/*****************************************************/
/* initialize all software and hardware */
/* This is called from the initialization routine in */
/* device support. */
/* motor_init() */
/*****************************************************/
static int motor_init()
{
struct controller *brdptr;
struct PIE710controller *cntrl;
int card_index, motor_index;
char buff[2][BUFF_SIZE], *pbuff;
int total_axis;
int status;
int version;
asynStatus success_rtn;
static const char output_terminator[] = "\n";
static const char input_terminator[] = "\n";
initialized = true; /* Indicate that driver is initialized. */
/* Check for setup */
if (PIE710_num_cards <= 0)
return(ERROR);
for (card_index = 0; card_index < PIE710_num_cards; card_index++)
{
if (!motor_state[card_index])
continue;
brdptr = motor_state[card_index];
brdptr->ident[0] = (char) NULL; /* No controller identification message. */
brdptr->cmnd_response = false;
total_cards = card_index + 1;
cntrl = (struct PIE710controller *) brdptr->DevicePrivate;
status = version = 0;
/* Initialize communications channel */
success_rtn = pasynOctetSyncIO->connect(cntrl->asyn_port, 0,
&cntrl->pasynUser, NULL);
if (success_rtn == asynSuccess)
{
int retry = 0;
pasynOctetSyncIO->setOutputEos(cntrl->pasynUser, output_terminator,
strlen(output_terminator));
pasynOctetSyncIO->setInputEos(cntrl->pasynUser, input_terminator,
strlen(input_terminator));
/* Send a message to the board, see if it exists */
/* flush any junk at input port - should not be any data available */
pasynOctetSyncIO->flush(cntrl->pasynUser);
do
{
send_mess(card_index, GET_IDENT, (char) NULL);
status = recv_mess(card_index, buff[0], 1);
/* Parse out E710 revision (3 decimal places) and convert to int */
if ((pbuff = strchr(buff[0], 'V')))
version = NINT(atof(pbuff+1) * 1000);
else
version = 0;
/* Get second return string */
status = recv_mess(card_index, buff[1], 1);
retry++;
} while (status == 0 && !version && retry < 3);
}
if (success_rtn == asynSuccess && status > 0)
{
strcpy(brdptr->ident, buff[0]);
brdptr->localaddr = (char *) NULL;
brdptr->motor_in_motion = 0;
/* Check for E710 versions that need the status word shifted up 8 bits */
if ((version >= 5000 || version == 4019 || version == 4020) &&
version != 5018)
cntrl->statusShift = false;
else
cntrl->statusShift = true;
/* Determine # of axes. Request stage name. See if it responds */
for (total_axis = 0; total_axis < MAX_AXES; total_axis++)
{
send_mess(card_index, "#TP", PIE710_axis[total_axis]);
status = recv_mess(card_index, buff[0], 1);
if (!status)
break;
}
brdptr->total_axis = total_axis;
for (motor_index = 0; motor_index < total_axis; motor_index++)
{
struct mess_info *motor_info = &brdptr->motor_info[motor_index];
motor_info->status.All = 0;
motor_info->no_motion_count = 0;
motor_info->encoder_position = 0;
motor_info->position = 0;
brdptr->motor_info[motor_index].motor_motion = NULL;
/* PIE710 has DC motor support only */
motor_info->encoder_present = YES;
motor_info->status.Bits.EA_PRESENT = 1;
motor_info->pid_present = YES;
motor_info->status.Bits.GAIN_SUPPORT = 1;
cntrl->drive_resolution[motor_index] = POS_RES;
set_status(card_index, motor_index); /* Read status of each motor */
}
}
else
motor_state[card_index] = (struct controller *) NULL;
}
any_motor_in_motion = 0;
mess_queue.head = (struct mess_node *) NULL;
mess_queue.tail = (struct mess_node *) NULL;
free_list.head = (struct mess_node *) NULL;
free_list.tail = (struct mess_node *) NULL;
epicsThreadCreate((char *) "PIE710_motor", epicsThreadPriorityMedium,
epicsThreadGetStackSize(epicsThreadStackMedium),
(EPICSTHREADFUNC) motor_task, (void *) &targs);
return(OK);
}
+72
View File
@@ -0,0 +1,72 @@
/* File: drvPIE710.h */
/* Device Driver Support definitions for motor */
/*
* Original Author: Ron Sluiter
* Current Author: Joe Sullivan
* Date: 09/20/2005
*
* Modification Log:
* -----------------
* .00 09/13/2006 jps copied from drvPIC838.h
*/
#ifndef INCdrvPIE710h
#define INCdrvPIE710h 1
#include "motordrvCom.h"
#include "asynDriver.h"
#include "asynDriver.h"
#include "asynOctetSyncIO.h"
#define COMM_TIMEOUT 2 /* Timeout in seconds. */
#define POS_RES 0.0001 /* Position resolution. */
struct PIE710controller
{
asynUser *pasynUser; /* asynUser structure */
int asyn_address; /* Use for GPIB or other address with asyn */
CommStatus status; /* Controller communication status. */
double drive_resolution[4];
bool statusShift; /* Older E710 reversions need the status word shifted 8 bits */
char asyn_port[80]; /* asyn port name */
};
typedef union
{
epicsUInt16 All;
struct
{
#ifdef MSB_First
unsigned int cmnd_err :1; /* 15 - Command Error */
unsigned int na6 :1; /* 14 - */
unsigned int autozero :1; /* 13 - AutoZero function is running */
unsigned int plus_ls :1; /* 12 - Positive limit switch flag. */
unsigned int minus_ls :1; /* 11 - Negative limit switch flag. */
unsigned int moving :1; /* 10 - Moving indicator - position error outside tolerance */
unsigned int volt_limit :1; /* 9 - piezo voltage limit reached */
unsigned int torque :1; /* 8 - Servo-control status */
unsigned int nabyte :8;
#else
unsigned int nabyte :8;
unsigned int torque :1; /* 8 - Servo-control status */
unsigned int volt_limit :1; /* 9 - piezo voltage limit reached */
unsigned int moving :1; /* 10 - Moving indicator - position error outside tolerance */
unsigned int minus_ls :1; /* 11 - Negative limit switch flag. */
unsigned int plus_ls :1; /* 12 - Positive limit switch flag. */
unsigned int autozero :1; /* 13 - AutoZero function is running */
unsigned int na6 :1; /* 14 - */
unsigned int cmnd_err :1; /* 15 - Command Error */
#endif
} Bits;
} E710_Status_Reg;
/* Function prototypes. */
extern RTN_STATUS PIE710Setup(int, int);
extern RTN_STATUS PIE710Config(int, const char *, int);
#endif /* INCdrvPIE710h */