A solution for the 24 bits problem of the OMS-VME58, large moves, limits

The VME58 controllers of OMS store the motor positions in registers which are 24 bits wide. This may lead to problems, if a motor has a large conversion factor. In this case 24 bits not sufficient to perform large movements. In addition, the hard unit limits cannot be expressed in terms of 24 numbers as unit limits (soft limits). The following virtual motor script provides a workaround to this problem. A motor is moved between 0.1 and 90 units (hard limits).

Before the virtual motor can be used, the following command has to be entered: ONLINE> def vm1.

#!/usr/bin/perl -w
#
# file name: /online_dir/vm1.pl
# 
# mot16 is moved from 0.1 to 90, the hard limits
#
use Spectra; 

my ($method, $value_new) = @ARGV; 
my $buffer = " " x 100; 

my ( $lim_min, $lim_max) = ( 0, 90); 

my $status = 1; 

if( $method eq "set_position")
{
    #
    # read the current soft limits
    #
    my $min = Spectra::gmuli( "mot16"); 
    my $max = Spectra::gmula( "mot16"); 
    my $bl = Spectra::gmub( "mot16"); 
    #
    # if the requested position is outside the hard limits, 
    # return an error
    #
    if( $value_new < $lim_min ||
	$value_new > $lim_max)
    {
	$status = Spectra::error( "vm1: mot16, move outside limits $value_new not in [$lim_min, $lim_max]");
	goto finish;
    }
    #
    # if the requested position is within the soft
    # limits, execute the move
    #
    if( $value_new <= $max &&
	$value_new >= $min)
    {
	$status = Spectra::move( mot16 => $value_new);
	goto finish;	
    }
    #
    # move is outside the soft limits but within the
    # hard limits, move in two steps
    #
    if( $value_new > $max)
    {
	Util::log( "vm1: mot16 to " . $max . ", first step"); 
	$status = Spectra::move( mot16 => $max); 
	goto finish if( !$status);
	Spectra::rmsr( mot16 => 0); 
	Util::log( "vm1: mot16 unit-limit-max to " . $lim_max); 
	Spectra::smula( mot16 => $lim_max); 
	Util::log( "vm1: mot16 to " . $value_new); 
	$status = Spectra::move( mot16 => $value_new); 
	goto finish;
    }
    if( $value_new < $min)
    {
	Util::log( "vm1: mot16 to " . ($min + $bl*2) . ", first step"); 
	$status = Spectra::move( mot16 => ($min + $bl*2)); 
	goto finish if( !$status);
	Spectra::rmsr( mot16 => 0); 
	Util::log( "vm1: mot16 unit-limit-min to " . ($lim_min)); 
	Spectra::smuli( mot16 => $lim_min); 
	Util::log( "vm1: mot16 to " . $value_new); 
	$status = Spectra::move( mot16 => $value_new); 
	goto finish;
    }
    goto finish;
}

if( $method eq "get_position")
{
    $SYM{RETURN_VALUE} = Spectra::gmup( "mot16");
    goto finish;
}

if( $method eq "get_limit_min")
{
    $SYM{RETURN_VALUE} = $lim_min;
    goto finish;
}

if( $method eq "get_limit_max")
{
    $SYM{RETURN_VALUE} = $lim_max;
    goto finish;
}

if( $method eq "calibration")
{
    goto finish;
}

finish:
 $status;