Monday, April 9, 2018

Solving circuits with Python

Python is  a scripting languaje that is now quite popular.

It is used in a broad range of applications including performing scientific calculations thanks to the SciPy libraries.

This blog entry links to a pair of Google Colaboratory documents. Colaboratory documents are Python Jupyter Notebooks hosted in a Google Drive account that run the code in virtual machines owned by Google.

That way you don't need to have Python installed to try or modify the proposed code.

Solving circuits with SymPy

SymPy is one of the SciPy libraries. It enables you to perform symbolic calculations. This can come handy to solve electrical circuits like the one below:

In order to solve a circuit, you need to obtain a set of equations whose solution is the magnitude you want to know. In the above circuit, let's say that we want to know the value of Vo as function of Vs, R1, R2 and Is.

You start defining symbols for the circuit. We need symbols for the component values Vs, R1, R2 and Is and for the solution Vo.
As  we will solve the circuit using the nodal method that applies current equations in all nodes except the ground one, we also need symbols for the nodal voltages V1 and V2.
Also, using the full nodal method requires as to add a symbol, like iVs for the current in the source voltages.


# Create the circuit symbols
Vs,iVs,R1,R2,Is,Vo, V1, V2 = sympy.symbols('Vs,iVs,R1,R2,Is,Vo,V1,V2')


Now we define the equations of nodes 1 and 2. To do that, we initizalize an empty list of equations and add the two equations to this list. Using the nodal method, we apply the Kirchhoff KCL law on each node:


# Create an empty list of equations
equations = []

# Nodal equations
equations.append(iVs-(V1-V2)/R1)       # Node 1
equations.append(Is-(V2-V1)/R1-V2/R2)  # Node 2


In SymPy it is assumed that all equations are equal to zero.

In the nodal method we also need to add an equation for each voltage source that relates it to the node voltages. In SymPy, Eq means equal, so, Eq(Vs,V1) means Vs = V1.

# Voltage source equations
equations.append(sympy.Eq(Vs,V1))


The final equation is the one that contains the result we want to obtain for the circuit:

# Measurement equations
equations.append(sympy.Eq(Vo,V2))



Now we have a full set of equations:

iVs - (V1 - V2)/R1
Is - V2/R2 - (-V1 + V2)/R1
Eq(Vs, V1)
Eq(Vo, V2)

Those equations enables us to obtain Vo but a smaller set of equation will also work. In particular, as the first equation contains an unknown  iVs that is not found in any other equation, we can eliminate this equation if the only unknown we care for is Vo. We don't need, however, to know that to solve the circuit.

In these equations, some variables are unknowns, we make a list of them:

unknowns = [V1,V2,iVs,Vo]

Then we can solve the circuit using the solve function of the SymPy library:

# Solve the circuit
solution = sympy.solve(equations,unknowns)


That will yield the solutions for the unknowns:

V1 = Vs
V2 = R2*(Is*R1 + Vs)/(R1 + R2)
iVs = (-Is*R2 + Vs)/(R1 + R2)
Vo = R2*(Is*R1 + Vs)/(R1 + R2)

If you want to see more details, more circuit solutions or you want to test te code yourself, open this colaboratory document.


Automating the solution

As you can see we have followed a recipe for solving the circuit. That means that it can be automated. The circuit Python module, just does that: Solves a circuit using the nodal method recipe.

As we remember the circuit is:

We can describe it just with a list of components and measurements:

# Circuit 1 definiton
c1 = circuit.circuit()  # New circuit
c1.addV('Vs',1,0,5)     # Vs between 1 and GND with 5 V value
c1.addR('R1',1,2,1000)  # R1 between 1 and 2 with 1000 Ohm value
c1.addR('R2',2,0,1000)  # R2 between 2 and GND with 1000 Ohm value
c1.addI('Is',2,0,0.01)  # Is going from GND to 2 with 10 mA value
c1.addVM('Vo',2,0)      # Measurement Vo between 2 and GND


Then we can obtain the symbolic solution for Vo:

# Symbolic solution
print('Vo =',c1.solution['Vo'],'  (Symbolic)')


That yields:

Vo = R2*(Is*R1 + Vs)/(R1 + R2)   (Symbolic)

Note that this is the very same solution we obtained previously without using the SymPy module.

Also, as we have indicated the component values, we can also obtain the numerical solution:

# Numeric solution
print('Vo =',c1.particular['Vo'],'V   (Particular)')


That yields:

Vo = 7.5 V   (Particular)

If you want to see more about the circuit module, see other solutions or use your own code, open this colaboratory document.

Wednesday, March 7, 2018

Google colaboratory

This is an entry about my Google Colaboratory documents.

Google colaboratory allows you to execute Python code in virtual machines so that it is possible to execute and share code without having owning a Python execution environment. You just need to have a browser.

Colaboratory documents are Python Jupyter notebooks that allow you to include not only code but also text, formulas and images.

The colaboratory documents can be downloaded on your computer as Jupyter .ipynb documents and executed offline in a localPython evironment.

To access colaboratory you need to have a Google account. This is enough to see the documents, but if you want to execute your content, you must save a copy in your own Google Drive account.

Below yoy can find links to some documents created in Colabortory. They all import a Python calc module that includes support functions such as, for example, plot11, plot1n and plotnn that assist in curve drawing. The module is accessible thanks to GitHub.

The colaboratory document list is constantly updated. The current list of documents is accessible my Master Colaboratory Document.

What follows is a list of currently available documents. See the previous list for an updated list.

The documents organized by categories. 

Control

Documents related to mechanical and control subjects

Pendulum
Document that explains the physical behavior of a pendulum and that allows to simulate it.
https://colab.research.google.com/drive/1GAjq-R4cTyVu90KjOd9P0_r4L1dNJNx9



DC Motor
A document that explains how a DC motor works and also allows you to simulate its dynamic behavior.
https://colab.research.google.com/drive/1uOeXitZxeUZZdZlmT8d5pZNUr0QXrb5E#scrollTo=t6-DFI-JwoZr


Inverted pendulum
A document that deals with the control of an inverted pendulum, which is intrinsically unstable, and which explains how it can be stabilized using a PID controller and an electric motor.
https://colab.research.google.com/drive/1Jpje3UWRr-ZvVKR1SlcwoM-KI1OGBNYA#scrollTo=fmPgBsrTlnvd


 

Analog electronics

Documents related to analog electronics 

Common Emitter
Document on the operation of a simple amplifier based on a BJT in common emitter configuration.
https://colab.research.google.com/drive/1o57vd-1jAhsuXuMI_HxixXEJiKh7cqGU
 
  

Thursday, March 1, 2018

SLab updated to v1.3

I have just updated the SLab project in Github.

The new version afects three of the python source files:
slab.py, slab_meas.py, slab_fft.py

With those changes SLab should work both in Python 2.7 and 3.x branchs.

I have also added a new script slabTest.py in the main code folder. This scripts lets you check the basic SLab functionality so you can verify that you have a working SLab environment.

Current SLab version has been checked on Windows under Anaconda with Python 2.7.10 and 3.5.1.
Basic functionality has also been verified on Linux with Python 2.7.

Monday, February 19, 2018

About SLab DAC calibrations

This is a brief article about when you can rely on the DAC calibrations on the SLab system.

If you see the CurveVV command in the DC module that is used to obtain a DC voltage transfer curve of a Circuit Under Test (CUT), you will notice that you can use the basic configuration that uses DAC1 and ADC1:


Or a configuration that uses DAC1, ADC1 and ADC2:

If the DAC1 operation has ben properly calibrated, you may ask why do you need to take measurements on Vi using ADC2.

Well, the truth is that you cannot always rely on the DAC calibrations because they can depend on the load applied to their nodes. If you recall the DAC driver circuits, they are based on follower opamps or non inverting amplifiers.


Opamps have limited current capabilities. This doesn't affect to the ADCs because no current is drawn on the ADC nodes, but you can put any load on the DAC nodes and the opamps won't alway be able to cope with it.

The following figure shows a test circuit for the DAC output load capabilities. DAC 1 is connected to ADC1 and a grounded resistor R.

The following figure shows the ADC readings as function of the DAC values set for different values of the resistor R. You can see that the programmed DAC value gives the proper voltage to the node for resistances of 10k or more. For lower loads there is a degradation that increases at higher voltages. For a 100 Ohm load, the voltage is only good up to about 1.5 Volt with some degradation before reaching this point.


Is this behavior expected? Well, the MCP6002 opamp datasheet shows the following maximum short circuit currents:


At 3.3V and 25ºC the short circuit current is about 15 mA. For a 100 Ohm load that meas that the maximum voltage will be 1.5 V. This is the result shown on the measurement curves.
For a 1k resistor, the voltage limit should be 15 V, but we see some degradation before reaching the 3.3V limit. Why is that?

The limit in this case is the voltage headroom. The MCP6002 is a full rail opamp. That means that it should de capable to reach both supply rails. In practice, however, no opamp can be really full rail. You need some voltage difference between the output and the rails to maintain the output current. This minimum voltage difference to the rails is the Headroom voltage. The following figure, taken from the opamp datasheet shows the needed voltage to the rails as function of the current.


In our case, to reach 3.3V using a 1k resistor, we need to provide 3.3mA. From the above curve we can see that we need a headroom of about 100 mV to maintain this current. So we cannot get above 3.2V and that's about what we are seeing in our measurements.

The same experiment can be performed for loads connected to Vdd.

As you can imagine, the degradation will be, in this case, at the lower voltages, when the opamp needs to sink more current.


For a specified 15 mA short circuit current the maximum voltage drop to Vcc will be 1.5 V on a 100 Ohm load. As Vdd is 3.3 V, that gives a voltage of  1.8 V minimum voltage respect to ground. Just about the limit we are measuring.
The headroom voltage also explains why we cannot reach the 0V limit with a 1k load.

That's all for this article. When you driving voltages using SLab or any other instrument like a power supply or a function generator, there are always limits to the load you can put on the driven node.
If you are not sure that the node can be properly driven, it is a good idea to measure the REAL voltage value on the node instead of relying on the voltage selected on the instrument.

In the particular case of the CurveVV command, using ADC 2 on the node driven by DAC 1 guarantees that the final curves you obtain relate the REAL voltage input to the output voltage on the circuit.

Monday, February 12, 2018

SLab First Release

This article is also available, in spanish, in the companion AIM65 blog.

This is the first release of Small Lab (SLab), a project I have been working on for a long time.


SLab is a project to develop a tool for hands-on electronics learning on a minimum budget. The idea is to provide, to anyone who wants it, a system capable to inject excitations on a circuit and obtain measurements so that the circuit operation can be understand by practice.

Low cost means really low cost, below 40€ in my rough calculations for a full system with instrumentation and components to build the circuits.

SLab System (and disclaimer)

The SLab system is composed of a chain of components as shown in the figure below:

First we have our Circuit Under Test (CUT). This is a circuit that enables us to learn somethig about electronics. Then we have a hardware board that is able to inject signals on the circuit and measure the voltage on some of its nodes. The board connects to a PC where some Python modules interact with the board by sending command throug a serial over USB COM link. You are at the right end of the chain sending high level commands for the SLab system to execute. Those commands, if needed, can be written on Python scripts to ease repetitive tasks. You can also create your own libraries that connect with the SLab ones and extend the system capabilities.

Note the red isolation zone in the previous drawing. You are only supposed to connect the Circuit Under Test (CUT) to the hardware board. No electrical connection, except the USB cable, shall go outside of the protection zone. The CUT shall also be powered only by the hardware board.

If you want an additional layer of protection, or you are not sure of your own actions, you can use an isolated USB cable together with a powered HUB to run the harware board like in the figure below. That way you could damage the hardware board or the HUB but the PC will be more secure.

Either way the following disclaimer apply:

The author of this document takes no responsibility for any damage to you, your properties or equipment due to the use of the SLab system. This is true either if you are following the proper procedures or not.

The hardware

In order to keep costs as low as possible, the main hardware element of the system is a microcontroller demonstration board. The chosen board for this first release is the STM32 Nucleo64 F303RE board.

Nucleo F303RE Board

Why this board?. Well, it is cheap, currently only 9€ at farnell and it is quite capable. It includes the STM32F303RE microcontroller that features two 12 bit DACs, four 12 bit ADCs, 512KB of flash and 80KB of SRAM. It also is MBED enabled. That means that installing a binary firmware is just drag&drop. Moreover, the USB communication includes a serial over USB Com link that installs the driver as soon as you connect the board to a computer. Finally, as MBED is so easy to use, and the board is much more powerful than most Arduinos, having this board also enables you to play with firmware developement in your spare time if you want to.
 
