esrf

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

#%TITLE% piezo_gcs.mac $Revision: 1.2 $
#%NAME%
# Macros to control a piezo PI controller connected via GPIB line.
# ONLY GCS (General Command Set) compatible PI controller
# can be driven by this macro set.
#%DESCRIPTION%
#  This macro file allows to connect a piezo to a macro motor in SPEC.
#
#  %BR%Controllers currently supported are:
#%DL%
#%DT%PI E-516 (GPIB)%DD%
#%XDL%
#
#  For debug purpose mainly, it's also possible to configure a macro
#  counter that will read the position of a piezo axis. But to avoid 
#  duplicating parameters, the counter has no parameter and takes them
#  from its corresponding macro motor. In order to guess the motor
#  to use, the name of the counter must be the same as the motor with
#  %B%\"_c\"%B% added at the end. 
#  For instance: %B%\"nnn_x_c\"%B% for %B%\"nnn_x\"%B%
#
#%END%
#
#%SETUP%
#  In order to configure a macro motor:
#  %DL%
#    %DT% 1) 
#         You must have a "MOTORS" defined with:
#         %BR%
#         %DL%
#           %DT% DEVICE
#           set to "piezogcs"
#           %DT% TYPE
#           set to "Macro Motor"
#           %DT% ADDR
#           set to the GPIB_Address of the controller
#           %DT% NUM
#           must be set also
#         %XDL%
#    %DT% 2)
#         Per piezo axis you must define a motor with:
#         %BR%
#         %DL%
#           %DT% Controller
#           set to "MAC_MOT"
#           %DT% Unit
#           field must be set to the "MOTOR" entry.
#           %DT% Chan
#           field must be set to the piezo axis of the controller
#           (for instance "0" stands for axis "A", "1" for "B" etc) 
#         %XDL%
#    %DT% 3)
#         In the config file add for %B%each%B% motor (%B%WARNING%B%: these
#         parameters are critical and can damage your hardware if wrong. They
#         are specific to each axis and not to the controller. Therefore
#         check with Electronics Group the value and %B%DO%B% %B%NOT%B%
#         copy/paste these values)
#         %BR%
#         %DL%
#           %DT%MOTPAR:a7 = mu/V
#           resolution in micron per volt (ex: 35)
#           %DT%MOTPAR:a9 = Vout/Vcmd
#           ratio out volt / command volt (ex: 10)
#           %DT%MOTPAR:deadtime = seconds
#           sleep time after a motion (ex: 0.1)
#         %XDL%
#
#  %XDL%
#
#  In order to configure a macro counter:
#  %DL%
#    %DT% 1) 
#         You must have a "SCALERS" defined with:
#         %BR%
#         %DL%
#           %DT% DEVICE
#           set to "piezogcs_c"
#           %DT% TYPE
#           set to "Macro Counter"
#           %DT% NUM
#           must be set also
#         %XDL%
#    %DT% 2)
#         Per piezo axis you must define a counter with:
#         %BR%
#         %DL%
#           %DT% Device
#           set to "MAC_CNT"
#           %DT% Mnemonic
#           must the motor mne plus "_c"
#           %DT% Unit
#           do not mind
#           %DT% Chan
#           do not mind
#         %XDL%
#
#  %XDL%


#%END%
#
#%HISTORY%
#$Log: piezo_gcs.mac,v $
#Revision 1.2  2008/04/30 08:51:41  rey
#A number of modifications including / velocity parameter, state handling
#and extra checking
#
#Revision 1.1  2007/02/16 11:18:30  papillon
#* Remove version checking (not working)
#
#Revision 1.0  2006/03/06 08:15:25  perez
#Initial Revision
#
#
#%END%
#

constant PIEZO_GCS_HEAD "PIEZO GCS: "

global PIEZO_GCS[]
global PIEZO_GCS_C[]

