© James R. Strickland 2016

James R. Strickland, Junk Box Arduino, 10.1007/978-1-4842-1425-1_7

7. Logic Probe

James R. Strickland

(1)Highlands Ranch, Colorado, USA

One thing that is often hard to get your head around when you first start out with electronics is the mind-boggling speed at which things happen. The Cestino is, by modern standards, not especially fast with its 20MHz clock, or 50 nanoseconds per clock cycle. Nanoseconds are tiny. On the 50ns scale, humans move and think with the speed of plate-tectonics. It’s a time frame that is simply below our perception without tools.

The Need for Speed

Computers, and the logic from which they are made, are at home in nanosecond scale timeframes. Their great strength has always been the ability to execute our instructions, painfully put together in seconds and minutes, thousands or millions of times a second. (Remember, not all computers share the ATmega’s RISC nature and execute an instruction per clock cycle. Also, many actions take multiple instructions.) We haven’t really done anything at significant speed yet, and in fact in Chapter 6, we added hundred-millisecond delays just so we could see what the Cestino was up to. Also, the act of transferring data to our host computers adds delays.

The chapters that follow this one will involve much more complex circuits. We’ll be using multiple ports, reading and writing data at fairly brisk rates, generating clock signals, and so on. All these things, if we want to debug them effectively, require us to perceive logic states faster than we can see, and preferably without tying up the ATmega’s resources as a debugger. Oscilloscopes and logic analyzers have gotten much less expensive in recent years, but they’re still hundreds of dollars (new) for tools worth having, and they require a lot of expertise that’s really beyond the scope of this book to teach.

Back toward the beginning of the microcomputer revolution, however, there was another tool that did the same kinds of job, albeit one logic circuit at a time. They were called logic probes. We’re going to build a very, very simple one, shown in Figure 7-1, and try it out. Like the Cestino itself, we’ll leave this circuit assembled on the breadboard, so we can use it to debug the rest of our projects moving forward.

A340964_1_En_7_Fig1_HTML.jpg
Figure 7-1. Assembled Logic Probe

The Stuff You Need

The logic probe we’re going to build is rudimentary, so it needs only a few components .

New Parts

  • 2 680Ω resistors

  • 1 0.1μF capacitor

New or Used Parts

  • 1 74xx00 IC, where xx is F, LS, HCT, or any other type of 5v 7400 capable of sinking at least 4mA, and whose inputs go high around 2v. I used the 74LS00 from the previous chapter, arguably the worst choice due to its very low sink current, but it works well.

  • 2 LEDs, whatever color you like. Different colors would be ideal, so you can tell them apart at a glance. High output isn’t a good idea, due to the limited current available.

  • 1 long jumper, or a piece of hookup wire 4-6 inches long with two bare ends.

Design the Logic Probe

The simplest possible logic probe, albeit the one with the most limitations, is a pair of LEDs and dropping resistors, one with its anode on the + bus, one with its cathode on the - bus, and the free leads tied together. When connected to a logic circuit, if the circuit is high, the LED with its cathode on the - bus will light. If the circuit is low, the LED with its anode on the + bus, and if the circuit is pulsing, the two will switch back and forth down to a few tens of milliseconds, and both appear to be on continuously below that.

This circuit has some drawbacks. Ideally, a piece of test equipment should not affect the circuit under test enough to alter the results of the test. If you connect the simple LED logic probe to a current where the logic output is loaded to its limit, the current drawn by the LED and its dropping resistor may well cause that output to appear off, or low, when it’s not.

Our circuit, shown in Figure 7-2, will use one gate of a 74xx00 (a 74LS00, in my case) as a buffer, and a second as an inverter.

A340964_1_En_7_Fig2_HTML.jpg
Figure 7-2. Logic Probe Schematic

Because the 74xx00 is a quad-NAND gate, recall that its output only goes low if both inputs are high. Also, if you review the TI 74xx00 datasheet, the original 7400 is rated to source only 4mA, but sink 16, and the 74LS00 part I’m using can can source 4mA but can only sink 8mA. It makes far more sense to use the 74xx00 to switch the cathode of the LED to ground than the anode to +5v. This effectively turns the NAND gate into an AND gate, as we invert the NOT output with our LED. You can see in the schematic in Figure 7-2 that we have two gates wired this way, from the + bus to the anode of the LEDs, to dropping resistors (about 680Ω in my case, for a current of nearly 4mA. I don’t know where these LEDs came from or what their real characteristics are, so it pays to be conservative with the current.)

