esrf

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

#%NAME% 
#  PM.MAC - Macros to control a pico motor (New Focus, Inc) by RS232 or GPIB
#%DESCRIPTION%
#  This macro file allows to define pico motor as pseudo-motors in SPEC.
#  As this is implemented on the macro level not all commands will work.
#
#%EXAMPLE%
#%DL%
#%DT%  mv pm1 50  %DD% Send 50*(nbsetp/mm) steps to the pico motor controller
#        according to the parameter set in the SPEC configuration
#%DT%  ascan pm1 0 10 10 1 %DD%
#        (scan pm1 from 0 to 10 in 10 steps and count for 1 second)
#%DT%  a2scan pm1 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 pm1 from 0 to 20 micr.)
#%XDL%
#%END%

#%UU% [No of pm] [pm1 motor name] [pm1 device name] ...
#%MDESC% Adds the given picomotor to the already defined picomotors 
#
global PMON PM_LIST
list_init PM_LIST

#%UU% pm-device pm-mnemonic pm-slot pm-connector pm-channel
#%MDESC%
#   Add definitions for a pico motor pseudomotor
def pmadd  'pm_add("$1", "$2", "$3", "$4", "$5", "$6")'

#%IU% (pm-mnemonic, pm-device)
#%MDESC%
#   Add definitions for a pico motor pseudomotor
def pm_add(dev, mne, slot, con, ch, gpibaddr) '{
  local step_size speed

    pmoff
    list_add(PM_LIST,mne)
    list_setpar(PM_LIST,mne,"dev",dev)
    list_setpar(PM_LIST,mne,"slot",slot)
    list_setpar(PM_LIST,mne,"con",con)
    list_setpar(PM_LIST,mne,"ch",ch)
    list_setpar(PM_LIST,mne,"gpibaddr",gpibaddr)
    A[motor_num(mne)] = list_getpar(PM_LIST,mne,"pos")

    setup_tail("pm", sprintf("pm_%s %s", mne, mne))
    pmon

# set speed from config file
#    speed = motor_par(motor_num(mne), "velocity")
#    if (speed > 1500) 
#      speed = 1500
#    if (speed < 0.023)
#      speed = 0.023
#    esrf_io(dev, "DevSerWriteString", sprintf("@:SOUR:PULS:FREQ %f Hz\r",speed))
#    if (index(esrf_io(dev, "DevSerReadString", 2), "OK") == ))
#      printf("cannot set speed for pico motor %s !!\n", mne)
#    list_setpar(PM_LIST,mne,"speed",speed)

# read and set step size
    step_size = motor_par(motor_num(mne), "step_size")
    list_setpar(PM_LIST,mne,"stepsize",step_size)
      
}'

def pmunsetup '{
   pmdel("$2")
}'

#%UU% (pm-mnemonic)
#%MDESC%
#   Delete definitions for one PICO MOTOR mnemonic
#
def pmdel(mne) '{
    list_remove(PM_LIST,mne)
    cdef("", "", mne, "delete")
}'

#%UU%
#%MDESC%
def pmreset '
    pmoff
    list_init PM_LIST
'

#%UU
#%MDESC%
#  Shows current Pico pseudomotors definition.
#
def pmshow '{
  local pmno mne dev slot con ch addr speed

  if (pmno = list_n(PM_LIST)) {
 
    printf("\nPM pseudomotors are \"%s\"\n\n",PMON?"ACTIVE":"NOT ACTIVE")
    printf("  Motor          Device   Slot   Connector   Channel Speed        Config\n") 
    printf("------------------------------------------------------------------------\n") 
    for (i=1; i<=pmno; i++) {
      mne =  list_item(PM_LIST, i)
#      dev = list_getpar(PM_LIST, i, "dev")
#
#      slot = list_getpar(PM_LIST, i, "slot")
#      con = list_getpar(PM_LIST, i, "con")
#      ch = list_getpar(PM_LIST, i, "ch")
#      addr = slot*100 + con*10 + ch
#      esrf_io(dev, "DevSerWriteString", sprintf("@:INST:NSEL %d\r", addr))
#      if (index(esrf_io(dev, "DevSerReadString", 2), "OK") == 0) {
#        printf("cannot select pico motor %s !!\n", mne)
#      }
#      esrf_io(dev, "DevSerWriteString","@:SOUR:PULS:FREQ ?\r")
#      speed = esrf_io(dev, "DevSerReadString", 2)
      printf(" %6s %15s   %4s   %9s   %7s   %5s   ", mne, \
			   sprintf("%s:%s",list_getpar(PM_LIST,i,"dev"), \
			           list_getpar(PM_LIST,i,"gpibaddr")), \
			   list_getpar(PM_LIST, i, "slot"),\
			   list_getpar(PM_LIST, i, "con"),\
			   list_getpar(PM_LIST, i, "ch"), \
                           speed) 
      if (motor_num(mne) < 0) 
        printf("%11s\n","NOT DEFINED")
      else 
        printf("%11s\n","OK")
    }
    printf("\n")
  } else {
    printf("Nothing defined for Pico Motors\n")
  }
}' 

#%UU% 
#%MDESC% 
#  Deactivates definitions for pico motors pseudomotors.
def pmoff '
{
    local pmno

    pmno = list_n(PM_LIST)

    for (i = 1; i <= pmno; i++) {
        cdef("", "", list_item(PM_LIST, i), "delete")
    } 
    PMON=0
}'

