StepLib
Software Driver for SC-02 PC Based Stepper Controller

User Manual


Contents

1. StepLib - Driver for SC-02
1.1 Installation and Usage
1.2 Description Of Functions
1.2.1 Int Set_Base(Int Addr )
1.2.2 Int Set_Clk(Float Clkspd)
1.2.3 Int Set_Rmpfreq(Int Rcount)
1.2.4 Int Set_Rampup(Int Axis, Unsigned Newramp)
1.2.5 Int Set_Rampdn(Int Axis, Unsigned Newramp)
1.2.6 Int Set_Fbmode(Int Mode) 0
1.2.7 Int Set_Convert(Int Mode)
1.2.8 Int Step_Init(Void)
1.2.9 Int Step_Close(Void)
1.2.10 Int Drive_Enable(Int Axis)
1.2.11 Int Drive_Disable(Int Axis)
1.2.12 Int Stop_Axis(Int Axis, Int Flag)
1.2.13 Int Set_Iobit(Int Bitno)
1.2.14 Int Reset_Iobit(Int Bitno)
1.2.15 Int Load_Axis(Int Axis, Motor *Values)
1.2.16 Unsigned Readcount(Int Axis)
1.2.17 Unsigned Stepsleft(Int Axis)
1.2.18 Float Read_Speed(Int Axis)
1.2.19 Int Read_Rampstat(Int Axis)
1.2.20 Unsigned Char Read_Input(Void)
1.2.21 Int Set_Startspd(Int Axis,Int Spd)
1.2.22 Int Set_Stopspd(Int Axis,Int Spd)
1.2.23 Void Vtwo(Long Divisor, Int *A, Int *B)
1.2.24 Float Calib_Clk(Void)
1.2.25 Int Zero_Axis(Int *A)
1.2.26 Void Enable_Limits(Int Axis)
1.2.27 Void Disable_Limits(Int Axis)
1.3 Some Comments



1. StepLib - Driver for SC-02

The  SC-02  card need powerful programs to realise its  versatility  in  control.  From  the user manual for SC-02, programming the  SC-02  looks  formidable  and  it is so. This can be avoided by  using  the  STEPLIB  driver package.



1.1 Installation and Usage
The package consists of 4 files :
  1. Steplib.Lib - Containing the routines
  2. Steplib.H - Containing data structure definitions and global variables
  3. Exmpl2.C - Turbo C example program
  4. Exmpl2.Prj - Make file for example program


Installation is done by copying these onto the target computer.

The  library  module  is linkable to Turbo C programs.  Part  of  this  library  has  been coded in C and the rest in ASSEMBLER.  The  library,  when invoked, takes over the system timer for the purposes of ramping.  However,  the  ramping  routines  alter the  frequency  of  the  timer  interrupt  on the PC and hence the system clock would not be  accurate  for  the period for which the program linked to STEPLIB is active.  If  accurate time is required then the real time clock (RTC) can be  used.  It is essential that the library be initialised and closed by the user  program after entering and before quitting. The user program should be  a LARGE or HUGE memory model program.

This package consists of routines for the following operations :

  1. Setting up of parameters
    1. Base address
    2. Basic clock Frequency
    3. Ramping frequency
    4. Ramp up rate
    5. Ramp Down rate
    6. Feedback/Open loop mode
    7. Converter connected/ not connected
    8. Initialising and closing the card
  2. Control Port Operations
    1. Drive enable/disable
    2. Start/stop
    3. Digital I/O port operations
    4. Loading motion parameters
  3. Readback Operations
    1. Steps left
    2. Steps over
    3. Current control byte
    4. Current speed of the motor
    5. Digital I/O port
    6. Ramping status
However the package does not support the interrupt capabilities of the SC02 card.

All  programs  using the functions in the library  are  prototyped  in  STEPLIB.H  and  this file should be included in the  source  file.  The  important  data  structure defined in this include file is  the  MOTOR  type  structure  which  is  used for passing  data  to  the  load_axis  routine.



