esrf

Beamline Instrument Software Support
SPEC Macro documentation: [ Macro Index | BCU Home ]

#%TITLE%  PIEZO.MAC 
#%NAME% 
#  Macros to control a piezo connected to an ICV712 Vme card
#%DESCRIPTION%
#  This macro set let you use a piezo as a motor in spec. As this function
#  is implemented on the macro level - not all commands will work
#%EXAMPLE%
#%DL%
#%DT% mv piezo1 50  %DD%    (move the piezo1 to 50 micrometer)
#%DT%  ascan piezo2 0 10 10 1 %DD%
# (scan piezo2 from 0 to 10 microm. in 10 steps 
#                          and count for 1 second)
#%DT%  a2scan piezo1 0 20 opti -5 5 10 1 %DD%
#(scan the optical table stepper motor from
#     -5 to 5 degrees and scan at the same time the piezo1 from 0 to 20 micr.)
#%XDL%
#%END%

#%UU% [No of piezos] [piezo1 motor name] [piezo1 device name] ...
#%MDESC% Adds the given piezos to the already defined piezos 

def piezoadd '
{
global PIEZO_NO PIEZO_DEV PIEZO_MNE
local _pdev _pmne
_pdev[0]="$3" ; _pdev[1]="$5" ; _pdev[2]="$7" ; _pdev[3]="$9" ; _pdev[4]="$11"
_pmne[0]="$2" ; _pmne[1]="$4" ; _pmne[2]="$6" ; _pmne[3]="$8" ; _pmne[4]="$10"

nodev = int (($#-1)/2)

for (i=0; i< nodev; i++) {
    PIEZO_MNE[PIEZO_NO+i]=_pmne[i]
    PIEZO_DEV[PIEZO_NO+i]=_pdev[i]
  }

PIEZO_NO += nodev

piezoon
}'

#%UU%  [No of piezos] [piezo1 motor name] [piezo1 device name] ...
#%MDESC%

#               ... [piezo n motor name] [piezo n device name]
#             Sets up the piezo motor. You have to do that before 
#             you can use the piezo. If you
#             don't provide the dev name you will be asked for it . 
#             ATTENTION You have to enclose the device name with ""
#             otherwise the / in the name will be interpreted as a
#             division.
def piezosetup '
{
global PIEZO_NO PIEZO_DEV PIEZO_MNE PIEZO_MAXNO PIEZO_TIME PIEZO_MAXSTEP
global PIEZO_STEPSIZE PIEZO_OLDPOS PIEZO_ON
global ppstring
local _pmne _pdev nomne nodev

PIEZO_MAXNO=5

if ($# > PIEZO_MAXNO*2+1) {
  print "Usage:  piezosetup [no of piezos] [piezo mne 1] [dev name piezo1] .."
  print "                 ... [piezo mne n] [dev name piezon] "
  exit
}

_pdev[0]="$3" ; _pdev[1]="$5" ; _pdev[2]="$7" ; _pdev[3]="$9" ; _pdev[4]="$11"
_pmne[0]="$2" ; _pmne[1]="$4" ; _pmne[2]="$6" ; _pmne[3]="$8" ; _pmne[4]="$10"

if ($# == 0) {
  PIEZO_NO = getval("How many piezos do you want to use ",PIEZO_NO)
  for (i = 0; i < PIEZO_NO; i++) {
    PIEZO_MNE[i] = getval(sprintf("Mnemonic for piezo no %d",i + 1),\
				PIEZO_MNE[i])
    PIEZO_DEV[i] = getval(sprintf("ESRF Device name of piezo",i+1),\
				PIEZO_DEV[i])
  } 
} else {
  PIEZO_NO = $1
  for (i = 0; i < PIEZO_NO; i++) {
    PIEZO_MNE[i] = _pmne[i]
    PIEZO_DEV[i] = _pdev[i]
  }
}
} '
#%UU% <step delay time or 0> <max. jump> <step size>
#%MDESC%
# We test if the move is bigger than
# <max jump> and if yes move in steps of <step size> to the requested value.
# The time between each step is given in <step delay time>. If this time is
# equal to 0 then the safety service is desactivated.
def piezosafety '{
if ($#) {
  PIEZO_TIME = $1
  PIEZO_MAXSTEP = $2
  PIEZO_STEPSIZE = $3
} else {
  PIEZO_TIME = getval("Time between each safety piezo step (0 == no safety)",\
		       PIEZO_TIME)
  if (PIEZO_TIME) {
     PIEZO_MAXSTEP = getval("Maximum allowed step for single move",\
		            PIEZO_MAXSTEP)
     PIEZO_STEPSIZE = getval ("Step size for safety move", PIEZO_STEPSIZE)
  }
}
piezoon
}'


#%UU% 
#%MDESC% Defines pseudo motors for piezos. Switches these motors on. Move of
# pseudo motor will move piezos.
def piezoon '
{
  for (i=0;i<PIEZO_NO; i++) {
    cdef ("user_moveall",sprintf("_piezomove %s %s %f %f %f;",PIEZO_MNE[i],\
	 PIEZO_DEV[i], PIEZO_TIME, PIEZO_MAXSTEP, PIEZO_STEPSIZE), \
	 PIEZO_MNE[i], 0x1 )
    cdef ("user_getpangles",sprintf("_piezogetangles %s %s; ",PIEZO_MNE[i],\
	 PIEZO_DEV[i]), PIEZO_MNE[i], 0x1 )
  } 
  PIEZO_ON = 1
} '

#%UU%
#%MDESC% Switches all piezos off. Motor can be moved but no effect on piezos
def piezooff '{
  for (i=0; i<PIEZO_NO; i++) {
      cdef("","",PIEZO_MNE[i],"delete")
  }
  PIEZO_ON = 0
}'
                   