The gate driving LED_HIGH has one input tied to the + bus, and one input tied to the T_PROBE, the terminal where the probe is connected. In our case, a piece of wire connected to pin 12 of the 74LS00. The other input of this gate is tied to the + bus. When the T_PROBE input goes high, the gate output will go low, which switches the LED on.

The gate driving LED_LOW is different. It has one input tied to the output of the gate driving LED_HIGH, and the other input tied to the + bus. This means that its output will be low any time the output of the LED_HIGH gate is high, that is, LED_HIGH is not lit. So LED_LOW will be lit only when T_PROBE is connected to a low circuit.

Our logic probe may be operating at moderately high frequencies, so we need to think about timing as well.

One gate of a 7400 is rated to transition states in 22ns (nanoseconds), and the 74LS00 I’m using is rated to do it in 15ns. This translates to maximum frequencies of 45MHz and 65MHz respectively. How do I get that number? Easy. The reciprocal of transition time in seconds is the frequency in Hertz. So 1/0.000000022 seconds (22ns) is 45454545Hz, or about 45MHz. Likewise 1/65000000Hz (65MHz) is 0.000000015384seconds, which rounds to 15ns. I’ve found that the more I do these calculations, the more basic values wind up memorizing, like multiplication tables. One millesecond (1000ns) = 1 megahertz, 50ns=20MHz, 20ns=50MHz, and 1ns=1GHz, or 1 gigahertz.

Speed is important, and we clearly don’t have unlimited speed with the 7400 or even the more advanced 74LS00 that I’m using. Worse, we’re stacking two gates together. We could look closely at the transition curves and calculate exactly when the second gate begins its transition from on to off, thus turning the LED on, but our timing isn’t that critical. We can assume that all the transitions will be complete in twice the rated transition time, so we shouldn’t expect our probe to go faster than about 22.5MHz for the 7400 and 32.5MHz for the 74LS00. This is plenty fast for our projects. The LEDs can’t respond nearly that fast, and even if they could, our eyes can’t, and even if they could, there are no signals on our breadboard faster than the 20MHz TTL oscillator we’re using for the Cestino’s clock.

With the timing sorted out, we can talk about input current, which is the whole reason for using the 7400 as a buffer (and an inverter). We don’t want our logic probe to affect the logic circuit we’re testing.

The 74LS00’s inputs draw 20μA (micro-amperes) high, and 0.4mA (mili-amperes) low, giving them a minimum impedance of about 12,500Ω. (The plain 7400’s inputs draw more current: 40μA high, and 1.6mA low, for a minimum impedance of about 3kΩ. Which is still better than the LEDs.) Given that all the circuits we’re going to be setting up are TTL compatible, we know that they can source and sink currents in the low numbers of milliamperes at least, and we know not to load their outputs to the limit, so the 7400’s impedance is enough.

Note

As always, we’re treating impedance and resistance as the same thing. They’re not. Impedance is resistance at a given frequency. The reactance (AC or pulse resistance of capacitors and inductors) changes based on frequency. For our circuits and the speeds at which we’re working we don’t have to be too fussy about impedance matching, but keep in the back of your mind that at some point, as your circuits get faster, you will.

Don’t have a 74xx00? You can build this logic probe with just about any gate TTL IC . You’ll have to figure out the logic, and the output currents, and the dropping resistors for your LEDs, and your input impedance for yourself, but you’ve got those skills at this point. It’s a fun little project to design.

Build the Logic Probe

Having designed the logic probe, let’s go ahead and build it. As you can see in Figure 7-1, I built mine below the reset button of my Cestino. That way I can leave it assembled and it’s not in the way of the circuits to come, but it is powered and ready to use for debugging them.

Assuming you’re using a 7400 or a 74LS00, wire pins 1, 2, 4, 5, and 7 to the - bus. Pin 7 is the 74xx00’s ground pin, and 1, 2, 4, and 5 are the inputs of gates we’re not using. According to the datasheet, any unused inputs of the 74xx00 will drift high and may oscillate, causing problems for the other gates. Any unused gates should have their inputs grounded or held high. We’re grounding them.

Wire pins 10, 13, and 14 to the + bus.

Because we’re leaving this assembled, wire the .01μF capacitor from pin 14 to the socket row above it, toward the reset button, and from there to the - bus.

