#%TITLE% OSCIL.MAC
#%NAME%
# Macros for synchronisation beam shutter/Phi spindle
#
#%CATEGORY% Obsolete
#%DESCRIPTION%
# The macros allow the Phi spindle motion of the
# diffractometer and the control of the beam shutter to be synchronized . This macros
#should be not directly used and are called from other macros (see ccd.mac
# and mar.mac files)
#
#%LOG%
# $Log: oscil.mac,v $
# Revision 1.3 2012/05/04 14:06:53 guilloud
# *changed MI_PAR for a good function to read SR current
#
# Revision 1.2 2008/08/12 15:21:01 rey
# documentation changes
#
# Revision 1.1 2002/04/29 13:23:00 claustre
# Initial revision
#
# initial: 10.95
# author: L. claustre
# Modified:
# copy to the ICNTL master dir. and split into oscil.mac and bac24.mac
# 15/09/2000
# Now we can "oscillate" 2 axis the PX phi and omega spindle !!
# 04/06/98 L.C.
######################################################################
#%END%
#####################################################################
global OSCIL_P1 OSCIL_P2 OSCIL_P3 OSCIL_DEFVELOCITY OSCIL_MOTOR_NUM OSCIL_DEFVELOCITY OSCIL_SER_NUM
global OSCIL_MOTOR_NAME
global OSCIL_SY_MODE OSCIL_PREDELAY OSCIL_POSTDELAY
global DS_VCT6_NAME OSCIL_STEP_MARGIN
#####################################################################
#%UU% ["name of the PHI rotation motor"] ["name of the OMEGA rotation motor"] ["shutter-pre-delay"] ["shutter-post-delay"] ["synchro type"]
# %MDESC%
# has to be called first for initialisation of the goniostat axis control
# and synchronisation setting up.
#####################################################################
def oscilsetup'
{
#~~~~~~~~~~~~~~~~~~~~~~
spec_par("modify_step_size",1)
if ($#){
OSCIL_MOTOR_NAME = "$1"
OSCIL_PREDELAY = $2
OSCIL_POSTDELAY = $3
OSCIL_STEP_MARGIN = $4
OSCIL_SY_MODE= "$5"
DS_VCT6_NAME= "$6"
}
else {
OSCIL_MOTOR_NAME = sprintf("%s",getval("Name of axis", OSCIL_MOTOR_NAME))
OSCIL_PREDELAY = getval ("Pre Delay of the shutter to be used (ms)", OSCIL_PREDELAY)
OSCIL_POSTDELAY = getval ("Post Delay of the shutter to be used (ms)", OSCIL_POSTDELAY)
OSCIL_STEP_MARGIN = getval ("Delay before/after shutter open/close positions (steps))", OSCIL_STEP_MARGIN)
OSCIL_SY_MODE = sprintf("%s", getval ("Synchro hardware (bac24 / vct6)", OSCIL_SY_MODE))
if (OSCIL_SY_MODE == "vct6"){
DS_VCT6_NAME= sprintf("%s",getval("Name of the VCT6 device server",DS_VCT6_NAME))
} else if (OSCIL_SY_MODE == "bac24") {
}else {
print "Wrong synchro hardware type"
}
}
if((OSCIL_MOTOR_NUM = motor_num(OSCIL_MOTOR_NAME)) == -1) {
printf ("Error: Motor %s doesn\'t exist\n", OSCIL_MOTOR_NAME)
fprintf ("pipe","[B]abort_from_spec %s[E]",sprintf("Motor %s doesn\'t exist\n",OSCIL_MOTOR_NAME))
exit
}
if (OSCIL_SY_MODE != "bac24" && OSCIL_SY_MODE != "vct6") {
printf ("wrong Synchro. type (%s), allowed are vct6 or bac24",OSCIL_SY_MODE)
exit
}
#
# Back up the default velocity of the axis
#
OSCIL_DEFVELOCITY = motor_par(OSCIL_MOTOR_NUM,"velocity")
}'
#####################################################################
#%IU%
#%MDESC%
# clean up macro called when spec received the INT signal (by typing Ctrl-C)
# allows to stop the current command (e.g. a scan command), restores
# the defaults motor parameters (speed ..)
######################################################################
def oscil_cleanup '
{
rdef cleanup \'
undef cleanup
printf("Restore default configuration\n")
motor_par(OSCIL_MOTOR_NUM,"velocity", OSCIL_DEFVELOCITY)
if (OSCIL_SY_MODE == "vct6") {
vct6_clear
} else {
bac24_stop
}
\'
}'
#####################################################################
#%IU% ["Edge value"] ["gate value"]
#%MDESC%
#Set up parameters of the the VCT6 channel to get a gate generation
#according to the parameters.
#
#####################################################################
def vct6_set '
{
# Initialize the vct6 channels to the desired mode ( GateGen)
vct6_devname[0] = sprintf("%s/1", DS_VCT6_NAME)
vct6_devname[2] = sprintf("%s/3", DS_VCT6_NAME)
vct6_init[0] = 0 # Master
vct6_init[1] = 0 # No gate
vct6_init[2] = 1 # External clock
vct6_init[3] = 0 # Clock Frequency, Not used
vct6_init[4] = 0 # No free run mode
vct6_init[5] = 1 # External Start counting signal
vct6_init[6] = 0 # Internal stop counting
vct6_init[7] = 0 # Desabled divider mode
vct6_init[8] = 0 # Desabled autoclear of counting value
vct6_init[9] = 0 #
vct6_init[10] = 1 # External precount clock
esrf_io(vct6_devname[0], "DevCntInit", vct6_init)
# Test time
vct6_init[0] = 1 # Slave
vct6_init[1] = 0 # No gate
vct6_init[2] = 0 # Internal clock
vct6_init[3] = 1 # Clock Frequency of 1MHz
vct6_init[4] = 0 # No free run mode
vct6_init[5] = 0 # External Start counting signal
vct6_init[6] = 0 # Internal stop counting
vct6_init[7] = 0 # Desabled divider mode
vct6_init[8] = 0 # Desabled autoclear of counting value
vct6_init[9] = 0 #
vct6_init[10] = 0 # Internal precount clock
esrf_io(vct6_devname[2], "DevCntInit", vct6_init)
esrf_io(vct6_devname[0] ,"DevCntStop")
esrf_io(vct6_devname[0], "DevCntClear")
esrf_io(vct6_devname[0], "DevCntEdgeSet", $1)
esrf_io(vct6_devname[0], "DevCntPresetValue", $2)
esrf_io(vct6_devname[0], "DevCntStart")
esrf_io(vct6_devname[2], "DevCntStart")
}'
#####################################################################
#%IU%
#%MDESC%
# Stop the vct6 Master timer (channel 1)
#
#####################################################################
def vct6_stop '{
vct6_devname[0] = sprintf("%s/1", DS_VCT6_NAME)
esrf_io(vct6_devname[0] ,"DevCntStop")
esrf_io(vct6_devname[0], "DevCntClear")
}'
#####################################################################
#%IU% ["start angle"] ["stop angle"] ["time"]
#%MDESC%
# According to the motor parameters, the angle positions and the
# Oscillation time, performs the motor motion and the synchronisation
# with the fast beam shutter (by using the maxcount2 box or the VCT6 board).
##
#####################################################################
def phi_oscillation '
{
oscillation_prepare $*
oscillation
}'
#####################################################################
#%IU% ["start angle"] ["stop angle"] ["time"]
#%MDESC%
# According to the motor parameters, the angle positions and the
# Oscillation time, performs the motor motion and the synchronisation
# with the fast beam shutter (by using the maxcount2 box or the VCT6 board).
##
#####################################################################
def oscillation_prepare '
{
global SENSI42_
#
# D. Spruce
# controlling variables to switch on diagnostic mode or not
# the vct6 setup is done in the macro diag_rot_image which controls
# this variable
global DO_DIAGNOSTIC
#
# D. Spruce
# keep a record of the diode counts while collecting an image
#
global EXPOSURE_COUNTS START_COUNTS curr_intensity
global step_size enco_step_size velocity acceleration deceleration slew_rate
global dslope slope shutter_gate init_angle final_angle enco_step_time step_time predelay
global postdelay
global shutter_edge
# Added by D. Spruce
global nflux42
#
# Added by D. Spruce to return if in simulation mode 11/3/98
#
if ( set_sim(-1) ) {
fprintf("pipe","[B]finished[E]")
return
}
#
# Install the cleanup macro
#
oscil_cleanup
OSCIL_DEFVELOCITY= motor_par(OSCIL_MOTOR_NUM,"velocity")
acceleration = (2 * motor_par(OSCIL_MOTOR_NUM,"acceleration"))
enco_step_size = fabs(motor_par(OSCIL_MOTOR_NUM,"encoder_step_size"))
step_size = motor_par(OSCIL_MOTOR_NUM,"step_size")
velocity = fabs ($2 - $1) / ($3)
slew_rate = velocity * step_size
if (OSCIL_SY_MODE == "bac24") { # Bac24
enco_step_time = (1/(velocity *enco_step_size)) * 1000 # in ms
predelay = fabs(int(OSCIL_PREDELAY / enco_step_time))
postdelay = fabs(int(OSCIL_POSTDELAY / enco_step_time))
}
if (OSCIL_SY_MODE == "vct6"){ # VCT6
step_time = (1/(velocity * step_size)) * 1000 # in ms
predelay = fabs(int(OSCIL_PREDELAY / step_time))
postdelay = fabs(int(OSCIL_POSTDELAY / step_time))
}
if (MARDEBUG) {
if (OSCIL_SY_MODE =="bac24")
printf("enco. step time = %f ms\n", enco_step_time)
else
printf("motor step time = %f ms\n", step_time)
printf("sh. predelay = %d steps\n", predelay)
printf("sh. postdelay = %d steps\n", postdelay)
}
# VPAP has no deceleration parameter, slope=dslope
slope = (velocity * (acceleration / 1000)) + (OSCIL_STEP_MARGIN/step_size) # Slope in degree
dslope = slope
if (OSCIL_SY_MODE == "bac24") { # BAC24
shutter_gate = int(fabs($2 - $1) * enco_step_size)- postdelay
}
if (OSCIL_SY_MODE == "vct6") { # VCT6
shutter_gate = int(fabs($2 - $1) * step_size)- postdelay
}
if($1 > $2){
init_angle = $1 + slope
final_angle = $2 - dslope
} else {
init_angle = $1 - slope
final_angle = $2 + dslope
}
if (MARDEBUG) {
printf("velocity = %f deg./s (%d steps/s)\n", velocity, velocity * enco_step_size)
printf("calc. slope = %f deg.(s) (%d steps)\n", slope, slope* enco_step_size)
printf("shutter gate = %d step(s)\n", shutter_gate)
}
A[OSCIL_MOTOR_NUM] = init_angle
move_em;waitmove;get_angles
printf("Moving %s to %f \(- %f\)\n",OSCIL_MOTOR_NAME,init_angle+dslope,dslope)
#
# Get the real encoder position to calculate the P1 and P2
# Bac24 (Box), or the VCT6 counter values.
#
slope = fabs($1 - A[OSCIL_MOTOR_NUM])
if (OSCIL_SY_MODE == "bac24") { # Bac24
OSCIL_P1 = int(slope * enco_step_size)- predelay
OSCIL_P2 = OSCIL_P1 + shutter_gate + predelay
if (MARDEBUG) {
printf(" real slope = %f degree (%d steps)\n", slope, slope*enco_step_size)
printf("BAC24 P1 = %d steps\n", OSCIL_P1)
printf("BAC24 P2 = %d steps\n", OSCIL_P2)
}
bac24_2pos (OSCIL_P1, OSCIL_P2)
}
if (OSCIL_SY_MODE == "vct6") { # VCT6
shutter_edge = int(slope * step_size)- predelay
if (MARDEBUG) {
printf(" real slope = %f degree (%d steps)\n", slope, slope*step_size)
printf("SHUTTER EDGE = %d steps\n", shutter_edge)
printf("SHUTTER GATE = %d steps\n", shutter_gate)
}
vct6_set shutter_edge shutter_gate
}
}'
#####################################################################
#%IU%
#%MDESC%
# According to the motor parameters, the angle positions and the
# Oscillation time, performs the motor motion and the synchronisation
# with the fast beam shutter (by using the maxcount2 box or the VCT6 board).
# HAS TO BE CALLED AFTER A CALL OF oscillation_prepare
##
#####################################################################
def oscillation '
{
local _sr_current
#
# Now, start the oscillation
#
waitmove; get_angles
motor_par(OSCIL_MOTOR_NUM,"velocity", slew_rate)
A[OSCIL_MOTOR_NUM] = final_angle
printf("Moving %s to %f \(+ %f\)\n",OSCIL_MOTOR_NAME,final_angle-dslope,dslope)
#
# kludge to tell ProDC that the fast shutter is open
# (until its possible to really read the value, i.e its cabled
# D.Spruce 18/06/97
# added reading of pin42 (D.Spruce) 10/2/98
#
fprintf("pipe","[B]fast_shutter OPEN[E]")
#
# 17/5/99 count for the length of the exposure and normalise to 1 sec
# store the relevant pin diode counts to gice to prodc
# the pin diode name is really specific to the beamline
#
# Count for longer (proportional to the extra distance moved by phi)
# This is only necessary if the diode is AFTER the fast shutter so we
# make sure that the full exposure is captured while counting
# other wise we only need to count for the normal count time
# i.e 1 second
# time_to_count = (final_angle - init_angle) / ($2 - $1) * $3
# p "count for " time_to_count " seconds"
count_em 1
#
# put zap scan commands here to remove timing of all other movements
# D.Spruce
if ( DO_DIAGNOSTIC == 1) {
zapvct6start
}
move_em; waitmove
if ( DO_DIAGNOSTIC == 1) {
zapvct6stop
}
get_angles
get_counts
fprintf("pipe","[B]fast_shutter CLOSED[E]")
# Only normalise for the real time the shutter was open
global norm_factor
EXPOSURE_COUNTS = S[peh1]
p "got " EXPOSURE_COUNTS " counts"
mach_current = esrf_dc("sys/mach/current","DevRead")
if ( norm_factor == 0 ) { norm_factor = 5.43 }
if ( mach_current > 0 ) {
# curr_intensity = EXPOSURE_COUNTS /mach_current * norm_factor
curr_intensity = EXPOSURE_COUNTS
fprintf("pipe","[B]dc_msg %s[E]",sprintf("\tIntensity is %6.1f\n ",curr_intensity))
}
#
# Make sure there can be no errors here
#
# calculate the normalised flux for pin42 (ProDC has recently got current)
#
_sr_current = mi_SR_Current()
if ( MI_PAR["CURR"] != 0 ) {
nflux42 = flux42/(_sr_current/100)
}
else {
nflux42 = 0
}
Xval("pd42",sprintf("%7.2g",nflux42))
Xval("pd42c",sprintf("%d",S[cntti23]))
waitcount
#
# Restore the defaults motor velocity
#
undef cleanup
motor_par(OSCIL_MOTOR_NUM,"velocity", OSCIL_DEFVELOCITY)
if (OSCIL_SY_MODE == "bac24") { # Bac24
# Make the BAC24 I box inactive (for the shutter)
bac24_stop
}
fprintf("pipe","[B]finished[E]")
}'
#####################################################################
#%IU% ["channel-num"] ["gate-time"]
#%MDESC%
# allows us to generate from the VCT6 card a gate on the %B%channel-num%B%
# channel (1 to 2) of duration %B%gate-time%B% in seconds.
#####################################################################
def sy_test '
{
local vct6_devname vct6_init chan_num sy_time
if ($#) {
chan_num = $1
sy_time = $2
}
else {
chan_num = getval("GateGen channel number (1-2)", 1)
sy_time = getval("Time (s)", 1)
}
#
# Initialize the vct6 channels to the desired mode ( GateGen)
#
vct6_devname = sprintf("%s/%d", DS_VCT6_NAME, chan_num)
vct6_init[0] = 0 # Master
vct6_init[1] = 0 # No gate
vct6_init[2] = 0 # Internal clock
vct6_init[3] = 1 # Clock Frequency, 1 MHz
vct6_init[4] = 0 # No free run mode
vct6_init[5] = 0 # InternaL Start counting signal
vct6_init[6] = 0 # Internal stop counting
esrf_io(vct6_devname, "DevCntInit", vct6_init)
esrf_io(vct6_devname ,"DevCntStop")
esrf_io(vct6_devname, "DevCntClear")
esrf_io(vct6_devname, "DevCntPresetTime", sy_time)
esrf_io(vct6_devname, "DevCntStart")
esrf_io(vct6_devname, "DevCntStart")
}'
### +SW
def XHuberFinished '
{
on("pipe")
offt
printf("[B]Huber_finished[E]")
off("pipe")
ont
}'
### -SW
#%MACROS%
#%IMACROS%
#%DEPENDENCIES%
# The files oscil.mac and bac24.mac have to be read in ! done by: startup script
#%AUTHOR% Laurent Claustre, 15/09/2000
# $Revision: 1.3 $, $Date: 2012/05/04 14:06:53 $
#%TOC%
|