Main Page | Class List | File List | Class Members | File Members

ppdev_motion.c File Reference

Motion control for stages driven by unintelligent stepper motors. More...

#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/time.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <pthread.h>
#include <linux/ppdev.h>
#include <linux/parport.h>
#include "logerr.h"
#include "motion.h"

Classes

struct  Devicestate
 The bit pattern currently applied to the parallel port data register. More...
struct  Axismapping
 Logical to physical axis mapping. More...
struct  Stagelocation
 Coordinates representing a position along multiple axes. More...
struct  Stagecontrol
 Grouping of definitions for one parallel port and all its dependent axes. More...
struct  Translation
 Everything needed to control a translational stage axis. More...

Defines

#define resting_condition(a)

Typedefs

typedef const char * stagelabelp_t
 All the stage axis labels are immutable strings.
typedef const unsigned char axistates_t
 Representation of bit patterns controlling the stepper motor phases.

Enumerations

enum  stagecommandflags { STAGE_DEAD = 0, STAGE_LIVE = 1, STAGE_COMMANDABLE = 1<<1, STAGE_WATCHABLE = 1<<2 }
 Stage status flags.

Functions

axismappingp_t newaxismapping (const unsigned int axes)
 Make a new logical to physical axis mapping table.
void disposeaxismapping (axismappingp_t themap)
 Destroy a logical to physical axis mapping table.
void setaxismapping (axismappingp_t themap, const unsigned int logical, const axismapentry_t physical)
 Change an entry in a logical to physical axis mapping table.
stagelocationp_t newstagelocation (unsigned int axes)
 Make a new generalized stage coordinate vector.
void disposestagelocation (stagelocationp_t theloc)
 Destroy a generalized stage coordinate vector.
void setstagelocation (stagelocationp_t theloc, const unsigned int axisn, const coord_t newval)
 Change one coordinate in a generalized stage coordinate vector.
coord_t getstagelocation (const stagelocationp_t theloc, const unsigned int axisn)
 Access one coordinate in a generalized stage coordinate vector.
stagecontrolp_t newstage (const axismappingp_t themap)
 Initialize the data structures representing a stage (including the axes).
void disposestage (stagecontrolp_t stage)
 Destroy a stage data structure (without checking to see if it is in use).
int openstage (stagecontrolp_t stage, const char *path, const int flags)
 Connect to the physical port controlling the stage.
int closestage (stagecontrolp_t stage)
 Halt control of the stage, without de-allocating all data structures.
int movestage (stagecontrolp_t stage, const stagelocationp_t motn)
 Issue a request that the stage move to a particular position.
int findstage (stagecontrolp_t stage, stagelocationp_t posn)
 Copy the various axis positions into a coordinate structure.
int stageactive (stagecontrolp_t stage)
 Examine the stage to find if it is active.


Detailed Description

Motion control for stages driven by unintelligent stepper motors.

Some stages rely on the controlling computer to handle the low-level details of the motors that drive them, in contrast to those that dedicate an intelligent controller to these tasks, with which the controlling computer can communicate using some high-level protocol over something like a serial interface.

This particular implementation is for stages driven by stepper motors connected directly to parallel ports. Individual phases on the motor are either active or inactive depending on whether a particular bit on a parallel interface is asserted or not. The software can rotate the motor only by suppling a sequence of bit patterns that will cause the motor phases to activate and de-activate in the correct order. Apart from possibly microswitches that change input bits on the parallel interface when the stage reaches a home position, only a count of the steps moved by each motor gives any indication of the actual stage position. Individual motors drive each axis of the stage, but more than one motor may share a single port, provided we can assign each a distinct group of bits within the port.

We have based the low-level parallel port control on the ppdev driver, which exposes the necessary details of the port to user-level programs under Linux. Unlike the Solaris version of the motion control code, this means we do not have to provide a custom-written kernel module; documentation for ppdev is included as part of the Linux kernel source, and Tim Waugh (one of the original authors) provides a manual at http://people.redhat.com/twaugh/parport/html/parportguide.html for the Linux 2.4 kernel version. We rely on a Posix Threads implementation for two important aspects of the stage motion control: a distinct thread becomes responsible for handling each axis of the stage, and variations in the timeouts as the threads wait on condition variables determine the variations in the motor speed.

Author:
University of Arizona Digital Image Analysis Lab
Date:
2003
Version:
Id
ppdev_motion.c,v 1.6 2004/11/18 19:14:06 mmunro Exp

Define Documentation

#define resting_condition  ) 
 

Value:

((a->pos == a->goalpos) && \
                      (a->delay >= a->maxdelay) && \
                      ((a->delta < 0) == (a->backlash == 0)) && \
                      ((a->delta > 0) == (a->backlash == a->maxlash)))


Function Documentation

int closestage stagecontrolp_t  stage  ) 
 