Connect resistor R2 to the row containing pin 8, and leave an empty socket between it and pin 8. Plug the other end into the breadboard on the third socket straight down from there, then plug the cathode of LED_LOW into that row, and the anode of LED_LOW into the + bus.

Connect resistor R1 into the row containing pin 11 of the 74xx00, and again orient it straight down, right beside R2. Plug the other end of R1 into the breadboard socket just below pin 8. Once again, connect LED_HIGH’s cathode to the row where R1 is connected, and its anode into the + bus.

If you’re cutting the LEDs’ leads and bending them to fit the breadboard, remember that the square part of the lead will bend about three times before it breaks. That said, if you bend the anode lead to a right angle on LED_LOW and the cathode lead to a right angle on LED_HIGH, you’ll get a nice offset like I did so the two LEDs aren’t right on top of each other.

Now for the logic connection. Connect pin 9 to pin 11, and plug a jumper (or a longer piece of hookup wire stripped on both ends) into the socket next to pin 12. You’re done. That’s all there is to it.

Testing the Logic Probe

Make sure the probe lead of the logic probe is disconnected. Plug it into an unused socket row on the breadboard for safe keeping. When you connect the USB cable to the Cestino and to the host computer, LED_HIGH should light. How can that be, with no logic connected to the probe? Remember how the datasheet said un-connected inputs would drift high? That’s exactly what we’re seeing.

Now connect the probe lead to the + bus. Nothing happens? That’s good. That’s exactly what it should do. LED_HIGH should remain on.

If you connect the probe to the - bus, LED_HIGH should go off and stay off, and LED_LOW should come on.

If your LEDs aren’t lighting at all, check to make sure that you have them oriented the right way: cathode to resistor leading to the 74xx00, and anode to the + bus. Also, you wired the 74xx00’s power and ground circuits on pins 14 and 7 respectively, right?

If your LED_HIGH led came on when you connected the probe to the - bus but not when you connected it to the + bus, your LED_HIGH is wired backward and to the wrong bus. Turn it around and plug the anode into the + bus instead of the cathode into the - bus.

The same thing goes if your LED_LOW comes on while the probe is connected to the + bus. Both LEDs should be connected the same way: anode to the + bus, and cathode to the dropping resistor, even though they show opposite logic values.

To test your probe on pulsed circuits, plug the probe into pin 11 of the 74xx00. Both LEDs should light.

What’s happening here? Pin 11 is the output that drives LED_HIGH. At the moment of connection, pin 11 is low, which pulls the input pin 12 low, which sets the output pin 11 high. Which turns the output on. Repeat forever. With pin 11 tied to pin 12 and pin 13 tied to the + bus, our 74xx00’s gate oscillates, switching itself on and off as fast as it can. Each time it transitions from one state to the other, it switches one or the other output on, so fast that neither the LEDs nor our eyes can react to the difference, and both LEDs appear lit.

If your logic probe can pass these tests, it’s working.

Floating Pins

Now that we have a working logic probe, let’s have some fun with it. Plug the probe in to the socket row next to pin 1 (PB0) of the Cestino and hit reset.

Notice anything interesting?

When the Cestino LED flashes on (PB0 goes high), we get a high pulse, and when it goes off, we get a low pulse, exactly the way we’d expect. But a few seconds after the flashes stop, something interesting happens. LED_HIGH comes back on, but the Cestino LED does not.

This is not a malfunction. There are two fairly important facts to learn from this. First, at the end of the reset LED flash sequence, the Cestino holds PB0 low for a few seconds, but then it stops. Why is that?

I admit, I had to look it up. It turns out that the default state for any digital pin in Arduino is the input state: high impedance with no pull-up enabled. Once the flash sequence is finished, the Arduino core sets digital 1 (aka PB0) to that state. It no longer has a high enough current (in fact, it is delivering no current at all) to light the LED, but it isn’t grounded either. It’s floating.

The second fact is that the 74xx00’s input drifts high enough to trigger the LED_HIGH NAND gate even when tied to PB0 (Pin 1, aka Digital 1) of the Cestino. Now we have to ask ourselves if the input of the 74xx00 is high enough to make that pin read high, and to tell that, we’ll need a little code.

Logic Probe Test 1

