MX: A Portable Data Acquisition
and Control Toolkit
William M. Lavender
Biological, Chemical, and Physical Sciences
Department
Illinois Institute of Technology
Chicago, Illinois 60616
http://www.imca.aps.anl.gov/mx/
[email protected]
What is MX?
"
"
"
"
"
MX is a portable beamline control system.
It includes a pair of servers, mxserver and mxupdate, to
manage the hardware.
Both Tcl/Tk GUI applications and command line based
applications are currently supported.
Device drivers and core functionality are encapsulated in
the libMx library.
LibMx is written in ANSI C to maximize its ability to be
used from other languages and applications.
What is MX? (cont.)
"
"
"
"
Both servers and clients use the same libMx library and
can use the same device drivers.
Client-server operation is not required. This simplifies
the debugging of device drivers.
MX has its own TCP/IP protocol, but most of MX is
independent of the protocol used.
Clients can use foreign protocols exclusively, or a mix of
MX and foreign protocols.
Current Users of MX
 MRCAT, APS Sector 10-ID
materials science
 IMCA-CAT, APS Sector 17-ID and 17-BM
macromolecular crystallography
 BioCAT, APS Sector 18-ID
biophysical science
 SER-CAT, APS Sector 22-ID and 22-BM
macromolecular crystallography
 GCPCC Beamline, CAMD
