Interfacing a Junk Disk 5-1/4 inch Drive with a Parallel Port

Copyright, Towanda L. Malone
Department of Electrical Engineering
Morgan State University, Baltimore, MD 21239
August 10, 96

This discusses how to interface with the circuitry on a junk 5-1/4 inch disk drive so as to control the stepping motor. Although this discussion focuses on the early full height IBM drives, most of the points are probably common to most other disk drives .

See Figure #1.

The disk drive itself consists of two motors, one a servo and the other a stepping motor, the magnetic head, numerous sensors and a printed circuit board. The printed circuit board on the disk drive interfaces with a floppy disk controller card via a 34 terminal edge board connector. It is at this point that we are discussing interfacing with the disk drive and using the printer port to control the stepping motor.

The stepping motor is used to position the head at various radiuses. It is usually interfaced with the printed circuit board on the disk drive using a 6-pin connector. (A servo motor, briefly discussed below, is used to control the angular motion of the diskette).

The original IBM design provided for a common interface between the ISA controller card and the disk drives and the designers opted to put a fair amount of the circuitry on the printed circuit board associated with the disk drive. Thus, the stepping moto r may be controlled via the disk drive PCB with simply "Motor ON", "Direction" and "Step" signals. The printed circuit board (PCB) in the disk drive performs the necessary circuitry to translate these signals to the required sequential patterns to energi ze the stepping motor coils. (A full discussion of the operation of a stepping motor is contained in Volume I). The PCB also provides the necessary voltage drivers to operate the stepping motor coils.

See Figure #2. Note that the motor is turned "ON" with a logic zero on terminal 14. In our design, we tied this to ground. However, when using a number of motors this could well be controlled using an additional output from the Data Port so as select a particular motor.

Note that power is supplied via the 4-pin power connector on the disk drive. Both +12 and +5 are required. Potential inexpensive sources include your PC or a junk PC power supply.

In the following programs, DSKDRV_1.C is a very simple program to simply move the stepper back and forth. In DSKDRV_2.C, functions are used to control the direction, speed and the duration.

In DSKDRV_3.C, this has been expanded to read commands from an ASCII file. Commands include "T" (turn) with direction, speed and the number of steps, "P" (pause) where the amount of time to pause is specified and "Q" (quit). This is significant as you c an expand on this to develop your own language which the "customer" uses to control a stepping motor.

Notes.

The shaft on the stepping motor is pinned so as to limit the travel and may be removed to permit the motor to freely travel through 360 degrees.

You may desire to replace the stepping motor with another which is more amenable to mounting. Various AirPax steppers with 12VDC coils are available from All Electronics for less than $3.00. Be sure the substitute motor has the same coil voltage as the original and that the current is not appreciably above that of the original. That is, the resistance of the windings of the substitute should be equal to or greater than that of the original.

Old disk drives also contain a small servo motor. This discussion does not treat the operation of servos. However, the servo may be used as a small DC motor (+12 VDC)and, in fact, it was used in the discussion of DC motors elsewhere in this manual.

Disk drives also contain a number of optical sensors consisting of an LED and a photosensitive transistor. These are used to detect whether a disk is write protected and to detect the alignment hole in the disk.


/*
** Program DSKDRV_1.C
**
** Turns motor in one direction for 5 seconds, pauses for 5 seconds,
** turns ins other direction for 5 seconds.
**
** Towanda Malone, Morgan State University, August 10, '96
*/

#include <stdio.h>                                            /* 1 */
#include <dos.h>                                              /* 2 */
                                                              /* 3 */
#define DATA 0x03bc                                           /* 4 */
                                                              /* 5 */
int data = 0x00; /* note global */                            /* 6 */
                                                              /* 7 */
void main (void)                                              /* 8 */
{                                                             /* 9 */
   int n;                                                     /* 10 */
   data = data | 0x02;  /* direction set to logic 1 */        /* 11 */
   outportb(DATA, data);                                      /* 12 */
   for (n=0; n<100; n++)                                      /* 13 */
   /* turn in one direction for 5 seconds */                  /* 14 */
   {                                                          /* 15 */
      data = data | 0x01;  /* step high */                    /* 16 */
      outportb(DATA, data);                                   /* 17 */
      delay(25);                                              /* 18 */
      data = data & (~0x01);  /* step low */                  /* 19 */
      outportb(DATA, data);                                   /* 20 */
      delay(25);                                              /* 21 */
   }                                                          /* 22 */
   delay(5000); /* pause for 5 secs */                        /* 23 */
                                                              /* 24 */
   data = data & (~0x02);  /* direction set to logic 0 */     /* 25 */
   outportb(DATA, data);                                      /* 26 */
   for (n=0; n<100; n++)                                      /* 27 */
   /* turn in other direction for 5 seconds */                /* 28 */
   {                                                          /* 29 */
      data = data | 0x01;  /* step high */                    /* 30 */
      outportb(DATA, data);                                   /* 31 */
      delay(25);                                              /* 32 */
      data = data & (~0x01);  /* step low */                  /* 33 */
      outportb(DATA, data);                                   /* 34 */
      delay(25);                                              /* 35 */
   }                                                          /* 36 */
}                                                             /* 37 */
                                                              /* 38 */


