1. Computer interface
From the software's point of view, the grating has 2 devices:
1. Stepper motor. Controlled using a PC38 on axis 'y'.
2. Encoder, connected to serial port /dev/ttyS5
2. ic/Grating program
Cshell grating is controlled by the program ic/grating.
When the IC starts, the grating program open the devices
driver to the PC38 and encoder. The encoder is initialized
with the grating's scale factor using the command: "0sf25000\r:
The ic/grating performs 2 funtions during cshell operations:
init, and step
2.1 init
Sets up the pc38 y axis with velocity 5000, size 600000, backlash 250.
Reads the encoder.
EncoderPos is set to this position.
The PC38 axis is set to EncoderPos.
Grating.pos = pc38 position.
opt_order is set to 28.
user_order is set to 28.
2.2 step
Move the PC38 axis to a step position.
The pc38 moves the motor by output step and direction pulses. There is
no feedback loop between the motor & pc38.
At the end of the move the ic/grating program reads the encoder (encoderpos).
if (Encoderpos - Grating.pos ) > 30
a warning is printed on the XUI: WARNING Grating's encoder & motor out of sync by %ld steps
3. IC Sofware Commands.
The IC provide text command to control the grating's position, they are:
3.1 cvfwlen wlen - move the cvf, but affects user_order.
Used to move the cvf. The grating is not move the the user
order is set using the wlen, grating angle:
grating_angle = step2gangle( Grating.pos ).
user_order = gangle2order(wlen, grating_angle).
3.2 GratingPos - Position grating motor
command to move the grating to a step position. Range is 100000 to 400000
3.3 grating_rmove - Relative move for grating motor
move the grating relative to its current position. Range is -2000..+2000.
3.4. gwlen wlen - position grating by giving wlen.
input is wlen, range is 0.93 to 6.0.
order = wlengangle2order( wlen, BLAZE_ANGEL) // find optinum order for wlen
step = wlenorder2step( wlen, order ) // get step for this wlen & order.
opt_order = order;
user_order = order;
move motor by issuing gratingpos command.
3.5 order num - specify the user order.
can move grating to keep the same wavelen.
user_order = num. Input range is 8..60.
current_wlen = steporder2wlen(step, user_order )
new_pos = wlenorder2step( current_wlen, user_order).
move grating to new_pos using commmand: gratingpos new_pos.
3.6 wavelen - This command combines the CVFWlen and GWlen commands.
issue gwlen command.
issue cvfwlen command.
4. The XUI
Observing Parameter Screen:
"WaveLen" textbox issues "WaveLen" command.
The "cm-1" converts to wavelen and issues "WaveLen".
The display value is: wlen = steporder2wlen( grating_pos, user_order)
"CvfWlen" textbox issues "CvfWlen" command.
Motors details - provide details on the grating:
Grating_Pos - step position of the pc38.
GAngle - Grating angle: gangle = step2gratingangle( Grating_pos)
Order - opt_order.
User Order - user_order.
Wlen - wavelen: wlen = steporder2wlen( Grating_pos, user_order).
EncoderPos - reports the last encoder query.
5. FITS Header
GPOS is grating_pos. (Pc38 value)
GANGLE is Grating Angle. Angle = step2gratingangle(grating_pos). ORDER is user_order.
6. low level C function to convert between step, order, wavelength.
wlenorder2step() : step = f( wavelength, order)
steporder2wlen() : wavelength = f( step, order).
wlengangle2order() : "best" order = f( wavelength, grating_angle)
gratingangle2step() : step = f( grating_angle )
step2gratingangle() : grating_angle = f( step )
/************************************************************************
**
** Conversion tables and routines for grating wlen to step position
**
*************************************************************************
*/
/* This is the coefficient to convert grating angle(A) to steps (N)
** ie: N = -1055613 + 18634.8*A + 26.85632*A*A
*/
static double g_coeff[3] = { -1055613.0, 18634.80, 26.85632 };
#define GROOVE_SPACE 31.5195
/*----------------------------------------------------------------
** grating_wlen2step() - determine step from wlen and order.
**----------------------------------------------------------------
*/
int grating_wlenorder2step( step_ref, wlen, order )
long * step_ref; /* reference to step variable */
double wlen; /* wlen in microns */
long order; /* order */
{
int rc;
long step;
double gangle;
rc = ERR_NONE;
step = 0;
if( INRANGE( 0.93, wlen, 6.0 ) )
{
/* Find grating angle */
gangle = asin( (wlen*(double)order) / (GROOVE_SPACE*2.0)) * (180.0/M_PI);
rc = grating_gratingangle2step( &step, gangle );
}
else
rc = ERR_INV_RNG;
*step_ref = step;
return rc;
}
/*----------------------------------------------------------------
** grating_steporder2wlen() - determing wlen from step and order.
**----------------------------------------------------------------
*/
int grating_steporder2wlen( wlen_ref, step, order )
double *wlen_ref; /* Returns wlen as float to this address */
long step;
long order;
{
int rc;
double wlen;
double gangle;
rc = ERR_NONE;
wlen = 0;
if( INRANGE( 100000L, step, 400000L ) )
{
if( ERR_NONE == (rc = grating_step2gratingangle( &gangle, step)) )
wlen = (GROOVE_SPACE * 2.0 * sin(gangle*(M_PI/180.0))) / (double)order;
}
else
rc = ERR_INV_RNG;
*wlen_ref = wlen;
return rc;
}
/*----------------------------------------------------------------
** grating_wlengangle2order() - determines the best order to use for
** wlen & grating angle.
**----------------------------------------------------------------
*/
int grating_wlengangle2order( order_ref, wlen, angle )
long *order_ref; /* Returns order as a long to this address */
double wlen;
double angle;
{
int rc;
long order;
rc = ERR_NONE;
order = 0;
if( INRANGE( 0.93, wlen, 6.0 ) && INRANGE( 55.0, angle, 71.0 ))
{
order = ((2.0*GROOVE_SPACE * sin(angle * (M_PI/180.0))) / wlen) + 0.5;
}
else
rc = ERR_INV_RNG;
*order_ref = order;
return rc;
}
/*----------------------------------------------------------------
** grating_step2gratingangle() - converts grating angel to steps
**----------------------------------------------------------------
*/
int grating_gratingangle2step( step_ref, ang )
long *step_ref; /* Returns step as a long to this address */
double ang;
{
int rc;
double step;
rc = ERR_NONE;
step = 0;
if( INRANGE( 56.0, ang, 70.0))
step = ypoly( (double) ang, (double *) &g_coeff, 3);
else
rc = ERR_INV_RNG;
*step_ref = step;
return rc;
}
/*----------------------------------------------------------------
** grating_step2gratingangle(); convert steps to grating angle.
**----------------------------------------------------------------
*/
int grating_step2gratingangle( ang_ref, step )
double *ang_ref; /* Returns the grating angle to this address */
long step;
{
int rc;
double ang;
double c;
rc = ERR_NONE;
ang = 0;
if( INRANGE( 100000L, step, 400000L))
{
c = g_coeff[0] - step;
ang = (-g_coeff[1] + sqrt( (g_coeff[1]*g_coeff[1]) - (4*g_coeff[2]*c) )) /
( 2 * g_coeff[2] );
}
else
rc = ERR_INV_RNG;
*ang_ref = ang;
return rc;
}