It's essentially just an Arduino with probes connected to a number of analog and/or digital inputs with all the hard work done in the software, plus a "power" LED to show when it's alive
Trang 1Figure 11-3 Schematic of Arduino Oscilloscope / Logic Analyzer
Instructions
The circuit for this project couldn't be much simpler It's essentially just an Arduino with probes
connected to a number of analog and/or digital inputs with all the hard work done in the software, plus a
"power" LED to show when it's alive
In our prototype, we fitted a total of eight input probes but because the Duemilanove and most
other Arduino designs only have six analog inputs, we connected the first six probes to the analog inputs and the remaining two to digital inputs This allows up to six analog waveforms to be sampled, which is plenty for most applications, but still allows up to eight digital lines to be analyzed in case we need to
process an 8-bit parallel data bus
Alternatively, you could use an Arduino Mega and take advantage of the fact that the Mega has 16
analog inputs Just keep in mind that the more analog inputs you want to sample, the slower the
program will run and the lower your sample frequency will be
Or, if you only care about sampling one or two channels at a time, you could simplify things and
leave the rest of the inputs off entirely You could even use an Arduino Pro Mini and build the whole
thing into a large probe body to create a single-channel, handheld device with a USB connection on the back Bluetooth or ZigBee comms to the host computer would also be a possibility so that you could
make it totally wireless It's really up to you to decide how you want to configure it
You'll note that we specified a metal project case and shielded cable for the probes This is to reduce
"cross talk" where a signal presented on one input influences the readings of other inputs by inducing
Trang 2tiny currents in them You can certainly do without it but you may see a signal in one channel cause artifacts in the display for other channels
You'll also note that we didn't bother including any form of input protection for the Arduino itself The Arduino I/O lines are exposed directly on the front of the box as probe sockets, and the probes themselves connect those I/O lines straight to the circuit under test
Initially, that may seem a little crazy After all, what happens if you accidentally connect a probe to, say, a 24V circuit when the ATMega inputs are only rated to 5V?
The answer is that you'll probably blow at least that input on the ATMega CPU, if not the whole CPU itself, and will probably need to replace it However, the fact is that buying a new ATMega328 is
somewhere in the region of $8 at the time of writing, whereas fitting adequate input protection circuitry that would protect the CPU while not changing the characteristics of the inputs would be technically difficult and probably cost more than $8 in parts
So we made a pragmatic decision to keep the circuit simple and acknowledge the fact that the ATMega CPU is inexpensive enough that we can simply pop it out and replace it if anything goes
drastically wrong Hopefully that won't be a common occurrence!
Assemble the Case
To make the end result look a bit more professional, we used a die-cast aluminum case that we lightly sanded with fine sandpaper before spraying it with gloss black paint We also printed a front-panel overlay on self-adhesive paper with a color laser printer The resulting front panel isn't especially durable, but does dress it up a little and helps make it clear which probe socket is which The artwork for
our panel is available for download from the project page on the Practical Arduino web site in case you'd
like to use it
Start by drilling the mounting holes for the Arduino We mounted the case upside down with the lid
on the bottom, allowing the Arduino and shield to be mounted on the inside of the lid on plastic
standoffs with the probe sockets mounted on the side of the case Because the sides of the case slope inward slightly, the Arduino had to be positioned a little back from the edge so that the power socket would clear the side while still keeping it as close as possible to the edge so the USB socket would protrude
We used 10mm plastic spacers with 20mm M3 bolts passing up through the lid The Arduino sits on the spacers with plastic washers on top to insulate the nuts from the circuit board M3 nuts then hold it firmly in place and the result is that the Arduino is very securely mounted in the case The USB cable can
be inserted or removed with confidence that nothing will move around inside the box
Turn the base over and stick a self-adhesive rubber foot in each corner so that it will sit nicely on a workbench without the bolt heads on the bottom making it rock around all over the place (see Figure 11-4)
The square USB socket needs to protrude through the side of the case but cutting square holes neatly can be very tricky Depending on the material used in your project case you may be able to drill a single large hole in the middle of the area to be removed and then use a panel nibbler or Dremel tool to trim it to the correct dimensions Otherwise, you might need to drill a series of small holes around the perimeter to remove the bulk of the material, then finish up with a file to neaten up the edges The approach we took was to cut the hole as a slot from the edge of the case with a hacksaw and then breaking out the resulting tab This leaves a little gap under the USB socket, but it's on the side of the box
so it's not too unsightly and the result is that the cover can drop on easily over the Arduino
Trang 3Figure 11-4 Arduino mounted on 10mm spacers using M3 bolts
Next, mark the position for all the input probe sockets and the power LED
To keep the paintwork and front label looking neat and unblemished, we also printed a disposable copy of the label on normal paper to use as a placement stencil We taped the label to the box and used a center punch and a small hammer to tap a dimple into the center of each hole location, then removed
the stencil and drilled pilot holes for the LED and probe socket holes All this was done before the case
was sprayed so the paint wouldn't be marred by the drilling process
Once the paint was well and truly dry, we then stuck on the actual label and used a thin-blade craft knife to cut out all the holes (see Figure 11-5)
Insert the black panel-mount socket for the ground probe and the eight yellow sockets for the signal
probes, and tighten up the nuts to hold them in place We used RCA plugs and sockets in our prototype because they have a handy shield connection and are quite inexpensive However, because they're not known for having the best quality electrical connection, and because electrical noise is important in a
project like this, we used the best type we could get: gold-plated sockets and metal-body plugs If you
want to spend a bit more and use different connectors, you certainly can The ones we used for our
prototype worked fine for our purposes though
Trang 4Figure 11-5 Front panel label in place with holes drilled
Alternatively, if you don't care about analog input and will only be measuring digital logic levels, you don't need to care about shielding and can go for cheaper plugs and sockets Or you could do what many commercial logic analyzers do and combine all the inputs into a single multipin socket
Next, mount the power LED We used a relatively expensive panel-mount LED in a metal bezel, but you could just as easily use a regular LED and glue it into the hole or clip it into place with a plastic bezel
if you prefer (see Figure 11-6)
Figure 11-6 Connectors and LED mounted in front panel
At this point, the case looks like all the work is done, but it's still just a shell without the working
Trang 5Fit the Prototyping Shield
Cut eight short lengths of shielded single-core cable and strip back each end, then solder the center
conductor of each cable between the panel-mount sockets and the prototyping shield Inputs 0 through
5 connect to matching analog inputs 0 through 5, while inputs 6 and 7 connect to digital inputs 6 and 7, respectively Also connect the shield braid to the GND power bar on the prototyping shield and to the
outer terminals on the panel-mount sockets By connecting the sockets this way, the entire case is
connected to the Arduino ground and will be at 0V relative to the Arduino power supply, and each cable will be individually shielded between the socket and the prototyping shield The signal will then have to travel down through the unshielded header pin to the Arduino and along the Arduino PCB to the input
on the ATMega chip, of course, but by shielding as much of the signal path as practical, we improve the quality of the signal that will be sampled (see Figure 11-7)
Figure 11-7 Front panel connectors linked to prototyping shield using shielded cable
Because the project case is well connected to ground via all the signal shields, we don't need a
specific connection from the ground probe socket to the prototyping shield We simply soldered a short piece of wire from the center pin on the socket to the tab for the shield connection, providing a good link from the case to the center pin through the body of the socket
Next, fit the 680R resistor to the prototyping shield with one end connected to +5V and the other to a spare pad on the shield Then run a length of hookup wire from the end of the resistor to the anode
(long, or positive) lead of the panel-mount LED, and another short length of hookup wire from the
cathode (short, or negative) lead of the LED to one of the panel-mount socket tabs so it connects to
ground
Trang 6Make Test Probes
Depending on the types of circuits you test, you might find it handy to create a few different test probes for different purposes Options include an alligator clip for attaching to bare wires or a metal case; a spring-loaded hook clip for linking to component pins; and a straight sharp probe for general-purpose use Having a few different probe types handy can make things much easier
We made a ground probe with a nickel-plated RCA plug, a black spring-loaded hook clip, and a length of unshielded hookup wire We also made up test probes using shielded cable, connecting the center conductor to the test clip and the center pin of the RCA plug while the braided shield connects to the outer shield connection on the plug A short length of heat-shrink tubing at the probe end of the cable keeps the trimmed end of the shield braid neat (see Figure 11-8)
Figure 11-8 Ground probe and test probe
How Successive Approximation ADC Works
Converting an analog voltage level into its equivalent digital value (ADC) can be quite tricky, particularly
if it needs to be done both quickly and accurately The analog inputs on an ATMega CPU use a technique called "successive approximation ADC," which provides a decent trade-off between speed, accuracy, resolution, and complexity
Successive approximation ADC uses a network of capacitors with exponentially scaled values that are first completely discharged to an offset voltage provided by a comparator, then charged to the voltage of the signal being sampled The capacitors are then switched to the comparator input so that it
is exposed to the same voltage as the original signal but with that voltage provided by the capacitors rather than by the circuit under test, which is completely isolated at that point Each capacitor is then progressively switched to the reference voltage and the comparator compares the resulting voltage to
Trang 7The simplest way to conceptualize this is to imagine that the ADC starts with a very rough idea of
the level of the input and progressively narrows it down to a more accurate value The first reading, or
bit, simply checks whether it's in the top or bottom half of the voltage range If it's in the top half, it's 1; the lower half, it's 0 Then the second reading, or second bit, checks whether it's in the top or bottom
half of that range Every bit that is read doubles the resolution of the result by narrowing it down to a
smaller part of the range (see Figure 11-9)
Figure 11-9 Successive-approximation ADC
This means that the number of capacitors in the array determines the number of successive
readings and, therefore, the bits of resolution that the ADC can generate In an ATMega each analog
input uses a 10-capacitor array, so the highest resolution it can provide is a 10-bit value This
corresponds to a decimal number between 0 for a voltage at 0V, and 1023 for a voltage at the supply
voltage of the system
As you can imagine, it takes a little while for this process of discharging, switching, charging,
switching, then stepping through each capacitor
Adding more bits increases the resolution, but it also means more steps for the ADC circuit to
perform while doing the conversion Conversely, decreasing the number of bits also decreases the
conversion time A 10-bit sample on an ATMega used in an Arduino takes approximately 111
microseconds
Compare this to reading a digital input, which is essentially just feeding the input signal straight to the comparator and returning a single bit immediately without going through all the steps with the
capacitor array That's why a digital read can take place in under one microsecond but an analog read
takes more than one hundred times as long
Note that the terms "accuracy" and "resolution" do not mean the same thing, even though many
people use them interchangeably Resolution tells us the number of intervals on a scale being used to
measure something, while accuracy tells us how consistently the scale is applied The resolution on an
Trang 8sampling the last two bits, there is a little bit of jitter in the voltage being tested and so they might
fluctuate slightly even when reading a very consistent and accurately generated reference voltage The
resolution on the analog inputs may be 10 bits, but they don't actually provide quite that much accuracy
If you want to do analog reads at the highest possible speed at the expense of a little accuracy it's
possible to force the ATMega CPU to apply a custom prescaler value to the ADC clock Because the ADC
needs to perform a sequence of comparisons, the time it takes to complete an entire analog read is
dependent on how quickly it can perform each individual step The ATMega is rated to supply a clock
rate of between 50KHz and 200KHz to its ADC depending on a combination of the overall CPU clock
speed (16MHz on a typical Arduino) and the ADC prescaler factor The Arduino environment sets the
prescaler factor to a value of 128 in the file hardware/cores/arduino/wiring.c around line 231 This
results in an ADC clock rate of 16MHz / 128 = 125KHz, which is well within the 50KHz to 200KHz range
recommended by Atmel
125KHz is a fairly conservative ADC clock rate, though, and you can get massive ADC speed gains by
pushing it closer to its operational limit The ATMega datasheet notes that ADC clock speeds up to 1MHz
"do not reduce the ADC resolution significantly," which means that on a 16MHz Arduino you can push
the prescaler value as low as 16 to increase the ADC clock speed right up to 1MHz (i.e., 16MHz / 16) and
still get reasonably good accuracy The result is analog reads that complete in around 16 microseconds—
far faster than the 111 microseconds of a stock Arduino!
The settings can be altered by editing wiring.c so that it will apply to all programs you compile The
ATMega datasheet provides the data listed in Table 11-1 showing the effect of setting or clearing the
three ADC prescaler select bits
Table 11-1 ADC prescaler bits and division factor
0 0 0 2
0 0 1 2
0 1 0 4
0 1 1 8
1 0 0 16
1 0 1 32
1 1 0 64
1 1 1 128 Arduino sets all three bits to 1 in wiring.c with the following code:
sbi(ADCSRA, ADPS2);
sbi(ADCSRA, ADPS1);
Trang 9The sbi call sets the bit, and a corresponding cbi call can also clear the bit To set the prescaler value
to 16 you would modify those lines to the following:
sbi(ADCSRA, ADPS2);
cbi(ADCSRA, ADPS1);
cbi(ADCSRA, ADPS0);
Rather than changing the Arduino environment, though, you can also do it directly within your
Arduino program by using the previous code along with some macro definitions for sbi and cbi For
example, to change the prescaler value to 16 (first bit set, second and third bits cleared) you could start
by adding the following macro definitions at the top of your program:
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
Then, inside the setup() function of your program, set and clear the appropriate bits using the sbi() and cbi() macros as follows:
sbi(ADCSRA,ADPS2);
cbi(ADCSRA,ADPS1);
cbi(ADCSRA,ADPS0);
Of course you could also set and clear different bits to achieve other prescaler values depending on your requirements
Connection to Circuit under Test
Before testing a circuit the first thing to do is tie the Arduino oscilloscope's ground connection to the
circuit ground using the black probe plugged into the GND socket That provides the scope with a
ground reference that's at the same voltage as the circuit ground, allowing the voltage of test points to be measured relative to it
Figure 11-10 shows the ground lead connected to the ground of the circuit under test (an RFID
reader shield on an Arduino Mega, in this case) with the test probe connected to the RX pin on the serial data connection to the RFID module
If you need to frequently test ICs, you might find it worthwhile buying an IC test clip to suit the
packages you use An IC test clip is a spring-loaded device like a really wide clothes peg that fits over the top of an IC while it's in-circuit and exposes each pin as a test point on the top of the clip This brings the electrical connections up high above the circuit to a convenient point for you to attach test probes
Trang 10Figure 11-10 Connection to a circuit under test
Install Software in Arduino
Because all the hard work is done in the attached host, all the Arduino has to do is sample its inputs and send the values to the host as fast as possible The Arduino program is, therefore, almost as simple as the circuit
We've provided several different versions, though, because this project really pushes the limits of what the ATMega processor can do, and it's important to make the program run as fast as possible for the given test requirements You can have different versions ready to go on your host computer and push them across to the Arduino as required for different tests
Analog Read Version
The first version is the most flexible in terms of input values it can process but also the slowest, therefore providing the lowest sample rate This is a good general-purpose sample program because it uses the first six inputs as analog inputs and returns a value from 0 to 1023 for each of those inputs, then reads the last two inputs as digital inputs and returns a value of either 0 for LOW or 1023 for HIGH
However, this approach has performance limitations because reading an analog input takes over
100 microseconds, and the data stream returned to the host is quite verbose For a typical reading the