esrf

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

#%TITLE% piezo_serial.MAC
#%NAME% 
# Macros to control a piezo cristal connected via serial line. Version 2.0
#%DESCRIPTION%
#  This macro file allows to connect a piezo to a pseudo motor in SPEC.
#  Derived from dac.mac
#%DL%
#%DT%  History:
#%DT%    2.0 31.3.2000 Multiple channels per controller handled properly.
#%XDL%
#
#%EXAMPLE%
#%DL%
#%DT%  mv pzo1 5.3  %DD% Value of 5.3 (unit um) set in piezo pzo1.
#%DT%  ascan pzo2 0 10 10 1 %DD%
#        (scan pzo2 from 0 to 10 in 10 steps and count for 1 second)
#%DT%  a2scan pzo1 0 20 opti 0 5 10 1 %DD%
#        (scan the optical table stepper motor from
#        0 to 5 degrees and scan at the same time the pzo1 from 0 to 20 micr.)
#%XDL%
#%END%

#%UU% [No of pzos] [pzo1 motor name] [pzo1 device name] ...
#%MDESC% Adds the given piezos to the already defined pzos 
#
global PZOSER_ON PZOSER_LIST PZOSER_A_OLD PZOSER_DIRTY
list_test PZOSER_LIST

#%IU% pzo-mnemonic serial_id channel_nr servo_val
#%MDESC%
#   Add definitions for a piezo pseudomotor
def pzoseradd  'pzoser_add("$1", $2, "$3", $4)'

#%IU% (pzo-mnemonic, serial_id, channel_nr, servo_val)
#%MDESC%
#   Add definitions for a piezo pseudomotor
def pzoser_add(mne, dev, nr, serv) '{

   if (motor_num(mne) == -1) {
     printf("Motor \"%s\" does not exist, exit\n", mne)
     exit
   }
   
   if ((nr != "A") && (nr != "B") && (nr != "C") && (nr != "D")) {
     printf("Channel must be A, B, C or D exit\n")
     exit
   }
   
   pzoseroff
   
   list_add(PZOSER_LIST, mne)
   list_setpar(PZOSER_LIST, mne, "dev", dev)
   list_setpar(PZOSER_LIST, mne, "nr", nr)
   if (serv == 0)
     list_setpar(PZOSER_LIST, mne, "serv", 0)
   else
     list_setpar(PZOSER_LIST, mne, "serv", 1)

   pzoseron
   
   setup_tail("pzoser", sprintf("pzoser_%s %s", mne, mne))
}'

#%IU% (pzo-mnemonic)
#%MDESC%
#   Delete definitions for one PZO mnemonic
#
def pzoserunsetup '{
   pzoserdel("$2")
}'

#%IU% (pzo-mnemonic)
#%MDESC%
#   Delete definitions for one PZO mnemonic
#
def pzoserdel(mne) '{
   list_remove(PZOSER_LIST, mne)
   cdef("", "", mne, "delete")

}'


#%UU%
#%MDESC%
#  Reset internal lists.
def pzoserreset '
   pzoseroff
   list_init PZOSER_LIST
'

#%UU%
#%MDESC%
#  Shows current PZO pseudomotors definition.
#
def pzosershow '{
   local pzono mne

   if (pzono = list_n(PZOSER_LIST)) {
 
      printf("\nPIEZO pseudomotors are \"%s\"\n\n",PZOSER_ON?"ACTIVE":"NOT ACTIVE")
      printf("\t   Motor           Device  Channel  Servo       Config\n") 
      printf("\t------------------------------------------------------\n") 
      for (i=1; i<=pzono; i++) {
         mne =  list_item(PZOSER_LIST, i)
         printf("\t%8s  %15s  %7s  %5d", mne, \
                         list_getpar(PZOSER_LIST, mne, "dev"),\
                         list_getpar(PZOSER_LIST, mne, "nr"), \
                         list_getpar(PZOSER_LIST, mne, "serv"))
         if (motor_num(mne) < 0) 
            printf(" %11s\n","NOT DEFINED")
         else 
            printf(" %11s\n","OK")
      }
      printf("\n")
   } else
      printf("Nothing defined for PIEZO\n")
}' 

