esrf

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

#%NAME% 
#  VSCANNER.MAC - Macros to manage a piezo motor controlled by VSCANNER
#                 controller via RS232
#%DESCRIPTION%
#  This macro file allows to define a piezo motor controlled by vscanner as 
#  pseudo-motors in SPEC.
#  A VSCANNER box (defined by the parameter "dev") can drive up to two motors.
#  SPEC parameter "step_size" is taking into account to transform miroV used by
#  VSCANNER as unit in user unit.
#  SPEC parameter "velocity" ("steady state rate" in edconf) is used to define
#  speed used by piezo motor to move from one position to the other. If this
#  parameter is set to 0, the motor will be move instantaneously. 
#  UNIT: "steps / mm" are microVolts/mm
#        "steady state" rate is microV/s.
#
#%END%

need spec_utils

#%UU% <mnemonic> <SPEC serial line dev.> <vscanner ch. num.> <sign> <offset>
#%MDESC%
#   Add definitions for a piezo pseudomotor
def vscanadd  '{
  global VSCAN_BOX[] VSCAN_BOXNUM[] VSCAN_PAR[] VSCAN_NBBOX VSCANON

  local mne dev chnum nbox devname signe offset resp
  
  if ($# != 5) {
    p "Usage : <motor mnemonic> <VSCANNER serial line device> <channel number>"
    p "        <sign> <offset>"
    exit
  }
  
  mne    = "$1"
  dev    = $2
  chnum  = $3
  signe  = $4
  offset = $5
  
  if (motor_num(mne) == -1) {
    printf("motor \"%s\" not configured, exit !!!\n", mne)
    exit
  }
  
  if ((chnum != 1) && (chnum != 2)) {
    printf("VSCANNER has 2 channel numbered 1 or 2, exit !!!\n")
    exit
  }
  
  if ((signe != 1) && (signe != -1)) 
    signe = 1
    
  vscanoff

  devname = "VS" dev
  for (nbox=0;nbox<VSCAN_NBBOX;nbox++)
    if (VSCAN_BOX[nbox]["dev"] == devname)
      break
      
  if (nbox == VSCAN_NBBOX) {
    VSCAN_BOX[nbox]["dev"] = devname
    VSCAN_BOX[nbox][1] = ""
    VSCAN_BOX[nbox][2] = ""
    VSCAN_BOXNUM[devname] = nbox
    isgserial_add(devname, dev, 3, "VSCANNER")
    VSCAN_NBBOX++
  }

  VSCAN_BOX[nbox][chnum] = mne
  VSCAN_BOX[nbox]["moving"] = 0
  VSCAN_PAR[mne]["sign"] = signe
  VSCAN_PAR[mne]["offset"] = offset
  
  resp = isgserial_comm(devname, "?VER")
  if (index(resp, "VSCANNER") == 1) {
    if (VSCAN_PAR["setup_n"] != SETUP_N) 
      printf("Using %s on ISG_COMM_DEV %s as %s\n", resp, dev, devname)
    VSCAN_PAR["setup_n"] = SETUP_N
    
    motor_par(motor_num(mne), "disable", 0)
    isgserial_comm(devname, "NOECHO")

    setup_tail("vscan", sprintf("vscan_%s %s %d %d", mne, mne, nbox, chnum))
  
    vscanon
    
    VSCAN_BOX[nbox]["moving"] = 1
    vscan_getangles(devname)
  } else {
    printf("Error communicating to %s on ISG_COMM_DEV %s\n", devname, dev)
    printf("Disabling motor %s\n", mne)
    motor_par(motor_num(mne), "disable", 1)
  }
}'


def vscanunsetup '{
  local mne nbox chnum chnumo i
  
  mne   = "$2"
  nbox  = $3
  chnum = $4
  
  vscanoff
  
  if (chnum == 1)
    chnumo = 2
  else
    chnumo = 1
    
  if (VSCAN_BOX[nbox][chnumo] == "") {
    VSCAN_NBBOX--
    for (i=nbox;i<VSCAN_NBBOX;i++)
      VSCAN_BOX[i] = VSCAN_BOX[i+1] 
  } else {
    VSCAN_BOX[nbox][chnum] = ""
  }
  
  vscanon
}'

