Parallel Port Project

Bill Toomey

29 December 2003

Project Goal

The primary goal of this project is to explore the use of the data bits available on the parallel port of an Intel based PC running LINUX to control equipment external to the PC.

Special consideration is given to telescope control. Knowledge gained in this project will be used to position a telescope equipped with two stepper motors controlled through the parallel port.

Beyond this, there are a number of possible applications which can be developed from the knowledge gained in this project. Some of them are mentioned in the section titled "Project Follow Ons" later in this document.


We use PCs every day for an number of applications such as word processing and accounting, but we very rarely think of our PC's ability as an equipment controller.

If we look at our PC we find it usually has a game port, a parallel port, and one or 2 serial ports. This is enough to turn any PC into a hardware controller. If one needs more ports, one can also add one or more IO cards to the expansion slots to increase the port count. If one wishes to go beyond this, one could also add Analog to Digital and Digital to Analog cards.

As an amateur astronomer, I often come across applications where a PC can be used to control a piece of external equipment. These applications usually come with some canned control software that runs under a Microsoft OS.

My interest in exploring the use of Linux as the OS to control astronomical equipment started when I bought an old CCD camera for my telescope. I loaded the control software which was written for MSDOS onto my laptop running Microsoft Windows 98. All attempts to make the CCD camera work failed. After I had spent a considerable length of time troubleshooting the problem, a friend who knew more about Microsoft products than I did, told me that although MS Windows lets you think you are accessing the serial port, it will not let you do so. Sure enough, as soon as I booted the laptop in MSDOS, the CCD camera started working.

It was then that I decided that it would make more sense to use an OS where I had the source code available and could get direct access to the ports through my own code.

Technical Overview

When an operating system is written to run on a number of different hardware architectures, it is by necessity, written in a high level language. The UNIX family and its close relative LINUX are such operating systems.

It is customary to separate the portable higher level functions of the operating system from the hardware dependent lower level functions. In the case of UNIX/LINUX, the higher level functions are written in C. This code is portable between different hardware architectures. The hardware dependent lower level functions are usually written in the assembly language for the particular hardware used.

For most applications that use the parallel port, we can use a high level driver which hides the specific hardware implementation. The functions provided by the driver are machine independent, such as talking to a printer or scanner.

In this case however, we need to control the parallel port at the hardware level. This precludes the use of an existing driver to access the port. In this case we will have to use the assembler routines to directly manipulate the port. We will also have to use the specific hardware addresses for for the port.

In LINUX, the machine routines we are interested in are defined in the header file asm/io.h

The Parallel Port

The PC has three standard base addresses used for parallel ports.

   They are:
        0x3bc (956 decimal) /dev/lp0
        0x378 (888 decimal) /dev/lp1
        0x278 (632 decimal) /dev/lp2

Each port consists of three consecutive addresses starting at the base address.

The first of these, which is at the base address, consists of 8 data bits designated D0 through D7. They reside on pins 2 through 9 on the parallel port connector.

The second write byte is at address base+2. This is used for control bits in a printer application, but for our purpose, these are just other bits that can be used for external hardware control. There are four of of these bits brought out on the parallel port connector.

  They are:

        Bit 0 -STROBE     (0=high)      Pin 1  on the parallel port connector
        Bit 1 -AUTO_FD_XT (0=high)      Pin 14
        Bit 2 INIT        (1=high)      Pin 16
        Bit 3 -SLCT_IN    (0=high)      Pin 17

It is important to notice that bits 0, 2, and 3 are inverted. You can deal with this by using an XOR in you code, or adding inverter gates to your hardware outside the parallel port.

The remaining address, base+1, is a read only byte. It has 5 bits which are present on the parallel connector.

   They are:

        Bit 3 ERROR (1=high)            Pin 15
        Bit 4 SLCT  (1=high)            Pin 13
        Bit 5 PE    (1=high)            Pin 12
        Bit 6 ACK   (1=high)            Pin 10
        Bit 7 -BUSY (0=high)            Pin 11

Notice that Bit 7 is also inverted. These pins can be used for equipment to signal a condition to your program. An example would be if you had a motor opening or closing a door and a microswitch to signal when the door was open or closed. , You would then know when to turn off the motor.

It should be noted that the eight data bits are bidirectional on some parallel ports. If this is the case, the direction is controlled by base+2 Bit 5. This was not used in this project but is discussed in the Linux port HOW-TO. A pointer to this document is listed in the bibliography.