Using the proper software on the board, you can instruct it to send signals out of the DACs and read signals with the ADC inputs. The problem is that you usually need some buffering to prevent loading effects when you connect the ADCs and DACs to a Circuit Under Test (CUT).
The following figure shows a suitable solution based on opamp voltage followers for all DAC outputs and ADC inputs. See that it also adds a LED and a resistor so that we can see that the CUT is properly powered.

Drivers to interface the circuit

Note that DAC2, associated to pin D13, has a non inverter amplifier instead of a follower. This is needed because, in the F303RE board, the D13 pin is also connected to a LED, that prevents us to use the full range of the DAC and we are limited only to le lower half of the full range. This is no problem, however, as we will see later.

You can implement the driver circuit in a solderless breadboard and you have plenty of space left to put a circuit to be measured. The following figure shows the F303RE board, the driver circuit and a test circuit composed of a resistor and a diode.



If you have the capabilities to solder you can implement the driver circuit in a shield. The following figure shows the drivers on a shield board designed for Arduino. This is ok because F303RE board features Arduino compatible connectors.

Driver Shield

If you have option to build your own PCBs, you can create a better shield. The following figure shows the "Long Board". It includes the F303RE board, a milled PCB shield with the drivers, a solderless breadboard for the test circuit and an aluminium clad to join it all. A small electronics lab in a 28 x 8 cm form factor. The details are in the SLab documentation.

Long Board
The following image shows the shield diagram wit its 17 male pins. In includes two GND pins, a 3.3V Vdd pin, the two buffered DAC outputs, the four buffered ADC inputs and eight digital I/O lines. All of that can be controlled from Python code.

Depending on your resources and capabilities you can use the any of the hardware options to mix together the demonstration MCU board, the drivers, and space to mount a circit to test. Either way, in the end, you will have the elements shown in the following figure: A Vdd supply, two DAC outputs and four ADC inputs. You can also add the digital I/O but this is not needed for most analog circuits.

SLab elements


By using the proposed MCP6002 and MCP6004 operational amplifier chips, you get very high input impedance on the ADCs, and nearly full rail operation inside the 3.3V range of the board. The current capabilities of the opamps are not so great, but, as we are powering the system from the USB port, we are quite limited in the currents anyway.

It would be possible to design a driver interface circuit with more voltage and current range. And it will be done in the future, but, for now, the idea is to keep the system as cheap and simple as possible. Making a better interface circuit is not difficult at all, the problem is making it available, at low cost, for everyone.

The software

Bad software can make a low budget instrumentation device a nightmare to operate, and developing good software is difficult and time consuming. For this project, I have taken profit of the huge Python library and, in particular, of some SciPy libraries (NumPy and Matplotlib).

But Python is not easy to use on the F303RE board, and also, it would be very inefficient for performing timed measurement. So,the full system needs an additional element: the board firmware that is the middle element between the board ADCs and DACs and the Python code in the PC. It acts as a server for commands from a client PC.

The software structure somewhat resembles the firmata protocol with a server on the hardware board and a client on the PC. But it is not firmata. The main difference, apart from the fact that the communication is not MIDI, is that commands can include waveform generation and the reading of sequences of voltage values at constant rates (up to about 80kHz with the current firmware). Some functionalities, like the DC ones, could be performed adding a Python layer to firmata, but not all of them, specially for the AC ones. In general, the SLab system, it is more oriented towards analog signals than digital ones.


The board firmware

As the F303RE board is MBED enabled, the first version of the firmware has been developed in the MBED cloud compiler. I plan on designing a future version of the firmware, probably without MBED, to optimize the code as close as the board limits as possible. On the following table you can see that, when using only one channel, sampling time in transient measurements can be as low as 13 microseconds. This is not too bad for a microcontroller board, but far from the F303RE capabilities that can get sample rates in the MHz range. Most of the problems when using more than one channel are due to the fact that MBED uses only one ADC for all analog inputs son all four channels cannot be read at the same time. There is always room for improvement, and the firmware will be sure improved. When I have time, that's it.

Current firmware sample time transient capabilities
The board firmware communicates with the PC and basically receives commands, interfaces with the circuit through the DACs and ADCs, and reply a response to the PC. Some examples of  commands are:
  • Set a DAC voltage value
  • Read the voltage on an ADC input
  • Read a sequence of ADC values with at a constant sample rate
  • Store on the board SRAM waveforms to be generated later on the DACs
  • Generate waveforms and read the circuit response using at a constant sample rate
