Hardware 101 - was: ECM Bench Problem

Peter Gargano peter at ntserver.techedge.com.au
Sun Dec 12 03:18:34 GMT 1999


Dear Dr Plecan (Hardware 101 lecturer at the Uni of GMECM),

Here is my assignment for Hardware 101, where we had to design a 
circuit to produce a signal like that from a Hall Effect pickup
using a slotted wheel with 7 unequal slots designed to give a
positive edge at 0, 10, 60, 120, 180, 240, 300, and 360/0 (repeating).

Due to the difficulty of delivering my hardware to you by the 
assignment's deadline, I have taken the liberty to ask you to
supply the hardware - in this case a straightened paper-clip plugged 
into pin 2 of your PC's parallel port (LPT1) (you may wish to 
substitute a DB25P with an insulated wire soldered to pin 2, this
will enhance the life of your LPT port's DB connector).

My "hardware driver" follows - it is "hardwired" to produce an
increasing "RPM" from 600 to 6,000 over approximately a 10 second
period. Simply connect a signal measuring device to the hardware's
"output" - pin 2 mentioned above, and watch the signal!

For the CREDIT part of the question "design a circuit to allow the
RPM to be varied", I was going to supply a 555 timer circuit connected
to pin 10 of your LPT1, but I realised that you wouldn't receive this
in time either. So, I was going to ask you to supply your own games
joystick (a term I believe overstates the functionality of this device)
and use this to control the RPM. Unfortunately, due to the impending
assignment deadline, I will have to leave this as an exercise for you
to set your next semester's class.

Thank you again, Dr Plecan, for the learning experience you have
given me.

Here is my assignment (I compiled it with Borland C v3.1):

/*
 Hall Effect Ignition Sensor Emulator using LPT1.
 Uses PC's 8253 (or AT's 8254) timer channel 0 as time reference.

 Master Clock:           14.318180 MHz
 8253 Clock input:        1.193182 MHz  = master clock / 12
 8353 Clock period:       0.838095 uSec (p = 1/T of clock input)
 PC software clock:      54.925416 mSec (65536 * Clock period)
 PC Clock frequency      18.206507 Hz   (1/software clock)

In one second we get 1,193,182 clock pulses.
Time for one revolution (360 degrees of rotation) is:

    t = RPM / 60 (Secs.)

So the conversion from RPM (R) to counts/degree (Cpd) is

    Cpd = 1193182 / 360 x (R/60)
        = 198863.7 / R

History:
 12dec99 Peter Gargano - create
*/

#include <stdio.h>
#include <string.h>
#include <dos.h>

typedef unsigned char BYTE;
typedef unsigned int  WORD;

// the count represents degrees of rotation, the table entries should
// total 72 (360 degrees)

BYTE degreesInterval [14] = {
	 5,  5,  // 0   -> 10
	25, 25,  // 10  -> 60
	30, 30,  // 300 -> 120
	30, 30,  // 120 -> 180
	30, 30,  // 180 -> 240
	30, 30,  // 240 -> 300
	30, 30,  // 300 -> 360/0
};


WORD lptAddr;       // LPT port to use

WORD startCount;    // global timestamp
WORD lastCount;     // used for wrap around testing

//=======================================================================

WORD readCounter0 (void) {

	WORD count;

	outportb (0x43, 0);             // Command to read counter 0
	count = inportb(0x40);          // Read LSB
	count += (inportb(0x40) << 8);  // read MSB into MSB position
	return count;
}


// delayUntil returns when the elapsed count has been reached

void delayUntil (WORD limit) {

	WORD count;

	///printf (" - limit count = %04x (%d)\n", limit, limit);
	for (;;) {
		count = readCounter0 ();
		if (limit < lastCount) {  	// downcount to reach is lower (ie. NOT wrapped around)
			if (count < limit       // and count IS lower
			 || count > lastCount)  // OR count has wrapped around already
				 break;
		}
		else {                          // downcount to reach is higher (ie. wrap around)
			if (count < limit       // limit was reached
			 && count > lastCount)  // AND check that we have wrapped too!
				 break;
		}
	}
	lastCount = limit;  // new timestamp
}


void main (void)
{
	int  index;
	int  RPM;
	WORD cnt;

	int  i;
	WORD tot;

	lptAddr = 0x378;  // use LPT1
	lastCount = startCount = readCounter0 ();

	RPM = 600;
	for (i=0; i < 1000; i++) {

		RPM = 600 + (6*i); //debug
		tot = 0;
		for (index=0; index < 14; index++) {
			outportb (lptAddr, index);        // bit 0 (pin 2) will toggle as index++
			tot += degreesInterval [index];   // running total of degrees this rev
			cnt = (float) tot * (198863.7 / (float) RPM);  // count represented by tot
			///printf ("RPM=%d, index=%02d [=%d], cnt=%d. ", RPM, index, degreesInterval [index], cnt);
			delayUntil (startCount - cnt);
		}
		startCount -= cnt;
	}


void main (void)
{
	int  index;      //index into degrees table
	int  RPM;
	WORD cnt;

	int  i;
	WORD tot;

	lastCount = startCount = readCounter0 ();

	lptAddr = 0x378;  // use LPT1 for output

	RPM = 600;

	for (i=0; i < 1000; i++) {

		RPM = 600 + (6*i); ///debug
		tot = 0;
		for (index=0; index < 14; index++) {

			outportb (lptAddr, index);        // bit 0 (pin 2) will toggle as index++
			tot += degreesInterval [index];   // running total of degrees this rev
			cnt = (float) tot * (198863.7 / (float) RPM);  // count represented by tot
			///printf ("RPM=%d, index=%02d [=%d], cnt=%d. ", RPM, index, degreesInterval [index], cnt);
			delayUntil (startCount - cnt);
		}
		startCount -= cnt;
	}
}



More information about the Gmecm mailing list