macromolecular crystallography
Why I Wrote MX
"
"
"
"
Beamline control software packages have tended to be
environment specific and non-portable.
Many are centered around a particular interface method,
e.g. CAMAC or VME.
EPICS seemed to be a less than ideal choice, since it
requires a rather high level of expertise to setup,
maintain, and develop for.
Users sometimes bring in their own equipment that they
want to interface to the beamline.
MX Control System Goals
"
Encapsulate the core functionality in libraries like libMx.
"
Make client-server functionality available.
"
"
"
Require that libMx know very little about the application
programs invoking it.
Localize the knowledge libMx has of device hardware to
driver functions with well defined interfaces.
Minimize the effort required to implement new device
drivers by putting as much functionality as is possible
into generic code.
MX Control System Goals (cont.)
"
Emphasize operating system independence.
"
Require only ANSI C and BSD sockets or Winsock.
"
"
"
"
Be able to interoperate with pre-existing beamline
control systems.
Try to minimize built-in assumptions about the structure
of future data acquisition APIs.
Do not depend on the presence of software that may not
be freely distributed.
Make the source code freely available.
MX Platforms
"
Linux 2.0 and 2.2
-
GCC
"
SGI Irix 6.3 and 6.5
-
SGI C compiler
"
Solaris 2.5 and 2.6
-
SPARCompiler C or GCC
"
HP/UX 10.20
-
HP/UX C compiler
"
SunOS 4.1.4
-
SPARCompiler C
"
MacOS X
-
GCC
"
Windows 95, 98, NT 4 -
Visual C++ 4, 5, or 6
"
MSDOS 6.2
DJGPP 2.0.2 and Watt32
-
MX Internal Architecture
"
"
"
"
"
The fundamental object is the MX record.
Application programs maintain their set of MX records
in a doubly linked list called the MX database.
Each motor, scaler, serial port, or other device on a
beamline is represented as an individual MX record.
MX records are also used to store variables, server
connections, and even scan parameters.
Application programs control the beamline by invoking
the defined functions or methods for each device type.
MX Records
"
"
"
"
"
MX records are defined by the typedef MX_RECORD in
the header file libMx/mx_rec.h.
MX is not fully object oriented since it only has a fairly
restricted form of inheritance.
MX record types are organized in a fixed hierarchy of
superclasses, classes, and types.
Each MX record type has an associated MX driver
which implements the methods of this record type.
Methods are implemented via function tables defined in
the MX_DRIVER structure.
The MX_RECORD Structure
typedef struct mx_record_type {
long mx_superclass;
/* MXR_LIST_HEAD, MXR_INTERFACE, etc. */
long mx_class;
/* MXI_CAMAC, MXC_MOTOR, etc. */
long mx_type;
/* MXT_MTR_E500, MXT_MTR_PANTHER, etc. */
char name[MXU_RECORD_NAME_LENGTH+1];
char label[MXU_LABEL_LENGTH+1];
void *acl;
char acl_description[MXU_ACL_DESCRIPTION_LENGTH+1];
signed long handle;
int
precision;
int
resynchronize;
long
flags;
struct mx_record_type *list_head;
struct mx_record_type *previous_record;
struct mx_record_type *next_record;
void *record_superclass_struct; /* Ptr to MX_SCAN, MX_VARIABLE, etc. */
void *record_class_struct;
/* Ptr to MX_CAMAC, MX_MOTOR, etc. */
void *record_type_struct;
/* Ptr to MX_DSP6001, MX_E500, etc. */
void *record_function_list; /* Ptr to MX_RECORD_FUNCTION_LIST */
void *superclass_specific_function_list;
void *class_specific_function_list;
long
num_record_fields;
MX_RECORD_FIELD
*record_field_array;
struct mx_record_type *allocated_by;
long
num_groups;
struct mx_record_type **group_array;
long
num_parent_records;
struct mx_record_type **parent_record_array;
long
num_child_records;
struct mx_record_type **child_record_array;
MX_CLOCK_TICK event_interval;
MX_CLOCK_TICK next_event_time;
void *event_queue;
/* Ptr to MXSRV_QUEUED_EVENT */
void *application_ptr;
} MX_RECORD;
An MX record list
MX Device Types
MX Interface Types
Amplifier
Analog Input
Analog Output
Digital Input
Digital Output
Encoder
Motor
Multichannel Analyzer
Multichannel Encoder
Multichannel Scaler
Relay
Scaler
Table
Timer
CAMAC
Generic
GPIB
Port I/O
RS-232
MX Server Types
TCP/IP
MX Variable Types
Calc
EPICS
Inline
MX
MX Scan Types
MX has a selection of scan types optimized
for different kinds of experiments.
•Linear Scan
–
–
–
–
Input Scan
Motor Scan
Slit Scan
q-2q Scan
•List Scan
•Quick Scan
–
–
Joerger Quick Scan
MCS Quick Scan
•XAFS Scan
(multiple energy and k regions)
MX Motor Drivers
Am9513-based controller
APS undulator (EPICS)
Bruker D8 (prerelease)
Compumotor 6000/6K
DAC motor
Delta Tau PMAC
Delta Tau PMAC (EPICS)
DSP E500
EPICS motor record
IMS Panther HI/HE
Joerger SMC-24
LakeShore 330 temp. ctrl.
McLennan PM-304
MX network motor
National Inst. ValueMotion
Newport MM-3000
Newport MM-4000/4005
OMS VME-58 (Linux)
PI E-662 piezo controller
Pontech STP-100
Radix Databox motor
SCIPE network motor
Soft motor
Velmex VP9000
XIA HSC-1 slit controller
MX Pseudomotor Drivers
Delta (position difference)
Elapsed time
Linear function
Monochromator
Q = 4p sinq/l
Sector 18-ID mono
Slit center or width
Table pseudomotor
- (x, y, z, roll, pitch, yaw)
q-2q pseudomotor
Translation pseudomotor
X-ray energy
X-ray wavelength
X-ray wavenumber
XAFS wavenumber (k)
MX Monochromator Pseudomotor
The MX monochromator pseudomotor couples the motion
of several groups of dependent motors and devices such that
they track changes in the monochromator angle, q.
Supported dependency types
 Monochromator q (of course)
 Polynomial function of monochromator q
Polynomial function of monochromator energy
 APS undulator energy
 Fixed exit crystal separation
 Fixed exit crystal translation
 Diffractometer table height
 Diffractometer q
ADC Table Pseudomotor
 Supports linear x, y, and z translation of the rotation center.
 Supports pure roll, pitch, and yaw motions about the rotation center.
 Uses a small angle approximation for rotations.