#%UU
#%MDESC%
#  Shows current piezo pseudomotors definition.
#
def vscanshow '{
  local i j

  if (VSCAN_NBBOX != 0) {
 
    printf("\VSCANNER pseudomotors are \"%s\"\n\n",VSCANON?"ACTIVE":"NOT ACTIVE")
    printf("     Motor    Device   channel\n") 
    printf("------------------------------\n") 
    for (i=0; i<VSCAN_NBBOX; i++) {
      for (j=1;j<=2;j++)
        if (VSCAN_BOX[i][j] != "")
          printf(" %8s  %8s  %8d\n", VSCAN_BOX[i][j], VSCAN_BOX[i]["dev"], j)
    }
  } else {
    printf("No VSCANNER psuedo motors defined\n")
  }
}' 

#%UU% 
#%MDESC% 
#  Deactivates definitions for piezo motors pseudomotors.
def vscanoff '{
  local i

  for (i=0;i<VSCAN_NBBOX; i++)
    cdef("", "", VSCAN_BOX[i]["dev"], "delete")
  
  VSCANON=0
}'

#%UU% 
#%MDESC%
#  Activates definitions for piezo motor pseudomotors.
#
def vscanon '{
  local i dev
  
  for (i=0;i<VSCAN_NBBOX; i++) {
    dev = VSCAN_BOX[i]["dev"]
    cdef("user_checkall"  , sprintf("vscan_checkall(\"%s\")\n" , dev), dev)
    cdef("user_getpangles", sprintf("vscan_getangles(\"%s\")\n", dev), dev)
    cdef("user_motorsrun" , sprintf("vscan_motorsrun %s\n", dev), dev)
  } 
  VSCANON=1
  
  get_angles
  
  printf("Piezo Motor pseudomotors are now ACTIVE\n")
}'

#%IU%
#%MDESC%
#  move pseudo motor
def vscan_checkall(dev) '{
  local nbox vel comm aux
  local mne1 mot1 vel1 motmv1 scan_val1 lin_val1
  local mne2 mot2 vel2 motmv2 scan_val2 lin_val2

  nbox = VSCAN_BOXNUM[dev]
  mot1 = VSCAN_BOX[nbox][1]
  mot2 = VSCAN_BOX[nbox][2]
  mne1 = motor_num(mot1)
  mne2 = motor_num(mot2)
  
  vel1 = vel2 = -1
  motmv1 = motmv2 = 0
  scan_val1 = scan_val2 = 0
  
  if ((mne1 != -1) && (VSCAN_PAR[mot1]["oldpos"] != A[mne1])) {
    aux = VSCAN_PAR[mot1]["sign"] * \
          (A[mne1] - VSCAN_PAR[mot1]["offset"]) * motor_par(mne1, "step_size") / 1e6
    if (aux > 10)
      A[mne1] = VSCAN_PAR[mot1]["sign"] * 10 * 1e6 / motor_par(mne1, "step_size") + \
                VSCAN_PAR[mot1]["offset"]
    if (aux < 0)
      A[mne1] = VSCAN_PAR[mot1]["offset"]
          
    vel1 = motor_par(mne1, "velocity")
    if (vel1 == 0) {
      motmv1 = 1
      lin_val1 = VSCAN_PAR[mot1]["sign"] * \
                 (A[mne1] - VSCAN_PAR[mot1]["offset"]) * motor_par(mne1, "step_size") / 1e6
    } else {
      scan_val1 = VSCAN_PAR[mot1]["sign"] * \
                 (A[mne1] - VSCAN_PAR[mot1]["oldpos"]) * motor_par(mne1, "step_size") / 1e6
    }
    VSCAN_BOX[nbox]["moving"] = 2
  }

  if ((mne2 != -1) && (VSCAN_PAR[mot2]["oldpos"] != A[mne2])) {
    aux = VSCAN_PAR[mot2]["sign"] * \
         (A[mne2] - VSCAN_PAR[mot2]["offset"]) * motor_par(mne2, "step_size") / 1e6
    if (aux > 10)
      A[mne2] = VSCAN_PAR[mot2]["sign"] * 10 * 1e6 / motor_par(mne2, "step_size") + \
                VSCAN_PAR[mot2]["offset"]
    if (aux < 0)
      A[mne2] = VSCAN_PAR[mot2]["offset"]
          
    vel2 = motor_par(mne2, "velocity")
    if (vel2 == 0) {
      motmv2 = 1
      lin_val2 = VSCAN_PAR[mot2]["sign"] * \
                 (A[mne2] - VSCAN_PAR[mot2]["offset"]) * motor_par(mne2, "step_size") / 1e6
    } else {
      scan_val2 = VSCAN_PAR[mot2]["sign"] * \
                  (A[mne2]-VSCAN_PAR[mot2]["oldpos"]) * motor_par(mne2, "step_size") / 1e6
    }
    VSCAN_BOX[nbox]["moving"] = 2
  }
    
  vel = vel1
  if (vel2 > vel1)
    vel = vel2 
  
  if ((motmv1 != 0) || (motmv2 != 0)) {
    comm = sprintf("v")
    if (motmv1 != 0)
      comm = sprintf("%sx", comm)
    if (motmv2 != 0)
      comm = sprintf("%sy", comm)
    if (motmv1 != 0)
      comm = sprintf("%s %g", comm, lin_val1)
    if (motmv2 != 0)
      comm = sprintf("%s %g", comm, lin_val2)
      
    isgserial_comm(dev, comm)
  }

  if ((scan_val1 != 0) || (scan_val2 != 0)) {
    cdef("cleanup_once", sprintf("vscan_stop %s\n", dev), dev)
    comm = sprintf("vel %g", vel/1e9)
    isgserial_comm(dev, comm)
    comm = sprintf("line %g %g 1 c", scan_val1, scan_val2)
    isgserial_comm(dev, comm)
    isgserial_comm(dev, "scan 0 0 1 u")
    isgserial_comm(dev, "pshape all")
    isgserial_comm(dev, "start 1 noret")
  }
}'