#%IU% <mnemonic> <esrf device name>
#%MDESC% Read valueback from piezo device server and put it into A array
def _piezogetangles '{  
    local val

    val =  esrf_io("$2","DevReadValue")

    if (ESRF_ERR == 0) {
        A[$1] = val
        PIEZO_OLDPOS[$1] = val
    }
}'

#%IU% <mne> <device-name> <step delay time or none> <max. jump> <step size>
#%MDESC%
# Moves piezo . If 3rd parameter is none or 0 we will directly go to the new
# value. If the 3 parameter contains a time we test if the move is bigger then
# <max jump> and if yes move in steps of <step size> to the requested value.
# The time between each step is given in <step delay time>.

def _piezomove '{
  local DIFF newpos ix step_sign n_steps
  DIFF = A[$1]- PIEZO_OLDPOS[$1]
  if(DIFF) {
    if ("$3" != "none" && "$3" != "0" && fabs(DIFF) > $4){
      if(DIFF > 0) 
        step_sign = 1
      else 
        step_sign = -1
      if ($5) {
        n_steps = fabs (int ( DIFF / $5 ))
        for(ix = 1; ix <= n_steps; ix++) {
          newpos = PIEZO_OLDPOS[$1] + (ix * $5 * step_sign)
          esrf_io ("$2", "DevSetValue", newpos)
          sleep($3)
        }
      }  
    }
    esrf_io("$2","DevSetValue",A[$1])
    }
} '
                       
#%MACROS%
#%IMACROS%
#%DEPENDENCIES%
#  To use a piezo as a motor the following conditions have to be fulfilled:
#%UL%
#%LI% The file piezo.mac has to be read in               done by: startup s.
#    (this file needs: pseudo.mac , stchanges.mac)
#%LI% the piezo motors have to be configured            done by: SPECADM
#       (Controller NONE, mnemonic as in startupscript)
#%LI% setup the piezos ( with piezosetup )              done by: startup s.
#%XUL%
#%AUTHOR%
#%TOC%