1.2 Description of Functions
This  section  describes the functions included in the  library.   The  names  of  the routines are mentioned in the same format as  they  are  prototyped  in the library. All the names are case sensitive  and  are  available publicly with preceding underbars.

Each function description consists of the function name. The  variable  name  given with the function name is a dummy name and given  for  the  purposes of illustration. A short summary of the operations  performed  by  the routine is provided followed by a clear indication  of  inputs  and  outputs to the routines. Special considerations  are  illustrated  with examples.

1.2.1 int set_base(int addr)
This  function informs other routines in STEPLIB  of the base  address  that has been selected on the card

Call with :
                    addr  :  Base address of the card
Return Value :
                     0      if successful
                     1      if not

Default value of the address is factory set 340 (Hex)

Example :

     status = set_base(0x200)  /*** Sets base address as 200 (Hex) **/

     if ( status ==1)
         printf ("Error");
     else
         printf ("Everything OK");

1.2.2 int set_clk(float clkspd)
If the input frequency source to the counters has been selected as PC- bus  clock,  then  this  routine is used  to  inform  STEPLIB  of  the  prescalar  and  the bus frequency used. This speed depends  upon  the  jumper setting on the card.

Call with
  clkspd : Frequency used

Return Value :
  0      if successful
  1      if not

If  this  function is not called, it is assumed on  board  crystal  is  being used and the prescalar is 1/2.

Example :

If  the  PC clock of 12 MHz with prescalar 8 is  used,  the  resultant  frequency is 1.5 MHz. Hence,

     status = set_clk(1.5e6)                /** 1.5 MHz frequency */

will set the frequency appropriately.

1.2.3 int set_rmpfreq(int rcount)
This  function  selects  the frequency of  ramping  up.  Ideally  this  routine  is used to set the ramping frequency while tuning the  drives  with  the  motors.  The ramping time is set  to  5*rcount,  i.e..  the  software outputs a new speed every 5*rcount milliseconds.

Call with

       rcount    :     Ramping time required

Return Value

     0      if successful
                1      if not

Default value of ramping frequency is 10 milliseconds.

Example : To set a ramping frequency of 50 milliseconds

     status = set_rmpfreq(10)        /** sets 50 ms ramping time **/

1.2.4 int set_rampup(int axis, unsigned newramp)
1.2.5 int set_rampdn(int axis, unsigned newramp)
These  functions set the rate of ramping up or down of the motor.  The  value of newramp should be steps/s/s. The fresh value of the ramp  set  is  used  only in the next motion programmed and does not  affect  any  current motion. If newramp is 0, then no ramping is set and the  speed  is  applied directly as similarly the motor is stopped immediately  on  command.

Call with
  axis   :  Axis number ( 0,1 or 2 )
  newramp    :     Ramp up(down) rate required in steps/s/s
 

Return value
                0      if successful
                1      if not

Default value of the rates are 20 steps/s/s for up and down.

Example : For using low acceleration and high deceleration, in axis  0  and vice versa for axis 1,

 setramp(0,10) ;
 setramp(0,50) ;
 setramp(1,50) ;
 setramp(1,10) ;

1.2.6 int set_fbmode(int mode)
This function informs STEPLIB whether operation is open loop or closed  loop.

If  mode is 0, then the board is operated in the open loop mode,  else  it is operated in feedback mode.
Call with
       mode   :     0 ( open loop )
             or 1 ( closed loop )
Return Value
                0      if successful
                1      if not

Note : Jumper Setting for open loop or closed loop is required.

1.2.7 int set_convert(int mode)
This  routine is used to inform STEPLIB that converter card  is  being  used or not. If mode is 0, then converter card is present, else it  is  not.

Call with
  mode :  0 ( converter used ) or
    1 ( not used )

Return Value
                0      if successful
                1      if not

The  converter setting determines the actions taken on  initialisation  of the board. See description of step_init(...) for details.

1.2.8 int step_init(void)
1.2.9 int step_close(void)
The step_init initialises the SC-02 board. After initialisation :

The step_close routine closes the driver routines


Call with
  No input values
Return values
  0      if successful
                1      if not