#%IU%
#%MDESC%
#  Read pseudo motor position
def vscan_getangles(dev) '{
  local str mne1 mne2 mot1 mot2 nbox
  local tab[]
  local _read_val

  nbox = VSCAN_BOXNUM[dev]

  mot1 = VSCAN_BOX[nbox][1]
  mot2 = VSCAN_BOX[nbox][2]
  mne1 = motor_num(mot1)
  mne2 = motor_num(mot2)

  if (VSCAN_BOX[nbox]["moving"] != 0) {
    str = isgserial_comm(dev, "?vxy")
    split(str, tab)

    if (mne1 != -1) {
      if (tab[0] > 10)
        tab[0] = 10

      if (tab[0] < 0)
        tab[0] = 0

      _read_val = VSCAN_PAR[mot1]["sign"] * tab[0] * 1e6 / motor_par(mne1, "step_size") + \
          VSCAN_PAR[mot1]["offset"]

      if(!is_aprox(VSCAN_PAR[mot1]["oldpos"], _read_val, 0.0001)){
          A[mne1] = _read_val
          VSCAN_PAR[mot1]["oldpos"] = _read_val
      }
    }

    if (mne2 != -1) {
      if (tab[1] > 10)
        tab[1] = 10

      if (tab[1] < 0)
        tab[1] = 0

      _read_val = VSCAN_PAR[mot2]["sign"] * tab[1] * 1e6 / motor_par(mne2, "step_size") + \
                VSCAN_PAR[mot2]["offset"]

      if(!is_aprox(VSCAN_PAR[mot2]["oldpos"], _read_val, 0.0001)){
          A[mne2] = _read_val
          VSCAN_PAR[mot2]["oldpos"] = _read_val
      }
    }

    if (VSCAN_BOX[nbox]["moving"] == 1)
      VSCAN_BOX[nbox]["moving"] = 0
  }
  else {
      if (mne1 != -1){
          A[mne1] = VSCAN_PAR[mot1]["oldpos"]
      }

      if (mne2 != -1){
          A[mne2] = VSCAN_PAR[mot2]["oldpos"]
      }
  }
}'


#%IU%
#%MDESC%
#  check if pseudo motors are moving.
#  return 0 if moving
#         1 if stopped
def vscan_motorsrun '{
  local str dev nbox

  dev = "$1" 
  nbox = VSCAN_BOXNUM[dev]
  
  if (VSCAN_BOX[nbox]["moving"] != 0) {
    str = isgserial_comm(dev, "?state")

    if (index(str, "RUNNING") == 0) {
      VSCAN_BOX[nbox]["moving"] = 1
      return(0)
    } else {
      return(1)
    }
  }
}'

#%IU%
#%MDESC%
#  Stop movement on pseudo motor
def vscan_stop '{
  local dev
  
  dev = "$1"
  
  isgserial_comm(dev, "stop")
}'

#%MACROS%
#%IMACROS%
#%DEPENDENCIES%
#%AUTHOR%
#  G. Berruyer (10 Dec 2001)
#%TOC%