I’m not going to go through this code in any depth, because frankly, you’ve seen it before. It’s a stripped down version of TTL_Explorer_7400. It reads a different port and doesn’t write to any ports, and its loop control is different, but literally everything else is the same. The only wrinkle is that we mask all but bit 1 to ensure that we’re not reading noise from the other pins as they float. Of course, we’re using this code to read the state of a floating pin tied to a floating pin, so the results it generates have a lot of potential for randomness.

//Logic Probe Test 1
//----------------------------------------------------------
//This sketch checks to see if the value of PB0 changes due
// to the 74xx00's input rising. We mask out all the bits
// except PB0 so we don't pick up noise from uninvolved pins.
// ---------------------------------------------------------
//Hardware:
//74xx00 Logic Probe
//
// Wiring:
// Logic probe input connected to PB0/Digital1/Pin 1 of the
// ATmega 1284P. Optional: a 10k pull-down resistor
// from PB0 to the - bus. On my board it makes no difference.
// ----------------------------------------------------------
// James R. Strickland
// ----------------------------------------------------------
//precompiler definitions.
#define DELAYTIME 100 //How many mS (milliseconds) per update?


//global variables
byte counter = 0;


//-----------------------------------------------------------
//Zerobee
//-----------------------------------------------------------
//This function returns a string with the binary equivilent of
//the value passed to it in input expressed in 0bxxxxxxxx
//notation, with 8 bits for each byte regardless of their value.
//IMHO this makes binary values easier to read and compare.
//-----------------------------------------------------------
String zerobee(byte input) {
  String temp = "";
  for (int c = 0; c <= 7; c++) {
    if (input % 2) {
      temp = "1" + temp;
    } else {
      temp = "0" + temp;
    }
    input = input / 2;
  }
  temp = "0b" + temp;
  return (temp);
}


//setup() function - runs only once.
void setup() {
  Serial.begin(115200);
  DDRB = 0; //Set DDRB so all pins are inputs;
  PORTB = 0; //Clear all pull-up resistors on portB
  Serial.println("Starting…");
}


//loop() function - runs forever.
void loop() {
  for (int c = 0; c <= 20; c++) {
    Serial.println("PORTB:" + zerobee(0x0000001 & PINB));
    delay(DELAYTIME); //Wait DELAYTIME milliseconds.
  }
  Serial.println("Done.");
  while (0 == 0) {}; //Do nothing forever.
}

The results are equally uninteresting. Pin 0 of Port B reads zero, over and over again. We can answer the question conclusively: although the gate drifts high, its input does not pull the ATmega’s input logically high. This is good to know.

Full Speed Ahead

So we’ve proven our probe doesn’t trip the Cestino’s inputs. What else can we learn about the probe—and the Cestino?

Try this. Plug the logic probe’s input wire into pin 13 of the ATmega1284P, the clock input pin. Now press the reset button to make sure the Cestino still boots. (It should.)

If you look at the LEDs of the logic probe, both of them should be on. We’re feeding the probe a 20MHz signal, straight from the TTL oscillator that drives the ATmega. The 74xx00 can go that fast the way we’ve wired it. Barely. But the LEDs can’t come close. Nevertheless, the probe tells us the most important fact about that line: that there is a pulsed signal on it. Both LED_HIGH and LED_LOW are on, telling us the circuit is switching back and forth faster than the LEDs (and our eyes) can go. For debugging logic circuits, knowing that a line is changing states (rapidly, in this case) is often as useful as knowing the actual pulse pattern and speed. If our Cestino stopped working, for example, plugging the probe in on pin 13 would tell us conclusively that the oscillator is, in fact working (or if it is not.). It’s this ability to correctly identify pulsed circuits that sets our simple logic probe apart from the capabilities of our multimeter.

Debugging Ports with the Logic Probe

In the circuits to come, we’ll often be feeding a series of numbers to a given port, often for addresses. (I’ll explain addresses in Chapter 8. For now, you just need to know that they’re binary values on ports.) Because addresses are often in sequence, we can learn some additional things with the simple logic probe. Let’s get some code and try it out.

Binary Numbers for the Logic Probe

Once again, the code we’re going to use is derived from an earlier project, in this case, from Binary Numbers On Display. The only change we’ll make is the DELAYTIME precompiler definition (set it to 10ms), so just cut and paste the code, or make a copy and save it under a new name. It’s included here for your convenience.