/*
** Program DSKDRV_2.C
**
** Uses functions to turn motor in specified direction at defined
** speed for specified duration, and to stop motor for specified time.
**
** Towanda Malone, Morgan State University, August 10, '96
*/

#include <stdio.h>                                            /* 1 */
#include <dos.h>                                              /* 2 */
#include <sys\timeb.h>                                        /* 3 */
                                                              /* 4 */
#define DATA 0x03bc                                           /* 5 */
                                                              /* 6 */
#define CW 1                                                  /* 7 */
#define CCW 0                                                 /* 8 */
                                                              /* 9 */
int data = 0x00;                                              /* 10 */
                                                              /* 11 */
void turn_motor (int dir, int time, int duration);            /* 12 */
void pause_motor (int duration);                              /* 13 */
void Drive_dir (int dir);                                     /* 14 */
void Drive_step (int time);                                   /* 15 */
                                                              /* 16 */
void main (void)                                              /* 17 */
{                                                             /* 18 */
   turn_motor(CW, 50, 5000);  /* turn CW slow for 5 secs */   /* 19 */
                                                              /* 20 */
   turn_motor(CW, 25, 5000);  /* faster for 5 more secs */    /* 21 */
   pause_motor(5000);         /* pause for 5 secs */          /* 22 */
   turn_motor(CCW, 50, 5000); /* turn other way */            /* 23 */
   turn_motor(CCW, 25, 5000);                                 /* 24 */
}                                                             /* 25 */
                                                              /* 26 */
void turn_motor( int dir, int time, int duration)             /* 27 */
{                                                             /* 28 */
   struct timeb t_curr, t_start;                              /* 29 */
   int t_diff;                                                /* 30 */
                                                              /* 31 */
   ftime(&t_start);                                           /* 32 */
   Drive_dir(dir);                                            /* 33 */
   do                                                         /* 34 */
   {                                                          /* 35 */
      Drive_step(time);                                       /* 36 */
      ftime(&t_curr);                                         /* 37 */
      t_diff = (int) (1000.0 *(t_curr.time - t_start.time)    /* 38 */
             + (t_curr.millitm - t_start.millitm));          /* 39 */
   }                                                          /* 40 */
   while (t_diff <duration);                                  /* 41 */
}                                                             /* 42 */
                                                              /* 43 */
void pause_motor (int duration)                               /* 44 */
{                                                             /* 45 */
   struct timeb t_curr, t_start;                              /* 46 */
   int t_diff;                                                /* 47 */
                                                              /* 48 */
   ftime(&t_start);                                           /* 49 */
   outportb (DATA, 0x00);                                     /* 50 */
   do                                                         /* 51 */
   {                                                          /* 52 */
      ftime(&t_curr);                                         /* 53 */
      t_diff = (int) (1000.0 * (t_curr.time - t_start.time)   /* 54 */
             + (t_curr.millitm - t_start.millitm));          /* 55 */
   }                                                          /* 56 */
   while (t_diff < duration);                                 /* 57 */
}                                                             /* 58 */
                                                              /* 59 */
void Drive_dir(int dir)                                       /* 60 */
{                                                             /* 61 */
   if ( dir == CW)                                            /* 62 */
   {                                                          /* 63 */
      data = data|0x02;                                       /* 64 */
      outportb(DATA, data);                                   /* 65 */
   }                                                          /* 66 */
   else                                                       /* 67 */
   {                                                          /* 68 */
      data = data & (~0x02);                                  /* 69 */
      outportb(DATA, data);                                   /* 70 */
   }                                                          /* 71 */
}                                                             /* 72 */
                                                              /* 73 */
void Drive_step (int time)                                    /* 74 */
{                                                             /* 75 */
   data = data | 0x01;                                        /* 76 */
   outportb(DATA, data);                                      /* 77 */
   delay (time/2);                                            /* 78 */
   data = data ^ 0x01;                                        /* 79 */
   outportb(DATA, data);                                      /* 80 */
   delay (time/2);                                            /* 81 */
}                                                             /* 82 */
                                                              /* 83 */
                                                              /* 84 */
                                                              /* 85 */


/*
** Program DSKDRV_3.C
**
** Opens file "command.dat".  Fetches each line in turn acting on the
** command.
**
** Towanda Malone, Morgan State University, August 10, '96
*/

#include <stdio.h>                                            /* 1 */
#include <dos.h>                                              /* 2 */
#include <sys\timeb.h>                                        /* 3 */
                                                              /* 4 */