#%UU% 
#%MDESC% 
#  Deactivates definitions for PZO pseudomotors.
def pzoseroff '
{
   local pzono

   pzono = list_n(PZOSER_LIST)

   for (i = 1; i <= pzono; i++) {
      cdef("", "", list_item(PZOSER_LIST, i), "delete")
   } 
   PZOSER_ON=0
}'

#%UU% 
#%MDESC%
#  Activates definitions for PZO pseudomotors.
#
def pzoseron '
{
   local pzono num mne dev nr serv

   pzono = list_n(PZOSER_LIST)

   for (i=1; i <= pzono; i++) {
      num = motor_num(mne = list_item(PZOSER_LIST, i))
      if (num != -1 ) {
         dev = list_getpar(PZOSER_LIST, mne, "dev")
         nr  = list_getpar(PZOSER_LIST, mne, "nr")
         serv = list_getpar(PZOSER_LIST, mne, "serv")

         # set controller in ONLINE mode
         ser_put(dev, "ONL 1\n")
         sleep(0.1)
         
         # set step size parameters
         
         ser_put(dev, sprintf("SPA %s7 1\n", nr))
         ser_put(dev, sprintf("SPA %s8 0\n", nr))
         ser_put(dev, sprintf("SPA %s9 100\n", nr))
         ser_put(dev, sprintf("SPA %s10 0\n", nr))
         
         # set servo mode
         ser_put(dev, sprintf("SVO %s%d\n", nr, serv)) 
         sleep(0.1)
           
				 # moving by position
         cdef("user_checkall",   sprintf("_pzoser_move %s\n", mne), mne, 0x01)
         cdef("user_getpangles", sprintf("_pzoser_getpos %s\n", mne), mne, 0x01)
         
         # force reading first time
         PZOSER_DIRTY[num] = 1
      }
   } 
   PZOSER_ON=1

   setup_tail("pzoser", sprintf("pzoser_%s %s", mne, mne))

   # position control
   printf("PIEZO pseudomotors are now ACTIVE\n")
}'

#%IU%
#
def pzoser_force_read '{
   local mne val
   
   mne = "$1"
   val = $2
     
   list_setpar(PZOSER_LIST, mne, "read", val)
}'

#%IU%
#
def _pzoser_move '{
   local mne num dev nr serv

   mne = "$1"
   num = motor_num(mne)
   
   if ( A[num] != PZOSER_A_OLD[num] ) {

      dev  = list_getpar(PZOSER_LIST, mne, "dev")
      nr   = list_getpar(PZOSER_LIST, mne, "nr")
      serv = list_getpar(PZOSER_LIST, mne, "serv")
      
      ser_par(dev, "flush", 2)
      if (serv)
        ser_put(dev, sprintf("MOV %s%g\n", nr, A[num]))
      else
        ser_put(dev, sprintf("SVA %s%g\n", nr, A[num]))
        
      PZOSER_DIRTY[num] = 1
   }
}'

#%IU%
#
def _pzoser_getpos '{
   local mne num dev nr serv aux

   mne = "$1"
   num = motor_num(mne)
   force_read = list_getpar(PZOSER_LIST, mne, "read")
   if (( PZOSER_DIRTY[num] == 1 ) || (force_read > 0)) {

      dev  = list_getpar(PZOSER_LIST, mne, "dev")
      nr   = list_getpar(PZOSER_LIST, mne, "nr")
      serv = list_getpar(PZOSER_LIST, mne, "serv")

      ser_par(dev, "flush", 2)

      niter = 0
      # try several times to solve timeouts
      while (niter < 5) {

    
        if (serv)
          ser_put(dev, sprintf("POS? %s\n", nr))
        else
          ser_put(dev, sprintf("SVA? %s\n", nr))
      
         aux = ser_get(dev, "\n")
     
         if (aux != "") break
      
         niter += 1
      }
      PZOSER_A_OLD[num] = aux + 0.0
      PZOSER_DIRTY[num] = 0
   }
   A[num] = PZOSER_A_OLD[num]

}'