The most complex thing the board firmware can do is to generate two different arbitrary waveforms on the two DAC outputs and simultaneously read the four ADC inputs. After generatings the waves and collecting data for some time, the data is sent to the PC for processing.
The communication protocol between the board and the PC is fully documented so, if you have a board with at least two DACs and four ADC inputs and you know about firmware developement, you can create your own firmware to interface with the SLab system. The communication link implements CRC checking, but, as USB communication is quite reliable at short distances, the main purpose of the CRC is to detect software bugs.
The board capabilities are read from the board uppon connection, so no modifications need to be performed at the PC side if you develop a firmware for a new board.

Current board firmware is about 2500 lines of "C" code. You can find it in the SLab Github project. But, if you only want to use it, just download the binnary file and drag&drop it on the board to program it.

The firmware code is also available on MBED.

The SLab Python code
The board firmware interfaces with the circuit and needs to be as optimized as possible because it is what set the limits of the full system. But one important part of the software is Python code. Currently the SLab project has next to 6000 lines of Python code. It really is not that much because of comments and blank lines. Although comments are also important because they generate the SLab help subsystem. No exactly doxygen but is the same idea.

In order to work with a circuit, you open a Python interpreter, import the SLab module, then call SLab functions that communicate with the board, perform excitations and/or measurements and return the results. Thanks to Matplotlib the results can be shown on the screen, and, thanks to NumPy, the results can be manipulated to your heart's content.
All the SLab Python code is included in the same Github project as the firmware code. 

The first layer of the Python code is the calibration code. How do you obtain good measuments from instruments? By proper calibration, off course. Before using the board you should calibrate it. From the calibration procedure you obtain a set of curves, one for each DAC and ADC that describe how the real values relate to the inputs or outputs of those devices. As an example, the following figure shows the DAC ratiometric calibration curves that include the drivers indicated on the previous schematic. Note how DAC2 has a slope of two due to the non inverting amplifier operation. But you don't need to bother as calibration takes care of that. Once the calibration is completed, you can forget about it, SLab takes care of the details internally on each measurement.

DAC Calibration Curves
The last layer of the SLab code are the functions that the user can call. Those functions indicate the board to do something and return a result, if available. It can be as simple as setting one DAC to a given voltage value or as complex as measuring the distortion that a circuit induces on a sinewave or obtaining a bode plot by obtaining the response to several sinewaves. The simple commands are just directly sent to the board after calibration. The more complex commands require more Python code work do do their magic from the basic board firmware commands.


Some examples

Now, some examples of what can be done in SLab. Refer to the reference documentation for much more examples. Let's start playing with a simple low pass filter:

Low Pass Filter

You connect the buffered DAC1 output to the input of the filter and the buffered ADC1 input to the output of the filter. Then, you input the following Python code. You don't need to use interactive mode, but this is always an option.

The first six lines calculate the ideal response of a low pass filter using the NumPy library. The sixth line measures the real frequency response of the circuit connected between DAC1 and ADC1 for the same set of frequencies used on the previous calculations. You will obtain the following graph that compares the idel and real responses right after the last command.

Bode Plot
As the SLab system, to keep costs down, features no amplification stages , the dynamic range is not so great and bode plots start to get ugly, specially in the phase graph, after 30 dB atenuation levels.
The circuits can be much more complicated. The following circuit uses DAC1 to generate a sinewave and DAC2 to generate a random noise signal. From those signals, two differential signals with injected common noise are generated on V1 and V2. Then, a differential amplifier is used to reject the noise and recover the signal. On the image, unity gain amplifier are opamp followers and the inverting amplifier is an opamp inverting amplifier.
Common Noise Reject Circuit
The circuit has been mounted on a breadboard and tested using the following code that generates the signals, performs the measurement and plots the results. In this case, althoug SLab includes gaussian and uniform noise generation, we use numpy calls to generate the noise.

The following graph shows the differential signal, with common noise, at ADC1 and ADC2. It also shows the noise at ADC4 and how the signal is recovered without noise at ADC3. It looks like a simulation but they are real measurements.