LED test fixture:

The first piece of hardware necessary for this project was the breadboarding of an LED test fixture that allowed me to monitor the output bits on the parallel port. This was used to verify that I had the correct port address and that the bits behaved as expected. It was also used in the programming phase to verify that the bit patterns for the stepper motor winding sequencing was correct before the actual hardware was attached to the port.

The components for this test fixture consisted of a 380 ohm resistor in series with an LED for each data bit. This was assembled on a solderless breadboard.

Motor Control Board:

It was originally my intent to buffer the parallel port data bits and use them to control power transistors to switch external devices on and off, but a number of years ago, I ordered a stepper motor control board from an amateur astronomer, Mel Bartels which I had never used. After examining this board, it became clear that although this board was intended for an astronomical application, there was nothing in the design that was specific to this application.

A simplified way of looking at the motor control board is each data bit is buffered by a segment of a 74LS04 hex inverter. The bit is then passed through a 4N26 opto-isolator to electrically isolate the circuitry on the computer port side from the circuitry on the motor side. The bit is finally used to switch the power to the stepper motor winding through a TIP120 power transistor. The board also has all the required zener diodes to handle the back emf from the motor windings.

In the project demo, four of the bits are used to control a KP4M4-001 four phase unipolar stepper motor salvaged from an old 5 ¼ inch floppy drive. This motor steps in 3.6 degree increments. Since a stepper motor moves a known number of degrees for each step, it can be used in an open loop system. Stepper motors have a problem with speed and will not slew as quickly as a DC servo motor.

One bit is used to control a DC servo motor which was also salvaged from the floppy drive. It was used to spin the floppy. A DC servo motor us used when fast slewing is needed, but since it can not be known how far a DC servo motor has turned, it can only be used in a closed loop system when it is being used for positioning. In these cases, an optical encoder is attached to the shaft to give the shaft position. I have worked with optical encoders in the past for the positioning of telescopes, and find that they work very well and would not difficult to add to this application.

One bit is used to control a buzzer which I purchased from Radio Shack for my home alarm system.

The motor control board needs 5 volts for the circuitry on the parallel port side. I de-soldered the power plug from the floppy control board and used it to take power from the computer power supply. For the 12 volts necessary for the motor side of the board, I used a 7 amp-hour 12 volt gel cell.

The above demonstrates that the motor control board can be used for large variety of applications.

It should also be noted that this board also has the pullup resistors to control the five input bits on the base+1 byte. This makes it easy to use the input bits for feedback to a program.

I did a web search and found that Mel Bartels has gone commercial and has started a company to sell this board as well as a number of other items. I paid $70 for the board a number of years ago. It now sells for about $120, but I still think this is a reasonable price considering the board comes populated and tested. It is my intent to order another board as I move this research on to a telescope, and leave the present board on my work bench to do some robotics projects with my son's help.


All the programs described below exist in the source directory. There is a makefile that can be used to generate all the executables by changing to the source directory and typing ./make. All the text data files used by the programs are also in the source directory.

The goal is to have all of the functionality necessary for this application reside in class functions. The programs themselves will mearly use the class functions to achieve the desired results. Some of the programs below are proof of concept and the calculations made in them will be roled into classes in the h files.

Include Files


This include file contains the classes that touch the port itself. It is the goal to move this functionality into a loadable module.


This include file contans the scientific and math object classes I wrote. .


This include file contains miscilanius functions and constants I use, which are more of a programming nature.

Test Software

A number of programs were written to test out the port and to verify the proper operation of the demo configuration. These programs were then used for the demo.

These programs are all built around the sample program found in the Linux port HOW-TO. Since these programs were written to test the hardware, little time was taken to make the coding elegant. In a final application program, much more time would be spent making the code more versatile. These programs must be run as root to have direct access to the ports.


This program was used to probe the likely locations for the ports to determine which ones were available on the particular PC I was developing on. To run this program type ./port_probe. It will check the three most likely port addresses and print out which ones are present. This program takes no arguments.

dcon.cpp dcoff.cpp buzzeron.cpp buzzeroff.cpp

These programs turn the DC motor and the buzzer on and off. They take no arguments. Only the dcon.cpp and dcoff.cpp programs are listed in the source section since the only difference is the bit written. As a matter of fact dcoff.pp and buzzeroff.cpp do the same thing since I am not doing bit masking at this time.