#%UU% 
#%MDESC% 
#  set servo mode
def pzoser_setserv '{
  local mne serv dev nr
    
  mne = "$1"
  serv = $2
  
  dev = list_getpar(PZOSER_LIST, mne, "dev")
  nr  = list_getpar(PZOSER_LIST, mne, "nr")
  list_setpar(PZOSER_LIST, mne, "serv", serv)
  ser_put(dev, sprintf("SVO %s%d\n", nr, serv))
}'

def pzoser_geterr '{
  ser_put(dev, sprintf("ERR? %s%d\n", nr, serv))
  printf("PZOSER ERROR : |%s|\n", ser_get(dev))
}'

#%UU% 
#%MDESC% 
#  set limit
def pzoser_setlim '{
  local mne serv dev nr
    
  mne = "$1"
  limp = $2
  limm = $3
  
  dev = list_getpar(PZOSER_LIST, mne, "dev")
  nr  = list_getpar(PZOSER_LIST, mne, "nr")
  serv = list_getpar(PZOSER_LIST, mne, "serv")
  
  if (serv) {
    ser_put(dev, sprintf("PMA %s%g\n", nr, limp))
    ser_put(dev, sprintf("PMI %s%g\n", nr, limm))
  } else {
    ser_put(dev, sprintf("VMA %s%g\n", nr, limp))
    ser_put(dev, sprintf("VMI %s%g\n", nr, limm))
  }
}'

#%UU% 
#%MDESC% 
#  set limit
def pzoser_readlim '{
  local mne serv dev nr
    
  mne = "$1"
  
  dev = list_getpar(PZOSER_LIST, mne, "dev")
  nr  = list_getpar(PZOSER_LIST, mne, "nr")
  serv = list_getpar(PZOSER_LIST, mne, "serv")
  
  if (serv) {
    ser_put(dev, sprintf("PMA? %s\n", nr))
    printf("\"%s\" upper limit %g (microns)\n", mne, ser_get(0)+0)
    ser_put(dev, sprintf("PMI? %s\n", nr))
    printf("\"%s\" lower limit %g (microns)\n", mne, ser_get(0)+0)
  } else {
    ser_put(dev, sprintf("VMA? %s\n", nr))
    printf("\"%s\" upper limit %g (V)\n", mne, ser_get(0)+0)
    ser_put(dev, sprintf("VMI? %s\n", nr))
    printf("\"%s\" lower limit %g (V)\n", mne, ser_get(0)+0)
  }
}'

def pzoser_read_param '{
  local mne serv dev nr
    
  mne = "$1"
  
  dev = list_getpar(PZOSER_LIST, mne, "dev")
  nr  = list_getpar(PZOSER_LIST, mne, "nr")
  serv = list_getpar(PZOSER_LIST, mne, "serv")
         
  # set step size parameters
  ser_put(dev, sprintf("SPA? %s7\n", nr))
  sleep(0.1)
  printf("motor \"%s\" 7: %g\n", mne, ser_get(dev))
  ser_put(dev, sprintf("SPA? %s8\n", nr))
  sleep(0.1)
  printf("motor \"%s\" 8: %g\n", mne, ser_get(dev))
  ser_put(dev, sprintf("SPA? %s9\n", nr))
  sleep(0.1)
  printf("motor \"%s\" 9: %g\n", mne, ser_get(dev))
  ser_put(dev, sprintf("SPA? %s10\n", nr))
  sleep(0.1)
  printf("motor \"%s\" 10: %g\n", mne, ser_get(dev))
}'

#%MACROS%
#%IMACROS%
#%DEPENDENCIES%
#  To use a piezo as a motor the following conditions have to be fulfilled:
#%UL%
#%LI% The file piezo_gpib.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 pzosetup )              done by: startup s.
#%XUL%
#%AUTHOR% Holger
#%TOC%