Step_init should be called for the proper functioning. The  step_close  routine should be called before exiting form main program or else the  computer  will hang. However the input/output functions  will  perform  normally without calling step_init.

Example :

 set_base(mybase) ;
 set_clk(myclk) ;
 step_init() ;   /** using default modes, ramp values **/

     /**      Movement routines here       **/

 step_close() ;
 exit() ;
 

1.2.10 int drive_enable(int axis)
1.2.11 int drive_disable(int axis)
This routine sets (enable) or resets (disable) the drive enable bit in  the control nibble for axis.

Call with
       axis : Axis number ( 0,1 or 2)
Return Value
                0      if successful
                1      if not

1.2.12 int stop_axis(int axis, int flag)
This routine resets (stops) the start/stop bit in  the  control  nibble for axis. If flag is 0 then  the  motor is ramped down, else the motor is brought to  an  immediate  stop.

Call with
  axis  : Axis number ( 0,1 or 2 )
  flag       0  - Ramp down
    1  - Immediate stop required
Return Value
                0      if successful
                1      if not

This routine is used for operations asynchronous to  the  ramping  routines only. Under normal operation, whenever  a motion is programmed,  the  ramping routines operate the motor till the motion  is  completed  and  then  the  motors  are stopped. If however a stop  operation  is required during motion, for e.g. triggered by  an  input,  then this routine can be used.

The  action  of this routine on the control ports and  the  counters  depends upon whether the converter is used or not and hence care  must  be taken to use set_convert routine properly.

1.2.13 int set_iobit(int bitno)
1.2.14 int reset_iobit(int bitno)
These  routines  set or reset the I/O bits in the  digital  I/O  port.  Since  the  output ports are accessed through  byte  wide  operations,  these routines retain the status of the other bits.

Call with
       bitno  : Bit Number (0 to 7)
Return Value
                0      if successful
                1      if not

The  I/O  ports can be accessed asynchronously by user  software  using  directly the outportb, inportb calls. However, once such an  asynchronous  call has been used by the user, further calls to these routines may  not  function  properly  as the information about such modified  status  is  lost.  It  is advisable that the bits are accessed through  calls  to  set_iobit, reset_iobit only.

1.2.15 int load_axis(int axis, MOTOR *values)
This  function programs the axis with the speed and  movement  values  specified. The structure MOTOR is defined in steplib.h. This structure  is defined as follows :

          typedef struct mot_dat
 {
  float speed     ;
  char direction  ;
  char resolution ;
  char rampflg    ;
  unsigned int movement ;
 } MOTOR ;

In this speed is in steps per second, direction is 0 (bit reset) or  1  (bit  set), resolution is 0 ( full step,bit reset) or 1 (  half  step,  bit  reset), movement is in number of steps. All these are defined  in  steplib.h.  The background ramping routines will be used  for  ramping  with set rate values depending on whether rampflg is 1 or 0.

Call with
       axis     : Axis number
       values    :     Pointer to the MOTOR structure

Return value
                0      if successful
                1      if not

In  case the converter is used, the FULL step option is not valid  and  will return an error.

Drives are NOT enabled by this routine and the user should enable  the  drive  by a separate call to drive_enable(...),  if  not  already  enabled. The values structure passed to the routine is not affected by  the function.

Example  :  For  moving axis 1 with speed 500  steps/second  for  2000  steps, with ramping in half step mode, the following program will work  :

     MOTOR m1 ;
     char c1 ;
     m1.speed = 1000 ;          /** motion is in half steps **/
     m1.movement = 4000 ;       /** motion is in half steps **/
     m1.direction = CLOCKWISE ;  /** CLOCKWISE is defined in         steplib.h          **/
     m1.resolution = HALF ;   /** HALF is defined in steplib.h               **/
     m1.rampflg = TRUE ;    /** We want to ramp **/
     load_axis(1,&m1)    ;      /** motion starts**/

 c1 = getch() ;
      if ( c1== 'Q')
         stop_axis(1,1) ;  /** Stop immediately if Q **/
      else
        stop_axis(1,0) ;   /** Stop with Ramp down **/

 c1 = getch() ;
      if (c1== 'C')
       restart_axis(1) ;      /*** Continue motion **/
 