MX Application Programs
MX currently supports writing application programs
in C and Tcl/Tk. Support is planned for Python, C++,
and Labview.
Command line programs
motor - a general data acquisition and control program for MX.
mxget & mxput - shell commands for talking to an MX server.
goniostat - used by MarCCD to control the X-ray energy.
Tcl/Tk GUI programs
imcagui - a protein crystallography GUI capable of setting up
and performing MAD experiments.
optimize - an end-user GUI for performing simple optimizations
of the X-ray intensity.
mxgui - a general data acquisition and control GUI intended for
beamline staff users.
mxcontrol - an MX server control and log display GUI.
Selecting an Absorption Edge
MXGUI - A Beamline Staff GUI
MXGUI - Setting up a motor scan
MXGUI - Setting up an XAFS scan
MX Network Protocol
"
"
"
"
MX is bundled with a network protocol and a pair of
servers that implement it.
–
mxserver - manages hardware and handles
communication with clients.
–
mxupdate - handles automatic save and restore of
database parameters.
The protocol is designed to be simple to implement and
easy to extend.
Most of MX does not depend on this protocol and clients
are not required to use it.
This protocol is included so that MX can be a standalone
system.
MX Network Protocol (cont.)
"
"
"
"
"
"
MX protocol is an RPC style protocol.
Asynchronous callback support is planned but is not
fully implemented yet.
MX protocol messages have a binary header with an
ASCII body.
Uses record field names to identify the object of the
message. For example, ``theta.position''.
Currently 3 types of messages are implemented:
get_array_ascii, put_array_ascii, get_field_type. Other
types are planned.
The protocol is intended to have a simple core, but be
extensible by negotiation at runtime.
Future Plans for MX Protocol
"
Use numeric handles rather that passing record field
names.
"
Finish implementation of asynchronous callbacks.
"
Explore passing data using binary XDR format.
"
"
Add support for automatic resource discovery and
browsing of servers.
Improve support for security and add ACLs.
MX is Transport Independent
"
"
"
"
The driver API does not distinguish between remotely
and locally controlled devices.
Applications can switch between drivers and protocols
just by changing a config file.
Servers can be clients and clients can be servers.
Clients can simultaneously use several different network
protocols.
APS Sector 17-ID Control System
MX Simulated Devices
"
"
"
The driver API does not distinguish between real devices
and simulated devices.
Almost every MX driver type has a simulated driver
available.
Very useful for offline development and testing of new
software.
"
Potentially useful for user training.
"
Can use simulated devices alongside real devices.
MX Programming API
MX has an extensive API. All of it cannot be shown here,
so we show only motor related functions.
mx_motor_get_position()
mx_motor_is_busy()
mx_motor_positive_limit_hit()
mx_motor_negative_limit_hit()
mx_motor_move_absolute()
mx_motor_array_move_absolute()
mx_wait_for_motor_stop()
mx_wait_for_motor_array_stop()
mx_motor_soft_abort()
mx_motor_immediate_abort()
mx_motor_set_position()
mx_motor_find_home_position()
mx_motor_is_at_home_switch()
mx_motor_get_speed()
mx_motor_set_speed()
mx_motor_save_speed()
mx_motor_restore_speed()
mx_motor_set_speed_between_positions()
mx_motor_get_acceleration_type()
mx_motor_get_acceleration_parameters()
mx_motor_set_acceleration_parameters()
mx_motor_get_acceleration_time()
mx_motor_get_acceleration_distance()
mx_motor_compute_pseudomotor_position_
from_real_position()
mx_motor_compute_real_position_from_
pseudomotor_position()
mx_motor_compute_extended_scan_range()
mx_motor_constant_velocity_move()
mx_motor_get_parameter()
mx_motor_set_parameter()
Cu K-edge scan in C using MX
#include <stdio.h>
#include "mx_rec.h"
#include "mx_motor.h"
#include "mx_scalr.h"
#include "mx_timer.h"
#define DATABASE_FILENAME
"example.dat"
int main() {
MX_RECORD *record_list, *energy_motor_record;
MX_RECORD *i_zero_record, *i_trans_record, *timer_record;
double start, step_size, measurement_time, energy;
int i, num_steps, busy;
long i_zero_value, i_trans_value;
mx_setup_database( &record_list, DATABASE_FILENAME );
energy_motor_record = mx_get_record( record_list, "energy" );
i_zero_record
= mx_get_record( record_list, "Io" );
i_trans_record
= mx_get_record( record_list, "It" );
timer_record
= mx_get_record( record_list, "timer1" );
start = 8950; step_size = 1.0; num_steps = 101; measurement_time =
1.0;
for ( i = 0; i < num_steps; i++ ) {
mx_scaler_clear( i_zero_record );
mx_scaler_clear( i_trans_record );
energy = start + step_size * (double) i;
mx_motor_move_absolute( energy_motor_record, energy, 0 );
mx_timer_start( timer_record, measurement_time );
busy = TRUE;
while ( busy ) {
mx_msleep(10);
/* Wait for 10 milliseconds
*/
mx_timer_is_busy( timer_record, &busy );
}
mx_scaler_read( i_zero_record, &i_zero_value );
mx_scaler_read( i_trans_record, &i_trans_value );
printf( "%10.3f %10lu %10lu\n",
energy, i_zero_value, i_trans_value );
}
exit(0);
}
Cu K-edge scan in Tcl using MX
#! /opt/mx/bin/mxtclsh
set mxdir "/opt/mx" ; set database_filename "example.dat"
source [ file join $mxdir "lib" "mx.tcl" ]
package require Mx
::Mx::init
set
set
set
set
set
set
set
for
record_list
[ Mx::setup_database $database_filename ]
energy_motor_record [ $record_list get_record "energy" ]
i_zero_record
[ $record_list get_record "Io" ]
i_trans_record
[ $record_list get_record "It" ]
timer_record
[ $record_list get_record "timer1" ]
start 8950 ; set step_size 1.0 ; set num_steps 101
measurement_time 1.0
{ set i 0 } { $i < $num_steps } { incr i } {
$i_zero_record clear
$i_trans_record clear
set energy [ expr ( $start + $step_size * $i ) ]
$energy_motor_record move_absolute $energy
set busy 1
while { $busy } {
after 10
set busy [ $energy_motor_record is_busy ]
}
$timer_record start $measurement_time
set busy 1
while { $busy } {
after 10
set busy [ $timer_record is_busy ]
}
set i_zero_value [ $i_zero_record read ]
set i_trans_value [ $i_trans_record read ]
puts [ format "%10.3f %10lu %10lu" \
$energy $i_zero_value $i_trans_value ]
}
MX Driver Header File
/* ===== McLennan PM304 motor data structures ===== */
typedef struct {
MX_RECORD *rs232_record;
int axis_number;
int axis_encoder_number;
} MX_PM304;
MX_API
MX_API
MX_API
MX_API
MX_API
MX_API
MX_API
MX_API
MX_API
MX_API
MX_API
MX_API
MX_API
MX_API
MX_API
MX_API
MX_API
MX_API
MX_API
MX_API
MX_API
MX_API
mx_status_type
mx_status_type
mx_status_type
mx_status_type
mx_status_type
mx_status_type
mx_status_type
mx_status_type
mx_status_type
mx_status_type
mx_status_type
mx_status_type
mx_status_type
mx_status_type
mx_status_type
mx_status_type
mx_status_type
mx_status_type
mx_status_type
mx_status_type
mx_status_type
mx_status_type
mxd_pm304_initialize_type( long type );
mxd_pm304_create_record_structures( MX_RECORD *record );
mxd_pm304_finish_record_initialization(MX_RECORD *record );
mxd_pm304_delete_record( MX_RECORD *record );
mxd_pm304_print_motor_structure( FILE *file, MX_RECORD *record );
mxd_pm304_read_parms_from_hardware( MX_RECORD *record);
mxd_pm304_write_parms_to_hardware( MX_RECORD *record );
mxd_pm304_open( MX_RECORD *record );
mxd_pm304_close( MX_RECORD *record );
mxd_pm304_resynchronize( MX_RECORD *record );
mxd_pm304_motor_is_busy( MX_MOTOR *motor );
mxd_pm304_move_absolute( MX_MOTOR *motor );
mxd_pm304_get_position( MX_MOTOR *motor );
mxd_pm304_set_position( MX_MOTOR *motor );
mxd_pm304_soft_abort( MX_MOTOR *motor );
mxd_pm304_immediate_abort( MX_MOTOR *motor );
mxd_pm304_positive_limit_hit( MX_MOTOR *motor );
mxd_pm304_negative_limit_hit( MX_MOTOR *motor );
mxd_pm304_find_home_position( MX_MOTOR *motor );
mxd_pm304_constant_velocity_move( MX_MOTOR *motor );
mxd_pm304_get_parameter( MX_MOTOR *motor );
mxd_pm304_set_parameter( MX_MOTOR *motor );
extern MX_RECORD_FUNCTION_LIST mxd_pm304_record_function_list;
extern MX_MOTOR_FUNCTION_LIST mxd_pm304_motor_function_list;
MX Driver Header File (cont.)
/* Define some extra functions for the use of this driver. */
MX_API mx_status_type mxd_pm304_command( MX_PM304 *pm304, char *command,
char *response, int response_buffer_length,
int debug_flag );
MX_API mx_status_type mxd_pm304_getline( MX_PM304 *pm304,
char *buffer, int buffer_length, int debug_flag );
MX_API mx_status_type mxd_pm304_putline( MX_PM304 *pm304,
char *buffer, int debug_flag );
MX_API mx_status_type mxd_pm304_getc( MX_PM304 *pm304,
char *c, int debug_flag );
MX_API mx_status_type mxd_pm304_getc_nowait( MX_PM304 *pm304,
char *c, int debug_flag );
MX_API mx_status_type mxd_pm304_putc( MX_PM304 *pm304,
char c, int debug_flag );
extern long mxd_pm304_num_record_fields;
extern MX_RECORD_FIELD_DEFAULTS *mxd_pm304_rfield_def_ptr;
#define MXD_PM304_STANDARD_FIELDS \
{-1, -1, "rs232_record", MXFT_RECORD, NULL, 0, {0}, \
MXF_REC_TYPE_STRUCT, offsetof(MX_PM304, rs232_record), \
{0}, NULL, (MXFF_IN_DESCRIPTION | MXFF_IN_SUMMARY)}, \
\
{-1, -1, "axis_number", MXFT_INT, NULL, 0, {0}, \
MXF_REC_TYPE_STRUCT, offsetof(MX_PM304, axis_number), \
{0}, NULL, (MXFF_IN_DESCRIPTION | MXFF_IN_SUMMARY)}, \
\
{-1, -1, "axis_encoder_number", MXFT_INT, NULL, 0, {0}, \
MXF_REC_TYPE_STRUCT, offsetof(MX_PM304, axis_encoder_number), \
{0}, NULL, (MXFF_IN_DESCRIPTION | MXFF_IN_SUMMARY)}
An Example MX Driver Function
MX_EXPORT mx_status_type
mxd_pm304_move_absolute( MX_MOTOR *motor )
{
const char fname[] = "mxd_pm304_move_absolute()";
MX_PM304 *pm304;
char command[20];
char response[20];
long motor_steps;
mx_status_type status;
status = mxd_pm304_get_pointers( motor, &pm304, fname );
if ( status.code != MXE_SUCCESS )
return status;
motor_steps = motor->raw_destination.stepper;
/* Format the move command and send it. */
sprintf( command, "ma%ld", motor_steps );
status = mxd_pm304_command( pm304, command, response, sizeof response, PM304_DEBUG );
if ( status.code != MXE_SUCCESS )
return status;
/* Did we get an "OK" response? */
if ( strcmp( response, "OK" ) != 0 ) {
return mx_error( MXE_DEVICE_IO_ERROR, fname,
"Did not get 'OK' response from controller. Instead got '%s'", response );
}
return MX_SUCCESSFUL_RESULT;
}
Future Plans
"
Server-side improvements
–
Improve mxserver's ability to cope with broken or
missing hardware.
–
Add callback support to mxserver.
–
Performance and concurrency improvements.
–
Create servers to export MX services to other control
systems (EPICS, CORBA, etc.)
–
GUI database configuration tool.
–
GUI server control tool.
Future Plans (cont.)
"
"
Client-side improvements
–
Development of more application specific GUIs.
–
Export MX APIs to more languages: (Python, C++,
Labview, etc.)
–
Add client-side part of callback support.
General improvements
–
Port MX to new platforms: (QNX, VMS, etc. )
–
Collaborate with SER-CAT to develop MX systems
based on Delta Tau PMAC controllers.
–
Add new data file formats such as HDF/NeXus.
–
Addition of new drivers.
Summary
"
"
"
"
"
MX is now in use at 6 APS beamlines, 1 CAMD
beamline, and in X-ray labs at IIT.
Several beamlines at APS, ALS, NSLS, and CLS have
expressed interest.
Runs on a variety of hardware platforms.
Designed to interoperate with other control systems and
user interfaces.
We are interested in collaborating with other groups on
the further development and application of MX.
Acknowledgements
A. Howard
J. Chrzas
L. Keefe
C. Segre
B. Bunker
N. Leyarovska
H. Tostmann
J. Terry
J. Kropf
G. Bunker
R. Fischetti
J. Fait
G. Rosenbaum
J. Quintana
E. Westbrook
M. White
IMCA-CAT, IIT
IMCA-CAT, IIT
IMCA-CAT, IIT
MRCAT, IIT
MRCAT, Notre Dame
MRCAT, IIT
MRCAT, Univ. of Florida
MRCAT, IIT
MRCAT, Argonne Natl. Lab.
BioCAT, IIT
BioCAT, IIT
SER-CAT, Univ. of Georgia
SER-CAT, Univ. of Georgia
DND-CAT, Northwestern
ALS Beamline 4.2.2, MBC
GCPCC beamline at CAMD,
Univ. of Texas Medical Branch
Descargar

MX: A Portable Data Acquisition and Control Toolkit