Removed PiSrc; Added motorPi submodule

This commit is contained in:
kpetersn
2019-04-08 15:17:59 -05:00
parent f1c366b80a
commit 041f13119f
57 changed files with 5 additions and 11591 deletions
+3
View File
@@ -40,3 +40,6 @@
[submodule "modules/motorPiJena"]
path = modules/motorPiJena
url = https://github.com/epics-motor/motorPiJena.git
[submodule "modules/motorPi"]
path = modules/motorPi
url = https://github.com/epics-motor/motorPi.git
-45
View File
@@ -57,51 +57,6 @@ dbLoadRecords("$(MOTOR)/db/motorUtil.db", "P=IOC:")
#!asynOctetSetOutputEos("a-Serial[0]",0,"\r")
#!drvMCB4BDebug=4
# PI C-844 driver setup parameters:
# (1) maximum number of controllers in system
# (2) motor task polling rate (min=1Hz,max=60Hz)
#!PIC844Setup(1, 10)
# PI C-844 driver configuration parameters:
# (1) controller# being configured
# (2) ASYN port name
# (3) address (GPIB only)
#!PIC844Config(0, "a-Serial[0]")
#!drvPIC844debug = 4
# PI C-848 driver setup parameters:
# (1) maximum number of controllers in system
# (2) motor task polling rate (min=1Hz,max=60Hz)
#!PIC848Setup(1, 2)
# PI C-848 driver configuration parameters:
# (1) controller# being configured,
# (2) ASYN port name
#!PIC848Config(0, "a-Serial[0]")
#!drvPIC848debug = 4
# PI E-662 Piezo driver setup parameters:
# (1) maximum number of controllers in system
# (2) motor task polling rate (min=1Hz, max=60Hz)
#!PIC662Setup(1, 60)
# PI E-662 Piezo driver configuration parameters:
# (1) controller being configured
# (2) asyn port name (string)
#!PIC662Config(0, "serial1")
#!drvPIC662debug = 4
# PI C-862 DC-motor driver setup parameters:
# (1) maximum number of controllers in system
# (2) motor task polling rate (min=1Hz, max=60Hz)
#!PIC862Setup(1, 60)
# PI C-862 DC-motor driver configuration parameters:
# (1) controller being configured
# (2) asyn port name (string)
#!PIC862Config(0, "serial1")
#!drvPIC862debug = 4
# New Focus Picomotor Network Controller (model 8750/2) (setup parameters:
# (1) maximum number of controllers in system
# (2) maximum number of drivers per controller (1 - 3)
-23
View File
@@ -50,29 +50,6 @@ asynSetOption("L0", -1, "crtscts", "N")
#!asynOctetSetOutputEos("L0",0,"\r")
#!var drvMCB4BDebug 4
# PI C-844 driver setup parameters:
# (1) maximum number of controllers in system
# (2) motor task polling rate (min=1Hz,max=60Hz)
#!PIC844Setup(1, 10)
# PI C-844 driver configuration parameters:
# (1) controller# being configured,
# (2) ASYN port name
# (3) address (GPIB only)
#!PIC844Config(0, "L0")
#!var drvPIC844debug 4
# PI C-848 driver setup parameters:
# (1) maximum number of controllers in system
# (2) motor task polling rate (min=1Hz,max=60Hz)
#!PIC848Setup(1, 2)
# PI C-848 driver configuration parameters:
# (1) controller# being configured,
# (2) ASYN port name
#!PIC848Config(0, "L0")
#!drvPIC848debug = 4
# Micos MoCo driver setup parameters:
# Load MicosSetup once.
# (1) max # of controller groups. Controller groups are per serial
-12
View File
@@ -39,18 +39,6 @@ dbLoadRecords("$(MOTOR)/db/motorUtil.db", "P=IOC:")
#!asynOctetSetOutputEos("L0",0,"\r")
#!var drvMCB4BDebug 4
# PI C-844 driver setup parameters:
# (1) maximum number of controllers in system
# (2) motor task polling rate (min=1Hz,max=60Hz)
#!PIC844Setup(1, 10)
# PI C-844 driver configuration parameters:
# (1) controller# being configured,
# (2) ASYN port name
# (3) address (GPIB only)
#!PIC844Config(0, "L0")
#!var drvPIC844debug 4
# Micos MoCo driver setup parameters:
# Load MicosSetup once.
# (1) max # of controller groups. Controller groups are per serial
-49
View File
@@ -1,49 +0,0 @@
# ### PI_C630.iocsh ###
#- ###################################################
#- PORT - Serial port for communications
#- CONTROLLER - Optional: Which controller is being configured
#- Default: 0
#-
#- MAX_CONTROLLERS - Optional: Max number of controllers that will be configured
#- Default: 1
#-
#- NUM_AXES - Optional: Max number of axes per controller
#- Default: 1
#-
#- POLL_RATE - Optional: Controller poll rate in hertz
#- Default: 10
#-
#- CURR[1-9] - Optional: Current settings for axes 1 through 9
#- Current equals 100mA * setting, maximum 800mA.
#- Default: 0 (off)
#- ###################################################
#-################################################
#- PI C-630 driver setup parameters:
#- Load PIC630Setup once.
#- (1) max # of controller groups. Controller groups are per serial port.
#- (2) max # axes per controller group. Maximum 9. (addr 1-9)
#- (3) motor task polling rate (min=1Hz, max=60Hz, 10Hz works well)
#- Example:
#- PIC630Setup(1, 2, 10) 1 group. 2 axes (controllers) in the group. 10Hz poll.
$(PI_C630_INIT_COMPLETE="") PIC630Setup($(MAX_CONTROLLERS=1), $(NUM_AXES=1), $(POLL_RATE=10))
# PI C630 serial connection settings
iocshLoad("$(IP)/iocsh/setSerialParams.iocsh", "PORT=$(PORT), BAUD=19200, BITS=8, STOP=1, PARITY=none")
asynOctetSetInputEos( "$(PORT)", -1, "\r")
asynOctetSetOutputEos("$(PORT)", -1, "\r")
#- PIC630 driver configuration parameters:
#- Load one PIC630Config for each group of PI C-630 drivers.
#- (1) "Controller group" number
#- (2) MPF card
#- (3)-(11) Current setting per axis (1-9). Leave at 0 if unused.
#- Choices: 0=OFF, 1=100mA, 2=200mA, ... 8=800mA.
#- Example:
#- PIC630Config(0, "serial1, 5, 3, 0, 0, 0, 0, 0, 0, 0")
#- Group 0, asyn serial port 1, Axis1=.5A, Axis2=.3A, others OFF
PIC630Config($(CONTROLLER=0), "$(PORT)", $(CURR1=0), $(CURR2=0), $(CURR3=0), $(CURR4=0), $(CURR5=0), $(CURR6=0), $(CURR7=0), $(CURR8=0), $(CURR9=0))
epicsEnvSet("PI_C630_INIT_COMPLETE", "#")
-28
View File
@@ -1,28 +0,0 @@
# ### PI_C867.iocsh ###
#- ###################################################
#- PORT - Serial port for communications
#- CONTROLLER - Optional: Which controller is being configured
#- Controller port name will be PIC867$(CONTROLLER)
#- Default: 0
#-
#- NUM_AXES - Optional: Max number of axes per controller
#- Default: 1
#-
#- MOVING_POLL - Optional: Moving poll rate (in msec)
#- Default: POLL_RATE
#-
#- IDLE_POLL - Optional: Idle poll rate (in msec)
#- Default: POLL_RATE
#-
#- POLL_RATE - Optional: Poll rate in msec
#- Default: 100
#- ###################################################
# PI C867 serial connection settings
iocshLoad("$(IP)/iocsh/setSerialParams.iocsh", "PORT=$(PORT), BAUD=38400, BITS=8, STOP=1, PARITY=none")
asynOctetSetInputEos( "$(PORT)", -1, "\n\r")
asynOctetSetOutputEos("$(PORT)", -1, "\n")
PI_GCS2_CreateController("PIC867$(CONTROLLER)", "$(PORT)", $(NUM_AXES=0), 0, 0, $(MOVING_POLL=$(POLL_RATE=100)), $(IDLE_POLL=$(POLL_RATE=100)))
-31
View File
@@ -1,31 +0,0 @@
# ### PI_E710.iocsh ###
#- ###################################################
#- PORT - Serial port for communications
#- CONTROLLER - Optional: Which controller is being configured
#- Default: 0
#-
#- MAX_CONTROLLERS - Optional: Max number of controllers that will be configured
#- Default: 1
#-
#- POLL_RATE - Optional: Controller poll rate in hertz
#- Default: 10
#- ###################################################
#- PI E-710 driver setup parameters:
#- (1) maximum # of controllers,
#- (2) motor task polling rate (min=1Hz, max=60Hz)
$(E710_INIT_COMPLETE="") PIE710Setup($(MAX_CONTROLLERS=1), $(POLL_RATE=10))
# PI E710 serial connection settings
iocshLoad("$(IP)/iocsh/setSerialParams.iocsh", "PORT=$(PORT), BAUD=9600, BITS=8, STOP=1, PARITY=none")
asynOctetSetInputEos( "$(PORT)", -1, "\n")
asynOctetSetOutputEos("$(PORT)", -1, "\n")
#- PI E-710 driver configuration parameters:
#- (1) controller
#- (2) asyn port name (e.g. serial1 or gpib1)
#- (3) GPIB address (0 for serial)
PIE710Config($(CONTROLLER=0), "$(PORT)", 0)
epicsEnvSet("E710_INIT_COMPLETE", "#")
-30
View File
@@ -1,30 +0,0 @@
# ### PI_E816.iocsh ###
#- ###################################################
#- PORT - Serial port for communications
#- CONTROLLER - Optional: Which controller is being configured
#- Default: 0
#-
#- MAX_CONTROLLERS - Optional: Max number of controllers that will be configured
#- Default: 1
#-
#- POLL_RATE - Optional: Controller poll rate in hertz
#- Default: 10
#- ###################################################
#- PI E-816 driver setup parameters:
#- (1) maximum number of controllers in system
#- (2) motor task polling rate (min=1Hz,max=60Hz)
$(E816_INIT_COMPLETE="") PIE816Setup($(MAX_CONTROLLERS=1), $(POLL_RATE=10))
# PI E816 serial connection settings
iocshLoad("$(IP)/iocsh/setSerialParams.iocsh", "PORT=$(PORT), BAUD=38400, BITS=8, STOP=1, PARITY=none, HANDSHAKE=hardware")
asynOctetSetInputEos( "$(PORT)", -1, "\n")
asynOctetSetOutputEos("$(PORT)", -1, "\n")
# PI E-816 driver configuration parameters:
# (1) controller# being configured,
# (2) ASYN port name
PIE816Config($(CONTROLLER=0), "$(PORT)")
epicsEnvSet("E816_INIT_COMPLETE", "#")
+1
View File
@@ -19,6 +19,7 @@ SUBMODULES += motorMicronix
SUBMODULES += motorNPoint
SUBMODULES += motorOriel
SUBMODULES += motorPiJena
SUBMODULES += motorPi
# Allow sites to add extra submodules
-include Makefile.local
+1
Submodule modules/motorPi added at afb55469ab
-3
View File
@@ -27,9 +27,6 @@ ImsSrc_DEPEND_DIRS = MotorSrc
DIRS += AcsSrc
AcsSrc_DEPEND_DIRS = MotorSrc
DIRS += PiSrc
PiSrc_DEPEND_DIRS = MotorSrc
DIRS += PIGCS2Src
PIGCS2Src_DEPEND_DIRS = MotorSrc
-30
View File
@@ -1,30 +0,0 @@
# Makefile
TOP = ../..
include $(TOP)/configure/CONFIG
# Both the following line, and a line in the *.dbd file,
# must be uncommented to use diagnostic debugging messages.
#!USR_CXXFLAGS += -DDEBUG
DBD += devPIMotor.dbd
LIBRARY_IOC = PI
# Intelligent Motion Systems driver support.
SRCS += devPIC844.cc drvPIC844.cc PiRegister.cc
SRCS += devPIC630.cc drvPIC630.cc PIC630Register.cc
SRCS += devPIC848.cc drvPIC848.cc PIC848Register.cc
SRCS += devPIC662.cc drvPIC662.cc PIC662Register.cc
SRCS += devPIC862.cc drvPIC862.cc PIC862Register.cc
SRCS += devPIC663.cc drvPIC663.cc PIC663Register.cc
SRCS += devPIE710.cc drvPIE710.cc PIE710Register.cc
SRCS += devPIE516.cc drvPIE516.cc PIE516Register.cc
SRCS += devPIE517.cc drvPIE517.cc PIE517Register.cc
SRCS += devPIE816.cc drvPIE816.cc PIE816Register.cc
PI_LIBS += motor asyn
PI_LIBS += $(EPICS_BASE_IOC_LIBS)
include $(TOP)/configure/RULES
-68
View File
@@ -1,68 +0,0 @@
/*
FILENAME... PIC630Register.cc
USAGE... Register PIC630 motor device driver shell commands.
Version: 1.4
Modified By: sluiter
Last Modified: 2004/07/16 19:06:58
*/
/*****************************************************************
COPYRIGHT NOTIFICATION
*****************************************************************
(C) COPYRIGHT 1993 UNIVERSITY OF CHICAGO
This software was developed under a United States Government license
described on the COPYRIGHT_UniversityOfChicago file included as part
of this distribution.
**********************************************************************/
#include <iocsh.h>
#include "PIC630Register.h"
#include "epicsExport.h"
extern "C"
{
// PIC630 Setup arguments
static const iocshArg setupArg0 = {"Max. controller groups", iocshArgInt};
static const iocshArg setupArg1 = {"Max. axes per group", iocshArgInt};
static const iocshArg setupArg2 = {"Polling rate", iocshArgInt};
// PIC630 Config arguments
static const iocshArg configArg0 = {"Card being configured", iocshArgInt};
static const iocshArg configArg1 = {"asyn port name", iocshArgString};
static const iocshArg configArg2 = {"Ch 1 current setting", iocshArgInt};
static const iocshArg configArg3 = {"Ch 2 current setting", iocshArgInt};
static const iocshArg configArg4 = {"Ch 3 current setting", iocshArgInt};
static const iocshArg configArg5 = {"Ch 4 current setting", iocshArgInt};
static const iocshArg configArg6 = {"Ch 5 current setting", iocshArgInt};
static const iocshArg configArg7 = {"Ch 6 current setting", iocshArgInt};
static const iocshArg configArg8 = {"Ch 7 current setting", iocshArgInt};
static const iocshArg configArg9 = {"Ch 8 current setting", iocshArgInt};
static const iocshArg configArg10 = {"Ch 9 current setting", iocshArgInt};
static const iocshArg * const PIC630SetupArgs[3] = {&setupArg0, &setupArg1, &setupArg2};
static const iocshArg * const PIC630ConfigArgs[11] = {&configArg0, &configArg1, &configArg2, &configArg3, &configArg4, &configArg5, &configArg6, &configArg7, &configArg8, &configArg9, &configArg10};
static const iocshFuncDef setupPIC630 = {"PIC630Setup", 3, PIC630SetupArgs};
static const iocshFuncDef configPIC630 = {"PIC630Config", 11, PIC630ConfigArgs};
static void setupPIC630CallFunc(const iocshArgBuf *args)
{
PIC630Setup(args[0].ival, args[1].ival, args[2].ival);
}
static void configPIC630CallFunc(const iocshArgBuf *args)
{
PIC630Config(args[0].ival, args[1].sval, args[2].ival, args[3].ival, args[4].ival, args[5].ival, args[6].ival, args[7].ival, args[8].ival, args[9].ival, args[10].ival);
}
static void PIC630Register(void)
{
iocshRegister(&setupPIC630, setupPIC630CallFunc);
iocshRegister(&configPIC630, configPIC630CallFunc);
}
epicsExportRegistrar(PIC630Register);
} // extern "C"
-45
View File
@@ -1,45 +0,0 @@
/*
FILENAME... PIC630Register.h
USAGE... This file contains function prototypes for PIC630 IOC shell commands.
Version: 1.3
Modified By: sluiter
Last Modified: 2004/07/16 19:06:58
*/
/*
* Original Author: Ron Sluiter
* Date: 05/19/03
*
* Experimental Physics and Industrial Control System (EPICS)
*
* Copyright 1991, the Regents of the University of California,
* and the University of Chicago Board of Governors.
*
* This software was produced under U.S. Government contracts:
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
* and (W-31-109-ENG-38) at Argonne National Laboratory.
*
* Initial development by:
* The Controls and Automation Group (AT-8)
* Ground Test Accelerator
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Co-developed with
* The Controls and Computing Group
* Accelerator Systems Division
* Advanced Photon Source
* Argonne National Laboratory
*
* Modification Log:
* -----------------
*/
#include "motor.h"
#include "motordrvCom.h"
/* Function prototypes. */
extern RTN_STATUS PIC630Setup(int, int, int);
extern RTN_STATUS PIC630Config(int, const char *, int,int,int,int,int,int,int,int,int);
-63
View File
@@ -1,63 +0,0 @@
/*
FILENAME... PiRegister.cc
USAGE... Register IMS motor device driver shell commands.
*/
/*****************************************************************
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 "drvPIC662.h"
#include "epicsExport.h"
extern "C"
{
// Pi 662 Setup arguments
static const iocshArg setupArg0 = {"Max. controller count", iocshArgInt};
static const iocshArg setupArg1 = {"Polling rate", iocshArgInt};
// Pi 662 Config arguments
static const iocshArg configArg0 = {"Card being configured", iocshArgInt};
static const iocshArg configArg1 = {"asyn port name", iocshArgString};
static const iocshArg * const PIC662SetupArgs[2] = {&setupArg0, &setupArg1};
static const iocshArg * const PIC662ConfigArgs[2] = {&configArg0, &configArg1};
static const iocshFuncDef setupPIC662 = {"PIC662Setup", 2, PIC662SetupArgs};
static const iocshFuncDef configPIC662 = {"PIC662Config", 2, PIC662ConfigArgs};
static void setupPIC662CallFunc(const iocshArgBuf *args)
{
PIC662Setup(args[0].ival, args[1].ival);
}
static void configPIC662CallFunc(const iocshArgBuf *args)
{
PIC662Config(args[0].ival, args[1].sval);
}
static void PIC662motorRegister(void)
{
iocshRegister(&setupPIC662, setupPIC662CallFunc);
iocshRegister(&configPIC662, configPIC662CallFunc);
}
epicsExportRegistrar(PIC662motorRegister);
} // extern "C"
-72
View File
@@ -1,72 +0,0 @@
/*
FILENAME... PIC663Register.cc
USAGE... Register PI motor device driver shell commands.
*/
/*
* Copied from PIC862Register.cc by Jonathan Thompson, Jan 2011
*
* Modification Log:
* -----------------
* Jan 2011 - All references to 862 changed to 663
* Status register definitions changed to match 663
*/
/*****************************************************************
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 "drvPIC663.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 PIC663SetupArgs[2] = {&setupArg0, &setupArg1};
static const iocshArg * const PIC663ConfigArgs[3] = {&configArg0, &configArg1,
&configArg2};
static const iocshFuncDef setupPIC663 = {"PIC663Setup", 2, PIC663SetupArgs};
static const iocshFuncDef configPIC663 = {"PIC663Config", 3, PIC663ConfigArgs};
static void setupPIC663CallFunc(const iocshArgBuf *args)
{
PIC663Setup(args[0].ival, args[1].ival);
}
static void configPIC663CallFunc(const iocshArgBuf *args)
{
PIC663Config(args[0].ival, args[1].sval, args[2].ival);
}
static void PIC663motorRegister(void)
{
iocshRegister(&setupPIC663, setupPIC663CallFunc);
iocshRegister(&configPIC663, configPIC663CallFunc);
}
epicsExportRegistrar(PIC663motorRegister);
} // extern "C"
-65
View File
@@ -1,65 +0,0 @@
/*
FILENAME... PIC848Register.cc
USAGE... Register PI motor device driver shell commands.
*/
/*****************************************************************
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 "drvPIC848.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 PIC848SetupArgs[2] = {&setupArg0, &setupArg1};
static const iocshArg * const PIC848ConfigArgs[3] = {&configArg0, &configArg1,
&configArg2};
static const iocshFuncDef setupPIC848 = {"PIC848Setup", 2, PIC848SetupArgs};
static const iocshFuncDef configPIC848 = {"PIC848Config", 3, PIC848ConfigArgs};
static void setupPIC848CallFunc(const iocshArgBuf *args)
{
PIC848Setup(args[0].ival, args[1].ival);
}
static void configPIC848CallFunc(const iocshArgBuf *args)
{
PIC848Config(args[0].ival, args[1].sval, args[2].ival);
}
static void PIC848motorRegister(void)
{
iocshRegister(&setupPIC848, setupPIC848CallFunc);
iocshRegister(&configPIC848, configPIC848CallFunc);
}
epicsExportRegistrar(PIC848motorRegister);
} // extern "C"
-68
View File
@@ -1,68 +0,0 @@
/*
FILENAME... PIC862Register.cc
USAGE... Register PI motor device driver shell commands.
Version: 1.1
Modified By: Ramanathan
Last Modified: 2006/09/04 19:45:52
*/
/*****************************************************************
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 "drvPIC862.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 PIC862SetupArgs[2] = {&setupArg0, &setupArg1};
static const iocshArg * const PIC862ConfigArgs[3] = {&configArg0, &configArg1,
&configArg2};
static const iocshFuncDef setupPIC862 = {"PIC862Setup", 2, PIC862SetupArgs};
static const iocshFuncDef configPIC862 = {"PIC862Config", 3, PIC862ConfigArgs};
static void setupPIC862CallFunc(const iocshArgBuf *args)
{
PIC862Setup(args[0].ival, args[1].ival);
}
static void configPIC862CallFunc(const iocshArgBuf *args)
{
PIC862Config(args[0].ival, args[1].sval, args[2].ival);
}
static void PIC862motorRegister(void)
{
iocshRegister(&setupPIC862, setupPIC862CallFunc);
iocshRegister(&configPIC862, configPIC862CallFunc);
}
epicsExportRegistrar(PIC862motorRegister);
} // extern "C"
-65
View File
@@ -1,65 +0,0 @@
/*
FILENAME... PIE516Register.cc
USAGE... Register PI motor device driver shell commands.
*/
/*****************************************************************
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 "drvPIE516.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 PIE516SetupArgs[2] = {&setupArg0, &setupArg1};
static const iocshArg * const PIE516ConfigArgs[3] = {&configArg0, &configArg1,
&configArg2};
static const iocshFuncDef setupPIE516 = {"PIE516Setup", 2, PIE516SetupArgs};
static const iocshFuncDef configPIE516 = {"PIE516Config", 3, PIE516ConfigArgs};
static void setupPIE516CallFunc(const iocshArgBuf *args)
{
PIE516Setup(args[0].ival, args[1].ival);
}
static void configPIE516CallFunc(const iocshArgBuf *args)
{
PIE516Config(args[0].ival, args[1].sval, args[2].ival);
}
static void PIE516motorRegister(void)
{
iocshRegister(&setupPIE516, setupPIE516CallFunc);
iocshRegister(&configPIE516, configPIE516CallFunc);
}
epicsExportRegistrar(PIE516motorRegister);
} // extern "C"
-68
View File
@@ -1,68 +0,0 @@
/*
FILENAME... PIE517Register.cc
USAGE... Register PI motor device driver shell commands.
Version: $Revision: 1.1 $
Modified By: $Author: sullivan $
Last Modified: $Date: 2007-03-30 20:01:05 $
*/
/*****************************************************************
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 "drvPIE517.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 PIE517SetupArgs[2] = {&setupArg0, &setupArg1};
static const iocshArg * const PIE517ConfigArgs[3] = {&configArg0, &configArg1,
&configArg2};
static const iocshFuncDef setupPIE517 = {"PIE517Setup", 2, PIE517SetupArgs};
static const iocshFuncDef configPIE517 = {"PIE517Config", 3, PIE517ConfigArgs};
static void setupPIE517CallFunc(const iocshArgBuf *args)
{
PIE517Setup(args[0].ival, args[1].ival);
}
static void configPIE517CallFunc(const iocshArgBuf *args)
{
PIE517Config(args[0].ival, args[1].sval, args[2].ival);
}
static void PIE517motorRegister(void)
{
iocshRegister(&setupPIE517, setupPIE517CallFunc);
iocshRegister(&configPIE517, configPIE517CallFunc);
}
epicsExportRegistrar(PIE517motorRegister);
} // extern "C"
-65
View File
@@ -1,65 +0,0 @@
/*
FILENAME... PIE710Register.cc
USAGE... Register PI motor device driver shell commands.
*/
/*****************************************************************
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"
-68
View File
@@ -1,68 +0,0 @@
/*
FILENAME... PIE816Register.cc
USAGE... Register PI motor device driver shell commands.
Version: 1.1
Modified By: sullivan
Last Modified: 2007/03/30 20:01:05
*/
/*****************************************************************
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 "drvPIE816.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 PIE816SetupArgs[2] = {&setupArg0, &setupArg1};
static const iocshArg * const PIE816ConfigArgs[3] = {&configArg0, &configArg1,
&configArg2};
static const iocshFuncDef setupPIE816 = {"PIE816Setup", 2, PIE816SetupArgs};
static const iocshFuncDef configPIE816 = {"PIE816Config", 3, PIE816ConfigArgs};
static void setupPIE816CallFunc(const iocshArgBuf *args)
{
PIE816Setup(args[0].ival, args[1].ival);
}
static void configPIE816CallFunc(const iocshArgBuf *args)
{
PIE816Config(args[0].ival, args[1].sval, args[2].ival);
}
static void PIE816motorRegister(void)
{
iocshRegister(&setupPIE816, setupPIE816CallFunc);
iocshRegister(&configPIE816, configPIE816CallFunc);
}
epicsExportRegistrar(PIE816motorRegister);
} // extern "C"
-65
View File
@@ -1,65 +0,0 @@
/*
FILENAME... PiRegister.cc
USAGE... Register IMS motor device driver shell commands.
*/
/*****************************************************************
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 "drvPI.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 PIC844SetupArgs[2] = {&setupArg0, &setupArg1};
static const iocshArg * const PIC844ConfigArgs[3] = {&configArg0, &configArg1,
&configArg2};
static const iocshFuncDef setupPIC844 = {"PIC844Setup", 2, PIC844SetupArgs};
static const iocshFuncDef configPIC844 = {"PIC844Config", 3, PIC844ConfigArgs};
static void setupPIC844CallFunc(const iocshArgBuf *args)
{
PIC844Setup(args[0].ival, args[1].ival);
}
static void configPIC844CallFunc(const iocshArgBuf *args)
{
PIC844Config(args[0].ival, args[1].sval, args[2].ival);
}
static void PImotorRegister(void)
{
iocshRegister(&setupPIC844, setupPIC844CallFunc);
iocshRegister(&configPIC844, configPIC844CallFunc);
}
epicsExportRegistrar(PImotorRegister);
} // extern "C"
-33
View File
@@ -1,33 +0,0 @@
PI C-844
========
Serial communication using the GreensSpring XM Octal I/O.
---------------------------------------------------------
The GreensSpring XM Octal I/O has a 16 pin jumper block for each serial port.
Assume (the manual does not define this) that the jumper pins are numbered
from, top to bottom, and from left to right; i.e.,
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
Then the "Default jumbering ..." depicted in Fig. 2 of the GreensSpring XM
Octal I/O manual is jumpered as follows; 1-5, 2-6, 9-13, 10-14.
The correct jumpering for the C-844 is; 1-2, 5-6, 13-16.
M-111.12S stage to ACS driver adapter
=====================================
DB15 ELCO Func.
---- ---- -----
1 A ph1+
9 E ph1-
2 C ph2+
10 H ph2-
6 V +5V
14 W lim+
7 T,U,R Gnd
8 X lim-
-88
View File
@@ -1,88 +0,0 @@
Digital Piezo Controller
(c) 2003 Physik Instrumente GmbH
Model: E-516
Version: DSP V3.11
MCU V5
RS232: <Programmable>
12200,8,1,N (default)
EOL: '/n' (10) LF
Hardware Flow Control RTS/CTS
Commands:
<command> <axis>[<arg>]</n>
Where axis = A, B or C
* NO reply from motion commands
* Multiple command delimiter = "/n"
Reply: <reply string></n>
Position Resolution: 0.001 micrometers (um)
Effective Resolution: 0.01 (on target tolerance)
Setup:
NONE
=================== CONTROLLER SETUP =================
Communication Enable
ONL 1
Velocity Control Mode ON (required for on-target reading ONT?)
VCO A1
=================== MOTION =================
ENABLE/DISABLE Servo
SVO <axis>[1/0]
MOVE Absolute
MOV <axis><position>
MOVE Relative
MVR <axis><position>
GO HOME
#######
SET VELOCITY
VEL <axis><velocity>
Units: 0.01 to 999.999 um/ms
STOP MOTION
STP <axis>
=================== STATUS =================
READ Version Info
*IDN?
Return:
READ Commanded position
MOV? <axis>
Response: +0000.0000
READ Feedback position
POS? <axis>
Response: +0000.0000
Units: micrometer or microradian
READ Velocity (programmed)
VEL? <axis>
Response: 0.000000e+1
ON-TARGET:
ONT? <Axis>
0(false) or 1(true)
SERVO ENABLE
SVO? <axis>
0 or 1
-114
View File
@@ -1,114 +0,0 @@
Digital Piezo Controller
(c) 2003 Physik Instrumente GmbH
Model: E-710
Version: V5.023
RS232:
9600,8,1,N (default)
connection:
db9 pin 2 (Rx) -> Tx
db9 pin 3 (Tx) -> Rx
db9 pin 5 (Com) -> Com
db9 pin 7 \ -> n.c.
db9 pin 8 / -> n.c.
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.]
-326
View File
@@ -1,326 +0,0 @@
/* File: devPIC630.cc */
/* Device Support Routines for motor */
/*
* Original Author: Kurt Goetze
* Date: 02-07-2005
*
* Modification Log:
* -----------------
* .00 02-07-2005 kag initialized from devMicos.c
*/
/* Notes regarding the motor record / PI C-630:
* 1. JogF and JogR are implemented as moves to the corresponding soft limit.
* 2. HomeF and HomeR will simply move the positioner to the "0" position.
* 3. The only position you may "set" is 0. Others will be ignored.
*
*/
#include <string.h>
#include <math.h>
#include "motorRecord.h"
#include "motor.h"
#include "motordevCom.h"
#include "drvPIC630.h"
#include "epicsExport.h"
#define NINT(f) (long)((f)>0 ? (f)+0.5 : (f)-0.5)
/*----------------debugging-----------------*/
volatile int devPIC630debug = 0;
extern "C" {epicsExportAddress(int, devPIC630debug);}
static inline void Debug(int level, const char *format, ...) {
#ifdef DEBUG
if (level < devPIC630debug) {
va_list pVar;
va_start(pVar, format);
vprintf(format, pVar);
va_end(pVar);
}
#endif
}
/* Debugging levels:
* devPIC630debug >= 3 Print new part of command and command string so far
* at the end of PIC630_build_trans
*/
extern struct driver_table PIC630_access;
/* ----------------Create the dsets for devPIC630----------------- */
static struct driver_table *drvtabptr;
static long PIC630_init(int);
static long PIC630_init_record(void *);
static long PIC630_start_trans(struct motorRecord *);
static RTN_STATUS PIC630_build_trans(motor_cmnd, double *, struct motorRecord *);
static RTN_STATUS PIC630_end_trans(struct motorRecord *);
struct motor_dset devPIC630 =
{
{8, NULL, (DEVSUPFUN) PIC630_init, (DEVSUPFUN) PIC630_init_record, NULL},
motor_update_values,
PIC630_start_trans,
PIC630_build_trans,
PIC630_end_trans
};
extern "C" {epicsExportAddress(dset,devPIC630);}
/* --------------------------- program data --------------------- */
/* This table is used to define the command types */
static msg_types PIC630_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 **PIC630_cards;
/* --------------------------- program data --------------------- */
/* initialize device support for PIC630 stepper motor */
static long PIC630_init(int after)
{
long rtnval;
Debug(5, "PIC630_init: entry\n");
if (!after)
{
drvtabptr = &PIC630_access;
(drvtabptr->init)();
}
rtnval = motor_init_com(after, *drvtabptr->cardcnt_ptr, drvtabptr, &PIC630_cards);
Debug(5, "PIC630_init: exit\n");
return(rtnval);
}
/* initialize a record instance */
static long PIC630_init_record(void *arg)
{
struct motorRecord *mr = (struct motorRecord *) arg;
return(motor_init_record_com(mr, *drvtabptr->cardcnt_ptr, drvtabptr, PIC630_cards));
}
/* start building a transaction */
static long PIC630_start_trans(struct motorRecord *mr)
{
motor_start_trans_com(mr, PIC630_cards);
return(OK);
}
/* end building a transaction */
static RTN_STATUS PIC630_end_trans(struct motorRecord *mr)
{
motor_end_trans_com(mr, drvtabptr);
return(OK);
}
/* add a part to the transaction */
static RTN_STATUS PIC630_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 PIC630Controller *cntrl;
char buff[30];
int axis, card;
RTN_STATUS rtnval;
bool send;
double dval; /* placeholder for double values passed from motor record */
long ival; /* placeholder for ints passed from motor record */
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;
ival = NINT(dval);
rtnval = (RTN_STATUS) motor_start_trans_com(mr, PIC630_cards);
Debug(5, "PIC630_build_trans: entry, motor_start_trans_com=%d\n", rtnval);
motor_call = &(trans->motor_call);
motor_call->type = PIC630_table[command];
card = motor_call->card; /* card is the group of drivers per unique serial port */
axis = motor_call->signal; /* axis is PIC630 address, up to 9 (1-9) per serial port */
axis++; /* Note: Each PIC630 driver drives up to 3 motors */
brdptr = (*trans->tabptr->card_array)[card];
Debug(5, "PIC630_build_trans: axis=%d, command=%d\n", axis, command);
if (brdptr == NULL)
return(rtnval = ERROR);
cntrl = (struct PIC630Controller *) brdptr->DevicePrivate;
if (trans->state != BUILD_STATE)
return(rtnval = ERROR);
if (command == PRIMITIVE && mr->init != NULL && strlen(mr->init) != 0)
{
strcpy(motor_call->message, mr->init);
rtnval = motor_end_trans_com(mr, drvtabptr);
rtnval = (RTN_STATUS) motor_start_trans_com(mr, PIC630_cards);
motor_call->type = PIC630_table[command];
}
switch (command)
{
case MOVE_ABS:
case MOVE_REL:
case HOME_FOR:
case HOME_REV:
case JOG:
if (strlen(mr->prem) != 0)
{
strcpy(motor_call->message, mr->prem);
rtnval = motor_end_trans_com(mr, drvtabptr);
rtnval = (RTN_STATUS) motor_start_trans_com(mr, PIC630_cards);
motor_call->type = PIC630_table[command];
}
if (strlen(mr->post) != 0)
motor_call->postmsgptr = (char *) &mr->post;
break;
default:
break;
}
switch (command)
{
case MOVE_ABS:
sprintf(motor_call->message, "%dMA%ld", axis, ival);
break;
case MOVE_REL:
sprintf(motor_call->message, "%dMR%ld", axis, ival);
break;
case HOME_FOR:
sprintf(motor_call->message, "%dMA0", axis);
break;
case HOME_REV:
sprintf(motor_call->message, "%dMA0", axis);
break;
case LOAD_POS: /* PIC630 allows you to define the zero position only */
if (dval == 0.0)
sprintf(motor_call->message, "%dDH", axis);
else
rtnval = ERROR;
break;
case SET_VEL_BASE:
send = false;
trans->state = IDLE_STATE;
break; /* PIC630 does not use base velocity */
case SET_VELOCITY:
if (ival < 1) ival = 1;
if (ival > 200000) ival = 200000;
sprintf(motor_call->message, "%dSV%ld", axis, ival);
break;
case SET_ACCEL:
/* dval is acceleration in steps/sec/sec */
if (ival < 0) ival = 0;
if (ival > 500000) ival = 500000;
sprintf(motor_call->message, "%dSA%ld", axis, ival);
break;
case GO:
/*
* The PIC630 starts moving immediately on move commands, GO command
* does nothing
*/
send = false;
trans->state = IDLE_STATE;
break;
case SET_ENC_RATIO:
/*
* The PIC630 does not have the concept of encoder ratio, ignore this
* command
*/
send = false;
trans->state = IDLE_STATE;
break;
case GET_INFO:
/* ? what is this for ? */
break;
case STOP_AXIS: /* (decelerate to a) stop */
sprintf(motor_call->message, "%dST", axis);
break;
case JOG:
/*
* PIC630 does not have a jog command. Simulate with move absolute
* to the appropriate software limit. The record will prevent JOG motion
* beyond its soft limits
* First we send the Jog velocity...
*/
ival = (long) fabs((double) ival);
if (ival < 1) ival = 1;
if (ival > 200000) ival = 200000;
sprintf(motor_call->message, "%dSV%ld", axis, ival);
rtnval = motor_end_trans_com(mr, drvtabptr);
rtnval = (RTN_STATUS) motor_start_trans_com(mr, PIC630_cards);
motor_call->type = PIC630_table[command];
if (dval > 0.) /* jog pos */
sprintf(motor_call->message, "%dMA%ld", axis, (long)(mr->dhlm / mr->mres));
else /* jog neg */
sprintf(motor_call->message, "%dMA%ld", axis, (long)(mr->dllm / mr->mres));
break;
case SET_PGAIN:
break;
case SET_IGAIN:
break;
case SET_DGAIN:
break;
case ENABLE_TORQUE:
break;
case DISABL_TORQUE:
break;
case SET_HIGH_LIMIT:
case SET_LOW_LIMIT:
trans->state = IDLE_STATE;
break;
default:
send = false;
rtnval = ERROR;
}
if (send == false)
return(rtnval);
else
{
rtnval = motor_end_trans_com(mr, drvtabptr);
Debug(5, "PIC630_send_msg: motor_end_trans_com status=%d, exit\n", rtnval);
return(rtnval);
}
}
-301
View File
@@ -1,301 +0,0 @@
/*
FILENAME... devPIC662.cc
USAGE... Motor record device level support for Physik Instrumente (PI)
GmbH & Co. C-844 motor controller.
*/
/*
* Original Author: Ron Sluiter
* Date: 12/17/03
*
* Experimental Physics and Industrial Control System (EPICS)
*
* Copyright 1991, the Regents of the University of California,
* and the University of Chicago Board of Governors.
*
* This software was produced under U.S. Government contracts:
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
* and (W-31-109-ENG-38) at Argonne National Laboratory.
*
* Initial development by:
* The Controls and Automation Group (AT-8)
* Ground Test Accelerator
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Co-developed with
* The Controls and Computing Group
* Accelerator Systems Division
* Advanced Photon Source
* Argonne National Laboratory
*
* Modification Log:
* -----------------
* .01 03/08/06 jps - copied from devPI.cc
*/
#include <string.h>
#include <errlog.h>
#include "motorRecord.h"
#include "motor.h"
#include "motordevCom.h"
#include "epicsExport.h"
#include "drvPIC662.h"
extern struct driver_table PIC662_access;
/* ----------------Create the dsets for devPIC662----------------- */
static struct driver_table *drvtabptr;
static long PIC662_init(int);
static long PIC662_init_record(void *);
static long PIC662_start_trans(struct motorRecord *);
static RTN_STATUS PIC662_build_trans(motor_cmnd, double *, struct motorRecord *);
static RTN_STATUS PIC662_end_trans(struct motorRecord *);
struct motor_dset devPIC662 =
{
{8, NULL, (DEVSUPFUN) PIC662_init, (DEVSUPFUN) PIC662_init_record, NULL},
motor_update_values,
PIC662_start_trans,
PIC662_build_trans,
PIC662_end_trans
};
extern "C" {epicsExportAddress(dset,devPIC662);}
/* --------------------------- program data --------------------- */
/* This table is used to define the command types */
/* WARNING! this must match "motor_cmnd" in motor.h */
static msg_types PIC662_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 **PIC662_cards;
/* --------------------------- program data --------------------- */
/* initialize device support for PIC662 stepper motor */
static long PIC662_init(int after)
{
long rtnval;
if (!after)
{
drvtabptr = &PIC662_access;
(drvtabptr->init)();
}
rtnval = motor_init_com(after, *drvtabptr->cardcnt_ptr, drvtabptr, &PIC662_cards);
return(rtnval);
}
/* initialize a record instance */
static long PIC662_init_record(void *arg)
{
struct motorRecord *mr = (struct motorRecord *) arg;
return(motor_init_record_com(mr, *drvtabptr->cardcnt_ptr, drvtabptr, PIC662_cards));
}
/* start building a transaction */
static long PIC662_start_trans(struct motorRecord *mr)
{
motor_start_trans_com(mr, PIC662_cards);
return(OK);
}
/* end building a transaction */
static RTN_STATUS PIC662_end_trans(struct motorRecord *mr)
{
motor_end_trans_com(mr, drvtabptr);
return(OK);
}
/* add a part to the transaction */
static RTN_STATUS PIC662_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 PIC662controller *cntrl;
char buff[110];
int axis, card, maxdigits;
unsigned int size;
double dval, cntrl_units;
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;
motor_call = &(trans->motor_call);
card = motor_call->card;
axis = motor_call->signal + 1;
brdptr = (*trans->tabptr->card_array)[card];
if (brdptr == NULL)
return(rtnval = ERROR);
cntrl = (struct PIC662controller *) brdptr->DevicePrivate;
maxdigits = cntrl->res_decpts;
cntrl_units = dval * cntrl->drive_resolution;
if (PIC662_table[command] > motor_call->type)
motor_call->type = PIC662_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, "DEV:CONT REM\nPOS %.*f", maxdigits, cntrl_units);
break;
case MOVE_REL:
sprintf(buff, "DEV:CONT REM\nPOS:REL %.*f", maxdigits, cntrl_units);
break;
case HOME_FOR:
case HOME_REV:
send = false;
break;
case LOAD_POS:
send = false; /* Can't Load a Position */
break;
case SET_VEL_BASE:
break;
case SET_VELOCITY:
send = false; /* DC motor; not base velocity. */
break;
case SET_ACCEL:
send = false; /* DC motor; not base velocity. */
break;
case GO:
/* The PIC662 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:
// Force device polling to stop.
// There is no HALT command to the motor controller
cntrl->stop_status = true;
send = false;
break;
case JOG_VELOCITY:
case JOG:
send = false;
break;
case SET_PGAIN:
send = false;
break;
case SET_IGAIN:
send = false;
break;
case SET_DGAIN:
send = false;
break;
case ENABLE_TORQUE:
send = false;
break;
case DISABL_TORQUE:
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("PIC662_build_trans(): buffer overflow.\n");
else
strcat(motor_call->message, buff);
return(rtnval);
}
-306
View File
@@ -1,306 +0,0 @@
/*
FILENAME... devPIC663.cc
USAGE... Motor record device level support for Physik Instrumente (PI)
GmbH & Co. C-663 motor controller.
*/
/*
* Copied from devPIC862.cc by Jonathan Thompson, Jan 2011
*
* Modification Log:
* -----------------
* Jan 2011 - All references to 862 changed to 663
*/
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <errlog.h>
#include "motorRecord.h"
#include "motor.h"
#include "motordevCom.h"
#include "drvPIC663.h"
#include "epicsExport.h"
extern struct driver_table PIC663_access;
/* ----------------Create the dsets for devPIC663----------------- */
static struct driver_table *drvtabptr;
static long PIC663_init(int);
static long PIC663_init_record(void *);
static long PIC663_start_trans(struct motorRecord *);
static RTN_STATUS PIC663_build_trans(motor_cmnd, double *, struct motorRecord *);
static RTN_STATUS PIC663_end_trans(struct motorRecord *);
struct motor_dset devPIC663 =
{
{8, NULL, (DEVSUPFUN) PIC663_init, (DEVSUPFUN) PIC663_init_record, NULL},
motor_update_values,
PIC663_start_trans,
PIC663_build_trans,
PIC663_end_trans
};
extern "C" {epicsExportAddress(dset,devPIC663);}
/* --------------------------- program data --------------------- */
/* This table is used to define the command types */
/* WARNING! this must match "motor_cmnd" in motor.h */
static msg_types PIC663_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 **PIC663_cards;
/* --------------------------- program data --------------------- */
/* initialize device support for PIC663 servo motor */
static long PIC663_init(int after)
{
long rtnval;
if (!after)
{
drvtabptr = &PIC663_access;
(drvtabptr->init)();
}
rtnval = motor_init_com(after, *drvtabptr->cardcnt_ptr, drvtabptr, &PIC663_cards);
return(rtnval);
}
/* initialize a record instance */
static long PIC663_init_record(void *arg)
{
struct motorRecord *mr = (struct motorRecord *) arg;
return(motor_init_record_com(mr, *drvtabptr->cardcnt_ptr, drvtabptr, PIC663_cards));
}
/* start building a transaction */
static long PIC663_start_trans(struct motorRecord *mr)
{
motor_start_trans_com(mr, PIC663_cards);
return(OK);
}
/* end building a transaction */
static RTN_STATUS PIC663_end_trans(struct motorRecord *mr)
{
struct motor_trans *trans = (struct motor_trans *) mr->dpvt;
struct mess_node *motor_call;
char *msgptr;
int last;
/* Remove trailing cmnd separator (",") from message. */
motor_call = &(trans->motor_call);
msgptr = motor_call->message;
last = strlen(msgptr) - 1;
if (msgptr[last] == ',')
msgptr[last] = (char) NULL;
motor_end_trans_com(mr, drvtabptr);
return(OK);
}
/* add a part to the transaction */
static RTN_STATUS PIC663_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;
char buff[110];
int card;
unsigned int size;
double dval;
int cntrl_units;
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;
motor_call = &(trans->motor_call);
card = motor_call->card;
brdptr = (*trans->tabptr->card_array)[card];
if (brdptr == NULL)
return(rtnval = ERROR);
cntrl_units = (int) dval;
if (PIC663_table[command] > motor_call->type)
motor_call->type = PIC663_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%d,", cntrl_units);
break;
case MOVE_REL:
sprintf(buff, "MR%d,", cntrl_units);
break;
case HOME_FOR:
sprintf(buff, "FE0");
break;
case HOME_REV:
sprintf(buff, "FE1");
break;
case LOAD_POS:
if (cntrl_units == 0.0)
sprintf(buff, "DH");
else
rtnval = ERROR;
break;
case SET_VEL_BASE:
send = false; /* DC motor; not base velocity. */
break;
case JOG_VELOCITY:
case SET_VELOCITY:
sprintf(buff, "SV%d,", cntrl_units);
break;
case SET_ACCEL:
sprintf(buff, "SA%d,", cntrl_units);
break;
case ENABLE_TORQUE:
sprintf(buff, "MN");
break;
case DISABL_TORQUE:
sprintf(buff, "MF");
break;
case GO:
/* The PIC663 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:
sprintf(buff, "ST");
break;
case JOG:
/*
* C-663 does not have a jog command. Simulate with move absolute
* to the appropriate software limit.
*/
sprintf(buff, "SV%d,", abs(cntrl_units));
strcat(motor_call->message, buff);
if (dval > 0.)
sprintf(buff, "MA%d,", (int) (mr->dhlm / mr->mres));
else
sprintf(buff, "MA%d,", (int) (mr->dllm / mr->mres));
break;
case SET_PGAIN:
cntrl_units = (int) (32767 * dval);
sprintf(buff, "DP%d", cntrl_units);
break;
case SET_IGAIN:
cntrl_units = (int) (32767 * dval);
sprintf(buff, "DI%d", cntrl_units);
break;
case SET_DGAIN:
cntrl_units = (int) (32767 * dval);
sprintf(buff, "DD%d", cntrl_units);
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("PIC663_build_trans(): buffer overflow.\n");
else
{
strcat(motor_call->message, buff);
}
return(rtnval);
}
-300
View File
@@ -1,300 +0,0 @@
/*
FILENAME... devPIC844.cc
USAGE... Motor record device level support for Physik Instrumente (PI)
GmbH & Co. C-844 motor controller.
*/
/*
* Original Author: Ron Sluiter
* Date: 12/17/03
*
* Experimental Physics and Industrial Control System (EPICS)
*
* Copyright 1991, the Regents of the University of California,
* and the University of Chicago Board of Governors.
*
* This software was produced under U.S. Government contracts:
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
* and (W-31-109-ENG-38) at Argonne National Laboratory.
*
* Initial development by:
* The Controls and Automation Group (AT-8)
* Ground Test Accelerator
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Co-developed with
* The Controls and Computing Group
* Accelerator Systems Division
* Advanced Photon Source
* Argonne National Laboratory
*
* Modification Log:
* -----------------
* .01 12/17/03 rls - copied from devIM483PL.cc
* .02 01/22/03 rls - fix INIT field processing; support HOME and PID commands.
*/
#include <string.h>
#include <errlog.h>
#include "motorRecord.h"
#include "motor.h"
#include "motordevCom.h"
#include "epicsExport.h"
extern struct driver_table PIC844_access;
/* ----------------Create the dsets for devPIC844----------------- */
static struct driver_table *drvtabptr;
static long PIC844_init(int);
static long PIC844_init_record(void *);
static long PIC844_start_trans(struct motorRecord *);
static RTN_STATUS PIC844_build_trans(motor_cmnd, double *, struct motorRecord *);
static RTN_STATUS PIC844_end_trans(struct motorRecord *);
struct motor_dset devPIC844 =
{
{8, NULL, (DEVSUPFUN) PIC844_init, (DEVSUPFUN) PIC844_init_record, NULL},
motor_update_values,
PIC844_start_trans,
PIC844_build_trans,
PIC844_end_trans
};
extern "C" {epicsExportAddress(dset,devPIC844);}
/* --------------------------- program data --------------------- */
/* This table is used to define the command types */
/* WARNING! this must match "motor_cmnd" in motor.h */
static msg_types PIC844_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 **PIC844_cards;
/* --------------------------- program data --------------------- */
/* initialize device support for PIC844 stepper motor */
static long PIC844_init(int after)
{
long rtnval;
if (!after)
{
drvtabptr = &PIC844_access;
(drvtabptr->init)();
}
rtnval = motor_init_com(after, *drvtabptr->cardcnt_ptr, drvtabptr, &PIC844_cards);
return(rtnval);
}
/* initialize a record instance */
static long PIC844_init_record(void *arg)
{
struct motorRecord *mr = (struct motorRecord *) arg;
return(motor_init_record_com(mr, *drvtabptr->cardcnt_ptr, drvtabptr, PIC844_cards));
}
/* start building a transaction */
static long PIC844_start_trans(struct motorRecord *mr)
{
motor_start_trans_com(mr, PIC844_cards);
return(OK);
}
/* end building a transaction */
static RTN_STATUS PIC844_end_trans(struct motorRecord *mr)
{
motor_end_trans_com(mr, drvtabptr);
return(OK);
}
/* add a part to the transaction */
static RTN_STATUS PIC844_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;
char buff[110];
int axis, card, maxdigits;
unsigned int size;
double dval, cntrl_units;
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;
motor_call = &(trans->motor_call);
card = motor_call->card;
axis = motor_call->signal + 1;
brdptr = (*trans->tabptr->card_array)[card];
if (brdptr == NULL)
return(rtnval = ERROR);
cntrl_units = dval;
maxdigits = 2;
if (PIC844_table[command] > motor_call->type)
motor_call->type = PIC844_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, "TARG %.*f", maxdigits, cntrl_units);
break;
case MOVE_REL:
sprintf(buff, "TARG:RPOS %+.*f", maxdigits, cntrl_units);
break;
case HOME_FOR:
sprintf(buff, "TARG:FIND POS");
break;
case HOME_REV:
sprintf(buff, "TARG:FIND NEG");
break;
case LOAD_POS:
sprintf(buff, "AXIS:POS %+.*f;TARG CURR", maxdigits, cntrl_units);
break;
case SET_VEL_BASE:
send = false; /* DC motor; not base velocity. */
break;
case SET_VELOCITY:
sprintf(buff, "MVEL %.*f;", maxdigits, cntrl_units);
break;
case SET_ACCEL:
sprintf(buff, "ACC %.*f;", maxdigits, cntrl_units);
break;
case GO:
/* The PIC844 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:
sprintf(buff, "HALT");
break;
case JOG_VELOCITY:
case JOG:
sprintf(buff, "TARG:VEL %.*f", maxdigits, cntrl_units);
break;
case SET_PGAIN:
cntrl_units *= 32767;
sprintf(buff, "PID %.*f,,", maxdigits, cntrl_units);
break;
case SET_IGAIN:
cntrl_units *= 32767;
sprintf(buff, "PID ,%.*f,", maxdigits, cntrl_units);
break;
case SET_DGAIN:
cntrl_units *= 32767;
sprintf(buff, "PID ,,%.*f", maxdigits, cntrl_units);
break;
case ENABLE_TORQUE:
sprintf(buff, "AXIS:STAT ON");
break;
case DISABL_TORQUE:
sprintf(buff, "AXIS:STAT OFF");
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("PIC844_build_trans(): buffer overflow.\n");
else
strcat(motor_call->message, buff);
return(rtnval);
}
-329
View File
@@ -1,329 +0,0 @@
/*
FILENAME... devPIC848.cc
USAGE... Motor record device level support for Physik Instrumente (PI)
GmbH & Co. C-848 motor controller.
*/
/*
* Original Author: Ron Sluiter
* Date: 12/17/03
*
* Experimental Physics and Industrial Control System (EPICS)
*
* Copyright 1991, the Regents of the University of California,
* and the University of Chicago Board of Governors.
*
* This software was produced under U.S. Government contracts:
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
* and (W-31-109-ENG-38) at Argonne National Laboratory.
*
* Initial development by:
* The Controls and Automation Group (AT-8)
* Ground Test Accelerator
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Co-developed with
* The Controls and Computing Group
* Accelerator Systems Division
* Advanced Photon Source
* Argonne National Laboratory
*
* Modification Log:
* -----------------
* .01 12/17/03 rls - copied from devIM483PL.cc
* .02 01/22/03 rls - fix INIT field processing; support HOME and PID commands.
* .03 10/17/07 rls - Due LOAD_POS based on "reference" indicator.
* - If torque is disabled, clear error conditions before
* ENABLE_TORQUE command.
*/
#include <string.h>
#include <errlog.h>
#include "motorRecord.h"
#include "motor.h"
#include "motordevCom.h"
#include "drvPIC848.h"
#include "epicsExport.h"
extern struct driver_table PIC848_access;
/* ----------------Create the dsets for devPIC848----------------- */
static struct driver_table *drvtabptr;
static long PIC848_init(int);
static long PIC848_init_record(void *);
static long PIC848_start_trans(struct motorRecord *);
static RTN_STATUS PIC848_build_trans(motor_cmnd, double *, struct motorRecord *);
static RTN_STATUS PIC848_end_trans(struct motorRecord *);
struct motor_dset devPIC848 =
{
{8, NULL, (DEVSUPFUN) PIC848_init, (DEVSUPFUN) PIC848_init_record, NULL},
motor_update_values,
PIC848_start_trans,
PIC848_build_trans,
PIC848_end_trans
};
extern "C" {epicsExportAddress(dset,devPIC848);}
/* --------------------------- program data --------------------- */
/* This table is used to define the command types */
/* WARNING! this must match "motor_cmnd" in motor.h */
static msg_types PIC848_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 **PIC848_cards;
/* --------------------------- program data --------------------- */
/* initialize device support for PIC848 stepper motor */
static long PIC848_init(int after)
{
long rtnval;
if (!after)
{
drvtabptr = &PIC848_access;
(drvtabptr->init)();
}
rtnval = motor_init_com(after, *drvtabptr->cardcnt_ptr, drvtabptr, &PIC848_cards);
return(rtnval);
}
/* initialize a record instance */
static long PIC848_init_record(void *arg)
{
struct motorRecord *mr = (struct motorRecord *) arg;
return(motor_init_record_com(mr, *drvtabptr->cardcnt_ptr, drvtabptr, PIC848_cards));
}
/* start building a transaction */
static long PIC848_start_trans(struct motorRecord *mr)
{
motor_start_trans_com(mr, PIC848_cards);
return(OK);
}
/* end building a transaction */
static RTN_STATUS PIC848_end_trans(struct motorRecord *mr)
{
motor_end_trans_com(mr, drvtabptr);
return(OK);
}
/* add a part to the transaction */
static RTN_STATUS PIC848_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 PIC848controller *cntrl;
char buff[110];
int card, maxdigits;
unsigned int size;
double dval, cntrl_units, res;
RTN_STATUS rtnval;
bool send;
msta_field msta;
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;
msta.All = mr->msta;
rtnval = (RTN_STATUS) motor_start_trans_com(mr, PIC848_cards);
motor_call = &(trans->motor_call);
card = motor_call->card;
brdptr = (*trans->tabptr->card_array)[card];
if (brdptr == NULL)
return(rtnval = ERROR);
cntrl = (struct PIC848controller *) brdptr->DevicePrivate;
res = cntrl->drive_resolution[motor_call->signal];
cntrl_units = dval;
maxdigits = 5;
if (PIC848_table[command] > motor_call->type)
motor_call->type = PIC848_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, "MOV #%.*f", maxdigits, (cntrl_units * res));
break;
case MOVE_REL:
sprintf(buff, "MVR #%+.*f", maxdigits, (cntrl_units * res));
break;
case HOME_FOR:
sprintf(buff, "REF #");
break;
case HOME_REV:
sprintf(buff, "REF #");
break;
case LOAD_POS:
if (cntrl->reference[motor_call->signal] == true)
{
if (cntrl_units == 0.0)
sprintf(buff, "DFH #");
else
rtnval = ERROR;
}
else
sprintf(buff, "POS #%+.*f", maxdigits, (cntrl_units * res));
break;
case SET_VEL_BASE:
send = false; /* DC motor; not base velocity. */
break;
case SET_VELOCITY:
sprintf(buff, "VEL # %.*f", maxdigits, (cntrl_units * res));
break;
case ENABLE_TORQUE:
if (msta.Bits.EA_POSITION == 0) /* Test for torque disabled. */
{
/* Clear the axis status. */
sprintf(buff, "CLR #");
rtnval = motor_end_trans_com(mr, drvtabptr);
rtnval = (RTN_STATUS) motor_start_trans_com(mr, PIC848_cards);
motor_call->type = PIC848_table[command];
}
sprintf(buff, "SVO #1");
break;
case DISABL_TORQUE:
sprintf(buff, "SVO #0");
break;
case SET_ACCEL:
/* The PIC848 does not support acceleration commands. */
case GO:
/* The PIC848 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:
sprintf(buff, "HLT #");
break;
case JOG_VELOCITY:
case JOG:
sprintf(buff, "VEL #%.*f", maxdigits, (cntrl_units * res));
break;
case SET_PGAIN:
cntrl_units *= 32767;
sprintf(buff, "SPA #1 %.*f", maxdigits, cntrl_units);
break;
case SET_IGAIN:
cntrl_units *= 32767;
sprintf(buff, "SPA #2 %.*f", maxdigits, cntrl_units);
break;
case SET_DGAIN:
cntrl_units *= 32767;
sprintf(buff, "SPA #3 %.*f", maxdigits, cntrl_units);
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("PIC848_build_trans(): buffer overflow.\n");
else
{
strcat(motor_call->message, buff);
rtnval = motor_end_trans_com(mr, drvtabptr);
}
return(rtnval);
}
-310
View File
@@ -1,310 +0,0 @@
/*
FILENAME... devPIC862.cc
USAGE... Motor record device level support for Physik Instrumente (PI)
GmbH & Co. C-862 motor controller.
*/
/*
* Original Author: Ron Sluiter
* Current Author: Mohan Ramanathan
* Date: 09/04/2006
*
* Modification Log:
* -----------------
* .00 09/05/2006 mr copied from devPIC848.cc
* .01 09/25/2006 rls - strip trailing cmnd separator (",") from message.
* - simulate jogging with absolute moves to soft limit.
*/
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <errlog.h>
#include "motorRecord.h"
#include "motor.h"
#include "motordevCom.h"
#include "drvPIC862.h"
#include "epicsExport.h"
extern struct driver_table PIC862_access;
/* ----------------Create the dsets for devPIC862----------------- */
static struct driver_table *drvtabptr;
static long PIC862_init(int);
static long PIC862_init_record(void *);
static long PIC862_start_trans(struct motorRecord *);
static RTN_STATUS PIC862_build_trans(motor_cmnd, double *, struct motorRecord *);
static RTN_STATUS PIC862_end_trans(struct motorRecord *);
struct motor_dset devPIC862 =
{
{8, NULL, (DEVSUPFUN) PIC862_init, (DEVSUPFUN) PIC862_init_record, NULL},
motor_update_values,
PIC862_start_trans,
PIC862_build_trans,
PIC862_end_trans
};
extern "C" {epicsExportAddress(dset,devPIC862);}
/* --------------------------- program data --------------------- */
/* This table is used to define the command types */
/* WARNING! this must match "motor_cmnd" in motor.h */
static msg_types PIC862_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 **PIC862_cards;
/* --------------------------- program data --------------------- */
/* initialize device support for PIC862 servo motor */
static long PIC862_init(int after)
{
long rtnval;
if (!after)
{
drvtabptr = &PIC862_access;
(drvtabptr->init)();
}
rtnval = motor_init_com(after, *drvtabptr->cardcnt_ptr, drvtabptr, &PIC862_cards);
return(rtnval);
}
/* initialize a record instance */
static long PIC862_init_record(void *arg)
{
struct motorRecord *mr = (struct motorRecord *) arg;
return(motor_init_record_com(mr, *drvtabptr->cardcnt_ptr, drvtabptr, PIC862_cards));
}
/* start building a transaction */
static long PIC862_start_trans(struct motorRecord *mr)
{
motor_start_trans_com(mr, PIC862_cards);
return(OK);
}
/* end building a transaction */
static RTN_STATUS PIC862_end_trans(struct motorRecord *mr)
{
struct motor_trans *trans = (struct motor_trans *) mr->dpvt;
struct mess_node *motor_call;
char *msgptr;
int last;
/* Remove trailing cmnd separator (",") from message. */
motor_call = &(trans->motor_call);
msgptr = motor_call->message;
last = strlen(msgptr) - 1;
if (msgptr[last] == ',')
msgptr[last] = (char) NULL;
motor_end_trans_com(mr, drvtabptr);
return(OK);
}
/* add a part to the transaction */
static RTN_STATUS PIC862_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;
char buff[110];
int card;
unsigned int size;
double dval;
int cntrl_units;
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;
motor_call = &(trans->motor_call);
card = motor_call->card;
brdptr = (*trans->tabptr->card_array)[card];
if (brdptr == NULL)
return(rtnval = ERROR);
cntrl_units = (int) dval;
if (PIC862_table[command] > motor_call->type)
motor_call->type = PIC862_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%d,", cntrl_units);
break;
case MOVE_REL:
sprintf(buff, "MR%d,", cntrl_units);
break;
case HOME_FOR:
sprintf(buff, "FE0");
break;
case HOME_REV:
sprintf(buff, "FE1");
break;
case LOAD_POS:
if (cntrl_units == 0.0)
sprintf(buff, "DH");
else
rtnval = ERROR;
break;
case SET_VEL_BASE:
send = false; /* DC motor; not base velocity. */
break;
case JOG_VELOCITY:
case SET_VELOCITY:
sprintf(buff, "SV%d,", cntrl_units);
break;
case SET_ACCEL:
sprintf(buff, "SA%d,", cntrl_units);
break;
case ENABLE_TORQUE:
sprintf(buff, "MN");
break;
case DISABL_TORQUE:
sprintf(buff, "MF");
break;
case GO:
/* The PIC862 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:
sprintf(buff, "ST");
break;
case JOG:
/*
* C-862 does not have a jog command. Simulate with move absolute
* to the appropriate software limit.
*/
sprintf(buff, "SV%d,", abs(cntrl_units));
strcat(motor_call->message, buff);
if (dval > 0.)
sprintf(buff, "MA%d,", (int) (mr->dhlm / mr->mres));
else
sprintf(buff, "MA%d,", (int) (mr->dllm / mr->mres));
break;
case SET_PGAIN:
cntrl_units = (int) (32767 * dval);
sprintf(buff, "DP%d", cntrl_units);
break;
case SET_IGAIN:
cntrl_units = (int) (32767 * dval);
sprintf(buff, "DI%d", cntrl_units);
break;
case SET_DGAIN:
cntrl_units = (int) (32767 * dval);
sprintf(buff, "DD%d", cntrl_units);
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("PIC862_build_trans(): buffer overflow.\n");
else
{
strcat(motor_call->message, buff);
}
return(rtnval);
}
-312
View File
@@ -1,312 +0,0 @@
/*
FILENAME... devPIE516.cc
USAGE... Motor record device level support for Physik Instrumente (PI)
GmbH & Co. E-516 motor controller.
*/
/*
* 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 01/29/06 jps - copied from devPIE710.cc
*/
#include <string.h>
#include <errlog.h>
#include "motorRecord.h"
#include "motor.h"
#include "motordevCom.h"
#include "drvPIE516.h"
#include "epicsExport.h"
extern struct driver_table PIE516_access;
/* ----------------Create the dsets for devPIE516----------------- */
static struct driver_table *drvtabptr;
static long PIE516_init(int);
static long PIE516_init_record(void *);
static long PIE516_start_trans(struct motorRecord *);
static RTN_STATUS PIE516_build_trans(motor_cmnd, double *, struct motorRecord *);
static RTN_STATUS PIE516_end_trans(struct motorRecord *);
struct motor_dset devPIE516 =
{
{8, NULL, (DEVSUPFUN) PIE516_init, (DEVSUPFUN) PIE516_init_record, NULL},
motor_update_values,
PIE516_start_trans,
PIE516_build_trans,
PIE516_end_trans
};
extern "C" {epicsExportAddress(dset,devPIE516);}
/* --------------------------- program data --------------------- */
/* This table is used to define the command types */
/* WARNING! this must match "motor_cmnd" in motor.h */
static msg_types PIE516_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 **PIE516_cards;
/* --------------------------- program data --------------------- */
/* initialize device support for PIE516 stepper motor */
static long PIE516_init(int after)
{
long rtnval;
if (!after)
{
drvtabptr = &PIE516_access;
(drvtabptr->init)();
}
rtnval = motor_init_com(after, *drvtabptr->cardcnt_ptr, drvtabptr, &PIE516_cards);
return(rtnval);
}
/* initialize a record instance */
static long PIE516_init_record(void *arg)
{
struct motorRecord *mr = (struct motorRecord *) arg;
/* Disable change of direction testing in record support */
/* This is a closed-loop device */
mr->ntm = menuYesNoNO;
return(motor_init_record_com(mr, *drvtabptr->cardcnt_ptr, drvtabptr, PIE516_cards));
}
/* start building a transaction */
static long PIE516_start_trans(struct motorRecord *mr)
{
motor_start_trans_com(mr, PIE516_cards);
return(OK);
}
/* end building a transaction */
static RTN_STATUS PIE516_end_trans(struct motorRecord *mr)
{
motor_end_trans_com(mr, drvtabptr);
return(OK);
}
/* add a part to the transaction */
static RTN_STATUS PIE516_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 PIE516controller *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, PIE516_cards);
motor_call = &(trans->motor_call);
card = motor_call->card;
brdptr = (*trans->tabptr->card_array)[card];
if (brdptr == NULL)
return(rtnval = ERROR);
cntrl = (struct PIE516controller *) brdptr->DevicePrivate;
res = cntrl->drive_resolution[motor_call->signal];
cntrl_units = dval;
maxdigits = 3;
if (PIE516_table[command] > motor_call->type)
motor_call->type = PIE516_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, EOL_E516);
}
if (strlen(mr->post) != 0)
motor_call->postmsgptr = (char *) &mr->post;
break;
default:
break;
}
switch (command)
{
case MOVE_ABS:
sprintf(buff, "MOV #%.*f", maxdigits, (cntrl_units * res));
strcat(buff, EOL_E516);
break;
case MOVE_REL:
sprintf(buff, "MVR #%.*f", maxdigits, (cntrl_units * res));
strcat(buff, EOL_E516);
break;
case HOME_FOR:
case HOME_REV:
rtnval = ERROR;
break;
case LOAD_POS:
rtnval = ERROR;
break;
case SET_VEL_BASE:
send = false; /* DC motor; not base velocity. */
break;
case SET_VELOCITY:
sprintf(buff, "VEL #%.*f", maxdigits, (cntrl_units * res));
strcat(buff, EOL_E516);
break;
case ENABLE_TORQUE:
strcpy(buff, "SVO #1");
strcat(buff, EOL_E516);
break;
case DISABL_TORQUE:
strcpy(buff, "SVO #0");
strcat(buff, EOL_E516);
break;
case SET_ACCEL:
/* The PIE516 does not support acceleration commands. */
case GO:
/* The PIE516 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, "STP #");
strcat(buff, EOL_E516);
break;
case JOG_VELOCITY:
case JOG:
sprintf(buff, "VEL #%.*f", maxdigits, cntrl_units);
strcat(buff, EOL_E516);
break;
case SET_PGAIN:
send = false;
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("PIE516_build_trans(): buffer overflow.\n");
else
{
strcat(motor_call->message, buff);
rtnval = motor_end_trans_com(mr, drvtabptr);
}
return(rtnval);
}
-317
View File
@@ -1,317 +0,0 @@
/*
FILENAME... devPIE517.cc
USAGE... Motor record device level support for Physik Instrumente (PI)
GmbH & Co. E-516 motor controller.
Version: $Revision: 1.2 $
Modified By: $Author: sluiter $
Last Modified: $Date: 2008-03-14 20:21:37 $
*/
/*
* 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 08/10/16 Bruno Luvizotto (brunoluvizotto@gmail.com) - copied from devPIE516.cc
* .02 08/10/16 Bruno Luvizotto (brunoluvizotto@gmail.com) - edited the files for the E517 controller
*/
#include <string.h>
#include <stdlib.h>
#include <errlog.h>
#include "motorRecord.h"
#include "motor.h"
#include "motordevCom.h"
#include "drvPIE517.h"
#include "epicsExport.h"
extern struct driver_table PIE517_access;
/* ----------------Create the dsets for devPIE517----------------- */
static struct driver_table *drvtabptr;
static long PIE517_init(int);
static long PIE517_init_record(void *);
static long PIE517_start_trans(struct motorRecord *);
static RTN_STATUS PIE517_build_trans(motor_cmnd, double *, struct motorRecord *);
static RTN_STATUS PIE517_end_trans(struct motorRecord *);
struct motor_dset devPIE517 =
{
{8, NULL, (DEVSUPFUN) PIE517_init, (DEVSUPFUN) PIE517_init_record, NULL},
motor_update_values,
PIE517_start_trans,
PIE517_build_trans,
PIE517_end_trans
};
extern "C" {epicsExportAddress(dset,devPIE517);}
/* --------------------------- program data --------------------- */
/* This table is used to define the command types */
/* WARNING! this must match "motor_cmnd" in motor.h */
static msg_types PIE517_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 **PIE517_cards;
/* --------------------------- program data --------------------- */
/* initialize device support for PIE517 stepper motor */
static long PIE517_init(int after)
{
long rtnval;
if (!after)
{
drvtabptr = &PIE517_access;
(drvtabptr->init)();
}
rtnval = motor_init_com(after, *drvtabptr->cardcnt_ptr, drvtabptr, &PIE517_cards);
return(rtnval);
}
/* initialize a record instance */
static long PIE517_init_record(void *arg)
{
struct motorRecord *mr = (struct motorRecord *) arg;
/* Disable change of direction testing in record support */
/* This is a closed-loop device */
mr->ntm = menuYesNoNO;
return(motor_init_record_com(mr, *drvtabptr->cardcnt_ptr, drvtabptr, PIE517_cards));
}
/* start building a transaction */
static long PIE517_start_trans(struct motorRecord *mr)
{
motor_start_trans_com(mr, PIE517_cards);
return(OK);
}
/* end building a transaction */
static RTN_STATUS PIE517_end_trans(struct motorRecord *mr)
{
motor_end_trans_com(mr, drvtabptr);
return(OK);
}
/* add a part to the transaction */
static RTN_STATUS PIE517_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 PIE517controller *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, PIE517_cards);
motor_call = &(trans->motor_call);
card = motor_call->card;
brdptr = (*trans->tabptr->card_array)[card];
if (brdptr == NULL)
return(rtnval = ERROR);
cntrl = (struct PIE517controller *) brdptr->DevicePrivate;
res = cntrl->drive_resolution[motor_call->signal];
cntrl_units = dval;
maxdigits = 3;
if (PIE517_table[command] > motor_call->type)
motor_call->type = PIE517_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, EOL_E517);
}
if (strlen(mr->post) != 0)
motor_call->postmsgptr = (char *) &mr->post;
break;
default:
break;
}
switch (command)
{
case MOVE_ABS:
sprintf(buff, "MOV # %.*f", maxdigits, (cntrl_units * res));
strcat(buff, EOL_E517);
break;
case MOVE_REL:
sprintf(buff, "MVR # %.*f", maxdigits, (cntrl_units * res));
strcat(buff, EOL_E517);
break;
case HOME_FOR:
case HOME_REV:
rtnval = ERROR;
break;
case LOAD_POS:
rtnval = ERROR;
break;
case SET_VEL_BASE:
send = false; /* DC motor; not base velocity. */
break;
case SET_VELOCITY:
sprintf(buff, "VEL # %.*f", maxdigits, (cntrl_units * res));
strcat(buff, EOL_E517);
break;
case ENABLE_TORQUE:
strcpy(buff, "SVO #1");
strcat(buff, EOL_E517);
break;
case DISABL_TORQUE:
strcpy(buff, "SVO #0");
strcat(buff, EOL_E517);
break;
case SET_ACCEL:
/* The PIE517 does not support acceleration commands. */
case GO:
/* The PIE517 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, "STP #");
strcat(buff, EOL_E517);
break;
case JOG_VELOCITY:
case JOG:
sprintf(buff, "VEL # %.*f", maxdigits, cntrl_units);
strcat(buff, EOL_E517);
break;
case SET_PGAIN:
send = false;
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("PIE517_build_trans(): buffer overflow.\n");
else
{
strcat(motor_call->message, buff);
rtnval = motor_end_trans_com(mr, drvtabptr);
}
return(rtnval);
}
-307
View File
@@ -1,307 +0,0 @@
/*
FILENAME... devPIE710.cc
USAGE... Motor record device level support for Physik Instrumente (PI)
GmbH & Co. E-710 motor controller.
*/
/*
* 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 <errlog.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(int);
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(int after)
{
long rtnval;
if (!after)
{
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;
/* Disable change of direction testing in record support */
/* This is a closed-loop device */
mr->ntm = menuYesNoNO;
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);
}
-315
View File
@@ -1,315 +0,0 @@
/*
FILENAME... devPIE816.cc
USAGE... Motor record device level support for Physik Instrumente (PI)
GmbH & Co. E-816 motor controller.
Version: 1.1
Modified By: sullivan
Last Modified: 2007/03/30 20:01:05
*/
/*
* 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 01/29/06 jps - copied from devPIE710.cc
*/
#include <string.h>
#include <errlog.h>
#include "motorRecord.h"
#include "motor.h"
#include "motordevCom.h"
#include "drvPIE816.h"
#include "epicsExport.h"
extern struct driver_table PIE816_access;
/* ----------------Create the dsets for devPIE816----------------- */
static struct driver_table *drvtabptr;
static long PIE816_init(int);
static long PIE816_init_record(void *);
static long PIE816_start_trans(struct motorRecord *);
static RTN_STATUS PIE816_build_trans(motor_cmnd, double *, struct motorRecord *);
static RTN_STATUS PIE816_end_trans(struct motorRecord *);
struct motor_dset devPIE816 =
{
{8, NULL, (DEVSUPFUN) PIE816_init, (DEVSUPFUN) PIE816_init_record, NULL},
motor_update_values,
PIE816_start_trans,
PIE816_build_trans,
PIE816_end_trans
};
extern "C" {epicsExportAddress(dset,devPIE816);}
/* --------------------------- program data --------------------- */
/* This table is used to define the command types */
/* WARNING! this must match "motor_cmnd" in motor.h */
static msg_types PIE816_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 **PIE816_cards;
/* --------------------------- program data --------------------- */
/* initialize device support for PIE816 stepper motor */
static long PIE816_init(int after)
{
long rtnval;
if (!after)
{
drvtabptr = &PIE816_access;
(drvtabptr->init)();
}
rtnval = motor_init_com(after, *drvtabptr->cardcnt_ptr, drvtabptr, &PIE816_cards);
return(rtnval);
}
/* initialize a record instance */
static long PIE816_init_record(void *arg)
{
struct motorRecord *mr = (struct motorRecord *) arg;
/* Disable change of direction testing in record support */
/* This is a closed-loop device */
mr->ntm = menuYesNoNO;
return(motor_init_record_com(mr, *drvtabptr->cardcnt_ptr, drvtabptr, PIE816_cards));
}
/* start building a transaction */
static long PIE816_start_trans(struct motorRecord *mr)
{
motor_start_trans_com(mr, PIE816_cards);
return(OK);
}
/* end building a transaction */
static RTN_STATUS PIE816_end_trans(struct motorRecord *mr)
{
motor_end_trans_com(mr, drvtabptr);
return(OK);
}
/* add a part to the transaction */
static RTN_STATUS PIE816_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 PIE816controller *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, PIE816_cards);
motor_call = &(trans->motor_call);
card = motor_call->card;
brdptr = (*trans->tabptr->card_array)[card];
if (brdptr == NULL)
return(rtnval = ERROR);
cntrl = (struct PIE816controller *) brdptr->DevicePrivate;
res = cntrl->drive_resolution[motor_call->signal];
cntrl_units = dval;
maxdigits = 3;
if (PIE816_table[command] > motor_call->type)
motor_call->type = PIE816_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, EOL_E816);
}
if (strlen(mr->post) != 0)
motor_call->postmsgptr = (char *) &mr->post;
break;
default:
break;
}
switch (command)
{
case MOVE_ABS:
sprintf(buff, "MOV #%.*f", maxdigits, (cntrl_units * res));
strcat(buff, EOL_E816);
break;
case MOVE_REL:
sprintf(buff, "MVR #%.*f", maxdigits, (cntrl_units * res));
strcat(buff, EOL_E816);
break;
case HOME_FOR:
case HOME_REV:
rtnval = ERROR;
break;
case LOAD_POS:
rtnval = ERROR;
break;
case SET_VEL_BASE:
send = false; /* DC motor; not base velocity. */
break;
case SET_VELOCITY:
sprintf(buff, "VEL #%.*f", maxdigits, (cntrl_units * res));
strcat(buff, EOL_E816);
break;
case ENABLE_TORQUE:
strcpy(buff, "SVO #1");
strcat(buff, EOL_E816);
break;
case DISABL_TORQUE:
strcpy(buff, "SVO #0");
strcat(buff, EOL_E816);
break;
case SET_ACCEL:
/* The PIE816 does not support acceleration commands. */
case GO:
/* The PIE816 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, "MVR #0");
strcat(buff, EOL_E816);
break;
case JOG_VELOCITY:
case JOG:
sprintf(buff, "VEL #%.*f", maxdigits, cntrl_units);
strcat(buff, EOL_E816);
break;
case SET_PGAIN:
send = false;
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("PIE816_build_trans(): buffer overflow.\n");
else
{
strcat(motor_call->message, buff);
rtnval = motor_end_trans_com(mr, drvtabptr);
}
return(rtnval);
}
-60
View File
@@ -1,60 +0,0 @@
# Physik Instrumente (PI) GmbH & Co. C-844 driver support.
device(motor,VME_IO,devPIC844,"PIC844")
driver(drvPIC844)
registrar(PImotorRegister)
variable(drvPIC844debug)
# PI C630 support.
device(motor,VME_IO,devPIC630,"PI C630")
driver(drvPIC630)
registrar(PIC630Register)
variable(drvPIC630debug)
# Physik Instrumente (PI) GmbH & Co. C-848 driver support.
device(motor,VME_IO,devPIC848,"PIC848")
driver(drvPIC848)
registrar(PIC848motorRegister)
variable(drvPIC848debug)
# Physik Instrumente (PI) GmbH & Co. E-662 driver support.
device(motor,VME_IO,devPIC662,"PIC662")
driver(drvPIC662)
registrar(PIC662motorRegister)
variable(drvPIC662debug)
# Physik Instrumente (PI) GmbH & Co. C-862 driver support.
device(motor,VME_IO,devPIC862,"PIC862")
driver(drvPIC862)
registrar(PIC862motorRegister)
variable(drvPIC862debug)
# Physik Instrumente (PI) GmbH & Co. C-663 driver support.
device(motor,VME_IO,devPIC663,"PIC663")
driver(drvPIC663)
registrar(PIC663motorRegister)
variable(drvPIC663debug)
# Physik Instrumente (PI) GmbH & Co. E-710 driver support.
device(motor,VME_IO,devPIE710,"PIE710")
driver(drvPIE710)
registrar(PIE710motorRegister)
variable(drvPIE710debug)
# Physik Instrumente (PI) GmbH & Co. E-516 driver support.
device(motor,VME_IO,devPIE516,"PIE516")
driver(drvPIE516)
registrar(PIE516motorRegister)
variable(drvPIE516debug)
# Physik Instrumente (PI) GmbH & Co. E-517 driver support.
device(motor,VME_IO,devPIE517,"PIE517")
driver(drvPIE517)
registrar(PIE517motorRegister)
variable(drvPIE517debug)
# Physik Instrumente (PI) GmbH & Co. E-816 driver support.
device(motor,VME_IO,devPIE816,"PIE816")
driver(drvPIE816)
registrar(PIE816motorRegister)
variable(drvPIE816debug)
-110
View File
@@ -1,110 +0,0 @@
/*
FILENAME... drvPI.h
USAGE... This file contains driver "include" information that is specific to
Physik Instrumente (PI) GmbH & Co. motor controller driver support.
*/
/*
* Original Author: Ron Sluiter
* Date: 12/17/03
*
* Experimental Physics and Industrial Control System (EPICS)
*
* Copyright 1991, the Regents of the University of California,
* and the University of Chicago Board of Governors.
*
* This software was produced under U.S. Government contracts:
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
* and (W-31-109-ENG-38) at Argonne National Laboratory.
*
* Initial development by:
* The Controls and Automation Group (AT-8)
* Ground Test Accelerator
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Co-developed with
* The Controls and Computing Group
* Accelerator Systems Division
* Advanced Photon Source
* Argonne National Laboratory
*
*
*
* Modification Log:
* -----------------
* .01 12/17/03 rls - copied from drvIM483.h
* .02 07/12/04 rls - Converted from MPF to asyn.
*/
#ifndef INCdrvPIh
#define INCdrvPIh 1
#include "motor.h"
#include "motordrvCom.h"
#include "asynDriver.h"
#include "asynOctetSyncIO.h"
#define COMM_TIMEOUT 2 /* Timeout in seconds. */
/* PIC844 specific data is stored in this structure. */
struct PIC844controller
{
asynUser *pasynUser; /* For RS-232 */
int asyn_address; /* Use for GPIB or other address with asyn */
char asyn_port[80]; /* asyn port name */
CommStatus status; /* Controller communication status. */
};
/* Motion Condition register */
typedef union
{
unsigned short All;
struct
{
#ifdef MSB_First
unsigned int axis4ML :1; /* Axis#4 Minus Limit Switch */
unsigned int axis3ML :1; /* Axis#3 Minus Limit Switch */
unsigned int axis2ML :1; /* Axis#2 Minus Limit Switch */
unsigned int axis1ML :1; /* Axis#1 Minus Limit Switch */
unsigned int axis4PL :1; /* Axis#4 Plus Limit Switch */
unsigned int axis3PL :1; /* Axis#3 Plus Limit Switch */
unsigned int axis2PL :1; /* Axis#2 Plus Limit Switch */
unsigned int axis1PL :1; /* Axis#1 Plus Limit Switch */
unsigned int axis4ME :1; /* Axis#4 Motion-Error */
unsigned int axis3ME :1; /* Axis#3 Motion-Error */
unsigned int axis2ME :1; /* Axis#2 Motion-Error */
unsigned int axis1ME :1; /* Axis#1 Motion-Error */
unsigned int axis4IM :1; /* Axis#4 in motion */
unsigned int axis3IM :1; /* Axis#3 in motion */
unsigned int axis2IM :1; /* Axis#2 in motion */
unsigned int axis1IM :1; /* Axis#1 in motion */
#else
unsigned int axis1IM :1; /* Axis#1 in motion */
unsigned int axis2IM :1; /* Axis#2 in motion */
unsigned int axis3IM :1; /* Axis#3 in motion */
unsigned int axis4IM :1; /* Axis#4 in motion */
unsigned int axis1ME :1; /* Axis#1 Motion-Error */
unsigned int axis2ME :1; /* Axis#2 Motion-Error */
unsigned int axis3ME :1; /* Axis#3 Motion-Error */
unsigned int axis4ME :1; /* Axis#4 Motion-Error */
unsigned int axis1PL :1; /* Axis#1 Plus Limit Switch */
unsigned int axis2PL :1; /* Axis#2 Plus Limit Switch */
unsigned int axis3PL :1; /* Axis#3 Plus Limit Switch */
unsigned int axis4PL :1; /* Axis#4 Plus Limit Switch */
unsigned int axis1ML :1; /* Axis#1 Minus Limit Switch */
unsigned int axis2ML :1; /* Axis#2 Minus Limit Switch */
unsigned int axis3ML :1; /* Axis#3 Minus Limit Switch */
unsigned int axis4ML :1; /* Axis#4 Minus Limit Switch */
#endif
} Bits;
} C844_Cond_Reg;
/* Function prototypes. */
extern RTN_STATUS PIC844Setup(int, int);
extern RTN_STATUS PIC844Config(int, const char *, int);
#endif /* INCdrvPIh */
-574
View File
@@ -1,574 +0,0 @@
/* File: drvPIC630.cc */
/* Device Driver Support routines for motor */
/*
* Original Author: Kurt Goetze
* Date: 02-07-2005
*
* Modification Log:
* -----------------
* .00 02-07-2005 kag initialized from drvMicos.c
*/
/* The PI C-630 controller is a 3-axis controller/driver. Up to 3 controllers
* can be daisy-chained on one serial port (in this code this is considered a "card").
* More than 1 "card" can be configured, but each will need its own serial port.
* This means that up to 9 axes are controllable per serial port, addressed 1-9.
* Each axis has a current setting, which is handled by PIC630_config and motor_init.
*
* The Controllers MUST BE ON at bootup or this code will error out.
*/
#include <string.h>
#include <epicsThread.h>
#include <drvSup.h>
#include <stdlib.h>
#include <errlog.h>
#include "motor.h"
#include "drvPIC630.h"
#include "asynOctetSyncIO.h"
#include "epicsExport.h"
#define WAIT 1
#define BUFF_SIZE 100 /* Maximum length of string to/from PIC630 */
/*----------------debugging-----------------*/
volatile int drvPIC630debug = 0;
extern "C" {epicsExportAddress(int, drvPIC630debug);}
static inline void Debug(int level, const char *format, ...) {
#ifdef DEBUG
if (level < drvPIC630debug) {
va_list pVar;
va_start(pVar, format);
vprintf(format, pVar);
va_end(pVar);
}
#endif
}
/* Debugging notes:
* drvPIC630debug == 0 No debugging information is printed
* drvPIC630debug >= 1 Warning information is printed
* drvPIC630debug >= 2 Time-stamped messages are printed for each string
* sent to and received from the controller
* drvPIC630debug >= 3 Additional debugging messages
*/
volatile int PIC630_num_cards = 0;
volatile int PIC630_num_axis = 0;
volatile int PIC630_current[9]; /* current settings per axis */
/* 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 void start_status(int);
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 PIC630_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,
start_status,
&initialized,
NULL
};
struct
{
long number;
long (*report) (int);
long (*init) (void);
} drvPIC630 = {2, report, init};
extern "C" {epicsExportAddress(drvet, drvPIC630);}
static struct thread_args targs = {SCAN_RATE, &PIC630_access};
/*********************************************************
* Print out driver status report
*********************************************************/
static long report(int level)
{
int card;
if (PIC630_num_cards <=0)
printf(" No PIC630 controllers configured.\n");
else
{
for (card = 0; card < PIC630_num_cards; card++)
{
struct controller *brdptr = motor_state[card];
if (brdptr == NULL)
printf(" PIC630 controller %d connection failed.\n", card);
else
{
struct PIC630Controller *cntrl;
cntrl = (struct PIC630Controller *) brdptr->DevicePrivate;
printf(" PIC630 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 (PIC630_num_cards <= 0)
{
Debug(1, "init(): PIC630 driver disabled. PIC630Setup() missing from startup script.\n");
}
return ((long) 0);
}
static void query_done(int card, int axis, struct mess_node *nodeptr)
{
}
static void start_status(int card)
{
/* The PIC630 cannot query status or positions of all axes with a
* single command. This needs to be done on an axis-by-axis basis,
* so this function does nothing
*/
}
/**************************************************************
* Query position and status for an axis
* set_status()
************************************************************/
static int set_status(int card, int signal)
{
struct PIC630Controller *cntrl;
struct mess_node *nodeptr;
register struct mess_info *motor_info;
char command[BUFF_SIZE];
char response[BUFF_SIZE];
char cStatus;
int rtn_state;
long motorData;
char buff[BUFF_SIZE];
bool plusdir, ls_active = false;
msta_field status;
cntrl = (struct PIC630Controller *) motor_state[card]->DevicePrivate;
motor_info = &(motor_state[card]->motor_info[signal]);
nodeptr = motor_info->motor_motion;
status.All = motor_info->status.All;
signal++;
/* Request the status of this motor */
sprintf(command, "%dTS", signal);
send_mess(card, command, 0);
recv_mess(card, response, WAIT);
/* The response string is of the form "nTS:N" where N is an int (0-255)
bit0 (0x01) = moving
bit1 (0x02) = reference signal flag
bit2 (0x04) = pos. limit (0 = limit tripped)
bit3 (0x08) = neg. limit (0 = limit tripped)
bit4 (0x10) = command error
bit5 (0x20) = profile error
bit6 (0x40) = not used
bit7 (0x80) = Estop (0 = Estop) */
cStatus = (char) atoi(&response[4]);
/* check to see if motor is moving */
status.Bits.RA_DONE = (cStatus & 0x01) ? 0 : 1;
/* Request the position of this motor, find out which direction we're going */
/* The response string is of the form "1TP:1000" */
sprintf(command, "%dTP", signal);
send_mess(card, command, 0);
recv_mess(card, response, WAIT);
motorData = atoi(&response[4]);
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 = motorData;
motor_info->no_motion_count = 0;
}
plusdir = (status.Bits.RA_DIRECTION) ? true : false;
/* check limits, set indicators */
if (!(cStatus & 0x04)) /* if +lim */
{
status.Bits.RA_PLUS_LS = 1;
if (plusdir == true)
ls_active = true;
}
else
status.Bits.RA_PLUS_LS = 0;
if (!(cStatus & 0x08)) /* if -lim */
{
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;
/* 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, NULL);
/* The PIC630 will send back a response for a 'set' command */
recv_mess(card, buff, WAIT);
nodeptr->postmsgptr = NULL;
}
motor_info->status.All = status.All;
return (rtn_state);
}
/*****************************************************/
/* send a message to the PIC630 board */
/* send_mess() */
/*****************************************************/
static RTN_STATUS send_mess(int card, const char *com, char *name)
{
char buff[BUFF_SIZE];
char inp_buff[BUFF_SIZE];
int status = 0;
size_t nwrite;
struct PIC630Controller *cntrl;
/* Check that card exists */
if (!motor_state[card])
{
errlogPrintf("send_mess - invalid card #%d\n", card);
return (ERROR);
}
/* If the string is NULL just return */
if (strlen(com) == 0) return(OK);
cntrl = (struct PIC630Controller *) motor_state[card]->DevicePrivate;
strcpy(buff, com);
Debug(2, "send_mess: sending message to card %d, message=%s\n", card, buff);
pasynOctetSyncIO->write(cntrl->pasynUser, buff, strlen(buff), COMM_TIMEOUT, &nwrite);
/* This thing always echos everything sent to it. Read this response. */
status = recv_mess(card, inp_buff, WAIT);
return (OK);
}
/*****************************************************/
/* Read a response string from the PIC630 board */
/* recv_mess() */
/*****************************************************/
static int recv_mess(int card, char *com, int flag)
{
double timeout;
size_t nread = 0;
int eomReason;
int flush;
struct PIC630Controller *cntrl;
asynStatus status;
/* Check that card exists */
if (!motor_state[card])
{
errlogPrintf("recv_mess - invalid card #%d\n", card);
return (-1);
}
cntrl = (struct PIC630Controller *) motor_state[card]->DevicePrivate;
Debug(3, "recv_mess entry: card %d, flag=%d\n", card, flag);
if (flag == FLUSH)
{
flush = 1;
timeout = 0.;
}
else
{
flush = 0;
timeout = COMM_TIMEOUT;
}
if (flush) status = pasynOctetSyncIO->flush(cntrl->pasynUser);
status = pasynOctetSyncIO->read(cntrl->pasynUser, com, MAX_MSG_SIZE,
timeout, &nread, &eomReason);
if (nread < 1) com[0] = '\0';
if (nread > 0) {
Debug(2, "recv_mess: card %d, message = \"%s\"\n", card, com);
}
if (nread == 0) {
if (flag != FLUSH) {
Debug(1, "recv_mess: card %d ERROR: no response\n", card);
} else {
Debug(3, "recv_mess: card %d flush returned no characters\n", card);
}
}
return (nread);
}
/*****************************************************/
/* Setup system configuration */
/* PIC630Setup() */
/*****************************************************/
RTN_STATUS
PIC630Setup(int num_cards, /* maximum number of "controllers" in system */
int num_channels, /* max number of drivers */
int scan_rate) /* polling rate - 1/60 sec units */
{
int itera;
if (num_cards < 1 || num_cards > PIC630_NUM_CARDS)
PIC630_num_cards = PIC630_NUM_CARDS;
else
PIC630_num_cards = num_cards;
if (num_channels < 1 || num_channels > PIC630_NUM_AXIS)
PIC630_num_axis = PIC630_NUM_AXIS;
else
PIC630_num_axis = num_channels;
/* 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 PIC630Config 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 since this is just
* an array of pointers.
*/
motor_state = (struct controller **) malloc(PIC630_num_cards *
sizeof(struct controller *));
for (itera = 0; itera < PIC630_num_cards; itera++)
motor_state[itera] = (struct controller *) NULL;
return (OK);
}
/*****************************************************/
/* Configure a controller */
/* PIC630Config() */
/*****************************************************/
RTN_STATUS
PIC630Config(int card, /* "controller" being configured */
const char *name, /* port name for asyn */
int cur0, int cur1, int cur2, int cur3, int cur4, /* see below */
int cur5, int cur6, int cur7, int cur8)
{
struct PIC630Controller *cntrl;
if (card < 0 || card >= PIC630_num_cards)
return (ERROR);
motor_state[card] = (struct controller *) malloc(sizeof(struct controller));
motor_state[card]->DevicePrivate = malloc(sizeof(struct PIC630Controller));
cntrl = (struct PIC630Controller *) motor_state[card]->DevicePrivate;
strcpy(cntrl->asyn_port, name);
/* This is a current setting for each axis that will be sent during motor_init.
Valid settings are: 0=OFF, 1=100mA, 2=200mA, ... 8=800mA. */
PIC630_current[0] = cur0;
PIC630_current[1] = cur1;
PIC630_current[2] = cur2;
PIC630_current[3] = cur3;
PIC630_current[4] = cur4;
PIC630_current[5] = cur5;
PIC630_current[6] = cur6;
PIC630_current[7] = cur7;
PIC630_current[8] = cur8;
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 PIC630Controller *cntrl;
int card_index, motor_index;
char cmd[BUFF_SIZE];
char buff[BUFF_SIZE];
int total_axis = 0;
int status = 0;
int i;
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 (PIC630_num_cards <= 0)
{
Debug(1, "motor_init: *PIC630 driver disabled*\n");
Debug(1, "PIC630Setup() is missing from startup script.\n");
return (ERROR);
}
for (card_index = 0; card_index < PIC630_num_cards; card_index++)
{
if (!motor_state[card_index])
continue;
brdptr = motor_state[card_index];
brdptr->ident[0] = (char) NULL; /* No controller identification message. */
/* device echos? then set to true. else false */
brdptr->cmnd_response = false;
total_cards = card_index + 1;
cntrl = (struct PIC630Controller *) brdptr->DevicePrivate;
/* 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));
/* Each "controller chain" can have max 9 axes. */
total_axis = PIC630_num_axis;
brdptr->total_axis = total_axis;
/* flush any junk at input port - should not be any data available */
pasynOctetSyncIO->flush(cntrl->pasynUser);
/* Send a message to each PIC630 motor. See if controller responds */
for (motor_index = 0; motor_index < total_axis; motor_index++)
{
do
{
sprintf(cmd, "%dTS", (motor_index + 1));
send_mess(card_index, cmd, 0);
status = recv_mess(card_index, buff, WAIT);
retry++;
/* Return value is length of response string */
} while(status == 0 && retry < 3);
if (status == 0) break;
}
}
if (success_rtn == asynSuccess && status > 0)
{
brdptr->localaddr = (char *) NULL;
brdptr->motor_in_motion = 0;
/* how did this get here? brdptr->cmnd_response = true; */
start_status(card_index);
for (motor_index = 0; motor_index < total_axis; motor_index++)
{
struct mess_info *motor_info = &brdptr->motor_info[motor_index];
brdptr->motor_info[motor_index].motor_motion = NULL;
/* Wish I could turn off echo, can't :( */
/* Set motor current */
sprintf(buff,"%dDC%d", (motor_index + 1),PIC630_current[motor_index]);
for (i=0; i<=8; i++)
Debug(1, "PIC630_current[%d] = %d\n",i,PIC630_current[i]);
send_mess(card_index, buff, 0);
/* Stop motor */
sprintf(buff,"%dAB", (motor_index + 1));
send_mess(card_index, buff, 0);
strcpy(brdptr->ident, "PIC630");
motor_info->status.All = 0;
motor_info->no_motion_count = 0;
motor_info->encoder_position = 0;
motor_info->position = 0;
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;
Debug(3, "motor_init: spawning motor task\n");
epicsThreadCreate((char *) "PIC630_motor", epicsThreadPriorityMedium,
epicsThreadGetStackSize(epicsThreadStackMedium),
(EPICSTHREADFUNC) motor_task, (void *) &targs);
return(OK);
}
-35
View File
@@ -1,35 +0,0 @@
/* File: drvPIC630.h */
/* Device Driver Support definitions for motor */
/*
* Original Author: Kurt Goetze
* Current Author: Kurt Goetze
* Date: 02/07/2005
*
* Modification Log:
* -----------------
* .00 02/07/2005 kag initialized from drvMicos.h
* .01 03/30/2005 kag port to 3.14 / asyn
*/
#ifndef INCdrvPIC630h
#define INCdrvPIC630h 1
#include "motordrvCom.h"
#include "asynDriver.h"
/* PIC630 default profile. */
#define PIC630_NUM_CARDS 8 /* Maximum number of controller chains */
#define PIC630_NUM_AXIS 9 /* Maximum number of axes per chain */
#define COMM_TIMEOUT 2 /* Timeout in seconds. */
struct PIC630Controller
{
asynUser *pasynUser; /* asynUser structure */
char asyn_port[80]; /* asyn port name */
};
#endif /* INCdrvPIC630h */
-597
View File
@@ -1,597 +0,0 @@
/*
FILENAME... drvPIC662.cc
USAGE... Motor record driver level support for Physik Instrumente (PI)
GmbH & Co. C-844 motor controller.
*/
/*
* Original Author: Joe Sullivan
* Date: 03/08/06
*
* 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 03/08/06 jps - copied from drvPIC884.cc
*/
/*
DESIGN LIMITATIONS...
1 - Like all controllers, the PIC662 must be powered-on when EPICS is first
booted up.
2 - The PIC662 cannot be power cycled while EPICS is up and running. The
consequences are permanent communication lose with the PIC662 until
EPICS is rebooted.
*/
#include <string.h>
#include <math.h>
#include <epicsThread.h>
#include <drvSup.h>
#include <stdlib.h>
#include <errlog.h>
#include "motor.h"
#include "drvPIC662.h"
#include "epicsExport.h"
#define GET_IDENT "*IDN?"
#define GET_STATUS "*ESR?" // Status Register
#define GET_POS "POS?" // Status Register
#define PIC662_NUM_CARDS 8
#define MAX_AXES 1
#define BUFF_SIZE 100 /* Maximum length of string to/from PIC662 */
/*----------------debugging-----------------*/
volatile int drvPIC662debug = 0;
extern "C" {epicsExportAddress(int, drvPIC662debug);}
static inline void Debug(int level, const char *format, ...) {
#ifdef DEBUG
if (level < drvPIC662debug) {
va_list pVar;
va_start(pVar, format);
vprintf(format, pVar);
va_end(pVar);
}
#endif
}
/* --- Local data. --- */
int PIC662_num_cards = 0;
static char *PIC662_axis[4] = {"1", "2", "3", "4"};
/* 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 PIC662_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,
PIC662_axis
};
struct
{
long number;
long (*report) (int);
long (*init) (void);
} drvPIC662 = {2, report, init};
extern "C" {epicsExportAddress(drvet, drvPIC662);}
static struct thread_args targs = {SCAN_RATE, &PIC662_access, 0.0};
/*********************************************************
* Print out driver status report
*********************************************************/
static long report(int level)
{
int card;
if (PIC662_num_cards <=0)
printf(" No PIC662 controllers configured.\n");
else
{
for (card = 0; card < PIC662_num_cards; card++)
{
struct controller *brdptr = motor_state[card];
if (brdptr == NULL)
printf(" PIC662 controller %d connection failed.\n", card);
else
{
struct PIC662controller *cntrl;
cntrl = (struct PIC662controller *) brdptr->DevicePrivate;
printf(" PIC662 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 (PIC662_num_cards <= 0)
{
Debug(1, "init(): PIC662 driver disabled. PIC662Setup() 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 PIC662controller *cntrl;
struct mess_node *nodeptr;
register struct mess_info *motor_info;
/* Message parsing variables */
char buff[BUFF_SIZE];
E662_ESR_REG mstat;
int rtn_state;
int comm_status;
long motorData;
bool plusdir, ls_active = false, plusLS, minusLS;
bool eventflgs;
msta_field status;
cntrl = (struct PIC662controller *) motor_state[card]->DevicePrivate;
motor_info = &(motor_state[card]->motor_info[signal]);
nodeptr = motor_info->motor_motion;
status.All = motor_info->status.All;
send_mess(card, GET_STATUS, (char*) NULL);
comm_status = recv_mess(card, buff, 1);
if (comm_status == 0)
{
if (cntrl->status == NORMAL)
{
cntrl->status = RETRY;
rtn_state = 0;
}
else
{
cntrl->status = COMM_ERR;
status.Bits.CNTRL_COMM_ERR = 1;
status.Bits.RA_PROBLEM = 1;
rtn_state = 1;
}
goto exit;
}
cntrl->status = NORMAL;
status.Bits.CNTRL_COMM_ERR = 0;
status.Bits.EA_POSITION = 0;
mstat.All = atoi(&buff[0]);
eventflgs = (mstat.Bits.OpComplete ||
mstat.Bits.DevError ||
mstat.Bits.ExeError) ? true : false;
status.Bits.RA_DONE = (eventflgs || cntrl->stop_status)? 1 : 0;
cntrl->stop_status = false;
/*
* Parse motor position
* Position string format: 1TP5.012,2TP1.123,3TP-100.567,...
* Skip to substring for this motor, convert to double
*/
send_mess(card, GET_POS, (char*) NULL);
recv_mess(card, buff, 1);
motorData = NINT (atof(buff) / cntrl->drive_resolution);
if (motorData == motor_info->position)
{
if (nodeptr != 0) /* Increment counter only if motor is moving. */
if (motor_info->no_motion_count++ > 1)
status.Bits.RA_DONE = 1; // No done indicator - stop when at position
}
else
{
status.Bits.RA_DIRECTION = (motorData >= motor_info->position) ? 1 : 0;
motor_info->position = motorData;
motor_info->no_motion_count = 0;
}
// motor_info->encoder_position = (epicsInt32) motorData;
status.Bits.RA_PROBLEM = 0;
plusdir = (status.Bits.RA_DIRECTION) ? true : false;
// No hardware limit switch feedback
plusLS = false;
minusLS = 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;
/* 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 PIC662 board */
/* send_mess() */
/*****************************************************/
static RTN_STATUS send_mess(int card, char const *com, char *name)
{
char local_buff[MAX_MSG_SIZE];
struct PIC662controller *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("drvPIC662.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("drvPIC662.cc:send_mess() - invalid card #%d\n", card);
return(ERROR);
}
local_buff[0] = (char) NULL; /* Terminate local buffer. */
/* Make a local copy of the string. */
strcat(local_buff, com);
Debug(2, "send_mess(): message = %s\n", local_buff);
cntrl = (struct PIC662controller *) motor_state[card]->DevicePrivate;
pasynOctetSyncIO->write(cntrl->pasynUser, local_buff, strlen(local_buff),
COMM_TIMEOUT, &nwrite);
return(OK);
}
/*****************************************************/
/* receive a message from the PIC662 board */
/* recv_mess() */
/*****************************************************/
static int recv_mess(int card, char *com, int flag)
{
struct PIC662controller *cntrl;
size_t nread = 0;
asynStatus status = asynError;
int eomReason;
/* Check that card exists */
if (!motor_state[card])
return(ERROR);
cntrl = (struct PIC662controller *) 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 */
/* PIC662Setup() */
/*****************************************************/
RTN_STATUS
PIC662Setup(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 > PIC662_NUM_CARDS)
PIC662_num_cards = PIC662_NUM_CARDS;
else
PIC662_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 PIC662Config 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(PIC662_num_cards *
sizeof(struct controller *));
for (itera = 0; itera < PIC662_num_cards; itera++)
motor_state[itera] = (struct controller *) NULL;
return(OK);
}
/*****************************************************/
/* Configure a controller */
/* PIC662Config() */
/*****************************************************/
RTN_STATUS
PIC662Config(int card, /* card being configured */
const char *name) /* asyn port name */
{
struct PIC662controller *cntrl;
if (card < 0 || card >= PIC662_num_cards)
return (ERROR);
motor_state[card] = (struct controller *) malloc(sizeof(struct controller));
motor_state[card]->DevicePrivate = malloc(sizeof(struct PIC662controller));
cntrl = (struct PIC662controller *) motor_state[card]->DevicePrivate;
strcpy(cntrl->asyn_port, name);
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 PIC662controller *cntrl;
int card_index;
char buff[BUFF_SIZE];
int status;
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 (PIC662_num_cards <= 0)
return(ERROR);
for (card_index = 0; card_index < PIC662_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 PIC662controller *) brdptr->DevicePrivate;
/* Initialize communications channel */
success_rtn = pasynOctetSyncIO->connect(cntrl->asyn_port, 0,
&cntrl->pasynUser, NULL);
status = 0;
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, 1);
retry++;
} while (status == 0 && retry < 3);
}
if (success_rtn == asynSuccess && status > 0)
{
strcpy(brdptr->ident, &buff[0]);
brdptr->localaddr = (char *) NULL;
brdptr->motor_in_motion = 0;
brdptr->total_axis = 1; /* Single axis controller */
/* Fixed resolution */
cntrl->res_decpts = 3;
cntrl->drive_resolution = 1.0/pow(10.0,cntrl->res_decpts);
/* Set Controller to REMOTE mode */
send_mess(card_index, REMOTE_MODE, (char*) NULL);
{
struct mess_info *motor_info = &brdptr->motor_info[0];
motor_info->status.All = 0;
motor_info->no_motion_count = 0;
motor_info->encoder_position = 0;
motor_info->position = 0;
brdptr->motor_info[0].motor_motion = NULL;
/* PIC662 has DC motor support only */
motor_info->encoder_present = NO;
motor_info->status.Bits.EA_PRESENT = 0;
motor_info->pid_present = NO;
motor_info->status.Bits.GAIN_SUPPORT = 0;
set_status(card_index, 0); /* 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 *) "PIC662_motor", epicsThreadPriorityMedium,
epicsThreadGetStackSize(epicsThreadStackMedium),
(EPICSTHREADFUNC) motor_task, (void *) &targs);
return(OK);
}
-105
View File
@@ -1,105 +0,0 @@
/*
FILENAME... drvPIC662.h
USAGE... This file contains driver "include" information that is specific to
Physik Instrumente (PI) GmbH & Co. motor controller driver support.
*/
/*
* Original Author: Joe Sullivan
* Date: 12/17/03
*
* Experimental Physics and Industrial Control System (EPICS)
*
* Copyright 1991, the Regents of the University of California,
* and the University of Chicago Board of Governors.
*
* This software was produced under U.S. Government contracts:
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
* and (W-31-109-ENG-38) at Argonne National Laboratory.
*
* Initial development by:
* The Controls and Automation Group (AT-8)
* Ground Test Accelerator
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Co-developed with
* The Controls and Computing Group
* Accelerator Systems Division
* Advanced Photon Source
* Argonne National Laboratory
*
*
*
* Modification Log:
* -----------------
* .01 03/08/06 jps - copied from drvPI.h
*/
#ifndef INCdrvPIh
#define INCdrvPIh 1
#include "motor.h"
#include "motordrvCom.h"
#include "asynDriver.h"
#include "asynOctetSyncIO.h"
#define COMM_TIMEOUT 2 /* Timeout in seconds. */
// E662 Command: switch to remote control mode
// This is done before each positioning move because
// the controller defaults to 'Local' mode on power up.
// Status can be read while in 'Local' mode.
#define REMOTE_MODE "DEV:CONT REM"
/* PIC662 specific data is stored in this structure. */
struct PIC662controller
{
asynUser *pasynUser; /* For RS-232 */
int asyn_address; /* Use for GPIB or other address with asyn */
char asyn_port[80]; /* asyn port name */
CommStatus status; /* Controller communication status. */
bool stop_status; /* Signal to set_status() - stop polling */
double drive_resolution;
int res_decpts; /* Max decimal points */
};
/* Standard Event Status register */
typedef union
{
epicsUInt8 All;
struct
{
#ifdef MSB_First
unsigned int PowerOn :1; // (Bit 7) Power On
unsigned int UserReq :1; // User Request
unsigned int CmdError :1; // Command Error
unsigned int ExeError :1; // Execution Error
unsigned int DevError :1; // Device Dependant Error
unsigned int QueryError :1; // Query Error
unsigned int ReqControl :1; // Request Control
unsigned int OpComplete :1; // (Bit 0) Operation Complete
#else
unsigned int OpComplete :1; // (Bit 0) Operation Complete
unsigned int ReqControl :1; // Request Control
unsigned int QueryError :1; // Query Error
unsigned int DevError :1; // Device Dependant Error
unsigned int ExeError :1; // Execution Error
unsigned int CmdError :1; // Command Error
unsigned int UserReq :1; // User Request
unsigned int PowerOn :1; // (Bit 7) Power On
#endif
} Bits;
} E662_ESR_REG;
/* Function prototypes. */
extern RTN_STATUS PIC662Setup(int, int);
extern RTN_STATUS PIC662Config(int, const char *);
#endif /* INCdrvPIh */
-574
View File
@@ -1,574 +0,0 @@
/*
FILENAME... drvPIC663.cc
USAGE... Motor record driver level support for Physik Instrumente (PI)
GmbH & Co. C-663 motor controller.
*/
/*
* Copied from devPIC862.cc by Jonathan Thompson, Jan 2011
*
* Modification Log:
* -----------------
* Jan 2011 - All references to 862 changed to 663
* - Handling of status request results changed to cope with 663 output
*/
/*
DESIGN LIMITATIONS...
1 - Like all controllers, the PIC663 must be powered-on when EPICS is first
booted up.
*/
#include <string.h>
#include <epicsThread.h>
#include <drvSup.h>
#include <stdlib.h>
#include <errlog.h>
#include "motorRecord.h"
#include "motor.h"
#include "drvPIC663.h"
#include "epicsExport.h"
#define GET_IDENT 0x01
#define PIC663_NUM_CARDS 8
#define MAX_AXES 1
#define BUFF_SIZE 100 /* Maximum length of string to/from PIC663 */
/*----------------debugging-----------------*/
volatile int drvPIC663debug = 0;
extern "C" {epicsExportAddress(int, drvPIC663debug);}
static inline void Debug(int level, const char *format, ...) {
#ifdef DEBUG
if (level < drvPIC663debug) {
va_list pVar;
va_start(pVar, format);
vprintf(format, pVar);
va_end(pVar);
}
#endif
}
/* --- Local data. --- */
int PIC663_num_cards = 0;
/* 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 PIC663_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,
NULL
};
struct
{
long number;
long (*report) (int);
long (*init) (void);
} drvPIC663 = {2, report, init};
extern "C" {epicsExportAddress(drvet, drvPIC663);}
static struct thread_args targs = {SCAN_RATE, &PIC663_access, 0.017};
/*********************************************************
* Print out driver status report
*********************************************************/
static long report(int level)
{
int card;
if (PIC663_num_cards <=0)
printf(" No PIC663 controllers configured.\n");
else
{
for (card = 0; card < PIC663_num_cards; card++)
{
struct controller *brdptr = motor_state[card];
if (brdptr == NULL)
printf(" PIC663 controller %d connection failed.\n", card);
else
{
struct PIC663controller *cntrl;
cntrl = (struct PIC663controller *) brdptr->DevicePrivate;
printf(" PIC663 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 (PIC663_num_cards <= 0)
{
Debug(1, "init(): PIC663 driver disabled. PIC663Setup() 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 PIC663controller *cntrl;
struct mess_node *nodeptr;
struct mess_info *motor_info;
struct motorRecord *mr;
/* Message parsing variables */
char buff[BUFF_SIZE];
C663_Status_Reg1 mstat1;
C663_Status_Reg2 mstat2;
C663_Status_Reg3 mstat3;
epicsUInt16 dev_sts1, dev_sts2, dev_sts3;
int rtn_state, convert_cnt, charcnt;
epicsInt32 motorData;
bool plusdir, ls_active = false, plusLS, minusLS, LSactiveH;
msta_field status;
cntrl = (struct PIC663controller *) 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, "TS", (char*) NULL); /* Tell Status */
charcnt = recv_mess(card, buff, 1);
if (charcnt > 9)
convert_cnt = sscanf(buff, "S:%2hx %2hx %2hx\n",
&dev_sts1,&dev_sts2,&dev_sts3);
if (charcnt > 9 && 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;
}
}
mstat1.All = dev_sts1;
mstat2.All = dev_sts2;
mstat3.All = dev_sts3;
status.Bits.RA_DONE = (mstat1.Bits.on_target) ? 1 : 0;
status.Bits.EA_POSITION = (mstat1.Bits.drv_cur_act) ? 0 : 1;
status.Bits.RA_DIRECTION = 0;
plusLS = mstat2.Bits.hi_limit ? 0 : 1;
minusLS = mstat2.Bits.lo_limit ? 0 : 1;
/* Parse motor position */
send_mess(card, "TP", (char*) NULL); /* Tell Position */
recv_mess(card, buff, 1);
motorData = NINT(atof(&buff[2]));
if (motorData == motor_info->position)
{
if (nodeptr != 0) /* Increment counter only if motor is moving. */
motor_info->no_motion_count++;
}
else
{
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;
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 PIC663 board */
/* send_mess() */
/*****************************************************/
static RTN_STATUS send_mess(int card, char const *com, char *name)
{
char local_buff[MAX_MSG_SIZE];
struct PIC663controller *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("drvPIC663.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("drvPIC663.cc:send_mess() - invalid card #%d\n", card);
return(ERROR);
}
local_buff[0] = (char) NULL; /* Terminate local buffer. */
/* this device deos not have axis info and so name is ignored! */
strcat(local_buff, com); /* Make a local copy of the string. */
Debug(2, "send_mess(): message = %s\n", local_buff);
cntrl = (struct PIC663controller *) motor_state[card]->DevicePrivate;
pasynOctetSyncIO->write(cntrl->pasynUser, local_buff, strlen(local_buff),
COMM_TIMEOUT, &nwrite);
return(OK);
}
/*****************************************************/
/* receive a message from the PIC663 board */
/* recv_mess() */
/*****************************************************/
static int recv_mess(int card, char *com, int flag)
{
struct PIC663controller *cntrl;
size_t nread = 0;
asynStatus status = asynError;
int eomReason;
/* Check that card exists */
if (!motor_state[card])
return(ERROR);
cntrl = (struct PIC663controller *) 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;
}
else
com[nread - 1] = '\0'; /* Strip traling CR. */
Debug(2, "recv_mess(): message = \"%s\"\n", com);
return(nread);
}
/*****************************************************/
/* Setup system configuration */
/* PIC663Setup() */
/*****************************************************/
RTN_STATUS
PIC663Setup(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 > PIC663_NUM_CARDS)
PIC663_num_cards = PIC663_NUM_CARDS;
else
PIC663_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 PIC663Config 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(PIC663_num_cards *
sizeof(struct controller *));
for (itera = 0; itera < PIC663_num_cards; itera++)
motor_state[itera] = (struct controller *) NULL;
return(OK);
}
/*****************************************************/
/* Configure a controller */
/* PIC663Config() */
/*****************************************************/
RTN_STATUS
PIC663Config(int card, /* card being configured */
const char *name, /* asyn port name */
int addr) /* asyn address ( device address for daisy chaining */
{
struct PIC663controller *cntrl;
if (card < 0 || card >= PIC663_num_cards)
return(ERROR);
motor_state[card] = (struct controller *) malloc(sizeof(struct controller));
motor_state[card]->DevicePrivate = malloc(sizeof(struct PIC663controller));
cntrl = (struct PIC663controller *) 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 PIC663controller *cntrl;
int card_index, motor_index;
char buff[BUFF_SIZE];
int status;
asynStatus success_rtn;
static const char output_terminator[] = "\r";
static const char input_terminator[] = "\n\03";
initialized = true; /* Indicate that driver is initialized. */
/* Check for setup */
if (PIC663_num_cards <= 0)
return(ERROR);
for (card_index = 0; card_index < PIC663_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 PIC663controller *) brdptr->DevicePrivate;
/* 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);
/* To start communicating with the device requires to enable the device
To do this send "0x01" and a singel letter address (0-F)
To make sure we talk ask the status with "TB" command for the address
It replies "B:000x" where x is 0-F
The command "VE" provides a complete Identification string if we need.
*/
do
{
sprintf(buff,"\001%1XVE", cntrl->asyn_address);
send_mess(card_index, buff, (char*) NULL);
status = recv_mess(card_index, buff, 1);
retry++;
} while (status == 0 && retry < 3);
}
if (success_rtn == asynSuccess && status > 0)
{
strcpy(brdptr->ident, &buff[0]);
brdptr->localaddr = (char *) NULL;
brdptr->motor_in_motion = 0;
/* number of axes is always one.*/
brdptr->total_axis = 1;
motor_index = 0;
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;
/* PIC663 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;
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 *) "PIC663_motor", epicsThreadPriorityMedium,
epicsThreadGetStackSize(epicsThreadStackMedium),
(EPICSTHREADFUNC) motor_task, (void *) &targs);
return(OK);
}
-122
View File
@@ -1,122 +0,0 @@
/* File: drvPIC663.h */
/* Device Driver Support definitions for motor */
/*
* Copied from devPIC862.cc by Jonathan Thompson, Jan 2011
*
* Modification Log:
* -----------------
* Jan 2011 - All references to 862 changed to 663
* Status register definitions changed to match 663
*/
#ifndef INCdrvPIC663h
#define INCdrvPIC663h 1
#include "motordrvCom.h"
#include "asynDriver.h"
#include "asynDriver.h"
#include "asynOctetSyncIO.h"
#define COMM_TIMEOUT 2.0 /* Timeout in seconds. */
struct PIC663controller
{
asynUser *pasynUser; /* asynUser structure */
int asyn_address; /* Use for GPIB or other address with asyn */
CommStatus status; /* Controller communication status. */
char asyn_port[80]; /* asyn port name */
};
/* Operation status */
typedef union
{
epicsUInt16 All;
struct
{
#ifdef MSB_First
unsigned int na8 :8; /* NA8. */
unsigned int drv_cur_act :1; /* 7 - Drive current active. */
unsigned int brake_on :1; /* 6 - Brake on. */
unsigned int brake_off :1; /* 5 - Brake off. */
unsigned int macro_act :1; /* 4 - Macro running. */
unsigned int joy_on :1; /* 3 - Joystick on. */
unsigned int ref_drv_act :1; /* 2 - Reference drive active. */
unsigned int on_target :1; /* 1 - On target. */
unsigned int ready :1; /* 0 - Ready. */
#else
unsigned int ready :1; /* 0 - Ready. */
unsigned int on_target :1; /* 1 - On target. */
unsigned int ref_drv_act :1; /* 2 - Reference drive active. */
unsigned int joy_on :1; /* 3 - Joystick on. */
unsigned int macro_act :1; /* 4 - Macro running. */
unsigned int brake_off :1; /* 5 - Brake off. */
unsigned int brake_on :1; /* 6 - Brake on. */
unsigned int drv_cur_act :1; /* 7 - Drive current active. */
unsigned int na8 :8; /* NA8. */
#endif
} Bits;
} C663_Status_Reg1;
/* Hardware flags */
typedef union
{
epicsUInt16 All;
struct
{
#ifdef MSB_First
unsigned int na8 :8; /* NA8. */
unsigned int in_4 :1; /* 7 - Digital input 4. */
unsigned int in_3 :1; /* 6 - Digital input 3. */
unsigned int in_2 :1; /* 3 - Digital input 2. */
unsigned int in_1 :1; /* 4 - Digital input 1. */
unsigned int unused :1; /* 3 - No function. */
unsigned int hi_limit :1; /* 2 - Positive limit. */
unsigned int ref_signal :1; /* 1 - Reference signal. */
unsigned int lo_limit :1; /* 0 - Negative limit. */
#else
unsigned int lo_limit :1; /* 0 - Negative limit. */
unsigned int ref_signal :1; /* 1 - Reference signal. */
unsigned int hi_limit :1; /* 2 - Positive limit. */
unsigned int unused :1; /* 3 - No function. */
unsigned int in_1 :1; /* 4 - Digital input 1. */
unsigned int in_2 :1; /* 3 - Digital input 2. */
unsigned int in_3 :1; /* 6 - Digital input 3. */
unsigned int in_4 :1; /* 7 - Digital input 4. */
unsigned int na8 :8; /* NA8. */
#endif
} Bits;
} C663_Status_Reg2;
/* Error reporting */
typedef union
{
epicsUInt16 All;
struct
{
#ifdef MSB_First
unsigned int na8 :8; /* NA8. */
unsigned int error :8; /* Error code. */
#else
unsigned int error :8; /* Error code. */
unsigned int na8 :8; /* NA8. */
#endif
} Bits;
} C663_Status_Reg3;
#define C663_Status_Reg3_NO_ERROR 0x00
#define C663_Status_Reg3_RS232_TIMEOUT 0x01
#define C663_Status_Reg3_RS232_OVERFLOW 0x02
#define C663_Status_Reg3_MACRO_STORAGE_FULL 0x03
#define C663_Status_Reg3_MACRO_OUT_OF_RANGE 0x04
#define C663_Status_Reg3_WRONG_MACRO_CMD 0x05
#define C663_Status_Reg3_COMMAND_ERROR 0x06
/* Function prototypes. */
extern RTN_STATUS PIC663Setup(int, int);
extern RTN_STATUS PIC663Config(int, const char *, int);
#endif /* INCdrvPIC663h */
-648
View File
@@ -1,648 +0,0 @@
/*
FILENAME... drvPIC844.cc
USAGE... Motor record driver level support for Physik Instrumente (PI)
GmbH & Co. C-844 motor controller.
*/
/*
* Original Author: Ron Sluiter
* Date: 12/17/03
*
* Experimental Physics and Industrial Control System (EPICS)
*
* Copyright 1991, the Regents of the University of California,
* and the University of Chicago Board of Governors.
*
* This software was produced under U.S. Government contracts:
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
* and (W-31-109-ENG-38) at Argonne National Laboratory.
*
* Initial development by:
* The Controls and Automation Group (AT-8)
* Ground Test Accelerator
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Co-developed with
* The Controls and Computing Group
* Accelerator Systems Division
* Advanced Photon Source
* Argonne National Laboratory
*
* Modification Log:
* -----------------
* .01 12/17/03 rls - copied from drvIM483PL.cc
* .02 02/03/04 rls - Eliminate erroneous "Motor motion timeout ERROR".
* .03 07/12/04 rls - Converted from MPF to asyn.
* .04 09/09/04 rls - Retry on initial comm. (PIC844 comm. locks up when IOC
* is power cycled).
* .05 09/21/04 rls - support for 32axes/controller.
* .06 12/16/04 rls - asyn R4.0 support.
* - make debug variables always available.
* - MS Visual C compatibility; make all epicsExportAddress
* extern "C" linkage.
* .07 08/31/04 rls - Bug fix for no "break"'s in axis #4 switch/case stmts.
* in set_status().
*/
/*
DESIGN LIMITATIONS...
1 - Like all controllers, the PIC844 must be powered-on when EPICS is first
booted up.
2 - The PIC844 cannot be power cycled while EPICS is up and running. The
consequences are permanent communication lose with the PIC844 until
EPICS is rebooted.
*/
#include <string.h>
#include <epicsThread.h>
#include <drvSup.h>
#include <stdlib.h>
#include <errlog.h>
#include "motor.h"
#include "drvPI.h"
#include "epicsExport.h"
#define GET_IDENT "*IDN?"
#define PIC844_NUM_CARDS 8
#define MAX_AXES 8
#define BUFF_SIZE 100 /* Maximum length of string to/from PIC844 */
/*----------------debugging-----------------*/
volatile int drvPIC844debug = 0;
extern "C" {epicsExportAddress(int, drvPIC844debug);}
static inline void Debug(int level, const char *format, ...) {
#ifdef DEBUG
if (level < drvPIC844debug) {
va_list pVar;
va_start(pVar, format);
vprintf(format, pVar);
va_end(pVar);
}
#endif
}
/* --- Local data. --- */
int PIC844_num_cards = 0;
static char *PIC844_axis[4] = {"1", "2", "3", "4"};
/* 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 PIC844_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,
PIC844_axis
};
struct
{
long number;
long (*report) (int);
long (*init) (void);
} drvPIC844 = {2, report, init};
extern "C" {epicsExportAddress(drvet, drvPIC844);}
static struct thread_args targs = {SCAN_RATE, &PIC844_access, 0.0};
/*********************************************************
* Print out driver status report
*********************************************************/
static long report(int level)
{
int card;
if (PIC844_num_cards <=0)
printf(" No PIC844 controllers configured.\n");
else
{
for (card = 0; card < PIC844_num_cards; card++)
{
struct controller *brdptr = motor_state[card];
if (brdptr == NULL)
printf(" PIC844 controller %d connection failed.\n", card);
else
{
struct PIC844controller *cntrl;
cntrl = (struct PIC844controller *) brdptr->DevicePrivate;
printf(" PIC844 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 (PIC844_num_cards <= 0)
{
Debug(1, "init(): PIC844 driver disabled. PIC844Setup() 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 PIC844controller *cntrl;
struct mess_node *nodeptr;
register struct mess_info *motor_info;
/* Message parsing variables */
char buff[BUFF_SIZE];
C844_Cond_Reg mstat;
int rtn_state;
double motorData;
bool plusdir, ls_active = false, inmotion, plusLS, minusLS;
msta_field status;
cntrl = (struct PIC844controller *) motor_state[card]->DevicePrivate;
motor_info = &(motor_state[card]->motor_info[signal]);
nodeptr = motor_info->motor_motion;
status.All = motor_info->status.All;
send_mess(card, "AXIS:STAT?", PIC844_axis[signal]);
recv_mess(card, buff, 1);
if (strcmp(buff, "ON") == 0)
status.Bits.EA_POSITION = 1;
else if (strcmp(buff, "OFF") == 0)
status.Bits.EA_POSITION = 0;
else
{
if (cntrl->status == NORMAL)
{
cntrl->status = RETRY;
rtn_state = 0;
}
else
{
cntrl->status = COMM_ERR;
status.Bits.CNTRL_COMM_ERR = 1;
status.Bits.RA_PROBLEM = 1;
rtn_state = 1;
}
goto exit;
}
cntrl->status = NORMAL;
status.Bits.CNTRL_COMM_ERR = 0;
send_mess(card, "MOT:COND?", (char*) NULL);
recv_mess(card, buff, 1);
mstat.All = atoi(&buff[0]);
switch(signal)
{
case 0:
inmotion = mstat.Bits.axis1IM;
break;
case 1:
inmotion = mstat.Bits.axis2IM;
break;
case 2:
inmotion = mstat.Bits.axis3IM;
break;
case 3:
inmotion = mstat.Bits.axis4IM;
break;
default:
rtn_state = 1;
goto exit;
}
status.Bits.RA_DONE = (inmotion == YES) ? 0 : 1;
/*
* Parse motor position
* Position string format: 1TP5.012,2TP1.123,3TP-100.567,...
* Skip to substring for this motor, convert to double
*/
send_mess(card, "CURR:TPOS?", (char*) NULL);
recv_mess(card, buff, 1);
motorData = atof(buff);
if (motorData == motor_info->position)
{
if (nodeptr != 0) /* Increment counter only if motor is moving. */
motor_info->no_motion_count++;
}
else
{
epicsInt32 newposition;
newposition = NINT(motorData);
status.Bits.RA_DIRECTION = (newposition >= motor_info->position) ? 1 : 0;
motor_info->position = newposition;
motor_info->no_motion_count = 0;
}
plusdir = (status.Bits.RA_DIRECTION) ? true : false;
switch(signal)
{
case 0:
plusLS = mstat.Bits.axis1PL;
minusLS = mstat.Bits.axis1ML;
break;
case 1:
plusLS = mstat.Bits.axis2PL;
minusLS = mstat.Bits.axis2ML;
break;
case 2:
plusLS = mstat.Bits.axis3PL;
minusLS = mstat.Bits.axis3ML;
break;
case 3:
plusLS = mstat.Bits.axis4PL;
minusLS = mstat.Bits.axis4ML;
break;
default:
rtn_state = 1;
goto exit;
}
/* 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;
send_mess(card, "AXIS:POS?", (char*) NULL);
recv_mess(card, buff, 1);
motorData = atof(buff);
motor_info->encoder_position = (epicsInt32) motorData;
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 PIC844 board */
/* send_mess() */
/*****************************************************/
static RTN_STATUS send_mess(int card, char const *com, char *name)
{
char local_buff[MAX_MSG_SIZE];
struct PIC844controller *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("drvPIC844.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("drvPIC844.cc:send_mess() - invalid card #%d\n", card);
return(ERROR);
}
local_buff[0] = (char) NULL; /* Terminate local buffer. */
if (name != NULL)
{
strcpy(local_buff, "AXIS ");
strcat(local_buff, name); /* put in axis. */
strcat(local_buff, ";"); /* put in comman seperator. */
}
/* Make a local copy of the string. */
strcat(local_buff, com);
Debug(2, "send_mess(): message = %s\n", local_buff);
cntrl = (struct PIC844controller *) motor_state[card]->DevicePrivate;
pasynOctetSyncIO->write(cntrl->pasynUser, local_buff, strlen(local_buff),
COMM_TIMEOUT, &nwrite);
return(OK);
}
/*****************************************************/
/* receive a message from the PIC844 board */
/* recv_mess() */
/*****************************************************/
static int recv_mess(int card, char *com, int flag)
{
struct PIC844controller *cntrl;
size_t nread = 0;
asynStatus status = asynError;
int eomReason;
/* Check that card exists */
if (!motor_state[card])
return(ERROR);
cntrl = (struct PIC844controller *) 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 */
/* PIC844Setup() */
/*****************************************************/
RTN_STATUS
PIC844Setup(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 > PIC844_NUM_CARDS)
PIC844_num_cards = PIC844_NUM_CARDS;
else
PIC844_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 PIC844Config 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(PIC844_num_cards *
sizeof(struct controller *));
for (itera = 0; itera < PIC844_num_cards; itera++)
motor_state[itera] = (struct controller *) NULL;
return(OK);
}
/*****************************************************/
/* Configure a controller */
/* PIC844Config() */
/*****************************************************/
RTN_STATUS
PIC844Config(int card, /* card being configured */
const char *name, /* asyn port name */
int addr) /* asyn address (GPIB) */
{
struct PIC844controller *cntrl;
if (card < 0 || card >= PIC844_num_cards)
return (ERROR);
motor_state[card] = (struct controller *) malloc(sizeof(struct controller));
motor_state[card]->DevicePrivate = malloc(sizeof(struct PIC844controller));
cntrl = (struct PIC844controller *) 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 PIC844controller *cntrl;
int card_index, motor_index;
char buff[BUFF_SIZE];
int total_axis;
int status;
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 (PIC844_num_cards <= 0)
return(ERROR);
for (card_index = 0; card_index < PIC844_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 PIC844controller *) brdptr->DevicePrivate;
/* 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, 1);
retry++;
} while (status == 0 && retry < 3);
}
if (success_rtn == asynSuccess && status > 0)
{
strcpy(brdptr->ident, &buff[0]);
brdptr->localaddr = (char *) NULL;
brdptr->motor_in_motion = 0;
brdptr->total_axis = total_axis = 4;
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;
/* PIC844 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;
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 *) "PIC844_motor", epicsThreadPriorityMedium,
epicsThreadGetStackSize(epicsThreadStackMedium),
(EPICSTHREADFUNC) motor_task, (void *) &targs);
return(OK);
}
-619
View File
@@ -1,619 +0,0 @@
/*
FILENAME... drvPIC848.cc
USAGE... Motor record driver level support for Physik Instrumente (PI)
GmbH & Co. C-848 motor controller.
*/
/*
* Original Author: Ron Sluiter
* Date: 10/18/05
*
* 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 10/18/05 rls - copied from drvPIC844.cc
* .02 10/17/07 rls - Added "Motor motion timeout" error check.
* - Set "reference" home switch indicator.
*/
/*
DESIGN LIMITATIONS...
1 - Like all controllers, the PIC848 must be powered-on when EPICS is first
booted up.
*/
#include <string.h>
#include <epicsThread.h>
#include <drvSup.h>
#include <stdlib.h>
#include <errlog.h>
#include "motorRecord.h"
#include "motor.h"
#include "drvPIC848.h"
#include "epicsExport.h"
#define GET_IDENT "*IDN?"
#define PIC848_NUM_CARDS 8
#define MAX_AXES 4
#define BUFF_SIZE 100 /* Maximum length of string to/from PIC848 */
/*----------------debugging-----------------*/
volatile int drvPIC848debug = 0;
extern "C" {epicsExportAddress(int, drvPIC848debug);}
static inline void Debug(int level, const char *format, ...) {
#ifdef DEBUG
if (level < drvPIC848debug) {
va_list pVar;
va_start(pVar, format);
vprintf(format, pVar);
va_end(pVar);
}
#endif
}
/* --- Local data. --- */
int PIC848_num_cards = 0;
static char *PIC848_axis[4] = {"A", "B", "C", "D"};
static volatile int motionTO = 10;
/* 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 PIC848_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,
PIC848_axis
};
struct
{
long number;
long (*report) (int);
long (*init) (void);
} drvPIC848 = {2, report, init};
extern "C" {epicsExportAddress(drvet, drvPIC848);}
static struct thread_args targs = {SCAN_RATE, &PIC848_access, 0.0};
/*********************************************************
* Print out driver status report
*********************************************************/
static long report(int level)
{
int card;
if (PIC848_num_cards <=0)
printf(" No PIC848 controllers configured.\n");
else
{
for (card = 0; card < PIC848_num_cards; card++)
{
struct controller *brdptr = motor_state[card];
if (brdptr == NULL)
printf(" PIC848 controller %d connection failed.\n", card);
else
{
struct PIC848controller *cntrl;
cntrl = (struct PIC848controller *) brdptr->DevicePrivate;
printf(" PIC848 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 (PIC848_num_cards <= 0)
{
Debug(1, "init(): PIC848 driver disabled. PIC848Setup() 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 PIC848controller *cntrl;
struct mess_node *nodeptr;
struct mess_info *motor_info;
struct motorRecord *mr;
/* Message parsing variables */
char buff[BUFF_SIZE], axisID;
C848_Status_Reg mstat;
int rtn_state, convert_cnt, charcnt, tempInt;
epicsInt32 motorData;
bool plusdir, ls_active = false, plusLS, minusLS;
msta_field status;
cntrl = (struct PIC848controller *) 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, "STA? #", PIC848_axis[signal]);
charcnt = recv_mess(card, buff, 1);
if (charcnt > 2)
convert_cnt = sscanf(buff, "%c=%d\n", &axisID, &tempInt);
if (charcnt > 2 && convert_cnt == 2)
{
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;
}
}
mstat.All = tempInt;
status.Bits.RA_DONE = (mstat.Bits.Done) ? 1 : 0;
status.Bits.EA_POSITION = (mstat.Bits.torque) ? 1 : 0;
plusLS = mstat.Bits.plus_ls;
minusLS = mstat.Bits.minus_ls;
send_mess(card, "POS? #", PIC848_axis[signal]);
recv_mess(card, buff, 1);
motorData = NINT(atof(&buff[2]) / 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;
}
if (motor_info->no_motion_count > motionTO)
{
status.Bits.RA_PROBLEM = 1;
send_mess(card, "HLT #", PIC848_axis[signal]);
motor_info->no_motion_count = 0;
errlogSevPrintf(errlogMinor, "Motor motion timeout ERROR on card: %d, signal: %d\n",
card, signal);
}
else
status.Bits.RA_PROBLEM = 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;
/* 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 PIC848 board */
/* send_mess() */
/*****************************************************/
static RTN_STATUS send_mess(int card, char const *com, char *name)
{
char local_buff[MAX_MSG_SIZE];
struct PIC848controller *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("drvPIC848.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("drvPIC848.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[5] = *name; /* put in axis. */
}
Debug(2, "send_mess(): message = %s\n", local_buff);
cntrl = (struct PIC848controller *) motor_state[card]->DevicePrivate;
pasynOctetSyncIO->write(cntrl->pasynUser, local_buff, strlen(local_buff),
COMM_TIMEOUT, &nwrite);
return(OK);
}
/*****************************************************/
/* receive a message from the PIC848 board */
/* recv_mess() */
/*****************************************************/
static int recv_mess(int card, char *com, int flag)
{
struct PIC848controller *cntrl;
size_t nread = 0;
asynStatus status = asynError;
int eomReason;
/* Check that card exists */
if (!motor_state[card])
return(ERROR);
cntrl = (struct PIC848controller *) 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 */
/* PIC848Setup() */
/*****************************************************/
RTN_STATUS
PIC848Setup(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 > PIC848_NUM_CARDS)
PIC848_num_cards = PIC848_NUM_CARDS;
else
PIC848_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 PIC848Config 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(PIC848_num_cards *
sizeof(struct controller *));
for (itera = 0; itera < PIC848_num_cards; itera++)
motor_state[itera] = (struct controller *) NULL;
return(OK);
}
/*****************************************************/
/* Configure a controller */
/* PIC848Config() */
/*****************************************************/
RTN_STATUS
PIC848Config(int card, /* card being configured */
const char *name, /* asyn port name */
int addr) /* asyn address (GPIB) */
{
struct PIC848controller *cntrl;
if (card < 0 || card >= PIC848_num_cards)
return(ERROR);
motor_state[card] = (struct controller *) malloc(sizeof(struct controller));
motor_state[card]->DevicePrivate = malloc(sizeof(struct PIC848controller));
cntrl = (struct PIC848controller *) 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 PIC848controller *cntrl;
int card_index, motor_index;
char buff[BUFF_SIZE];
int total_axis;
int status;
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 (PIC848_num_cards <= 0)
return(ERROR);
for (card_index = 0; card_index < PIC848_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 PIC848controller *) brdptr->DevicePrivate;
/* 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, 1);
retry++;
} while (status == 0 && retry < 3);
}
if (success_rtn == asynSuccess && status > 0)
{
strcpy(brdptr->ident, &buff[0]);
brdptr->localaddr = (char *) NULL;
brdptr->motor_in_motion = 0;
/* Determine # of axes. Request stage name. See if it responds */
for (total_axis = 0; total_axis < MAX_AXES; total_axis++)
{
send_mess(card_index, "CST? #", PIC848_axis[total_axis]);
status = recv_mess(card_index, buff, 1);
if (strcmp(&buff[2],"NOSTAGE") == 0)
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;
/* PIC848 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;
/* Determine if stage has a reference (home) switch. */
send_mess(card_index, "REF? #", PIC848_axis[motor_index]);
status = recv_mess(card_index, buff, 1);
if (strcmp(&buff[2],"0") == 0)
cntrl->reference[motor_index] = false;
else
cntrl->reference[motor_index] = true;
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 *) "PIC848_motor", epicsThreadPriorityMedium,
epicsThreadGetStackSize(epicsThreadStackMedium),
(EPICSTHREADFUNC) motor_task, (void *) &targs);
return(OK);
}
-87
View File
@@ -1,87 +0,0 @@
/* File: drvPIC848.h */
/* Device Driver Support definitions for motor */
/*
* Original Author: Ron Sluiter
* Current Author: Ron Sluiter
* Date: 09/20/2005
*
* Modification Log:
* -----------------
* .00 09/20/2005 rls copied from drvPIC630.h
* .01 10/17/2007 rls - Added "reference" home switch indicator.
- increased position resolution scaler.
*/
#ifndef INCdrvPIC848h
#define INCdrvPIC848h 1
#include "motordrvCom.h"
#include "asynDriver.h"
#include "asynDriver.h"
#include "asynOctetSyncIO.h"
#define COMM_TIMEOUT 2 /* Timeout in seconds. */
#define POS_RES 0.000001 /* Position resolution. */
struct PIC848controller
{
bool reference[4]; /* reference sensor; if true, axis position can
* only be set to zero; if false, axis position
* must be set before axis can be moved. */
asynUser *pasynUser; /* asynUser structure */
int asyn_address; /* Use for GPIB or other address with asyn */
CommStatus status; /* Controller communication status. */
double drive_resolution[4];
char asyn_port[80]; /* asyn port name */
};
typedef union
{
epicsUInt16 All;
struct
{
#ifdef MSB_First
unsigned int na15 :1;
unsigned int na14 :1;
unsigned int axisID :2; /*12-13 - Axis ID; 0/A, 1/B, 2/C, 3/D */
unsigned int na11 :1;
unsigned int in_motion :1; /*10 - Axis in motion flag. */
unsigned int axis_on :1; /* 9 - Axis on; always on (1). */
unsigned int torque :1; /* 8 - Servo-control status. */
unsigned int cmnd_err :1; /* 7 - Command error flag. */
unsigned int minus_ls :1; /* 6 - Negative limit switch flag. */
unsigned int plus_ls :1; /* 5 - Positive limit switch flag. */
unsigned int max_pos_err :1; /* 4 - Maximum position error is exceeded. */
unsigned int index :1; /* 3 - Index pulse received flag. */
unsigned int breakpt :1; /* 2 - Breakpoint reached flag. */
unsigned int wrap_around :1; /* 1 - Position wrap-around flag. */
unsigned int Done :1; /* 0 - Axis trajectory complete. */
#else
unsigned int Done :1; /* 0 - Axis trajectory complete. */
unsigned int wrap_around :1; /* 1 - Position wrap-around flag. */
unsigned int breakpt :1; /* 2 - Breakpoint reached flag. */
unsigned int index :1; /* 3 - Index pulse received flag. */
unsigned int max_pos_err :1; /* 4 - Maximum position error is exceeded. */
unsigned int plus_ls :1; /* 5 - Positive limit switch flag. */
unsigned int minus_ls :1; /* 6 - Negative limit switch flag. */
unsigned int cmnd_err :1; /* 7 - Command error flag. */
unsigned int torque :1; /* 8 - Servo-control status. */
unsigned int axis_on :1; /* 9 - Axis on; always on (1). */
unsigned int in_motion :1; /*10 - Axis in motion flag. */
unsigned int na11 :1;
unsigned int axisID :2; /*12-13 - Axis ID; 0/A, 1/B, 2/C, 3/D */
unsigned int na14 :1;
unsigned int na15 :1;
#endif
} Bits;
} C848_Status_Reg;
/* Function prototypes. */
extern RTN_STATUS PIC848Setup(int, int);
extern RTN_STATUS PIC848Config(int, const char *, int);
#endif /* INCdrvPIC848h */
-600
View File
@@ -1,600 +0,0 @@
/*
FILENAME... drvPIC862.cc
USAGE... Motor record driver level support for Physik Instrumente (PI)
GmbH & Co. C-862 motor controller.
*/
/*
* Original Author: Ron Sluiter
* Current Author: Mohan Ramanathan
* Date: 09/04/2006
*
* NOTES
* -----
* - This driver works with both the C-862 and C-863.
*
* Modification Log:
* -----------------
* .00 09/05/2006 mr copied from drvPIC848.cc
* .01 09/25/2006 rls Set LS error indicator based on LS active high/low
* configuration indicator and the state of the LS.
* .02 09/28/2006 rls C-862 drops transmitted characters on move command;
* need "status update delay".
*/
/*
DESIGN LIMITATIONS...
1 - Like all controllers, the PIC862 must be powered-on when EPICS is first
booted up.
*/
#include <string.h>
#include <epicsThread.h>
#include <drvSup.h>
#include <stdlib.h>
#include <errlog.h>
#include "motorRecord.h"
#include "motor.h"
#include "drvPIC862.h"
#include "epicsExport.h"
#define GET_IDENT 0x01
#define PIC862_NUM_CARDS 8
#define MAX_AXES 1
#define BUFF_SIZE 100 /* Maximum length of string to/from PIC862 */
/*----------------debugging-----------------*/
volatile int drvPIC862debug = 0;
extern "C" {epicsExportAddress(int, drvPIC862debug);}
static inline void Debug(int level, const char *format, ...) {
#ifdef DEBUG
if (level < drvPIC862debug) {
va_list pVar;
va_start(pVar, format);
vprintf(format, pVar);
va_end(pVar);
}
#endif
}
/* --- Local data. --- */
int PIC862_num_cards = 0;
/* 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 PIC862_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,
NULL
};
struct
{
long number;
long (*report) (int);
long (*init) (void);
} drvPIC862 = {2, report, init};
extern "C" {epicsExportAddress(drvet, drvPIC862);}
static struct thread_args targs = {SCAN_RATE, &PIC862_access, 0.017};
/*********************************************************
* Print out driver status report
*********************************************************/
static long report(int level)
{
int card;
if (PIC862_num_cards <=0)
printf(" No PIC862 controllers configured.\n");
else
{
for (card = 0; card < PIC862_num_cards; card++)
{
struct controller *brdptr = motor_state[card];
if (brdptr == NULL)
printf(" PIC862 controller %d connection failed.\n", card);
else
{
struct PIC862controller *cntrl;
cntrl = (struct PIC862controller *) brdptr->DevicePrivate;
printf(" PIC862 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 (PIC862_num_cards <= 0)
{
Debug(1, "init(): PIC862 driver disabled. PIC862Setup() 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 PIC862controller *cntrl;
struct mess_node *nodeptr;
struct mess_info *motor_info;
struct motorRecord *mr;
/* Message parsing variables */
char buff[BUFF_SIZE];
C862_Status_Reg1 mstat1;
C862_Status_Reg2 mstat2;
C862_Status_Reg3 mstat3;
C862_Status_Reg4 mstat4;
C862_Status_Reg5 mstat5;
epicsUInt16 dev_sts1, dev_sts2, dev_sts3, dev_sts4, dev_sts5, dev_sts6;
int rtn_state, convert_cnt, charcnt;
epicsInt32 motorData;
bool plusdir, ls_active = false, plusLS, minusLS, LSactiveH;
msta_field status;
cntrl = (struct PIC862controller *) 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, "TS", (char*) NULL); /* Tell Status */
charcnt = recv_mess(card, buff, 1);
if (charcnt > 18)
convert_cnt = sscanf(buff, "S:%2hx %2hx %2hx %2hx %2hx %2hx\n",
&dev_sts1,&dev_sts2,&dev_sts3,&dev_sts4,&dev_sts5,&dev_sts6);
if (charcnt > 18 && convert_cnt == 6)
{
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;
}
}
mstat1.All = dev_sts1;
mstat2.All = dev_sts2;
mstat3.All = dev_sts3;
mstat4.All = dev_sts4;
mstat5.All = dev_sts5;
status.Bits.RA_DONE = (mstat1.Bits.trty_done) ? 1 : 0;
status.Bits.EA_POSITION = (mstat1.Bits.motor_off) ? 0 : 1;
status.Bits.RA_DIRECTION = (mstat3.Bits.mvdir_pol) ? 1 : 0;
/* Set +/- LS indicator based on limit switch active high/low
configuration and the state of the limits switch. */
LSactiveH = (mstat4.Bits.lmt_high) ? true : false;
if (LSactiveH == true)
{
plusLS = mstat5.Bits.plus_ls;
minusLS = mstat5.Bits.minus_ls;
}
else
{
plusLS = !mstat5.Bits.plus_ls;
minusLS = !mstat5.Bits.minus_ls;
}
/* Parse motor position */
send_mess(card, "TP", (char*) NULL); /* Tell Position */
recv_mess(card, buff, 1);
motorData = NINT(atof(&buff[2]));
if (motorData == motor_info->position)
{
if (nodeptr != 0) /* Increment counter only if motor is moving. */
motor_info->no_motion_count++;
}
else
{
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;
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 PIC862 board */
/* send_mess() */
/*****************************************************/
static RTN_STATUS send_mess(int card, char const *com, char *name)
{
char local_buff[MAX_MSG_SIZE];
struct PIC862controller *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("drvPIC862.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("drvPIC862.cc:send_mess() - invalid card #%d\n", card);
return(ERROR);
}
local_buff[0] = (char) NULL; /* Terminate local buffer. */
/* this device deos not have axis info and so name is ignored! */
strcat(local_buff, com); /* Make a local copy of the string. */
Debug(2, "send_mess(): message = %s\n", local_buff);
cntrl = (struct PIC862controller *) motor_state[card]->DevicePrivate;
pasynOctetSyncIO->write(cntrl->pasynUser, local_buff, strlen(local_buff),
COMM_TIMEOUT, &nwrite);
return(OK);
}
/*****************************************************/
/* receive a message from the PIC862 board */
/* recv_mess() */
/*****************************************************/
static int recv_mess(int card, char *com, int flag)
{
struct PIC862controller *cntrl;
size_t nread = 0;
asynStatus status = asynError;
int eomReason;
/* Check that card exists */
if (!motor_state[card])
return(ERROR);
cntrl = (struct PIC862controller *) 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;
}
else
com[nread - 1] = '\0'; /* Strip traling CR. */
Debug(2, "recv_mess(): message = \"%s\"\n", com);
return(nread);
}
/*****************************************************/
/* Setup system configuration */
/* PIC862Setup() */
/*****************************************************/
RTN_STATUS
PIC862Setup(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 > PIC862_NUM_CARDS)
PIC862_num_cards = PIC862_NUM_CARDS;
else
PIC862_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 PIC862Config 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(PIC862_num_cards *
sizeof(struct controller *));
for (itera = 0; itera < PIC862_num_cards; itera++)
motor_state[itera] = (struct controller *) NULL;
return(OK);
}
/*****************************************************/
/* Configure a controller */
/* PIC862Config() */
/*****************************************************/
RTN_STATUS
PIC862Config(int card, /* card being configured */
const char *name, /* asyn port name */
int addr) /* asyn address ( device address for daisy chaining */
{
struct PIC862controller *cntrl;
if (card < 0 || card >= PIC862_num_cards)
return(ERROR);
motor_state[card] = (struct controller *) malloc(sizeof(struct controller));
motor_state[card]->DevicePrivate = malloc(sizeof(struct PIC862controller));
cntrl = (struct PIC862controller *) 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 PIC862controller *cntrl;
int card_index, motor_index;
char buff[BUFF_SIZE];
int status;
asynStatus success_rtn;
static const char output_terminator[] = "\r";
static const char input_terminator[] = "\n\03";
initialized = true; /* Indicate that driver is initialized. */
/* Check for setup */
if (PIC862_num_cards <= 0)
return(ERROR);
for (card_index = 0; card_index < PIC862_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 PIC862controller *) brdptr->DevicePrivate;
/* 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);
/* To start communicating with the device requires to enable the device
To do this send "0x01" and a singel letter address (0-F)
To make sure we talk ask the status with "TB" command for the address
It replies "B:000x" where x is 0-F
The command "VE" provides a complete Identification string if we need.
*/
do
{
sprintf(buff,"\001%1XVE", cntrl->asyn_address);
send_mess(card_index, buff, (char*) NULL);
status = recv_mess(card_index, buff, 1);
retry++;
} while (status == 0 && retry < 3);
}
if (success_rtn == asynSuccess && status > 0)
{
strcpy(brdptr->ident, &buff[0]);
brdptr->localaddr = (char *) NULL;
brdptr->motor_in_motion = 0;
/* number of axes is always one.*/
brdptr->total_axis = 1;
motor_index = 0;
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;
/* PIC862 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;
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 *) "PIC862_motor", epicsThreadPriorityMedium,
epicsThreadGetStackSize(epicsThreadStackMedium),
(EPICSTHREADFUNC) motor_task, (void *) &targs);
return(OK);
}
-172
View File
@@ -1,172 +0,0 @@
/* File: drvPIC862.h */
/* Device Driver Support definitions for motor */
/*
* Original Author: Ron Sluiter
* Current Author: Mohan Ramanathan
* Date: 09/04/2006
*
* Modification Log:
* -----------------
* .00 09/05/2006 mr copied from drvPIC848.h
* .01 09/25/2006 rls COMM_TIMEOUT must be a float.
* .02 09/26/2006 rsl bit fields must be padded out to 16 bit words for
* WRS compiler.
*/
#ifndef INCdrvPIC862h
#define INCdrvPIC862h 1
#include "motordrvCom.h"
#include "asynDriver.h"
#include "asynDriver.h"
#include "asynOctetSyncIO.h"
#define COMM_TIMEOUT 2.0 /* Timeout in seconds. */
struct PIC862controller
{
asynUser *pasynUser; /* asynUser structure */
int asyn_address; /* Use for GPIB or other address with asyn */
CommStatus status; /* Controller communication status. */
char asyn_port[80]; /* asyn port name */
};
/* LM629 Status bits */
typedef union
{
epicsUInt16 All;
struct
{
#ifdef MSB_First
unsigned int na8 :8; /* NA8. */
unsigned int motor_off :1; /* 7 - Motor loop OFF. */
unsigned int breakpt :1; /* 6 - Breakpoint reached flag. */
unsigned int max_pos_err :1; /* 5 - Maximum position error is exceeded. */
unsigned int max_pos_lmt :1; /* 4 - Maximum position Limit exceeded. */
unsigned int index :1; /* 3 - Index pulse received flag. */
unsigned int trty_done :1; /* 2 - Trajectory Complete. */
unsigned int cmnd_err :1; /* 1 - Command error flag. */
unsigned int busy :1; /* 0 - Busy. */
#else
unsigned int busy :1; /* 0 - Busy. */
unsigned int cmnd_err :1; /* 1 - Command error flag. */
unsigned int trty_done :1; /* 2 - Trajectory Complete. */
unsigned int index :1; /* 3 - Index pulse received flag. */
unsigned int max_pos_lmt :1; /* 4 - Maximum position Limit exceeded. */
unsigned int max_pos_err :1; /* 5 - Maximum position error is exceeded. */
unsigned int breakpt :1; /* 6 - Breakpoint reached flag. */
unsigned int motor_off :1; /* 7 - Motor loop OFF. */
unsigned int na8 :8; /* NA8. */
#endif
} Bits;
} C862_Status_Reg1;
/* Internal operation flags */
typedef union
{
epicsUInt16 All;
struct
{
#ifdef MSB_First
unsigned int na8 :8; /* NA8. */
unsigned int brd_addr :1; /* 7 - Board Addressed. */
unsigned int num_mode :1; /* 6 - Number mode in Effect. */
unsigned int ldzero_dis :1; /* 3 - Leading Zero Suppression disabled. */
unsigned int macro_act :1; /* 4 - Macro Command called. */
unsigned int ldzero_act :1; /* 3 - Leading Zero Suppression active. */
unsigned int cmnd_err :1; /* 2 - Command error flag. */
unsigned int wait_prgs :1; /* 1 - Wait in Progress. */
unsigned int echo_on :1; /* 0 - Echo ON. */
#else
unsigned int echo_on :1; /* 0 - Echo ON. */
unsigned int wait_prgs :1; /* 1 - Wait in Progress. */
unsigned int cmnd_err :1; /* 2 - Command error flag. */
unsigned int ldzero_act :1; /* 3 - Leading Zero Suppression active. */
unsigned int macro_act :1; /* 4 - Macro Command called. */
unsigned int ldzero_dis :1; /* 3 - Leading Zero Suppression disabled. */
unsigned int num_mode :1; /* 6 - Number mode in Effect. */
unsigned int brd_addr :1; /* 7 - Board Addressed. */
unsigned int na8 :8; /* NA8. */
#endif
} Bits;
} C862_Status_Reg2;
/* Motor loop flags */
typedef union
{
epicsUInt16 All;
struct
{
#ifdef MSB_First
unsigned int na8 :8; /* NA8. */
unsigned int int_comm :1; /* 7 - Command error flag. */
unsigned int move_err_ex :1; /* 6 - Move Error Excess flag. */
unsigned int na34 :2;
unsigned int move_err :1; /* 3 - Move Error */
unsigned int mvdir_pol :1; /* 2 - Move driection polarity. */
unsigned int na30 :2;
#else
unsigned int na30 :2;
unsigned int mvdir_pol :1; /* 2 - Move driection polarity. */
unsigned int move_err :1; /* 3 - Move Error */
unsigned int na34 :2;
unsigned int move_err_ex :1; /* 6 - Move Error Excess flag. */
unsigned int int_comm :1; /* 7 - Command error flag. */
unsigned int na8 :8; /* NA8. */
#endif
} Bits;
} C862_Status_Reg3;
/* Signal lines status */
typedef union
{
epicsUInt16 All;
struct
{
#ifdef MSB_First
unsigned int na44 :12;
unsigned int brake_on :1; /* 3 - Brake ON. */
unsigned int find_prgs :1; /* 2 - Find Edge Operation in Progress. */
unsigned int lmt_high :1; /* 1 - Limit Switch Active Stet HIGH */
unsigned int lmt_on :1; /* 0 - Limit Swicth ON flag. */
#else
unsigned int lmt_on :1; /* 0 - Limit Swicth ON flag. */
unsigned int lmt_high :1; /* 1 - Limit Switch Active Stet HIGH */
unsigned int find_prgs :1; /* 2 - Find Edge Operation in Progress. */
unsigned int brake_on :1; /* 3 - Brake ON. */
unsigned int na44 :12;
#endif
} Bits;
} C862_Status_Reg4;
/* Signal lines inputs */
typedef union
{
epicsUInt16 All;
struct
{
#ifdef MSB_First
unsigned int na54 :12;
unsigned int minus_ls :1; /* 3 - Negative limit signal flag. */
unsigned int plus_ls :1; /* 2 - Positive limit signal flag. */
unsigned int index :1; /* 1 - Reference signal flag */
unsigned int na50 :1;
#else
unsigned int na50 :1;
unsigned int index :1; /* 1 - Reference signal flag */
unsigned int plus_ls :1; /* 2 - Positive limit signal flag. */
unsigned int minus_ls :1; /* 3 - Negative limit signal flag. */
unsigned int na54 :12;
#endif
} Bits;
} C862_Status_Reg5;
/* Function prototypes. */
extern RTN_STATUS PIC862Setup(int, int);
extern RTN_STATUS PIC862Config(int, const char *, int);
#endif /* INCdrvPIC862h */
-669
View File
@@ -1,669 +0,0 @@
/*
FILENAME... drvPIE516.cc
USAGE... Motor record driver level support for Physik Instrumente (PI)
GmbH & Co. E-516 motor controller.
*/
/*
* 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 03/26/07 jps - copied from drvPIC710.cc tested on PI VER "DSP V3.11,MCU V5"
*/
/*
DESIGN LIMITATIONS...
1 - Like all controllers, the PIE516 must be powered-on when EPICS is first
booted up.
*/
#include <string.h>
#include <epicsThread.h>
#include <drvSup.h>
#include <stdlib.h>
#include <errlog.h>
#include "motorRecord.h"
#include "motor.h"
#include "drvPIE516.h"
#include "epicsExport.h"
#define GET_IDENT "VER?"
#define SET_ONLINE "ONL 1" /* Set Online Mode ON */
#define SET_VELCTRL "VCO A1 B1 C1" /* Set Velocity Control Mode - Required for DONE */
#define READ_ONLINE "ONL?" /* Read Online Mode */
#define READ_POS "POS? #" /* Read position */
#define READ_OVERFLOW "OVF? #" /* Read Servo Overflow Status */
#define READ_ONTARGET "ONT? #" /* Read Position ON Target */
#define READ_SERVO "SVO? #" /* Read Servo Enable Status */
#define PIE516_NUM_CARDS 10
#define MAX_AXES 3
#define BUFF_SIZE 100 /* Maximum length of string to/from PIE516 */
/*----------------debugging-----------------*/
volatile int drvPIE516debug = 0;
extern "C" {epicsExportAddress(int, drvPIE516debug);}
static inline void Debug(int level, const char *format, ...) {
#ifdef DEBUG
if (level < drvPIE516debug) {
va_list pVar;
va_start(pVar, format);
vprintf(format, pVar);
va_end(pVar);
}
#endif
}
/* --- Local data. --- */
int PIE516_num_cards = 0;
static char *PIE516_axis[] = {"A", "B", "C"};
/* 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 PIE516_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,
PIE516_axis
};
struct
{
long number;
long (*report) (int);
long (*init) (void);
} drvPIE516 = {2, report, init};
extern "C" {epicsExportAddress(drvet, drvPIE516);}
static struct thread_args targs = {SCAN_RATE, &PIE516_access, 0.0};
/*********************************************************
* Print out driver status report
*********************************************************/
static long report(int level)
{
int card;
if (PIE516_num_cards <=0)
printf(" No PIE516 controllers configured.\n");
else
{
for (card = 0; card < PIE516_num_cards; card++)
{
struct controller *brdptr = motor_state[card];
if (brdptr == NULL)
printf(" PIE516 controller %d connection failed.\n", card);
else
{
struct PIE516controller *cntrl;
cntrl = (struct PIE516controller *) brdptr->DevicePrivate;
printf(" PIE516 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 (PIE516_num_cards <= 0)
{
Debug(1, "init(): PIE516 driver disabled. PIE516Setup() 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 PIE516controller *cntrl;
struct mess_node *nodeptr;
struct mess_info *motor_info;
struct motorRecord *mr;
/* Message parsing variables */
char buff[BUFF_SIZE];
int rtn_state;
unsigned int overflow_status, ontarget_status, servo_status, online_status;
epicsInt32 motorData;
bool plusdir, ls_active, plusLS, minusLS;
bool readOK;
msta_field status;
cntrl = (struct PIE516controller *) 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;
recv_mess(card, buff, FLUSH);
readOK = false;
send_mess(card, READ_ONLINE, (char*) NULL);
if (recv_mess(card, buff, 1) && sscanf(buff, "%d", &online_status))
{
if (!online_status)
{
/* Assume Controller Reboot - Set ONLINE and Velocity Control ON */
send_mess(card, SET_ONLINE, (char*) NULL);
send_mess(card, SET_VELCTRL, (char*) NULL);
}
send_mess(card, READ_ONTARGET, PIE516_axis[signal]);
if (recv_mess(card, buff, 1) && sscanf(buff, "%d", &ontarget_status))
{
send_mess(card, READ_OVERFLOW, PIE516_axis[signal]);
if (recv_mess(card, buff, 1) && sscanf(buff, "%d", &overflow_status))
{
send_mess(card, READ_SERVO, PIE516_axis[signal]);
if (recv_mess(card, buff, 1) && sscanf(buff, "%d", &servo_status))
{
send_mess(card, READ_POS, PIE516_axis[signal]);
if (recv_mess(card, buff, 1))
{
motorData = NINT(atof(buff) / cntrl->drive_resolution[signal]);
readOK = true;
}
}
}
}
}
if (readOK)
{
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;
}
}
/* Always DONE if torque disabled */
status.Bits.RA_DONE = (ontarget_status) ? 1 : 0;
status.Bits.RA_HOME = status.Bits.RA_DONE;
status.Bits.EA_POSITION = (servo_status) ? 1 : 0; /* Torgue disabled flag */
ls_active = plusLS = minusLS = false;
/* LS status may be true but servo is not within position error - keep updating */
/* No Limit switches but if the Servo Controller overflows indicate with a + LS */
if (status.Bits.RA_DONE)
plusLS = overflow_status ? true : false;
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 PIE516 board */
/* send_mess() */
/*****************************************************/
static RTN_STATUS send_mess(int card, char const *com, char *name)
{
char local_buff[MAX_MSG_SIZE];
char *pbuff;
struct PIE516controller *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("drvPIE516.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("drvPIE516.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);
pbuff = strchr(local_buff, '#');
if (pbuff != NULL)
*pbuff = *name;
else
Debug(1, "send_mess(): NAME ERROR: message = %s\n", local_buff);
}
Debug(2, "send_mess(): message = %s\n", local_buff);
cntrl = (struct PIE516controller *) motor_state[card]->DevicePrivate;
pasynOctetSyncIO->write(cntrl->pasynUser, local_buff, strlen(local_buff),
COMM_TIMEOUT, &nwrite);
return(OK);
}
/*****************************************************/
/* receive a message from the PIE516 board */
/* recv_mess() */
/*****************************************************/
static int recv_mess(int card, char *com, int flag)
{
struct PIE516controller *cntrl;
size_t nread = 0;
asynStatus status = asynError;
int eomReason;
/* Check that card exists */
if (!motor_state[card])
return(ERROR);
cntrl = (struct PIE516controller *) 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 */
/* PIE516Setup() */
/*****************************************************/
RTN_STATUS
PIE516Setup(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 > PIE516_NUM_CARDS)
PIE516_num_cards = PIE516_NUM_CARDS;
else
PIE516_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 PIE516Config 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(PIE516_num_cards *
sizeof(struct controller *));
for (itera = 0; itera < PIE516_num_cards; itera++)
motor_state[itera] = (struct controller *) NULL;
return(OK);
}
/*****************************************************/
/* Configure a controller */
/* PIE516Config() */
/*****************************************************/
RTN_STATUS
PIE516Config(int card, /* card being configured */
const char *name, /* asyn port name */
int addr) /* asyn address (GPIB) */
{
struct PIE516controller *cntrl;
if (card < 0 || card >= PIE516_num_cards)
return(ERROR);
motor_state[card] = (struct controller *) malloc(sizeof(struct controller));
motor_state[card]->DevicePrivate = malloc(sizeof(struct PIE516controller));
cntrl = (struct PIE516controller *) 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 PIE516controller *cntrl;
int card_index, motor_index;
char buff[BUFF_SIZE], *pbuff;
int total_axis;
int status;
int version;
bool online;
asynStatus success_rtn;
static const char output_terminator[] = EOL_E516;
static const char input_terminator[] = EOL_E516;
initialized = true; /* Indicate that driver is initialized. */
/* Check for setup */
if (PIE516_num_cards <= 0)
return(ERROR);
for (card_index = 0; card_index < PIE516_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 PIE516controller *) 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);
/* Assure that Controller is ONLINE */
do
{
online = false;
/* Set Controller to ONLINE mode */
send_mess(card_index, SET_ONLINE, (char*) NULL);
send_mess(card_index, READ_ONLINE, (char*) NULL);
if ((status = recv_mess(card_index, buff, 1)))
online = (atoi(buff)==1) ? true : false;
else
retry++;
} while (online == false && retry < 3);
send_mess(card_index, GET_IDENT, (char*) NULL);
status = recv_mess(card_index, buff, 1);
/* Parse out E516 revision (2 decimal places) and convert to int */
if ((pbuff = strchr(buff, 'V')))
version = NINT(atof(pbuff+1) * 100);
else
version = 0;
}
if (success_rtn == asynSuccess && online == true)
{
strcpy(brdptr->ident, buff);
brdptr->localaddr = (char *) NULL;
brdptr->motor_in_motion = 0;
/* Check for E516 versions that need the status word shifted up 8 bits */
if (version >= 311)
cntrl->versionSupport = true;
else
cntrl->versionSupport = false;
/* Determine # of axes. Request stage name. See if it responds */
for (total_axis = 0; total_axis < MAX_AXES; total_axis++)
{
send_mess(card_index, READ_POS, PIE516_axis[total_axis]);
status = recv_mess(card_index, buff, 1);
if (!status)
break;
}
brdptr->total_axis = total_axis;
/* Turn ON velocity control mode - All axis */
send_mess(card_index, SET_VELCTRL, (char*) NULL);
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;
/* PIE516 has DC motor support only */
motor_info->encoder_present = YES;
motor_info->status.Bits.EA_PRESENT = 1;
motor_info->pid_present = NO;
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 *) "PIE516_motor", epicsThreadPriorityMedium,
epicsThreadGetStackSize(epicsThreadStackMedium),
(EPICSTHREADFUNC) motor_task, (void *) &targs);
return(OK);
}
-74
View File
@@ -1,74 +0,0 @@
/* File: drvPIE516.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 INCdrvPIE516h
#define INCdrvPIE516h 1
#include "motordrvCom.h"
#include "asynDriver.h"
#include "asynDriver.h"
#include "asynOctetSyncIO.h"
#define COMM_TIMEOUT 2 /* Timeout in seconds. */
#define POS_RES 0.001 /* Position resolution. */
#define EOL_E516 "\n" /* Command End-Of-Line = LF (0x10) */
struct PIE516controller
{
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 versionSupport; /* Track supported Versions - include in Report */
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;
} E516_Status_Reg;
/* Function prototypes. */
extern RTN_STATUS PIE516Setup(int, int);
extern RTN_STATUS PIE516Config(int, const char *, int);
#endif /* INCdrvPIE516h */
-682
View File
@@ -1,682 +0,0 @@
/*
FILENAME... drvPIE517.cc
USAGE... Motor record driver level support for Physik Instrumente (PI)
GmbH & Co. E-516 motor controller.
Version: $Revision: 1.1 $
Modified By: $Author: sullivan $
Last Modified: $Date: 2007-03-30 20:01:05 $
*/
/*
* 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 08/10/16 Bruno Luvizotto (brunoluvizotto@gmail.com) - copied from devPIE516.cc.
* .02 08/10/16 Bruno Luvizotto (brunoluvizotto@gmail.com) - edited the files for the E517 controller.
* Tested on PI VER:
* FW_DSP: 02.034
* FW_FPGA: 02.040
* FW_MCU: 1.22.6
*/
/*
DESIGN LIMITATIONS...
1 - Like all controllers, the PIE517 must be powered-on when EPICS is first
booted up.
*/
#include <string.h>
#include <stdlib.h>
#include <epicsThread.h>
#include <drvSup.h>
#include <errlog.h>
#include "motorRecord.h"
#include "motor.h"
#include "drvPIE517.h"
#include "epicsExport.h"
#define GET_IDENT "VER?"
#define SET_ONLINE "ONL # 1" /* Set Online Mode ON */
#define SET_VELCTRL "VCO # 1" /* Set Velocity Control Mode - Required for DONE */
#define READ_ONLINE "ONL? #" /* Read Online Mode */
#define READ_POS "POS? #" /* Read position */
#define READ_OVERFLOW "OVF? #" /* Read Servo Overflow Status */
#define READ_ONTARGET "ONT? #" /* Read Position ON Target */
#define READ_SERVO "SVO? #" /* Read Servo Enable Status */
#define PIE517_NUM_CARDS 10
#define MAX_AXES 3
#define BUFF_SIZE 100 /* Maximum length of string to/from PIE517 */
/*----------------debugging-----------------*/
volatile int drvPIE517debug = 0;
extern "C" {epicsExportAddress(int, drvPIE517debug);}
static inline void Debug(int level, const char *format, ...) {
#ifdef DEBUG
if (level < drvPIE517debug) {
va_list pVar;
va_start(pVar, format);
vprintf(format, pVar);
va_end(pVar);
}
#endif
}
/* --- Local data. --- */
int PIE517_num_cards = 0;
static char *PIE517_axis[] = {"1 ", "2 ", "3 "}; //{"A", "B", "C"};
/* 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 PIE517_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,
PIE517_axis
};
struct
{
long number;
long (*report) (int);
long (*init) (void);
} drvPIE517 = {2, report, init};
extern "C" {epicsExportAddress(drvet, drvPIE517);}
static struct thread_args targs = {SCAN_RATE, &PIE517_access, 0.0};
/*********************************************************
* Print out driver status report
*********************************************************/
static long report(int level)
{
int card;
if (PIE517_num_cards <=0)
printf(" No PIE517 controllers configured.\n");
else
{
for (card = 0; card < PIE517_num_cards; card++)
{
struct controller *brdptr = motor_state[card];
if (brdptr == NULL)
printf(" PIE517 controller %d connection failed.\n", card);
else
{
struct PIE517controller *cntrl;
cntrl = (struct PIE517controller *) brdptr->DevicePrivate;
printf(" PIE517 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 (PIE517_num_cards <= 0)
{
Debug(1, "init(): PIE517 driver disabled. PIE517Setup() 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 PIE517controller *cntrl;
struct mess_node *nodeptr;
struct mess_info *motor_info;
struct motorRecord *mr;
/* Message parsing variables */
char buff[BUFF_SIZE];
int rtn_state;
unsigned int overflow_status, ontarget_status, servo_status, online_status;
epicsInt32 motorData;
bool plusdir, ls_active, plusLS, minusLS;
bool readOK;
msta_field status;
cntrl = (struct PIE517controller *) 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;
recv_mess(card, buff, FLUSH);
readOK = false;
// send_mess(card, READ_ONLINE, PIE517_axis[signal]);
// if (recv_mess(card, buff, 1) && sscanf(buff, "%d", &online_status))
// {
// if (!online_status)
// {
// /* Assume Controller Reboot - Set ONLINE and Velocity Control ON */
// send_mess(card, SET_ONLINE, PIE517_axis[signal]);
// //send_mess(card, SET_VELCTRL, (char*) NULL);
// }
send_mess(card, READ_ONTARGET, PIE517_axis[signal]);
if (recv_mess(card, buff, 1) && sscanf(buff, "%d", &ontarget_status))
{
send_mess(card, READ_OVERFLOW, PIE517_axis[signal]);
if (recv_mess(card, buff, 1) && sscanf(buff, "%d", &overflow_status))
{
send_mess(card, READ_SERVO, PIE517_axis[signal]);
if (recv_mess(card, buff, 1) && sscanf(buff, "%d", &servo_status))
{
send_mess(card, READ_POS, PIE517_axis[signal]);
if (recv_mess(card, buff, 1))
{
motorData = NINT(atof(buff) / cntrl->drive_resolution[signal]);
readOK = true;
}
}
}
}
// }
if (readOK)
{
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;
}
}
/* Always DONE if torque disabled */
status.Bits.RA_DONE = (ontarget_status) ? 1 : 0;
status.Bits.RA_HOME = status.Bits.RA_DONE;
status.Bits.EA_POSITION = (servo_status) ? 1 : 0; /* Torgue disabled flag */
ls_active = plusLS = minusLS = false;
/* LS status may be true but servo is not within position error - keep updating */
/* No Limit switches but if the Servo Controller overflows indicate with a + LS */
if (status.Bits.RA_DONE)
plusLS = overflow_status ? true : false;
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 PIE517 board */
/* send_mess() */
/*****************************************************/
static RTN_STATUS send_mess(int card, char const *com, char *name)
{
char local_buff[MAX_MSG_SIZE];
char *pbuff;
struct PIE517controller *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("drvPIE517.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("drvPIE517.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);
pbuff = strchr(local_buff, '#');
if (pbuff != NULL)
*pbuff = *name;
else
Debug(1, "send_mess(): NAME ERROR: message = %s\n", local_buff);
}
Debug(2, "send_mess(): message = %s\n", local_buff);
cntrl = (struct PIE517controller *) motor_state[card]->DevicePrivate;
pasynOctetSyncIO->write(cntrl->pasynUser, local_buff, strlen(local_buff),
COMM_TIMEOUT, &nwrite);
return(OK);
}
/*****************************************************/
/* receive a message from the PIE517 board */
/* recv_mess() */
/*****************************************************/
static int recv_mess(int card, char *com, int flag)
{
struct PIE517controller *cntrl;
size_t nread = 0;
asynStatus status = asynError;
int eomReason;
char *pos;
/* Check that card exists */
if (!motor_state[card])
return(ERROR);
cntrl = (struct PIE517controller *) motor_state[card]->DevicePrivate;
if (flag == FLUSH)
pasynOctetSyncIO->flush(cntrl->pasynUser);
else
status = pasynOctetSyncIO->read(cntrl->pasynUser, com, BUFF_SIZE,
COMM_TIMEOUT, &nread, &eomReason);
pos=strchr(com,'=');
if(pos != NULL)
strcpy(com,&pos[1]);
if ((status != asynSuccess) || (nread <= 0))
{
com[0] = '\0';
nread = 0;
}
Debug(2, "recv_mess(): message = \"%s\"\n", com);
return(nread);
}
/*****************************************************/
/* Setup system configuration */
/* PIE517Setup() */
/*****************************************************/
RTN_STATUS
PIE517Setup(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 > PIE517_NUM_CARDS)
PIE517_num_cards = PIE517_NUM_CARDS;
else
PIE517_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 PIE517Config 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(PIE517_num_cards *
sizeof(struct controller *));
for (itera = 0; itera < PIE517_num_cards; itera++)
motor_state[itera] = (struct controller *) NULL;
return(OK);
}
/*****************************************************/
/* Configure a controller */
/* PIE517Config() */
/*****************************************************/
RTN_STATUS
PIE517Config(int card, /* card being configured */
const char *name, /* asyn port name */
int addr) /* asyn address (GPIB) */
{
struct PIE517controller *cntrl;
if (card < 0 || card >= PIE517_num_cards)
return(ERROR);
motor_state[card] = (struct controller *) malloc(sizeof(struct controller));
motor_state[card]->DevicePrivate = malloc(sizeof(struct PIE517controller));
cntrl = (struct PIE517controller *) 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 PIE517controller *cntrl;
int card_index, motor_index;
char buff[BUFF_SIZE], *pbuff;
int total_axis;
int status;
int version;
bool online;
asynStatus success_rtn;
static const char output_terminator[] = EOL_E517;
static const char input_terminator[] = EOL_E517;
initialized = true; /* Indicate that driver is initialized. */
/* Check for setup */
if (PIE517_num_cards <= 0)
return(ERROR);
for (card_index = 0; card_index < PIE517_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 PIE517controller *) 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);
/* Assure that Controller is ONLINE */
online = true;
//do
//{
// online = false;
// /* Set Controller to ONLINE mode */
// send_mess(card_index, SET_ONLINE, (char*) NULL);
// send_mess(card_index, READ_ONLINE, (char*) NULL);
// if ((status = recv_mess(card_index, buff, 1)))
//online = (atoi(buff)==1) ? true : false;
// else
//retry++;
//} while (online == false && retry < 3);
//send_mess(card_index, GET_IDENT, (char*) NULL);
//status = recv_mess(card_index, buff, 1);
/* Parse out E517 revision (2 decimal places) and convert to int */
if ((pbuff = strchr(buff, 'V')))
version = NINT(atof(pbuff+1) * 100);
else
version = 0;
}
if (success_rtn == asynSuccess && online == true)
{
strcpy(brdptr->ident, buff);
brdptr->localaddr = (char *) NULL;
brdptr->motor_in_motion = 0;
/* Check for E517 versions that need the status word shifted up 8 bits */
/*if (version >= 311)
cntrl->versionSupport = true;
else
cntrl->versionSupport = false;*/
/* Determine # of axes. Request stage name. See if it responds */
for (total_axis = 0; total_axis < MAX_AXES; total_axis++)
{
send_mess(card_index, READ_POS, PIE517_axis[total_axis]);
status = recv_mess(card_index, buff, 1);
if (!status)
break;
}
brdptr->total_axis = total_axis;
/* Turn ON velocity control mode - All axis */
//send_mess(card_index, SET_VELCTRL, (char*) NULL);
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;
/* PIE517 has DC motor support only */
motor_info->encoder_present = YES;
motor_info->status.Bits.EA_PRESENT = 1;
motor_info->pid_present = NO;
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 *) "PIE517_motor", epicsThreadPriorityMedium,
epicsThreadGetStackSize(epicsThreadStackMedium),
(EPICSTHREADFUNC) motor_task, (void *) &targs);
return(OK);
}
-75
View File
@@ -1,75 +0,0 @@
/* File: drvPIE516.h */
/* Device Driver Support definitions for motor */
/*
* Original Author: Ron Sluiter
* Current Author: Joe Sullivan
* Date: 09/20/2005
*
* Modification Log:
* -----------------
* .01 08/10/16 Bruno Luvizotto (brunoluvizotto@gmail.com) - copied from drvPIE516.h
* .02 08/10/16 Bruno Luvizotto (brunoluvizotto@gmail.com) - edited the files for the E517 controller
*/
#ifndef INCdrvPIE517h
#define INCdrvPIE517h 1
#include "motordrvCom.h"
#include "asynDriver.h"
#include "asynDriver.h"
#include "asynOctetSyncIO.h"
#define COMM_TIMEOUT 2 /* Timeout in seconds. */
#define POS_RES 0.001 /* Position resolution. */
#define EOL_E517 "\n" /* Command End-Of-Line = LF (0x10) */
struct PIE517controller
{
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 versionSupport; /* Track supported Versions - include in Report */
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;
} E517_Status_Reg;
/* Function prototypes. */
extern RTN_STATUS PIE517Setup(int, int);
extern RTN_STATUS PIE517Config(int, const char *, int);
#endif /* INCdrvPIE517h */
-639
View File
@@ -1,639 +0,0 @@
/*
FILENAME... drvPIE710.cc
USAGE... Motor record driver level support for Physik Instrumente (PI)
GmbH & Co. E-710 motor controller.
*/
/*
* 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 <stdlib.h>
#include <errlog.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-----------------*/
volatile int drvPIE710debug = 0;
extern "C" {epicsExportAddress(int, drvPIE710debug);}
static inline void Debug(int level, const char *format, ...) {
#ifdef DEBUG
if (level < drvPIE710debug) {
va_list pVar;
va_start(pVar, format);
vprintf(format, pVar);
va_end(pVar);
}
#endif
}
/* --- 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
@@ -1,72 +0,0 @@
/* 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 */
-682
View File
@@ -1,682 +0,0 @@
/*
FILENAME... drvPIE816.cc
USAGE... Motor record driver level support for Physik Instrumente (PI)
GmbH & Co. E-816 motor controller.
Version: 1.1
Modified By: sullivan
Last Modified: 2008/10/23 20:01:05
Version: 1.2
Modified By: K. Gofron & K. Lauer
Last Modified: 2011/09/19
Changes required for PIE621 controller.
*/
/*
* Original Author: Ron Sluiter
* Date: 10/18/05
* Current Author: John Hammonds
*
* 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 03/26/07 jph - copied from drvPIE816.cc tested on PI VER "DSP V3.11,MCU V5"
*/
/*
DESIGN LIMITATIONS...
1 - Like all controllers, the PIE816 must be powered-on when EPICS is first
booted up.
*/
#include <string.h>
#include <epicsThread.h>
#include <drvSup.h>
#include <stdlib.h>
#include <errlog.h>
#include "motorRecord.h"
#include "motor.h"
#include "drvPIE816.h"
#include "epicsExport.h"
#define GET_IDENT "*IDN?"
#define SET_ONLINE "ONL 1" /* Set Online Mode ON */
/*#define SET_VELCTRL "VCO A1 B1 C1" */ /* Set Velocity Control Mode - Required for DONE */
#define READ_ONLINE "ONL?" /* Read Online Mode */
#define READ_POS "POS? #" /* Read position */
#define READ_OVERFLOW "OVF? #" /* Read Servo Overflow Status */
#define READ_ONTARGET "ONT? #" /* Read Position ON Target */
#define READ_SERVO "SVO? #" /* Read Servo Enable Status */
#define PIE816_NUM_CARDS 10
#define MAX_AXES 12
#define BUFF_SIZE 100 /* Maximum length of string to/from PIE816 */
/*----------------debugging-----------------*/
volatile int drvPIE816debug = 0;
extern "C" {epicsExportAddress(int, drvPIE816debug);}
static inline void Debug(int level, const char *format, ...) {
#ifdef DEBUG
if (level < drvPIE816debug) {
va_list pVar;
va_start(pVar, format);
vprintf(format, pVar);
va_end(pVar);
}
#endif
}
/* --- Local data. --- */
int PIE816_num_cards = 0;
static char *PIE816_axis[] = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
"K","L"};
/* 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 PIE816_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,
PIE816_axis
};
struct drvPIE816_drvet
{
long number;
long (*report) (int);
long (*init) (void);
} drvPIE816 = {2, report, init};
extern "C" {epicsExportAddress(drvet, drvPIE816);}
static struct thread_args targs = {SCAN_RATE, &PIE816_access, 0.0};
/*********************************************************
* Print out driver status report
*********************************************************/
static long report(int level)
{
int card;
if (PIE816_num_cards <=0)
printf(" No PIE816 controllers configured.\n");
else
{
for (card = 0; card < PIE816_num_cards; card++)
{
struct controller *brdptr = motor_state[card];
if (brdptr == NULL)
printf(" PIE816 controller %d connection failed.\n", card);
else
{
struct PIE816controller *cntrl;
cntrl = (struct PIE816controller *) brdptr->DevicePrivate;
printf(" PIE816 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 (PIE816_num_cards <= 0)
{
Debug(1, "init(): PIE816 driver disabled. PIE816Setup() 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 PIE816controller *cntrl;
struct mess_node *nodeptr;
struct mess_info *motor_info;
struct motorRecord *mr;
/* Message parsing variables */
char buff[BUFF_SIZE];
int rtn_state;
unsigned int overflow_status, ontarget_status, servo_status, online_status;
epicsInt32 motorData;
bool plusdir, ls_active, plusLS, minusLS;
bool readOK;
msta_field status;
cntrl = (struct PIE816controller *) 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;
recv_mess(card, buff, FLUSH);
readOK = false;
//send_mess(card, READ_ONLINE, (char*) NULL);
/* if (recv_mess(card, buff, 1) && sscanf(buff, "%d", &online_status))
{
if (!online_status)
{
*//* Assume Controller Reboot - Set ONLINE and Velocity Control ON */
/*send_mess(card, SET_ONLINE, (char*) NULL);
send_mess(card, SET_VELCTRL, (char*) NULL);
}
*/
send_mess(card, READ_ONTARGET, PIE816_axis[signal]);
if (recv_mess(card, buff, 1) && sscanf(buff, "%d", &ontarget_status))
{
send_mess(card, READ_OVERFLOW, PIE816_axis[signal]);
if (recv_mess(card, buff, 1) && sscanf(buff, "%d", &overflow_status))
{
send_mess(card, READ_SERVO, PIE816_axis[signal]);
if (recv_mess(card, buff, 1) && sscanf(buff, "%d", &servo_status))
{
send_mess(card, READ_POS, PIE816_axis[signal]);
if (recv_mess(card, buff, 1))
{
motorData = NINT(atof(buff) / cntrl->drive_resolution[signal]);
readOK = true;
}
}
}
}
/*
}
*/
if (readOK)
{
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;
}
}
/* Always DONE if torque disabled */
status.Bits.RA_DONE = (ontarget_status) ? 1 : 0;
status.Bits.RA_HOME = status.Bits.RA_DONE;
status.Bits.EA_POSITION = (servo_status) ? 1 : 0; /* Torgue disabled flag */
ls_active = plusLS = minusLS = false;
/* LS status may be true but servo is not within position error - keep updating */
/* No Limit switches but if the Servo Controller overflows indicate with a + LS */
if (status.Bits.RA_DONE)
plusLS = overflow_status ? true : false;
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 PIE816 board */
/* send_mess() */
/*****************************************************/
static RTN_STATUS send_mess(int card, char const *com, char *name)
{
char local_buff[MAX_MSG_SIZE];
char *pbuff;
struct PIE816controller *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("drvPIE816.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("drvPIE816.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);
pbuff = strchr(local_buff, '#');
if (pbuff != NULL)
*pbuff = *name;
else
Debug(1, "send_mess(): NAME ERROR: message = %s\n", local_buff);
}
Debug(2, "send_mess(): message = %s\n", local_buff);
cntrl = (struct PIE816controller *) motor_state[card]->DevicePrivate;
pasynOctetSyncIO->write(cntrl->pasynUser, local_buff, strlen(local_buff),
COMM_TIMEOUT, &nwrite);
return(OK);
}
/*****************************************************/
/* receive a message from the PIE816 board */
/* recv_mess() */
/*****************************************************/
static int recv_mess(int card, char *com, int flag)
{
struct PIE816controller *cntrl;
size_t nread = 0;
asynStatus status = asynError;
int eomReason;
/* Check that card exists */
if (!motor_state[card])
return(ERROR);
cntrl = (struct PIE816controller *) 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 */
/* PIE816Setup() */
/*****************************************************/
RTN_STATUS
PIE816Setup(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 > PIE816_NUM_CARDS)
PIE816_num_cards = PIE816_NUM_CARDS;
else
PIE816_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 PIE816Config 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(PIE816_num_cards *
sizeof(struct controller *));
for (itera = 0; itera < PIE816_num_cards; itera++)
motor_state[itera] = (struct controller *) NULL;
return(OK);
}
/*****************************************************/
/* Configure a controller */
/* PIE816Config() */
/*****************************************************/
RTN_STATUS
PIE816Config(int card, /* card being configured */
const char *name, /* asyn port name */
int addr) /* asyn address (GPIB) */
{
struct PIE816controller *cntrl;
if (card < 0 || card >= PIE816_num_cards)
return(ERROR);
motor_state[card] = (struct controller *) malloc(sizeof(struct controller));
motor_state[card]->DevicePrivate = malloc(sizeof(struct PIE816controller));
cntrl = (struct PIE816controller *) 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 PIE816controller *cntrl;
int card_index, motor_index;
char buff[BUFF_SIZE], *pbuff;
int total_axis;
int status;
int version;
bool online;
asynStatus success_rtn;
static const char output_terminator[] = EOL_E816;
static const char input_terminator[] = EOL_E816;
initialized = true; /* Indicate that driver is initialized. */
/* Check for setup */
if (PIE816_num_cards <= 0)
return(ERROR);
for (card_index = 0; card_index < PIE816_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 PIE816controller *) 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);
/* Assure that Controller is ONLINE */
online = true;
/* do
{
online = false;
*/
/* Set Controller to ONLINE mode */
/* send_mess(card_index, SET_ONLINE, (char*) NULL);
send_mess(card_index, READ_ONLINE, (char*) NULL);
if ((status = recv_mess(card_index, buff, 1)))
online = (atoi(buff)==1) ? true : false;
else
retry++;
} while (online == false && retry < 3);
*/
send_mess(card_index, GET_IDENT, (char*) NULL);
status = recv_mess(card_index, buff, 1);
/* Parse out E816 revision (2 decimal places) and convert to int */
if ((pbuff = strchr(buff, 'V')))
version = NINT(atof(pbuff+1) * 100);
else
version = 0;
}
if (success_rtn == asynSuccess && online == true)
{
strcpy(brdptr->ident, buff);
brdptr->localaddr = (char *) NULL;
brdptr->motor_in_motion = 0;
/* Check for E816 versions that need the status word shifted up 8 bits */
/*
if (version >= 311)
cntrl->versionSupport = true;
else
cntrl->versionSupport = false;
*/
/* Determine # of axes. Request stage name. See if it responds */
for (total_axis = 0; total_axis < MAX_AXES; total_axis++)
{
send_mess(card_index, READ_POS, PIE816_axis[total_axis]);
status = recv_mess(card_index, buff, 1);
if (!status)
break;
}
brdptr->total_axis = total_axis;
/* Turn ON velocity control mode - All axis */
/*send_mess(card_index, SET_VELCTRL, (char*) NULL);*/
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;
/* PIE816 has DC motor support only */
motor_info->encoder_present = YES;
motor_info->status.Bits.EA_PRESENT = 1;
motor_info->pid_present = NO;
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 *) "PIE816_motor", epicsThreadPriorityMedium,
epicsThreadGetStackSize(epicsThreadStackMedium),
(EPICSTHREADFUNC) motor_task, (void *) &targs);
return(OK);
}
-74
View File
@@ -1,74 +0,0 @@
/* File: drvPIE816.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 INCdrvPIE816h
#define INCdrvPIE816h 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. */
#define EOL_E816 "\n" /* Command End-Of-Line = LF (0x10) */
struct PIE816controller
{
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 versionSupport; /* Track supported Versions - include in Report */
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;
} E816_Status_Reg;
/* Function prototypes. */
extern RTN_STATUS PIE816Setup(int, int);
extern RTN_STATUS PIE816Config(int, const char *, int);
#endif /* INCdrvPIE816h */