You don't need to provide inputs to the circuit. The following example is an astable circuit, based on a hysteresis comparator that generates a square wave.

Astable Circuit
 The measurements of some circuit nodes are shown below. The code is here.

Astable transient operation

You don't always need to operate with time varying signals. You can also perform DC calculations. The following figure shows the collector current for various base currents on a bipolar transistor. Each point on the curve is an independent DC reading with some time given between the setting the input and reading the output. You can find the associated code here.


In the stock SLab system you are limited to the 3.3V range of the Nucleo board. But using the two DACs in bridge configuration can give a -3.3V to +3.3V range in some circuits. This is the case of the full bridge rectifier:

Full Bridge Circuit
The 100k R2 resistor provides some bias on the outputs when no diode is conducting. You can neglect it to ease the understanding of the circuit. The measured input to output voltage response is shown in the following figure:

Bridge Voltage Curve
You can find the code here.



The documentation

We have a hardware board. We have the firmware on the board and the Python code on the PC. If you know enough about electronics and want to use the SLab system, you only need to add in the SLab reference documentation and you are on the track for messing with circuits.

The current documentation to setup the hardware and the software and to reference all the SLab functions (there are a lot of them) is 239 pages in several PDF files. The Python code folder, also includes a folder with 31 examples in self contained Python code files. 

But one of the SLab project objectives was about learning electronics. That's why the SLab project also contains 222 pages of tutorials about several devices and circuits. Currenty the subjets are:
  • Linear Operational Amplifier circuits (7 files)
  • Diode circuits (4 files)
  • BJT circuits (2 files)
I will keep adding files when I have time. Perhaps I will also add some experiments on the blog.

Last words (for now)

SLab is an ongoing project. The board firware will be improved in the future and more tutorials about circuits will be added. Now we are on the first release version 1.2. All the files can be obtained in Github or in a Zip file, also on Github.

I want to end this blog entry just showing a dual wave arbitrary waveform generated with the SLab system just for fun.


Isn't it pretty? Wanna see the code?

Article updates


19/2/2018
Updated the RC filter code. AC functions now are inside the slab_ac module and not in the main slab Python module.
Added a new system description together with security recommendations and a disclaimer.

Tuesday, March 22, 2016

Building a simple circuit probe


The Goals

Sometimes you need to check one circuit and test some of its nodes. Usually a tester in voltage mode is a good solution, but it has a pair of problems. First, it measures about zero both when the node is driven at zero volts and when the node is floating (not driven at all). Second, it gives the information on the tester display, so you need to take the view from the circuit to the tester to check the voltage.

The proposed circuit somewhat qualifies as a logic probe. It should give no indication when the node is not being driven and it should give a different indication when the node is driven at high or a low voltage.

A lot of logic probes are not self powered. They rely on the circuit supply to operate. In my case I would like the probe to be usable also a as a continuity tester. If we set ground in one point of the circuit and we probe another point, the continuity can be detected between both points because a low level will be driven even if the circuit is not powered at all.

The Circuit

The following figure shows the schematic of the circuit.

Probe Schematic

The circuit is powered with a 3V CR2032 battery. When the probe is not connected to anything, the probe voltage, as set with R1 and R2 will be 1.5V. As both Operational Amplifiers (MCP6002) have very low bias current (1pA), no voltage drops on R3 and 1.5V is also seen on the non inverting input of U2 and on the inverting input of U1.

Resistors R4, R5 and R6 define a voltage divider that sets 1V on the inverting input of U2 and 2V on the non inverting input of U1. With 1.5V on the probe, both operationals saturate at high level (3V) so both LEDs are OFF.

If we set the probe tip to a voltage below 1V (The trip point of U2), U2 will saturate at low level and the Blue LED will turn ON. In a similar way, if the probe tip voltage is set above 2V (The trip point of U1), U1 will saturate at low level and the White LED will turn ON. I know white is a strange color for high level. A red color will be better buy I had no red LEDs similar to the blue one at hand.

Operational Amplifiers are not the best suited components for this project. As they are used as comparators, a dual comparator could be better in this case. The choice of the MCP6002 dual opamp was only because I had them available.


Circuit operation

In the end, the circuit puts a 1.5V voltage on the probe tip, provided by the two 100k resistors, so it behaves like a 1.5V source with a 50k series resistance. If the probe voltage is kept between 1V and 2V, no LED is lit. If the probe voltage is below 1V, the blue LED turns ON. And if the probe voltage is above 2V, the white LED will turn ON.