#%UU% [personal msg]
#%MDESC%
# Switch on or off the print of debug messages
#
def piezogcsdebug '{
 global PIEZO_GCS[]

 if(PIEZO_GCS["debug"]) {
  rdef piezogcs__debug \'#\$#\'
  print PIEZO_GCS_HEAD"debug mode is OFF"
  PIEZO_GCS["debug"]=0
 } else {
  rdef piezogcs__debug \'print "PIEZO GCS:","$*"\'
  print PIEZO_GCS_HEAD"debug mode is ON"
  PIEZO_GCS["debug"]=1
 }
}'

# No debug by default
def piezogcs__debug \'#\$#\'


#%IU% 
#%MDESC%
# Check if controller was well configured
#
def piezogcs_checkctl() '{
  if(PIEZO_GCS["on"] != 1) {
   print PIEZO_GCS_HEAD"ERROR: no controller, try \"reconfig\""
   return(-1)
  }
}'


#%IU% 
#%MDESC%
# Convert channel from digit to single ASCII char
#
def piezogcs_getch(ch) '{
  local nr

  if(ch==0) { nr="A" } else
  if(ch==1) { nr="B" } else
  if(ch==2) { nr="C" } else {
   print PIEZO_GCS_HEAD"ERROR: \""mne"\" wrong channel, only 3 axis supported"
   PIEZO_GCS["on"]=0
   nr="?"
  }
  piezogcs__debug "channel : \""nr"\""
  return nr
}'



#%IU%
#%MDESC%
# MACRO MOTOR:
# Called by spec after reading the config file
#
def piezogcs_config(num,type,p1,p2,p3) '{
 global PIEZO_GCS[]

 # p1==?? p2==number of motors supported
 if(type=="ctrl") {

     piezogcs__debug "config(): new controller"

     # check that the controller is switched on
     if(gpib_poll(piezogcs_ADDR) == -1) {
         print PIEZO_GCS_HEAD"ERROR: no controller found at address "piezogcs_ADDR
         PIEZO_GCS["on"]=0
         #return(".error.")
     } else { 
         PIEZO_GCS["on"]=1
     }

     piezogcs__debug "config(): switch controller online"
     gpib_put(piezogcs_ADDR,"ONL 1\n")
     sleep(0.1)
 }

 # p1==unit p2==module p3==channel
 if(type=="mot") {
     local nr
     local mne
     local a7 a8 a9 a10
     local dev

     mne=motor_mne(num)

     print "configuring motor " motor_mne(num) " configuration"
     if (piezogcs_checkctl() == -1) {
         print PIEZO_GCS_HEAD" motor " motor_mne(num) " is unusable"
         #return(".error.")
         return  
     }

     if (( nr=piezogcs_getch(p3) ) == "?") { return }
  

     # get and check piezo parameters for that axis
   
     a7   = motor_par(num,"a7")
     a9   = motor_par(num,"a9")
     a8   = motor_par(num,"a8")
     a10  = motor_par(num,"a10")
     vel  = motor_par(num,"vel")

     if(a7 == 0) {
         print PIEZO_GCS_HEAD"Warning: \""mne"\" \"a7\" parameter not set."
     }

     if(a9 == 0) {
         print PIEZO_GCS_HEAD"Warning: \""mne"\" \"a9\" parameter not set."
     }

     dev = motor_par(num,"address")

     # configure the axis
     if ( a7 != 0 ) {
          print PIEZO_GCS_HEAD"Warning: \""mne"\" \"a7\" parameter set to " a7
          piezogcs__debug "config(): a7: "a7
          gpib_put(dev, sprintf("SPA %s7 %d\n", nr, a7))
     }

     if ( a9 != 0 ) {
           print PIEZO_GCS_HEAD"Warning: \""mne"\" \"a9\" parameter set to " a9
           piezogcs__debug "config(): a9: "a9
           gpib_put(dev, sprintf("SPA %s9 %d\n", nr, a9))
     }

     if ( vel != 0 ) {
          print PIEZO_GCS_HEAD"Warning: \""mne"\" \"vel\" parameter set to " vel
          gpib_put(dev, sprintf("VEL %s%f\n", nr, vel))
          print PIEZO_GCS_HEAD"Warning: velocity control activated "
          gpib_put(dev, sprintf("VCO %s\n", nr ))
     }
  }
  
}'