Halt control of the stage, without de-allocating all data structures.

This is the inverse of openstage(), returning to a state similar to that when the stage data structures were allocated but unused. We wait for stage activity to cease, cancel the controlling threads for each axis, place the port in a quiescent state, then close it.

Parameters:
stage the open stage to be closed.
Returns:
an error code on failure, zero on success.
See also:
disposestage()

openstage()

void disposeaxismapping axismappingp_t  themap  ) 
 

Destroy a logical to physical axis mapping table.

Parameters:
themap the map to destroy.
See also:
newaxismapping()

void disposestage stagecontrolp_t  stage  ) 
 

Destroy a stage data structure (without checking to see if it is in use).

Parameters:
stage the stage to destroy.
See also:
newstage()

closestage()

void disposestagelocation stagelocationp_t  theloc  ) 
 

Destroy a generalized stage coordinate vector.

Parameters:
theloc the stage coordinates to destroy.
See also:
newstagelocation()

int findstage stagecontrolp_t  stage,
stagelocationp_t  posn
 

Copy the various axis positions into a coordinate structure.

If the stage is at rest, this finds its current position; however if the axes are in motion the stage may have moved from the recorded position before this returns.

Parameters:
stage the stage whose position will be found.
posn where to record the coordinates.
Returns:
an error code on failure, zero on success.

coord_t getstagelocation const stagelocationp_t  theloc,
const unsigned int  axisn
 

Access one coordinate in a generalized stage coordinate vector.

Parameters:
theloc the coordinate vector to examine.
axisn selects the logical axis number.
Returns:
the current position ascribed to this axis.
See also:
setstagelocation()

int movestage stagecontrolp_t  stage,
const stagelocationp_t  motn
 

Issue a request that the stage move to a particular position.

Parameters:
stage the stage to move.
motn the requested position.
Returns:
an error code on failure, zero on success.

axismappingp_t newaxismapping const unsigned int  axes  ) 
 

Make a new logical to physical axis mapping table.

The logical axes are numbered from 0 to axes - 1, and the physical axes are initially assigned the same numbers.

Parameters:
axes the number of axes in the mapping.
Returns:
the newly-allocated mapping.
See also:
disposeaxismapping()

setaxismapping()

stagecontrolp_t newstage const axismappingp_t  themap  ) 
 

Initialize the data structures representing a stage (including the axes).

The new stage is defined in terms of a logical to physical axis mapping, and we construct it by allocating not only the stage structure, but the structures that represent the physical port and the individual axes. However we leave to openstage() the task of opening the physical port and starting the threads responsible for controlling each axis.

Parameters:
themap the logical to physical axis mapping.
Returns:
the newly-allocated stage structure.
See also:
openstage()

disposestage()

stagelocationp_t newstagelocation unsigned int  axes  ) 
 

Make a new generalized stage coordinate vector.

Parameters:
axes the number of axes requiring positions.
Returns:
the newly-allocated position information.
See also:
disposestagelocation()

setstagelocation()

getstagelocation()

int openstage stagecontrolp_t  stage,
const char *  path,
const int  flags
 

Connect to the physical port controlling the stage.

We need a stage data structure previously allocated by newstage() and a path that defines the physical port controlling the stage hardware (something like /dev/parportN). We attempt to open the port, then perform some initialization on it (e.g., setting up control registers and making sure it is in a quiescent state), then start the detached threads controlling each axis.

Parameters:
stage the previously allocated stage control structure.
path the device port path.
flags additional flags specifying attributes for the stage.
Returns:
an error code on failure, zero on success.
See also:
newstage()

closestage()

void setaxismapping axismappingp_t  themap,
const unsigned int  logical,
const axismapentry_t  physical
 

Change an entry in a logical to physical axis mapping table.

Parameters:
themap the map to modify.
logical the logical axis number.
physical the new corresponding physical number.

void setstagelocation stagelocationp_t  theloc,
const unsigned int  axisn,
const coord_t  newval
 

Change one coordinate in a generalized stage coordinate vector.

Parameters:
theloc the coordinate vector to modify.
axisn selects the logical axis number.
newval the new position ascribed to this axis.
See also:
getstagelocation()

int stageactive stagecontrolp_t  stage  ) 
 

Examine the stage to find if it is active.

We try to acquire the lock on the stage structure, and immediately determine that the stage is busy if we can't acquire it, without examining anything else. As soon as we find an axis that's not in its resting state we also determine the stage must be busy, but test it again after waiting one polling interval (currently a hard-wired constant). However we release the lock before returning, so it's quite possible that the stage is busy again by the time this returns, if no other conditions are imposed.

Parameters:
stage the stage to examine.
Returns:
a non-zero code if the stage is active, zero if it is not.


Generated on Sat Dec 4 17:12:35 2004 for trees by  doxygen 1.3.9.1