//Binary Numbers For the Logic Probe
//-----------------------------------------------------------
//This sketch counts in binary from 0 to 255, then resets.
//It's a really, really short sketch.
// ----------------------------------------------------------
//Hardware:
//The Logic Probe, wired to PC0, for starters, then PC1, PC2,
//and so on.
// ----------------------------------------------------------
// James R. Strickland
// ----------------------------------------------------------


//precompiler definitions.
#define DELAYTIME 10 //How many mS (milliseconds) per update?


//setup() function - runs only once.
void setup() {
  DDRC = 0b11111111; //Set DDRC to all outputs.
  PORTC=1;
}


//loop() function - runs forever.
void loop() {
  PORTC++; //Take whatever is in PORTC and add 1.
  delay(DELAYTIME); //Wait DELAYTIME milliseconds.
}

Connect the logic probe to PC0, on pin 22 of the ATmega1284P of your Cestino. Once the sketch is running, you’ll notice both LED_HIGH and LED_LOW are on continuously. With only a 10ms delay, we can’t see that they’re changing. If we go to PC1, on pin 23, however, we are effectively increasing the delay to 20ms, and we can start to see the flicker. On PC2, with 40ms delay, the flicker is pronounced, clearly flashing both LEDs. On PC3 with 80ms delay, each LED clearly turns off and the other clearly turns on. With 160ms on PC4, the flashing is positively sedate, a little fast perhaps for car turn signals, but not too bad. On PC5, it’s much more like a car turn signal indicator, at 320ms or about 1/3 of a second between pulses. On PC6 we’re getting a pulse every 640ms, or a two pulses every 3 seconds, and on PC7, we’re getting them at less than 1 per second.

It’s easy to see how you could debug an address circuit as it counts up addresses and make sure the pulses are visibly slower from the low order bits to the high order bits. This assumes that the addresses are being called in sequence from low to high, of course, but that’s what test code is for.

As an exercise, try setting the delay to zero, which should get us a pulse every few cycles of the 20MHz clock. Even though the Arduino core’s code is not known to be particularly instruction (and thereby time) efficient, when we let the ATmega1284P run at full speed, even PC7, 1/128th speed from PC0, is still faster than the LEDs (and our eyes) can respond. Debug code had better include generous use of delay(), too.

Credit Where Credit’s Due

As usual, I have to credit Quinn Dunki’s Blondiehacks blog ( http://quinndunki.com/blondihacks/ ) for my newfound appreciation of logic probes. When I started back digging into TTL level debugging, the first thing I bought was the Logic Shrimp, a now-discontinued inexpensive logic analyzer, that let me essentially probe eight channels at the same time with my desktop computer. It’s a very useful thing, but it’s an awfully specialized tool, and I couldn’t see asking readers to buy one. The logic probe was the right answer. As for the circuit, I saw a design for a simple logic probe with two LEDs wired in opposite directions somewhere on the net, but I can no longer find it. Buffering that with the 74xx00 was engineering by convenience on my part, solely to increase the input impedance and isolate the circuit under test with an IC I had readily to hand.

Further: Better Logic Probes and Logic Analysers

It goes without saying that the logic probe described here is primitive. It’s designed, as I’ve said repeatedly, mostly to keep its input impedance high and deliver the most basic logic probe functionality. There are numerous ways it could be improved.

Most obviously, a way of actually measuring pulse lengths under about 30ms would be a big help. This could be done with a counter, like the 74xx92 described in the last chapter, which would divide the number of pulses by up to 12. In order to generate visible pulses from the 20MHz TTL oscillator, we’d need a bunch of them, so dual counters like the 74LS393 would be a good choice. We could then wire an LED from the + bus and one from the - bus to the lowest order output bit to get normal logic probe function, and a third LED that could be switched from the low order output to the high order output would provide both pulse indication and show the relative frequency, something my logic probe can’t do.

But hey, why stop there? If we added a couple of seven segment drivers and a reset on a known frequency (another oscillator) we could output the frequency itself as multiples of 255 hertz per the oscillator’s frequency. The engineering could get complicated pretty fast.

Adding a micro-controller, say, an ATmega328, would let us auto-range the frequency counter and time the pulses.

We could also keep the probe simple and add more channels, although it ceases to be a logic probe somewhere along there and grows into a logic analyzer if you add some accurate timing, some memory, and a nice display system.

This one will do for our needs from here on. Building a better one? That’s up to you.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.226.165.70