#define DATA 0x03bc                                           /* 5 */
                                                              /* 6 */
#define CW 1                                                  /* 7 */
#define CCW 0                                                 /* 8 */
                                                              /* 9 */
int data = 0x00;                                              /* 10 */
                                                              /* 11 */
void Drive_dir (int dir);                                     /* 12 */
void Drive_step (int time);                                   /* 13 */
void turn_motor (int dir, int time, int duration);            /* 14 */
void pause_motor (int duration);                              /* 15 */
                                                              /* 16 */
void main (void)                                              /* 17 */
{                                                             /* 18 */
   FILE *fr;                                                  /* 19 */
   int x, dir, duration, speed, time;                         /* 20 */
   char line[50], op;                                         /* 21 */
   fr = fopen( "a:\cmd_file.dat","rt");                       /* 22 */
   while(1)                                                   /* 23 */
   {                                                          /* 24 */
      fgets (line, 50, fr);                                   /* 25 */
      switch(toupper(line[0]))                                /* 26 */
      {                                                       /* 27 */
         case 'P':                                            /* 28 */
            sscanf (line, "%c %d", &op, &duration);           /* 29 */
            pause_motor(duration);                            /* 30 */
            break;                                            /* 31 */
                                                              /* 32 */
         case 'Q':                                            /* 33 */
            fcloseall();                                      /* 34 */
            exit(0);                                          /* 35 */
                                                              /* 36 */
        case 'T':                                             /* 37 */
            sscanf (line, "%c %d %d %d",                      /* 38 */
                    &op, &dir, &speed, &duration);            /* 39 */
            turn_motor (dir, speed, duration);                /* 40 */
            break;                                            /* 41 */
                                                              /* 42 */
        default:                                              /* 43 */
            printf(" Unknown Command\n");                     /* 44 */
            exit(0);                                          /* 45 */
    }                                                         /* 46 */
   }                                                          /* 47 */
}                                                             /* 48 */
                                                              /* 49 */
void turn_motor(int dir, int time, int duration)              /* 50 */
{                                                             /* 51 */
   struct timeb t_curr, t_start;                              /* 52 */
   int t_diff;                                                /* 53 */
                                                              /* 54 */
   ftime(&t_start);                                           /* 55 */
   Drive_dir( dir);                                           /* 56 */
   do                                                         /* 57 */
   {                                                          /* 58 */
      Drive_step(time);                                       /* 59 */
      ftime(&t_curr);                                         /* 60 */
      t_diff = (int) (1000.0 *(t_curr.time - t_start.time)    /* 61 */
             + (t_curr.millitm - t_start.millitm));           /* 62 */
   }                                                          /* 63 */
   while (t_diff <duration);                                  /* 64 */
}                                                             /* 65 */
                                                              /* 66 */
                                                              /* 67 */
void pause_motor (int duration)                               /* 68 */
{                                                             /* 69 */
   struct timeb t_curr, t_start;                              /* 70 */
   int t_diff;                                                /* 71 */
                                                              /* 72 */
   ftime(&t_start);                                           /* 73 */
   outportb (DATA, 0x00);                                     /* 74 */
   do                                                         /* 75 */
   {                                                          /* 76 */
      ftime(&t_curr);                                         /* 77 */
      t_diff = (int) (1000.0 * (t_curr.time - t_start.time)   /* 78 */
             + (t_curr.millitm - t_start.millitm));           /* 79 */
   }                                                          /* 80 */
   while (t_diff < duration);                                 /* 81 */
}                                                             /* 82 */
                                                              /* 83 */
void Drive_dir(int dir)                                       /* 84 */
{                                                             /* 85 */
   if ( dir == CW)                                            /* 86 */
   {                                                          /* 87 */
      data = data|0x02;                                       /* 88 */
      outportb(DATA, data);                                   /* 89 */
   }                                                          /* 90 */
   else                                                       /* 91 */
   {                                                          /* 92 */
      data = data & (~0x02);                                  /* 93 */
      outportb(DATA, data);                                   /* 94 */
    }                                                         /* 95 */
}                                                             /* 96 */
                                                              /* 97 */
void Drive_step (int time)                                    /* 98 */
{                                                             /* 99 */
      data = data | 0x01;                                     /* 100 */
      outportb(DATA, data);                                   /* 101 */
      delay (time/2);                                         /* 102 */
      data = data ^ 0x01;                                     /* 103 */
      outportb(DATA, data);                                   /* 104 */
      delay (time/2);                                         /* 105 */
}                                                             /* 106 */

File COMMAND.DAT. This ASCII file is prepared by the user to control the motor as required to perform a task.

T 0 25 5000 /* turn one way fast for 5000 ms */
P 5000 /* pause for 5000 ms */
T 1 50 5000 /* turn other way for 5000 ms */
Q           /*quit*/