1.2.16 unsigned readcount(int axis)
1.2.17 unsigned stepsleft(int axis)
These  routines  report the status of a programmed motion,  while  the  motion is being performed. readcount returns the number of steps moved  since starting, and stepsleft returns the number of steps remaining to  be moved in axis.

Call with
  axis    : Axis Number ( 0,1 or 2)

Return Value
                     Number of Steps

Example : Continuing  the  example  for  load_axis, to  display  the  amount  of  movement made, the following change can be made

MOTOR m1 ;
char c1;
int moved, notmoved ;

m1.speed = 1000 ;      /** motion is in half steps **/
m1.movement = 4000 ;   /** motion is in half steps **/
m1.direction = CLOCKWISE ;
m1.resolution = HALF ;
m1.rampflg = TRUE    ;
load_axis(1,&m1)     ;  /** motion starts **/
/** Changed to display steps left and steps over      **/
      while (!bioskey(1))

     {
 moved = stepsover(1) ;
 notmoved = stepsleft(1) ;
 printf ("%d,%d\r", moved,notmoved) ;
      }
 if ( c1== 'Q')
  stop_axis(1,1) ;   /** Stop immediately if Q **/
 else
  stop_axis(1,0) ;   /** Stop with Ramp down **/

 c1 = getch() ;
 if (c1 == 'C')
  restart_axis(1) ;     /** Continue motion **/
 

1.2.18 float read_speed(int axis)
This function reports the current speed of axis

Call with
       axis     :     Axis number (0,1 or 2)

Return Value
  Current speed of axis

The  reported  value  of speed is always the programmed  value  if  no  ramping has been requested for.

1.2.19 int read_rampstat(int axis)
This  routine reports the status of ramping operation.  This  function  can  be  used if the user wishes to wait for the motor to  come  to  a  stable speed before next operation.

Call with
  axis : Axis Number (0,1 or 2)
Return Value
                  0      No motion
  1     Ramping up
  2      Moving at constant speed
  3      Ramping down

If ramp rates are zero, this routine always returns 0 if the motor  is  stopped or 2 if the motor is moving.

Example : Suppose it is required to start axis 0, wait for it to reach  stable speed before axis 1 starts.

 MOTOR m1 ;
 char c1 ;
 int moved, notmoved ;

 m1.speed = 1000 ;
 m1.movement = 4000 ;
 m1.direction = CLOCKWISE ;
 m1.resolution = HALF ;
 m1.rampflg = TRUE ;

 load_axis(0,&m1) ;

 /** Checking for  stable speed **/

 while (read_rampstat(0) != 2) ;      /** Stable speed reached,        can move axis 1 now **/
 m1.speed = 1000 ;
 m1.movement = 4000 ;
 m1.direction = CLOCKWISE ;
 m1.resolution = HALF ;
 m1.rampflg = TRUE ;
 load_axis(1,&m1) ;
 

1.2.20 unsigned char read_input(void)
This routine reports the status of the digital inputs.

Call with
  None.

Return Value
    Status of Port

The  port  can  be  read directly  also  without  disturbing  the operation of this function.

1.2.21 int set_startspd(int axis,int spd)
The routine sets the starting speed of the motor while ramping up to the required speed.  The parameter spd is to be specified in steps per second.  The start speed for each of the three axes can be set independently.  Specifying the start speed of an axis while a motion is executed in that particular axis, the next move in that axis will with the new start speed. Specifying a null start speed will lead to the assumption of the default start speed of 50.

Call with:
  axis   :   Axis Number (0,1 or 2)
  spd : Speed in steps/second.
Return Value:

   0  If successful
   1 Failure
Example:

To set the start speed of the second axis to a low start speed, perhaps because it is carrying a high inertial load, say 20 steps per second :

   status = set_startspd(1,20) ;