When you probe a node in the circuit, you can sense its voltage using a high impedance voltmeter. That will give you the open circuit voltage (Voc). This voltage can be driven with different strengths. The drive strength is related to the equivalent resistance at the node. For a linear non reactive circuit it will be the equivalent Thevenin resistance. In the end, the equivalent circuit will be something like that:

Simplified equivalent circuit



Here we have the 1.5V and 50k resistance provided by the probe and the Voc and Rth associated with the probed node. As we know, the LEDs will lit when the probe voltage Vp is above 2V or below 1V. The following graph shows the LED status as function of Voc and Rth.

LED status as function on Voc and Rth
For low Thevenin equivalent resistances (below 1k) only the Voc voltage determines if each LED is lit of not. For higher node resistances the threshold Voc voltage shifts due to the resistor interaction in the circuit.
We can see that at 100k Thevenin resistance we need 0V to lit the Blue led. For higher resistances we will need a negative voltage to lit the LED. Same for the white led: at 100k or more Thevenin resistance you need more than 3V to turn ON the LED. So, the circuit, not only senses the node voltage but also its drive strength.

From the curve we can see that, when used as continuity tester, it can detect continuity (or lack of isolation) for resistances up to 100k. To lower the resistance detection threshold, the  R1 and R2 resistors could be changed for lower values.


Effects of the probe on the circuit under test

Measuring any magnitude always modifies the device under test (DUT). Sometimes this error is negligible. For instance, using a good quality voltmeter to measure the voltage between two nodes usually introduces a 10 megaohm resistance between the measured nodes.

Measuring the drive strength always affects the DUT. In our case we are applying a 1.5V voltage with a drive strength of 50k. If the node has a Thevenin resistance similar or higher than 50k, we are actively modifying the node voltage and potentially inducing a modification in the behaviour of the DUT.



Give it some protection

As explained before, resistor R3 should not have any current in normal operation. IC inputs,  like the ones on the MCP6002 device, don't like to be driven above Vcc (3V in our case) or below GND. Trying to go outside of this limits will trigger the internal protections on the device. The R3 resistor guarantees that it will not cause a high input current.
The circuit has been used to probe a low impedance 20V node and it operated correclty, detecting a higher than 2V level, without any harm done to the probe. This would not be the case if R3 wasn't present.

Frequency limits

If the tip voltage changes with time alternating between voltages over 2V and below 1V, both LEDs will lit during some time. At low frequencies the blinking is apparent. At higher frequencies, over the Flicker fusion frequency, both LEDs seem to be lit at the same time. The circuit, however, due to some technical limits like the use of opamps instead of comparators has a maximum frequency of operation at about 50kHz. A square signal over this frequency doesn't lit any LED.

This is no problem as the main purpose of the probe was to test static nodes but it should be taken into account for dynamic nodes. It is usual for logic probes to have an special detection mode for pulsed signals with frequencies up to several MHz. This is not the case in this circuit.


Building the probe

The probe has been fabricated in a prototyping perfboard.

Built Probe
From left to right you have the probe tip, the three R1, R2 and R3 resistors, both LEDs and their R7 and R8 resistors, the MCP6002 dual opamp and the three R4, R5 and R6 resistors.
Ending the board we have the ground connection and the three pin power connector.
The LEDs are close to the tip so that we don't need to move the eyes from the circuit to check if they are lit.

The back side of the probe board is shown in the following figure. All the wiring has been done using thin, isolated, solid wire.

Probe, solder side

The three pin power connector uses the center pin for Vdd (+3V) and the other two pins for ground. A CR2032 socket is connected to a three pin female socket to provide the supply to the circuit.
As the connector is symmetric, it can be connected with the battery facing the top of the bottom of the board. As the supply is detachable from the probe, we don't need a power switch.

Power Supply
The ground connection is provided by an aligator clip connected to a short stranded wire.

Ground connection

The final probe with the supply and ground terminal is shown in the following figure.

Probe with battery and ground connection

In order to check for continuity or to check diferential voltages, a second ground probe has been built using a thin piece of coper board and some heat-shrink tubing. As you can see, touching both probe tips makes the system behave as a continuity tester.


Main probe and ground probe