252 lines
8.5 KiB
Plaintext
252 lines
8.5 KiB
Plaintext
From: fdeck@sleepy.helios.nd.edu (francis deck)
|
||
Subject: CHEAP 8-BIT ADC FOR IBM PC
|
||
|
||
PLANS FOR A 4-CHANNEL 8-BIT ANALOG-TO-DIGITAL CONVERTER FOR PC
|
||
|
||
Francis J. Deck
|
||
fdeck@grumpy.helios.nd.edu
|
||
|
||
This is an extremely simple ADC for the PC. It connects to the parallel
|
||
printer port, and runs from a 9V battery. All parts are available from
|
||
Digi-Key Corporation (1-800-DIGI-KEY), and cost is under $20, including box!
|
||
Input voltage range is 0 to 5 V. Driver software is in Turbo Pascal. I
|
||
measured the speed to be roughly 1200 samples/sec on an 8 MHz XT, and 5700/sec
|
||
on the same PC with a 10 MHz 80286/cache accelerator card turned on.
|
||
|
||
You'll see that this circuit doesn't require a bidirectional 8-bit i/o port.
|
||
It should work even on the most wild of clones. I've had it going on IBM,
|
||
Zenith, Jameco, etc.
|
||
|
||
Needless to say, this is not an extreme precision device, but should suffice
|
||
for many medium-speed application, such as temperature logging or alarms. An
|
||
LM34 temperature sensor (10 mV/F output) would allow 2 degree resolution, for
|
||
instance. For signals which are noisy beyond 1 LSB (roughly 20 mV), taking
|
||
several readings and averaging them will improve the effective resolution by
|
||
the square root of the number of readings.
|
||
|
||
SCHEMATIC DIAGRAM:
|
||
________________
|
||
+ | |
|
||
__|__ |
|
||
___ 9 V |
|
||
_____ battery |
|
||
___ |
|
||
| |
|
||
| |
|
||
__|__ <
|
||
___ > 1 K Resistor
|
||
_ <
|
||
> Parallel Printer Port:
|
||
| (pin numbers shown are
|
||
| 1 for DB25 male plug)
|
||
_______|_________
|
||
| V+ | 12 2
|
||
| clk |----------------o D0
|
||
Inputs: | | 2 3
|
||
3 | cs' |----------------o D1
|
||
A0 o----------| in0 | 13 4
|
||
4 | din |----------------o D2
|
||
A1 o----------| in1 | 10 10
|
||
5 | dout |----------------o Acknowledge
|
||
A2 o----------| in2 | 7 18
|
||
6 | dgnd |----------------o Ground
|
||
A3 o----------| in3 | |
|
||
8 | | |
|
||
Gnd o----------| agnd | __|__
|
||
| | ___
|
||
| ADC0833CCN | _
|
||
| A to D Conv. |
|
||
| |
|
||
| vcc vref/2 |
|
||
|_________________|
|
||
| 7 | 9
|
||
| |
|
||
| | +2.5 V
|
||
__|__ |
|
||
0.1 uF _____ |
|
||
Disc | |
|
||
Capacitor | | +
|
||
| ____|___|
|
||
| | / \
|
||
| / \ LM336Z-2.5
|
||
| /_____\ Precision Reference IC
|
||
| |
|
||
| | -
|
||
----------|
|
||
__|__
|
||
___
|
||
_
|
||
|
||
Note: The pins of the LM336 can be identified as follows: The (+) terminal is
|
||
the middle pin. Now, look at the lettering on the chip, while holding the chip
|
||
with pins down and lettering facing you, the (-) terminal is on the right.
|
||
|
||
Some notes: First, V+ is the input to an internal Zener regulator, and power
|
||
supplies ranging from +9 to +15 V can be used. This makes it convenient to
|
||
mount the circuit inside an existing powered device, such as a light meter.
|
||
The circuit can also be powered by eliminating the battery and resistor, and
|
||
connecting a +5 V supply to the Vcc terminal.
|
||
|
||
I made a tiny little printed circuit board for this device, but it's hardly
|
||
necessary, considering the low component count. A little piece of perfboard
|
||
will suffice. Don't use cables longer than 1m to connect to the PC, since
|
||
raw TTL isn't very good for long-haul data transmission.
|
||
|
||
PARTS LIST [fmg - prices may have changed since the time this was posted!]
|
||
|
||
All the parts come from Digi-Key Corp, 1-800-DIGI-KEY.
|
||
|
||
Component Part # Price
|
||
--------- ------ -----
|
||
ADC0833 ADC0833CCN $5.00
|
||
LM336-2.5 LM336Z-2.5 1.05
|
||
1k ohm 1.0KQ .26/5
|
||
0.1 uF P4311-ND 1.70/10
|
||
DB25 male plug 225M-ND 1.08
|
||
14-pin IC skt. A9314 .29
|
||
9 V batt. snap BS6I-ND .22
|
||
9 V batt. P104 1.04
|
||
----------------------------------------
|
||
TOTAL: 10.64
|
||
|
||
DRIVER SOFTWARE LISTING
|
||
|
||
These codes are all written in Turbo Pascal.
|
||
|
||
{-------- ADC driver ANALOG.PAS -------}
|
||
|
||
unit analog;
|
||
|
||
interface
|
||
|
||
{-------- User-modifyable constants ------}
|
||
|
||
const
|
||
nlpt = 1; {printer port number}
|
||
vref = 2.5; {reference voltage for ADC}
|
||
|
||
{-------- Read an ADC channel --------}
|
||
|
||
function analog_read (ch: integer): real;
|
||
|
||
implementation
|
||
|
||
var
|
||
in_addr, out_addr: word; {i/o addresses}
|
||
|
||
const
|
||
cs = 2; {ADC chip select line}
|
||
di = 4; {ADC data input line}
|
||
clk = 1; {ADC clock line}
|
||
dout = 64; {ADC data output line}
|
||
|
||
a: array[0..3] of byte = {Channel select word, bit #1}
|
||
(0,di,0,di);
|
||
|
||
b: array[0..3] of byte = {Channel select word, bit #2}
|
||
(0,0,di,di);
|
||
|
||
{-------- Read an ADC channel --------}
|
||
|
||
function analog_read (ch: integer): real;
|
||
|
||
var
|
||
result: byte;
|
||
i: integer;
|
||
|
||
begin
|
||
{transmit chip setup sequence as per ADC0833 data sheet}
|
||
|
||
port[out_addr] := 0;
|
||
port[out_addr] := di;
|
||
port[out_addr] := di + clk;
|
||
port[out_addr] := di;
|
||
port[out_addr] := di + clk;
|
||
port[out_addr] := di;
|
||
port[out_addr] := a[ch];
|
||
port[out_addr] := a[ch] + clk;
|
||
port[out_addr] := b[ch];
|
||
port[out_addr] := b[ch] + clk;
|
||
port[out_addr] := di;
|
||
port[out_addr] := di + clk;
|
||
port[out_addr] := di;
|
||
port[out_addr] := di + clk;
|
||
port[out_addr] := 0;
|
||
|
||
{the main conversion loop}
|
||
|
||
result := 0;
|
||
for i := 1 to 8 do begin
|
||
result := result*2;
|
||
port[out_addr] := clk;
|
||
if port[in_addr] and dout <> 0 then result := result + 1;
|
||
port[out_addr] := 0;
|
||
end;
|
||
port[out_addr] := cs;
|
||
|
||
analog_read := result*vref*7.8125e-3;
|
||
end;
|
||
|
||
{-------- Initialization Section --------}
|
||
|
||
const
|
||
base: word = $40;
|
||
offs: array[1..3] of word = ($08,$0a,$0c);
|
||
dummy: real;
|
||
|
||
begin
|
||
{find out where printer port is}
|
||
|
||
out_addr := memw[base:offs[nlpt]];
|
||
in_addr := out_addr + 1;
|
||
|
||
{place ADC in idling mode}
|
||
|
||
port[out_addr] := cs;
|
||
|
||
{read ADC a few times to let it settle}
|
||
|
||
dummy := analog_read(0);
|
||
|
||
end.
|
||
|
||
{-------- End of ANALOG.PAS ---------}
|
||
|
||
{-------- Test program TEST.PAS --------}
|
||
|
||
program test;
|
||
|
||
uses
|
||
crt,
|
||
analog;
|
||
|
||
var
|
||
i: integer;
|
||
|
||
begin
|
||
while not keypressed do begin
|
||
for i := 0 to 3 do write (analog_read(i):3:3,' ');
|
||
writeln;
|
||
delay (500);
|
||
end;
|
||
end.
|
||
|
||
{-------- End of TEST.PAS --------}
|
||
|
||
If there is suitable interest in this topic, measured by how much e-mail y'all
|
||
send me, I will continue to post simple circuits. In the future, I may have
|
||
to switch to Postscript or HP-GL format for the schematics, which I'd mail to
|
||
interested persons.
|
||
|
||
[fmg - the above started a heated debate on the format of posted schematics -
|
||
the result of which seems to have been loss of interested in posting
|
||
them... bummer]
|
||
|
||
Incidentally, there's a real *gold mine* of inexpensive ICs out there which do
|
||
all sorts of things, and which, like the ADC0833 above, use *synchronous
|
||
serial i/o*, meaning that the send and receive data one bit at a time under
|
||
control of an external clock signal. This kind of i/o is very conducive to
|
||
parallel port connection, as I've shown. I will soon post a list of such
|
||
chips which range from ADC and DACs to remote digital peripherals to EEPROMs
|
||
to graphic equalizers!
|
||
|