#%IU% 
#%MDESC%
#  Activates definitions for pico motor pseudomotors.
#
def pmon '{
    local pmno num mne

    pmno = list_n(PM_LIST)

    for (i=1; i <= pmno; i++) {
        num = motor_num(mne = list_item(PM_LIST, i))
        if (num != -1 ) {
        cdef("user_checkall",sprintf("pmmove %s\n", mne), mne, 0x01)
        cdef("user_getpangles",sprintf("pmgetangles %s\n", mne), mne, 0x01)
        cdef("user_cleanup2",sprintf("pmstop %s\n", mne), mne, 0x01)
        }
    } 
    PMON=1
    printf("Pico Motor pseudomotors are now ACTIVE\n")
}'

def pmread '{
  local dev gpibaddr

  p pm_get("$1")
}'
 
#%IU%
#%MDESC%
#  Stop all configured pico motors
#
def pmstop '{
  local slot con ch addr pm_com

  slot = list_getpar(PM_LIST, "$1", "slot")
  con = list_getpar(PM_LIST, "$1", "con")
  ch = list_getpar(PM_LIST, "$1", "ch")
  addr = slot*100 + con*10 + ch

  pm_com = sprintf(":INST:NSEL %d", addr)
  pm_send("$1", pm_com)
  if (index(pm_get("$1"), "OK") == 0) {
    printf("cannot select pico motor %s !!\n", list_item(PM_LIST, "$1"))
    exit
  }

  pm_com = ":INST:STAT 0"
  pm_send("$1", pm_com)
  if (index(pm_get("$1"), "OK") == 0) {
    printf("cannot stop pico motor %s !!\n", list_item(PM_LIST, "$1"))
    exit
  }
}'

#%IU%
#
def pmmove '{
  local slot con ch addr old_pos nbstep pm_com

# check if we need to move
  old_pos = list_getpar(PM_LIST, "$1", "pos") + 0
  if (A[$1] != old_pos) {

# select the motor
    slot = list_getpar(PM_LIST, "$1", "slot")
    con = list_getpar(PM_LIST, "$1", "con")
    ch = list_getpar(PM_LIST, "$1", "ch")
    addr = slot*100 + con*10 + ch

    pm_com = sprintf(":INST:NSEL %d", addr)
    pm_send("$1", pm_com)
    if (index(pm_get("$1"), "OK") == 0) {
      printf("cannot select pico motor %s !!\n", list_item(PM_LIST, "$1"))
      exit
    }

# set direction of rotation
    nbstep = A[$1] - old_pos
    if (nbstep < 0)
      pm_com = ":SOUR:DIR CW"
    else
      pm_com = ":SOUR:DIR CCW"
    pm_send("$1", pm_com)
    if (index(pm_get("$1"), "OK") == 0) {
      printf("cannot change rotation dir. for pico motor %s !!\n", list_item(PM_LIST, "$1"))
      exit
    }

# move the motor
    nbstep = fabs(nbstep) * list_getpar(PM_LIST, "$1", "stepsize")
    pm_com = sprintf(":SOUR:PULS:COUN %d", nbstep)
    pm_send("$1", pm_com)
    if (index(pm_get("$1"), "OK") == 0) {
      printf("cannot move pico motor %s !!\n", list_item(PM_LIST, "$1"))
      exit
    }
    list_setpar(PM_LIST,"$1","pos",A[$1])
  }
}'

#%IU%
#
def pmgetangles '{
 local mne
 mne = "$1"
 A[$1] = list_getpar(PM_LIST,mne,"pos")
}'

#%IU%
#%MDESC%
#  Set New position value to a pico motor
#
def pmset '{
 local mne

 if ($# != 2) {
   p "Usage : pmset [motor mne.] [new pos]"
   exit
 }

 mne = "$1"
 list_setpar(PM_LIST,mne,"pos", $2)
 A[$1] = $2
}'

#%IU%
#%MDESC%
#  Send command to pico controller
#
def pm_send(nmot, com) '{
  local dev gpibaddr

  dev = list_getpar(PM_LIST, nmot, "dev")
  if (dev == "gpib")
    gpibaddr = list_getpar(PM_LIST, nmot, "gpibaddr")

  if (dev == "gpib")
    gpib_put(gpibaddr, com)
  else
    esrf_io(dev, "DevSerWriteString", sprintf("@%s\r", com))
  return(0)
}'

#%IU%
#%MDESC%
#  Get answer from pico controller
#
def pm_get(nmot) '{
  local dev gpibaddr

  dev = list_getpar(PM_LIST, nmot, "dev")
  if (dev == "gpib")
    gpibaddr = list_getpar(PM_LIST, nmot, "gpibaddr")

  if (dev == "gpib")
    return(gpib_get(gpibaddr))
  else
    return(esrf_io(dev, "DevSerReadString", 2))
}'


#%MACROS%
#%IMACROS%
#%DEPENDENCIES%
#  To use a pico motor the following conditions have to be fulfilled:
#%UL%
#%LI% The file pm.mac has to be read in               done by: startup s.
#    (this file needs: pseudo.mac , stchanges.mac)
#%LI% the pico motors have to be configured           done by: SPECADM
#       (Controller NONE, mnemonic as in startupscript)
#%LI% setup the pico motors (with pmsetup )           done by: startup s.
#%XUL%
#%AUTHOR%
#%TOC%