This program simulates the single stepping of the the stepper motor on the LED tester. This is done by applying power to each of the four motor windings in succession. This is done by sending the sequence 1 2 4 8 1 2 4 8 ... to the parallel port. If you were single stepping the motor on the upper 4 bits, you would send the sequence 16 32 64 128 16 32 64 128 ... If you wanted to spin two stepper motors at the same time (one on the lower 4 bits and one on the upper 4 bits) you would send the sum of the two sequences 17 34 68 136 17 34 68 136 ...


This program simulates the half stepping of the stepper motor on the LED tester. This can be done because applying current to two adjacent stator windings will cause the rotor to position itself half way between the two windings. The half step pattern would be 1 3 2 6 4 12 8 9 1 3 2 6 4 12 8 9 ... If this pattern looks confusing, look at it written in binary. It should then be clear how the windings are being half stepped. This technique doubles the angular resolution of the stepper motor. In the case of the demo stepper motor, this is 1.7 degrees per half step.


This program uses a technique called Pulse Width Modulation to use 1/10th steps to increase the angular resolution. This is possible because the inductance of the motor winding smoothes out the square waves from the port data. By turning each of two adjacent winding on for a different percentage of the cycle, the rotor can be positioned at a fraction of the distance between the two windings. For a more detailed discussion of this technique, see Mel Bartels' website.

Telescope Tracking Programs

When the stepper motors are attached to a telescope mount in the final application, one motor will control the rotation around the polar axis. The other motor will control how far the scope will point north or south of the celestial equator.

The following programs will be combined in the final telescope application as functions that can be called to control of the telescope.