#%IU%(motor_num)
#%MDESC%
# MACRO MOTOR:
# return the position read from the controller
#
def piezogcs_getpos(num) '{
 local dev
 local ch
 local nr
 local aux
 local pos

 mne = motor_mne(num)
 dev = motor_par(num,"address")
 ch  = motor_par(num,"channel")
 nr  = piezogcs_getch(ch)

 gpib_put(dev, sprintf("POS? %s\n", nr)) 
 aux = gpib_get(dev, "\n")
 pos = aux + 0.0
 return(pos)
}'

#%IU%
#%MDESC%
# MACRO MOTOR:
# Called by spec on motor operation.
#
def piezogcs_cmd(num,key,p1,p2) '{
 local mne
 local addr
 local dev
 local ch
 local nr

 if(num == "..") { return }


 mne = motor_mne(num)
 dev = motor_par(num,"address")
 ch  = motor_par(num,"channel")
 nr  = piezogcs_getch(ch)

 if (PIEZO_GCS["on"] == 0 ) return(0)

 #
 # return the current motor position in mm or deg
 #
 if (key == "position") {
  local pos
  pos = piezogcs_getpos(num) 
  piezogcs__debug "position() : pos    :  "pos" micron"
  return(pos)
 }


 #
 # start a motion (p1==abs pos, p2==rel pos, with pos in mm or deg)
 #
 if (key == "start_one") {
  local aux

  piezogcs__debug "start_one(): pos     :  "p1" micron"
  gpib_put(dev, sprintf("MOV %s%g\n", nr, p1)) 

  if((t=motor_par(num,"deadtime")) != 0) {
   piezogcs__debug "start_one(): sleeping:  "t" seconds"
   sleep(t)
  }
 }

 if (key == "get_status") {
   gpib_put(dev, sprintf("ONT? %s\n", nr, p1)) 
   stat = gpib_get(dev)  
   if (stat == 0) { # moving
      return 0x02
   } else {
      return 0
   }
 } 
 # stop a single motor
 #
 if (key == "abort_one") {

  piezogcs__debug "abort_one()"

  mne = motor_mne(num)
  dev = motor_par(num,"address")
  ch  = motor_par(num,"channel")
  nr  = piezogcs_getch(ch)

  gpib_put(dev, sprintf("STP %s\n", nr)) 
  return
 }

}'



#%IU%
#%MDESC%
# MACRO MOTOR:
# Called by spec after reading the config file
#
def piezogcs_c_config(num,type,p1,p2,p3) '{
  global  PIEZO_GCS_C[]

  #
  #
  #
  if(type=="ctrl") {
   PIEZO_GCS_C["on"]=1
  }

  #
  #
  #
  if(type=="cnt") {
    local mne
    local mot_mne mot_num

    mne=cnt_mne(num)
    mot_mne=substr(mne,1,index(mne,"_c")-1)
    if((mot_num=motor_num(mot_mne)) == -1) {
      print PIEZO_GCS_HEAD"ERROR: \""mne"\" invalid counter name"
      print "The name must the same as the motor name but with \"_c\" added"
      PIEZO_GCS_C["on"]=0
      return 
    }
    PIEZO_GCS_C[mne]["mot_num"]=mot_num
  }
}'



#%IU%
#%MDESC%
# MACRO MOTOR:
# Called by spec on counter operation.
#
def piezogcs_c_cmd(num,key,p1,p2) '{
  global  PIEZO_GCS_C[]

  if (key == "counts") {
    local pos
    local mot_num
    local mne
    mne=cnt_mne(num)
    mot_num=PIEZO_GCS_C[mne]["mot_num"]
    p "           "mot_num
    pos = piezogcs_getpos(mot_num) 
    return(pos)
  }
}'

#
#%MACROS%
#%IMACROS%
#%AUTHOR% BLISS 2006
#%TOC%