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.