This program develops the ability to rotate the telescope about the polar axis (the axis which is parallel to the Earth's polar axis) at a rate opposite to the spin of the Earth's axis. This will compensate for the rotation of the Earth and keep the telescope pointed at the same point on the celestial sphere. To do this the program needs to know the step size of the stepper motor, and the gearing ratio between the motor and the axis of rotation to calculate the rate at which the motor needs to be stepped. This function uses the PWM stepping to have this motion as smooth as possible. If the step size is too large, the image in the telescope will appear to jump.


This program develops the ability to point the telescope at a specific point on the celestial sphere. To do this the program needs to know the orientation of the celestial sphere at the present moment, the location of the object on the celestial sphere, and where the telescope is pointing at the present time. This will use the half step routine to speed up the slew. This program is not yet written.


This program will track an object that does not remain at a fixed location on the celestial sphere, such as a planet or a comet. To do this, this program will need to know all information needed for slew.c as well as the way the object moves on the celestial sphere. This program is not yet written but will use the functionality of the programs in the next section when it is.

Spherical Astronomy & Orbital Mechanics Functions

The telescope tracking programs described in the previous section contain the control functions necessary to point the telescope when we know where we want it pointed. The programs in this section start to build the mathematical infrastructure necessary to know where we want the telescope to point. These functions in standalone programs have value since their output can be used to manually point a telescope or binoculars.


This program reads a file that contains the latitude, longitude and altitude of the telescope or observer, and from the computer time, calculates the Local Mean Sidereal Time (LMST). This can be displayed and updated at regular intervals. This routine will be used in the position code. The LMST gives us the orientation of the celestial sphere for the point on the Earth where the observation is being made.


This program reads a file which contains the celestial coordinates of an object in a standard epoch and calculates its hour angle for the telescope's location and the LMST. It also calculates the azimuth and altitude of the object. This will eventually use a database of objects from which the object can be chosen (a good project for the data structures course). At this time, this program does not contain corrections for Precession and Nutation, but these will be added later. This routine will tell the telescope pointing routines where to point the telescope. It uses stars.txt as the default file to obtain the data for the celestial object to calculate the values for.


This program reads a file that contains an object's position and velosity vectors at a given instant in time and uses the f & g series to calculate the position and velosity vectors at some other time. These values from the file can be obtained from the Astronomical Almanac. Given the position vector of the Earth and of the object, we can calculate where we need to point the telescope on the celestial sphere to see the object. The orbital elements can also be calculated from the position and velocity vectors. I must admit that I could also find the object's position on the celestial sphere from the orbital elements, which are also available in the Astronomical Almanac, but vectors are my favorate mathematical objects, and this gave me a good reason to write a Vector class with a rich set of member functions. The included files that can be used are earth1.txt and mercury1.txt. The usage is ./fg_series mercury1.txt.


The steps outlined above should be sufficient as a proof of concept. They contain all the software and hardware elements necessary to adapt the parallel port as a mechanism to bring external equipment under computer control.

Project Follow Ons

A number of ideas have come to mind for follow on projects to this project.

One project my son and I have talked about is the building of a remote control robot. The idea here would be to build a platform that could hold a laptop with a wireless LAN card. The laptop would control the drive motors to the wheels. You could then log into the laptop remotely and control the vehicle. If you put a webcam on the laptop, then you would not even have to see the vehicle to decide which way to make it go. We have decided that it is important to put a fail-safe in the code to stop the vehicle if it looses its network connection, because it you don't, and if it ever got out of range of the wireless LAN, then it would continue until the battery ran down or it ran out of gas.

An other idea I had was for my home alarm system. I have a Radio Shack alarm system which I installed in my home. It has a number of sensors set up in four zones. When the alarm goes off, I have no way of knowing which sensor on which zone has tripped the system. If I used the parallel port in the read direction, I could monitor each sensor. I could then record which one tripped and when. This way I could have a record of how an intruder moved around my house, or which sections of my house was accessed even if the alarm was shut off.

I want to build a greenhouse. If I did I would like to build a circuit with a thermistor and an analog to digital chip. I could then connect this to the parallel port and get a record of the temperature every minute or so. This could lead to some interesting data analysis.

If the buzzer is replaced by a ham radio morse code key, then you can write a program that will take your typed text and transmit it as morse code.



The following references address the use of the parallel port and the use of stepper motors:

Linux I/O Port Mini-How-To

This How-To describes how to access the ports on Intel based PC hardware when using the Linux OS. This also contains the sample code that was the basis of my port access programs.

Mel Bartels' website

This website gives a good tutorial on computerizing telescopes. It also gives pointers to Mel's commercial venture where you can buy the stepper motor interface board I used in this project.

Stepper Motor website

I used this website to get the information I needed on the KP4M4-001 stepper motor used in my demo. It also has a number of links to other sites that are of interest. Doing a Yahoo search will give many more sites that I found useful.

"The Robot Builder's Bonanza" Second Edition by Gordon McComb, McGraw Hill ISBN 0-07-136296-7.

This book is a good introduction to the use of electronics to control hardware.


These books were used to develop the astronomical software part of my project.

"Textbook on Spherical Astronomy" by W. M. Smart, sixth edition revised by R. M. Green, Cambridge University Press ISBN 0 521 29180 1.

This is the classic textbook on spherical astronomy. It was from this book that I gained my understanding of this subject.

"Computational Spherical Astronomy" by Laurence G. Taff, Krieger Publishing Company ISBN 0-89464-478-5.

This textbook is a more modern (1981) treatment of the subject. This is the book that I used to develop most of my spherical geometry software calculations.

"Astronomical Algorithms" by Jean Meeus, Willmann-Bell, Inc. ISBN 0-943396-35-2.

This book contains a wealth of algorithms that you find you need to bridge the theory presented in the above two textbooks, such as calculating the Julian Day Number for a given date.

"An Introduction to Celestial Mechanics" Second Revised Edition by Forest Ray Moulton, Dover Publications, Inc. ISBN 0-486-64687-4.

This is one of the classic textbooks on celestial mechanics, and served as an overview of the subject.

"Fundamentals of Astrodynamics" by Roger R. Bate, Donald D. Mueller, and Jerry E. White, Dover Publications, Inc. ISBN 0-486-60061-0.

This textbook was developed for a course at the Air Force Academy, and for this reason has a much less theoretical and a more practical approach to the subject. I only used this book for backup.

"Fundamentals of Celestial Mechanics" Second Edition by J. M. A. Danby, Willmann-Bell, Inc. ISBN 0-943396-20-4.

I used Appendix A of this book to program my Ellipse class. I will eventually use it to program the classes for the remaining conic sections.

"Methods of Orbit Determination for the Micro Computer" by Dan Boulet, Willmann-Bell, Inc. ISBN 0-943396-34-4.

I used this book for the development of my f & g series routines.

"The Astronomical Almanac 2000" U. S. Government Printing OfficeISBN 0-16-049869-4.

This Almanac was used for the starting data in a number of the calculations. The data in this almanac was also used to verify the correctness of the algorithms used.