1.2.22 int set_stopspd(int axis,int spd)
This routine is similar to the set_startspd routine, with the difference that it sets the speed from which the motor drops to a complete stop while ramping down from its current running speed. The default value is 50 steps per second and operates similar to the previous routine.

Call with:

  axis   :   Axis Number (0,1 or 2)
  spd : Speed in steps/second.

Return Value:

   0 If successful
   1 If failed

Example:

To set the stop of the first axis to virtually instant stop, the following can be used:

   status = set_stopspd(1,1000) ;

1.2.23 void vtwo(long divisor, int *a, int *b)
This function splits the number divisor into two integers a and b such that:

  divisor = a*b

in an optimal way i.e. such that the residual is minimum.  This routine has been provided for splitting the speed divisor into two numbers which can then be programmed in the respective counters of the SC02 card.  This function may be used for direct programming the card rather than through the load_axis(...) method.

Call with:
  divisor :    number to be split
  *a  Pointer to integer a
  *b  Pointer to integer b

Returns:

   0 Successful
   1 Failed

Example:

Suppose the clock frequency selected is F and the speed required is Speed, then to program the speed of motion directly:

   unsigned long divisor ;
   int a,b ;
   divisor = F/Speed ;
   vtwo(divisor,&a,&b) ;

The numbers a,b can now be written to the appropriate counters

1.2.24 float calib_clk(void)
The function uses the counters of the SC02 cards themselves to determine the basic clock frequency that has been chosen.  The function takes about 5 secs to execute and returns the value of the basic clock frequency.

Call with:
  none

Returns:
    The frequency as a floating point number

Example:

Suppose one does not know the frequency of the clock source used for the clock prescalar selection in hardware, the following code can be used to set the appropriate frequency:

   set_clk(calib_clk()) ;

1.2.25 int zero_axis(int *a)
This function takes the mechanical system to the 0 reference position as determined by lower limit switch fixed on the mechanism
.
The process is as follows:

Call with:

  *a[3] :  pointer to array for specifying axis(es) in which     zeroing operation is to be done.

Return value:
  0  : Successful

Note that if the limit switches are not fixed or connected or malfunctioning this routine will hang the computer and the motors will continuously rotate in  the anti-clockwise direction.

Example:

To search for reference in the 0 and 2 axes,

   int a = {1,0,1}
   zero_axis(a) ;

1.2.26 void enable_limits(int axis)
1.2.27 void disable_limits(int axis)
The STEPLIB routines provides for the automatic checking of over driving in either directions beyond the limits set by the limit switches.  The default status of this checking is OFF for all the axes.  The above routines provide for enabling (disabling) such checking in any specific axis.

In case of running with the limits checking enabled, and the motor hitting the limit switch in the specified direction, the call to read_rampstat(..) will return 0 i.e. indicating that the motor is stopped.  However, stepsleft will return the proper values which indicates the number of steps remaining to be moved when the limit was hit.

Call to these functions may be made even while axis is in motion and will be in effect immediately.

Call with:

  axis  :  Axis on which to enable or disable limit operation

Return :
   Always 0

Example:

The following piece of code assumes that the motor is to be moved say in a jogging mode and a limit was hit. However, it over travel is required in that direction for other purposes. SOMESPEED, MAX_MOVEMENT are constants denoting the speed at which the motor is to be moved and the maximum movement possible with the mechanism respectively.

  MOTOR m ;
  m.speed = SOMESPEED ;
  m.movement = MAX_MOVEMENT ;   .   .  .   enable_limits(0) ;
  load_axis(0,&m) ;
  while (read_rampstat(0)) ;
  if (steps_left(0))    /** Is motion complete **/
  {
   disable_limits(0) ;
   m.movement = MAX_MOVEMENT ;    .    .   }
  else      /** Motion was complete **/



1.3 Some Comments
If  the  interrupt  capabilities are required  to  be  utilised,  then  additional programs can be written, but they can still use the STEPLIB  routines  without any conflict. The only requirement is that  the  ISR  used for this purpose should enable the timer interrupt immediately on  entry.

An  example program EXMPL2.C has been provided  which  highlights  the method of usage of most of the functions.