100% found this document useful (3 votes)
923 views171 pages

Arduino Measurement Lab

Electronics

Uploaded by

lofa szarka
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
Download as pdf or txt
100% found this document useful (3 votes)
923 views171 pages

Arduino Measurement Lab

Electronics

Uploaded by

lofa szarka
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
Download as pdf or txt
Download as pdf or txt
You are on page 1/ 171

Arduino Measurement Lab

Burkhard Kainka
Copyright © 2022 Burkhard Kainka
All rights reserved.
ISBN: 9798831847703
Independently published

Foreword

A well-equipped electronics lab is full of power supplies, measuring


devices, test equipment and signal generators. In addition, there are tools,
components and the many assemblies and projects that you are currently
working on. It can get crowded in the lab. Wouldn't it be better to have one
compact device for almost all tasks? All in one, small and versatile, and
also inexpensive and easy to procure.

After several attempts with other systems the choice fell on the Arduino
Nano. On this basis, a PC interface as versatile as possible for measurement
and control is to be developed. It simply hangs on a USB cable and,
depending on the software, forms the measuring head of a digital voltmeter
or PC oscilloscope, a signal generator, an adjustable voltage source, a
frequency counter, an ohmmeter a capacitance meter, a characteristic curve
recorder and much more.

The circuits and methods collected here are not only relevant for exactly
these tasks in the electronics laboratory, but many details can also be used
in completely different contexts. Often one encounters complex tasks in the
field of measurement technology during development work with
microcontrollers. In many cases, the methods from this book can then be
used. You have a starting point and can develop the software in the desired
direction.

Stay creative!

Burkhard Kainka

Software and more information about the book:


https://www.b-kainka.de/MeasurementLab.html
CONTENTS

1 Preparations
1.1 Choice of controller
1.2 The Arduino Nano
1.3 Voltage supply
2 Preliminary tests
2.1 Port outputs
2.2 Analog inputs and outputs
2.3 The serial plotter
2.4 PWM signal generator
2.5 A sawtooth generator
2.6 Direct digital synthesis
3 GCC programming
3.1 Fast port outputs
3.2 PWM output
3.3 Timer interrupt
3.4 Fast sine wave generator
3.5 AD buffering
4 The MSR Laboratory
4.1 Dual-channel DDS generator
4.2 Binary serial transmission
4.3 Frequency setting
4.4 Deflection times and dual-channel operation
4.5 Triggering
4.6 DC voltage output
5 Additional inputs and outputs
5.1 Phase adjustment of the DDS
5.2 Signal generator up to 8 MHz
5.3 Frequency measurement
5.4 Additional analog inputs
5.5 Capacitance measurement from 1 pF
5.6 Resistance measurement up to 1 MΩ
5.7 Resistance measurement from 1Ω
6 Measurements and experiments
6.1 Subsampling
6.2 Investigation at higher frequencies
6.3 Measurement on a synchronous signal
6.4 Frequency response of a low-pass filter
6.5 An LC low pass
6.6 LC resonance
6.7 Transistor test circuit
7 Firmware extensions
7.1 Alternative DDS functions
7.2 Reduced amplitude
7.3 Triangle and sawtooth
7.4 XY representation
7.5 Frequency sweep
7.6 Ramp function
7.7 Measurement of characteristic curves
8 Application examples
8.1 The emitter follower
8.2 Emitter follower as impedance converter
8.3 Sallen key filter
8.4 Beat generator
8.5 Operational amplifier
8.6 Voltage doubling
8.7 All-pass filter
8.8 Bandpass filter
Appendix
List of components used

1 Preparations
The first considerations for a universal measuring system went in the
direction of a digital PC oscilloscope combined with a signal generator. The
decisive factor is the achievable cut-off frequency.

1.1 Choice of the controller

In the first experiment I tested a Bluepill board with a STM32 controller.


This Cortex M3 controller with a clock rate up to 72 MHz has a very fast
AD converter and an integrated USB interface. Basically all tasks can be
done by the same controller. Analog data is stored while at the same time
values of a DDS table are sent to the fast PWM outputs to generate sine
signals or other waveforms.

The experiments went quite far, but in the end some interfering factors
came to light. For the chosen tasks it is important that the measuring sample
and the outputs run in a fast and very accurate time frame. Sampling rates
up to 100 kHz at a PWM frequency of 125 kHz with two output and two
input channels each were achieved. But there was a permanent slight flutter
in the time frame, the cause of which was to be found in the simultaneous
demands of the USB interface. If the actual measurement and signal output
is executed in a timer interrupt with 100 kHz, no other interrupt should be
allowed. As soon as a second timer interrupt or as in this case a USB
interrupt is added, the absolutely uniform time grid is over.

In addition, there were delivery problems. The general semiconductor crisis


in 2021 meant that the Bluepill board was also hard to come by. That also
ended this way. Bye bye Bluepill!

There are also other STM controllers. A development board STM32 Nucleo
with a Cortex-M0 controller F040R8 with up to 64 MHz was used. The
crucial difference was that it has no internal USB interface and transfers its
data via the serial interface. The controller transmits its data only when it is
measured and is hardly loaded by it serial data transmission. In fact, this
completely eliminated signal processing flutter. Actually the project was on
a good way. But I would have had to build a separate board with the
STM32 controller and a USB/serial converter, which would have been
relatively expensive in the end.
When you enter the 32-bit world, the high clock rate is usually the first
thing that catches your eye. This should allow fast signal processing in real
time. However, disappointment often follows. The more complex software
eats up the advantage. This and the procurement problems have led to
existing 8-bit controllers becoming more interesting again.

The third attempt used an 8051-compatible N76E003 from Nuvoton. It has


16 kByte and runs with 16 MHz. Its big advantage are several timers and an
own PWM unit. This made it possible to achieve a clock rate of 50 kHz, in
which both the analog data for the oscilloscope could be measured and the
DDS data could be output to the PWM. All time-critical operations run in a
single timer routine.

During further development, the requirements increased because a trigger


function was to be included and the gate time of a frequency counter was to
be measured at the same time. Therefore, the sampling rate had to be
reduced to 32 kHz.

At this point I became curious: What would an ATmega328 do in


comparison? First I tested it with Bascom and was immediately positively
surprised. The controller used in the Arduino has only three timers, but it is
possible here to use one timer at the same time for PWM output and for a
timer interrupt. The sampling rate is now equal to the PWM output
frequency 62.5 kHz. In addition, the serial transmission rate of 1 MBaud
could be used, making intermediate storage of the measured values
unnecessary. This effectively allows the same speed that was achieved with
an STM32. In addition, it has been shown that many of the additional
functions fit into the interrupt without consuming too much time.

That was four attempts with the same goal. The winner so far has been the
ATmega328 on an Arduino Nano. The system is very cheap and widely
used. Many readers should already have this board. However, this is not
necessarily true for Bascom. Therefore now the wish came up to work with
the Arduino IDE if possible. However, Arduino sketches are not real-time
capable, because there are still things going on in the background that you
don't necessarily see. This is the reason why Bascom is much faster than the
Arduino-C in most cases.
The decisive breakthrough came with the realization that the Arduino IDE
can also be used for pure C. This makes it possible to use the familiar
programming environment with its reliable bootloader and simple
operation, while at the same time achieving maximum working speed of the
controller.

This establishes the essential cornerstones of the development: An Arduino


Nano is supplied with data and energy via its USB cable and returns
measured values. Everything is evaluated and displayed on the PC.
Programming the PC software with VB6 is only dealt with in passing,
whereby the user can fall back on ready-made programs. The book focuses
on firmware development in C, optimization of the measurement
procedures and typical use of the measurements.

You don't need much more than a solderless breadboard and a nano. There
is still room on the board for an operational amplifier and other components
for filters or circuits to be tested. This also demonstrates the correct use of
digital measurement devices. Many possible measurement errors can occur
in the same way with this simple low sampling rate device as with a fast
DSO. If you work with it on a small scale, you will be less likely to be
surprised on a large scale. Working with the small measurement laboratory
is thus at the same time a useful basic course.

1.2 The Arduino Nano

All measurement programs presented in this book run on the Arduino Uno
as well as on the Arduino Nano. It only depends on the controller, the
ATmega328. The Arduino Nano has the advantage that it can be put on a
breadboard together with other components.
Arduino Nano on the breadboard

Besides the original Arduino Nano, there are several very inexpensive
replicas. All of them use the same pinout and can be used for the
experiments in this book. They differ in some technical details and often
also in the USB socket. Mostly a USB mini connector is used. It has the
advantage of greater mechanical stability, which benefits experimental
work. However, USB micro or USB C cables are now more common.

The outer connectors have been renamed to D0 to D13 and A0 to A7


according to Arduino style and can be addressed with the Arduino IDE
under these names. But for deeper programming it is important to know
also the original names of the controller.
From the circuit diagram of the Arduino Nano

1.3 Voltage supply

The original Arduino Nano uses a USB converter FT232RL, whose internal
voltage regulator also provides the 3.3 V to the outside. Besides there are
several replicas which use the cheaper USB converter CH340. It also has a
3.3V output, but with less current. Some replicas therefore use an additional
voltage regulator, others use the output of the CH340 or leave the 3.3V
output completely free.
Like any Arduino, the Nano can get its operating voltage of 5 V either from
the USB or from an external voltage source with at least 7 V to Vin. The
original Nano uses a Schottky diode in series with the USB supply, whose
forward voltage reduces the operating voltage by up to 0.3 V. This diode
prevents damage to the PC if a higher voltage is ever accidentally applied to
the NANO.

Some nano-replicas do without the series connection of the Schottky diode


in the interest of the full operating voltage. Often the diodes are connected
antiparallel between VCC and GND. This provides protection against
incorrectly polarized voltage, but not against overvoltage at VCC.

Overvoltage, something like that can never happen to me, everyone would
say. But during the work on this book it happened nevertheless. Because the
Arduino Nano was programmed as an oscilloscope and as a signal generator
adjustable within wide limits at the same time, it should examine the
switching behavior of a reed relay, which was connected to the laboratory
power supply with 30 V via a switching transistor. There must have been a
mistake and the 30 V came directly to the analog input A0 and from there
via the internal protection diode at the port connector of the ATmega to the
VCC line. The nano survived this almost unharmed, only the pin A0 had an
internal termination against GND afterwards. But a USB hub and a webcam
connected to it at the same time were destroyed. Later it was found out that
the USB hub had a series diode, which probably prevented an even bigger
damage to the PC.
By the way, the replica version of the Nano mostly used in Franzis
packages would have prevented this damage just like the original Nano,
because both have the Schottky diode in series with the USB supply.

Another pitfall lurks with all Nanos: The VIN connection normally remains
free when the controller is supplied via USB. If you connect it to GND, the
5V voltage regulator gets into a forbidden state, which can lead to a latchup.
The regulator then triggers like a thyristor and can get extremely hot. Also a
relatively large capacitor between VIN and GND can trigger this state at the
moment of power-up by its charging current. So this pin should be left free
if you don't want to connect an external power supply.

General precautions mainly concern the power supply used. An external


power supply to Vin should only be used in exceptional cases, because
double caution is then necessary. The safest way is to supply power via the
USB port, with an interposed USB hub providing even more safety. The
disadvantage is often a reduced voltage at VCC, where instead of 5.0 V
often only 4.5 V are measured. If the USB hub has an optional external
power supply, this can be connected if high accuracy is required. VCC also
serves as a voltage reference for the AD converter.

If a higher voltage is needed internally, a voltage doubling can be used,


which is presented in chapter 8.6. Possible errors are then less dangerous,
because the circuit cannot supply large currents.

All connections to the outside, e.g. to external measuring objects, should be


checked particularly carefully. For safety, additional series resistors of 1 kΩ
to 10 kΩ can be connected in series to test leads, which provide effective
current limitation in the event of a fault.
2 Preliminary tests
At first, quite normal Arduino Sketches are to be used here. Thereby you
can test the different inputs and outputs, get to know typical measurement
methods and at the same time examine how fast the controller can work
with them.

2.1 Port outputs

Whenever I want to test an Arduino, I first load the program Blink from the
examples (group 01. Basics).
void setup() { pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
digitalWrite(LED_BUILTIN, HIGH);
delay(1000);
digitalWrite(LED_BUILTIN, LOW);
delay(1000);
}

The built-in LED will then flash at a rate of 0.5 Hz, as it is turned on for
one second and turned off for one second.

The internal LED is connected with its series resistor to pin D13. Here you
can connect an additional external LED with its own series resistor. With
modern, high-efficiency LEDs, a low current far below 1 mA is sufficient.
Therefore a resistor of 10 kΩ is suggested here.
Additional connection of an external LED

Now you can experiment with the waiting times. Is flashing at 25 Hz still
clearly perceptible to the eye? The waiting times must be reduced to a total
of 40 ms.

void loop() {
digitalWrite(LED_BUILTIN, HIGH);
delay(20);
digitalWrite(LED_BUILTIN, LOW);
delay(20);
}

With a further reduction to twice 1 ms, a tone of 500 Hz can already be


generated. A piezo loudspeaker is high-impedance enough to be connected
directly to the port. One hears a pure tone. The first impression is therefore
that the Arduino is real-time capable in the millisecond range.
Piezo speaker connection

A loop without any waiting times gives an even better impression. The
decisive question is what speed is then achieved. The test first shows that
the LED seems to be permanently lit. And an audible sound is no longer
produced.

void loop() {
digitalWrite(LED_BUILTIN, HIGH);
digitalWrite(LED_BUILTIN, LOW);
}

An examination with an oscilloscope shows that the port is switched on for


about 3 µs and remains off for about 3.8 µs. A frequency counter measures
147 kHz, resulting in a period of 6.8 µs.
Fast square wave signals

Even closer examination shows that isolated interruptions of a few


microseconds occur in the signal. They are probably due to the time
measurement in the Arduino. A timer interrupt runs in the background,
which periodically interrupts the program flow to measure the time. This is
important if you want to execute operations at defined times, but is rather
annoying for time-critical tasks. So the goal must be to disable all
interfering background processes. While the Arduino is best suited for
simple tasks, the controller used can do much more when it comes to time-
critical processes.
An interruption in the signal

2.2 Analog inputs and outputs

A good starting point for processing analog quantities is the program


AnalogInOutSerial from the examples (group 03. Analog). It performs
measurements at input A0 and sends the measured values via the serial
interface with 9600 baud. In addition, the data is output via the quasi-analog
output at pin 9 as a PWM signal.

const int analogInPin = A0;


const int analogOutPin = 9;

int sensorValue = 0;
int outputValue = 0
void setup() {
Serial.begin(9600);
}

void loop() {
sensorValue = analogRead(analogInPin);
outputValue = map(sensorValue, 0, 1023, 0, 255);
analogWrite(analogOutPin, outputValue);
Serial.print("sensor = ");
Serial.print(sensorValue);
Serial.print("\t output = ");
Serial.println(outputValue);
delay(2);
}

For the first tests it is a good idea to connect an LED to D9. Additionally
you can connect the piezo transducer to get an impression of the PWM
signal.

Listening to the PWM signal


First, the analog input A0 is to be connected to 5V, i.e. to the highest
measurable voltage. The LED is on. With a connection to 3V3 the LED
lights up weaker. And if you connect A0 to GND, it is completely off. At
5V and GND the piezo remains silent, at other voltages the PWM signal is
heard as a tone.
Because the program sends its data serially to the PC, one can view them
with the serial monitor. For the highest voltage of 5 V you get the measured
value 1023, which is the largest possible 10-bit number, because the AD
converter in the ATmega has a resolution of 10 bits. This value is converted
to 255 for the output, because all PWM outputs in the Arduino are driven
with a resolution of 8 bits. The smallest value 0 is measured when the input
is connected to GND.

Data in serial monitor


When measuring the stabilized voltage of 3.3 V, an analog value of 738 is
displayed. This can be used to calculate for a reference of 5 V:
738 / 1023 * 5 V = 3.61 V
This measurement error of about 10% comes from the fact that the
reference voltage is actually the operating voltage VCC. VCC obviously
had an error of about 10% because the Arduino was connected to the USB
via a hub. In fact, a voltmeter was used to measure a voltage of 4.5 V at
VCC. But this can be changed and the Arduino can be connected directly to
the PC, a 5 V power supply can be connected to the hub or an additional
supply of 9 V to 12 V can be connected to Vin so that the built-in 5 V
regulator provides an accurate operating voltage. Special care must be taken
when connecting a voltage higher than 5 V.

2.3 The serial plotter

If you start the serial plotter instead of the serial monitor, you get a diagram
of the measured data. Text and numbers are separated and the numerical
values are plotted in different colors. The plotter automatically adjusts its y-
axis to the occurring numerical values. The x-axis has a width of 500
measuring points.

Fixed voltage 3.3 V and ripple voltages


The diagram shows different situations. At the beginning, A0 was at 3.3 V,
so the known measured value of 738/739 was plotted. Then the measuring
cable was disconnected. The displayed voltage decreased only slowly
because the capacitance of the measurement input was still charged to the
previously measured voltage. After that the open input was touched with
the finger. One can already recognize the approach of the finger by a rising
50 Hz interference signal. When touched completely, the extreme values 0
and 1023 also appeared. After releasing, the input had a random voltage,
which again changed only slowly.
The result looks somewhat different if the input is first connected to GND
and then disconnected. The open input then slowly strives towards an
average value of 200. The AD input charges up to this value by the
measurements. This has to do with the way the AD converter works. A very
small capacitor is first connected to the input to take a sample. After that, its
charge is measured in several steps, while it itself is partially charged. For a
reliable measurement, the connected DUT must not be too high impedance.
If you value that an open input shows zero like a usual DVM, you have to
add a resistor against GND.

Voltage at the open input

The Sketch was reduced to the absolute minimum in the interest of higher
speed. In addition, the highest standard baud rate was set to 115200 bits per
second.
void setup() {
Serial.begin(115200);
}

void loop() {
Serial.println(analogRead(A0));
}

Fast measurement of a 50 Hz signal


The signal source was a simple piece of cable on the table that picked up 50
Hz noise. The distortions and deviations from the pure sinusoidal form
originate from electrical loads which impulse the network. We can now see
about nine full oscillations of 20 ms each, which adds up to 180 ms for a
total of 500 measurement points. This results in a time interval of the
measurements of 360 µs, i.e. a sampling rate of 2.8 kHz.
A further increase in transmission speed to 1 Mbaud brought only a slight
improvement.
void setup() {
Serial.begin(1000000);
}
void loop() {
Serial.println(analogRead(A0));
}

Measurement with 1 Mbaud


Now five oscillations are imaged with 20 ms each. This results in an
effective sampling rate of 5 kHz, so that the mapped period is 100 ms. For
comparison: In the end, up to 62.5 kHz is achieved with the same hardware
and pure C programming.

2.4 PWM signal generator

Here, signals are to be generated at the same time as the measurement,


which are then measured again themselves. For this purpose a PWM signal
with a pulse ratio of 100/255 is generated at pin 9. Additionally the analog
input A0 is to be connected with the PWM output D9.
void setup() {
Serial.begin(1000000);
analogWrite(9, 100);
}

void loop() {
Serial.println(analogRead(A0));
}

The measured PWM signal


The measurement clearly shows that the generated square wave signal has a
pulse width of less than 50%. The temporal resolution is not sufficient for
even more precise statements. However, the frequency can be determined.
53 pulses can be recognized. With a measuring time of 100 ms, this means a
frequency of 530 Hz. With an external frequency meter, 490 Hz were
measured.
The measurement with a fast oscilloscope shows very clearly the pulse
ratio. The signal has a period of 2 ms, which confirms the frequency of 500
Hz. The PWM signal does not show any interruptions or phase jitter
because it is generated solely by the timer hardware in the ATmega and thus
not influenced by the program flow.

The PWM signal in high resolution


The PWM frequency of approx. 500 Hz is sufficient to control the
brightness of LEDs, but it is too low for many other tasks. For comparison:
In the end, the MSR laboratory works with a PWM frequency of 62.5 kHz,
which is more than a hundred times higher.

2.5 A sawtooth generator

Despite the low PWM frequency, the basic principle of digital signal
generation can already be tested. One outputs new voltage values of the
desired waveform in regular intervals. The PWM output serves here as a
simple DA converter and needs in addition an RC element as a low pass
filter.

Smoothing of the PWM signal


Here 10 kΩ and 100 nF were used, which means a cutoff frequency of 160
Hz, which is below the PWM frequency.
First a sawtooth signal is to be generated. The output value is increased
continuously until there is an overflow from 255 to 0. The calculation and
the output must be included in the measurement loop.
unsigned char out;

void setup() {
Serial.begin(1000000);
}
void loop() {
Serial.println(analogRead(A0));
out++;
analogWrite(9, out);
}

Sawtooth signal with residuals of the PWM frequency


The result shows the generated sawtooth signal, but at the same time strong
residues of the PWM signal. The smoothing is not sufficient because the
PWM frequency is too close to the cutoff frequency.
Stronger filtering
If the cutoff frequency is reduced by a factor of 10 to 16 Hz (100 kΩ and
100 nF), this already leads to a significant deformation of the desired signal.
Here you can see the problem: The PWM frequency must be as far as
possible above the generated signal frequency, so that a desired waveform
can be generated with justifiable filter effort. By the way, it is more
favorable to generate sinusoidal signals, because a low-pass filter can only
cause a phase shift and a reduction of the amplitude, but not a change of the
waveform. In the later firmware, the PWM frequency is increased to 62.5
kHz, which simplifies the filtering considerably.

2.6 Direct digital synthesis

The following example shows the principle of DDS (Direct Digital


Synthesis) in the construction of a sine generator. First, a sine table is
created, in this case with 256 base values. At regular intervals, a value is
then read from the table and output as an analog value. The current phase is
always stored in a variable, in this case unsigned int phase, i.e. an integer with a
width of 16 bits.
A contant number is added to this variable each time, which is proportional
to the desired frequency of the sine signal. Only the upper eight bits are
used as position in the sine table. Thus, one wanders through the table at a
selectable speed and thus generates a sine oscillation with a selectable
frequency.

unsigned char out;


unsigned char sinus[255];
unsigned int phase, n;

void setup() {
Serial.begin(1000000);
for (n=0; n<256; n++){
sinus[n]= 127+127*sin(PI*2*n/256);
}}

void loop() {
Serial.println(analogRead(A0));
phase += 256;
out = sinus[phase >> 8];
analogWrite(9, out);
}
The sinusoidal signal filtered with 100 kΩ and 100 nF
In the same loop not only the DDS signal is generated, but also the
measuring points for the oscillogram are measured and sent. The
oscillogram shows a sine function and remnants of the PWM signal, using a
low pass filter with 100 kΩ and 100 nF. It is noticeable that there are
smooth spots, which should actually be at the highest and lowest points of
the sine, where the PWM signal changes to a DC voltage. However, the
low-pass filter provides a phase shift, so that the extreme values are reached
only a little later.
The sinusoidal signal in this case is very slow and has a frequency of only
about 16 Hz. It is difficult to determine the frequency from the self
measurement because the measurement loop runs slower by an unknown
factor due to the additional calculation steps. However, the image recorded
with an external oscilloscope shows that an undisturbed sinusoidal signal of
low frequency is produced overall.
The generated sinusoidal signal

Additional connection of an LED


You can connect a LED with series resistor to D9 and observe the soft
blinking directly. It becomes even more beautiful if you make the frequency
even smaller ( phase += 10; ).
void loop() {
Serial.println(analogRead(A0));
phase += 10;
out = sinus[phase >> 8];
analogWrite(9, out);
}

The experiments so far show that a common Arduino sketch is too slow to
process signals in an interesting range. So the task must be to increase the
speed. This is achieved by pure C programming and an optimization of all
steps. The end result is an extensive measurement lab with a sampling rate
of 62.5 kHz.
3 GCC programming

The first tests have shown that Arduino sketches are not really real-time
capable. Things run in the background that you can't see. Many time-critical
tasks cannot be solved this way. One way out is that the IDE can also
compile pure C code, because the GCC compiler is used in the background.
Usually every sketch contains a function void setup() and a function void
loop() . If you delete these two, everything stays clean. Instead a function int
main(void)is needed.

It is really only translated what is written there. Thus, there are no


background processes and no restrictions or presets anymore. But now you
have to initialize everything by yourself and you have to do without some
luxury. So you have to go deeper and study the datasheet of the
ATmega328.

3.1 Fast port outputs

The first pure C program is to switch port B0 (Arduino D9) and generate a
fast square wave signal. The whole port is written with one command, so
that also fast 8-bit outputs are possible.
int main(void)
{
DDRB=255;
while(true){
PORTB=1;
PORTB=0;
}}

The result: At D8 a square wave signal with 4 MHz is generated! So the


program runs about 30 times faster than the corresponding Arduino sketch.
Since the controller works with 16 MHz, only four clocks are needed. Each
port output needs one clock, the return to the beginning of the loop needs
two clocks.
How does the compiler know how to translate such registers as DDRB and
PORTB? Normally a C program has some include files that define all this.
In the Arduino IDE you only have to select the board (Arduino Nano), then
it is clear that the ATmega328 is used. In the background the appropriate
file is inserted, so that now all registers of the chip are known. So you get
both: A pure C program and the easy programmability via the bootloader.

3.2 PWM output

The ATmega328 has three timers, which can form two PWM outputs each.
Only timer 1 is a 16 bit timer. It can generate PWM signals with a
resolution of 10 bits. Timers 0 and 2 generate 8-bit PWM signals. Arduino
sketches use timer 1 with the outputs at B1 and B2 in the interest of
unifying all six PWM outputs also with a resolution of 8 bits. Here now the
timer 0 shall be used to keep the timer 1 free for other tasks.
All three timers can be used for quite different tasks. The data sheet reveals
which registers must be used in detail. For a fast PWM with timer 0 the
control register TCCR0A must be written with 0xA3. The timer is
controlled directly by the 16 MHz clock of the controller or by a prescaler.
The highest speed is reached with TCCR0B = 0x01 . Now there are two PWM
outputs at the ports PD5 (OC0B) and PD6 (OC0A), which are controlled by
the registers OCR0B and OCR0A. Both are initially set to half the final
value 128.
Controller connections and functions

RC element for smoothing


Low-pass filter at PWM output OC0A
int main(void)
{
unsigned char d=0;
DDRD = 254; //D1...D7 Output
TCCR0A = 0xA3; //Timer0 Fast PWM at PD5/6
TCCR0B = 0x01; //16 MHz
OCR0A =128;
OCR0B =128;
while(true){
d++;
OCR0A =d;
}
}

At pin D5 (OC0B) the PWM signal can be measured with a pulse width of
50% and a frequency of 62.5 kHz. The PWM frequency results with 16000
kHz / 256 = 62.5 kHz, because a full period needs 256 clocks. So this is the
fastest output if you want to have a resolution of 8 bits.
The first PWM output OC0A (PD6) is incremented in a fast loop. However,
the oscillogram shows that counting up is considerably faster than the PWM
output. Therefore there are only three outputs per 256 counting steps.

High count PWM output


To obtain a finer resolution of the sawtooth signal, the count-up must be
slowed down. For this purpose a counting loop was used. Because an empty
counting loop is optimized away by the compiler, the actually unnecessary
repeated assignment to DDRB is now executed here.
int main(void)
{
unsigned char d, n;
DDRD = 254;
TCCR0A = 0xA3; //Timer0 Fast PWM at PD5/6
TCCR0B = 0x01; //16 MHz
OCR0A =128;
OCR0B =128;
while(true){
d++;
OCR0A =d;
for (n=0; n<100; n++){DDRD = 254;}
}
}

With this slowing down one recognizes now the sawtooth signal formed by
the low pass filter with approx. 160 Hz. By shortening the counting loop,
higher frequencies can be obtained.

Sawtooth signal with better resolution

3.3 Timer interrupt


Better than a counting loop is the use of a timer interrupt. In this case the
timer 0 can be used at the same time as a timer, which generates an interrupt
at each overflow. Additionally with sei() the global interrupt must be
allowed. And there must be an endless loop in which the program does
nothing else. The interrupt function ISR (TIMER0_OVF_vect) is then called
again and again with a frequency of 62.5 kHz. All changes of the pulse
width are now synchronous to the PWM signal itself.

unsigned char d;

ISR (TIMER0_OVF_vect)
{
d+=8;
OCR0A=d;
}

int main(void)
{
unsigned char n;
DDRD = 254;
TCCR0A = 0xA3; //Timer0 Fast PWM at PD5/6
TCCR0B = 0x01; //16 MHz
TIMSK0 = 0x01; //Timer0 Overflow Interrupt
OCR0A =128;
OCR0B =128;
be();
while(true);
}

With an increase in single steps one would get an output frequency of


62500 Hz / 256 = 244 Hz. Here, however, the output is increased by 8 each
time. This results in a signal frequency of 1953 Hz.
Increased output frequency

3.4 Fast sine wave generator

From here it is only a small step to a sine DDS generator. First, an array
unsigned char dds[256] is declared and filled with 256 values of a full sine wave.
The sine function used in it comes from the Math library, which is included
at the beginning with #include < math.h>. In addition, a 16-bit wide phase acc
ph is required, which is repeatedly incremented by a constant amount in the
timer interrupt. The upper eight bits of the phase accumulator then serve as
address pointer into the sine table.

#include < math.h>


unsigned char dds[256];
unsigned int ph;

ISR (TIMER0_OVF_vect)
{
ph+=500;
OCR0A=dds[ph>>8];
}

int main(void)
{
unsigned int n;
for (n=0;n<256;n++) dds[n]= 127+127*sin(PI*n/128.0);
DDRD = 254;
TCCR0A = 0xA3; //Timer0 Fast PWM at PD5/6
TCCR0B = 0x01; //16 MHz
TIMSK0 = 0x01; //Timer0 Overflow Interrupt
OCR0A =128;
OCR0B =128;
be();
while(true);
}
A DDS sinus signal with 500 Hz
Instead of the previous sawtooth signal, a sinusoidal signal with 1953 Hz is
now generated. You can change the constant value 500 within wide limits to
create completely different frequencies.

Measurement with the AD converter


The next step is to bring the measurement at an analog input into the timer
interrupt. And the data must be sent to the PC. With the serial interface we
first borrow again from the Arduino environment, by initializing the
interface with Serial.begin and transmitting the signal continuously with
Serial.println .
However, the initialization of the AD converter is done entirely on foot,
because this achieves a much higher speed. In most cases the 10-bit AD
converter supplies the lower 8 bits in the ADCL register and the remaining
two bits in the ADCH register. One must then read both registers and
combine the contents into a 16-bit number. Here the result is shifted to the
left by the initialization and appears with the eight most significant bits in
ADCH. So if you are satisfied with 8 bits, you only have to read one
register.
The AD converter uses a prescaler of the processor clock because it cannot
measure accurately at full speed. The more accurate you want to measure,
the slower the AD converter has to work. But if only a resolution of 8 bits is
required anyway, one can afford to use an ADC clock of 1 MHz. Usually,
each measurement process is started individually and then waited until the
AD converter has finished the measurement. In the interest of further time
saving, here the AD converter is automatically started at each overflow of
timer 0. Thus, it runs synchronously to the DDS generator and it is no
longer necessary to query when a new measurement result is available.

#include < math.h>

unsigned char dds[256];


unsigned int ph;

ISR (TIMER0_OVF_vect)
{
PORTD |= 4;
ph+=500;
OCR0A=dds[ph>>8];
Serial.println(ADCH);
PORTD &= ~4;
}

int main(void)
{
unsigned int n;
Serial.begin(1000000);
for (n=0;n<256;n++) dds[n]= 127+127*sin(PI*n/128.0);
DDRD = 254;
TCCR0A = 0xA3; //Timer0 Fast PWM at PD5/6
TCCR0B = 0x01; //16 MHz
TIMSK0 = 0x01; //Timer0 Overflow Interrupt
OCR0A =128;
OCR0B =128;
ADMUX = 0x60; //ADC Ref = VCC, Left adjusted;
ADCSRB = 4; //Timer0 Start
ADCSRA = 0xE4; //ADC Enable, Start, Auto Trigger, 1MHz;
be();
while(true);
}

So all in all the DDS signal is now generated in the same clock and the
result is measured and sent to the PC. The result in the Arduino plotter now
actually looks very good.

The signal measured with the same controller


The true signal with only 48 Hz
But now comes a disappointment. If you look at the generated signal with
an external oscilloscope, it is not so perfect anymore. For one thing, it only
has a frequency of 48 Hz. And for another, the lower half-wave is much
sharper than the upper one.
The interrupt function switches PD2 on at the beginning and off again at the
end. You can therefore observe at this pin how much time is used in the
interrupt. Ideally, considerably less than 16 µs is needed, because only then
the clock of 62.5 kHz can be kept. However, a measurement at PD2 shows
that at least 100 µs are used, and sometimes considerably more.

Measurement of the interrupt time


Too large computing times in the interrupt function
The problem is caused by the serial costly data transmission with
Serial.println(ADCH). Reading the measurement result is very fast, but then
several bytes have to be sent, where each byte needs at least about 10 µs.
If you look at the data stream with the program Terminal.exe, you get a byte
display in addition to the text display. The number 230 is transmitted with a
total of five bytes. The three digits are coded with their ASCII characters:
50, 51, 48, followed by the control characters Carriage Return (CR, 13)
Line Feed (LF 10). In the lower half-wave, however, there are also
measured values up to 99, which thus get by with only two digits. Here the
time passes faster, which leads to a deformation of the oscillogram.
Serial transmission in text format

If you look at the data transmission directly at the TXD line, you can see
that the five bytes are transmitted directly one after the other. However,
there is a longer pause between two data packets. This is probably caused
by the preparation of the data and its conversion into a text.
Signals on the TXD line
The best way to solve this problem is to actually send only one byte for one
measured byte. This means that the measured data in byte format is sent
directly as such and not first converted into a text. However, this requires a
modified evaluation of the data. The Arduino plotter can then no longer be
used, but you have to develop your own software.

3.5 AD buffering

For the beginning the serial plotter is very convenient, because you don't
have to work on two construction sites at the same time. As an intermediate
solution, it is advisable to first save the data in an array and only then send
it.
#include < math.h>
unsigned char dds[256];
unsigned char osz[500];
unsigned int ph, n, i, j;

ISR (TIMER0_OVF_vect)
{
PORTD |= 4;
ph += 256;
OCR0A = dds[ph >> 8];
if (i < 500) {
osz[i] = ADCH;
i++;
}
PORTD &= ~4;
}

int main(void)
{
unsigned int n;
Serial.begin(1000000);
for (n = 0; n < 256; n++) dds[n] = 127 + 127 * sin(PI * n
/ 128.0);
DDRD = 254;
TCCR0A = 0xA3; //Timer0 Fast PWM at PD5/6
TCCR0B = 0x01; //16 MHz
TIMSK0 = 0x01; //Timer0 Overflow Interrupt
OCR0A = 128;
OCR0B = 128;
ADMUX = 0x60; //ADC Ref = VCC, Left adjusted;
ADCSRB = 4; //4 'Timer0 Start 0= free running
ADCSRA = 0xE4; //ADC Enable, Start, Auto Trigger, 1MHz;
be();
while (true) {
i = 0;
for (n = 1; n < 65000; n++) {
for (j = 1; j < 20; j++){ asm ("nop");}
}
for (n = 0; n < 500; n++) {
Serial.println(osz[n]);
}
}
}

The storage is started when i is set to 0 from outside and terminated when i
= 499 is reached. The output of the 500 measured values is done in the
main program. In addition, a waiting loop was inserted so that the
oscillogram stands still for about one second after each output.

Intrinsic measurement of the sinusoidal signal

A full sinusoidal oscillation is output here in 256 points, so that almost two
full oscillations fit on the screen with its 500 measuring points. The
frequency of the signal is 244 Hz, as already calculated above in connection
with sawtooth signals: 16 MHz / 256 / 256 = 244 Hz.

External measurement: 244 Hz, 2.5 Vpp

The measurement with the external oscilloscope confirms the frequency of


244 Hz. The sinusoidal signal is generated continuously and does not show
any interruptions, phase jumps or distortions due to the measurement.
During the serial output of the data, the output can be interrupted by the
timer interrupt, but this does not disturb the process.

A look at the signal at PD2 shows the low utilization of the interrupt routine
of only about 10% of the available 16 µs.
Measurement of time utilization at D2

The program now also allows higher signal frequencies. At a sine frequency
of 2 kHz ( ph += 2098; ) one can already recognize remains of the PWM
frequency. That these remainders are at the extreme values of the sinusoidal
oscillation is indicated by a phase shift of approx. 90 degrees. This means at
the same time that the low pass filter is already operated far beyond its
cutoff frequency of 160 Hz and that the amplitude of the useful signal with
200 mV becomes accordingly small. The basic problem is that the PWM
frequency should be as far as possible above the useful frequency, but with
a resolution of 8 bits it is limited to 62.5 kHz. A possible solution lies in a
multi-pole low-pass filter with a steeper slope. This topic will be discussed
in more detail below.
The generated 2 kHz signal across 10 kΩ at 100 nF
The own measurement with the Arduino plotter shows that a signal of 2
kHz is already represented very well. For this measurement the cutoff
frequency of the low pass filter was increased to 1.6 kHz (10 kΩ and 10
nF), so that the signal voltage fits better to the measuring range 5 V.
Remnants of the PWM signal cannot be detected here. But this is due to the
fact that the AD sampling is synchronous to the PWM signal. A residual
signal still present at 62.5 kHz would always be measured in the same
phase and thus appear as smooth. So you have to keep in mind that the
synchronous measurement makes the signal look a bit more perfect than it
actually is. The comparison measurement with an external oscilloscope and
higher sampling rate, on the other hand, still shows residuals of the PWM
under the same conditions (2 kHz, 10 kΩ and 10 nF).
Measurement of the own 2 kHz signal over 10 kΩ at 10 nF
Comparison measurement with an external oscilloscope
With its sampling rate of 62.5 kHz, the oscilloscope is already fully suitable
for the entire AF range. The decisive factor is that the sampling rate is at
least twice as high as the highest occurring signal frequency. In the audio
sector, a sampling rate of 44.1 kHz is often used for the frequency range up
to 20 kHz, although very steep-edged filters are used. So the sampling rate
is higher than required. Therefore, the oscilloscope realized with the
Arduino can already correctly display typical audio signals.

Representation of a music signal from the radio


4 The MSR Laboratory
At this point in the development, a new user interface with enhanced
capabilities is to be deployed. The label MSR (German: Messen Steuern
Regeln) can be translated as measurement and control. The goal of the
development is a combination of numerous functions:

Oscilloscope with up to two channels


Switchable time axes
Trigger functions
Two DDS sinus generators
0 to 5 kHz
Additional DDS rectangular outputs
Two adjustable voltage sources

The MSR program

The user program is developed in VB6 and will be presented here only in
passing. The task is also solvable with other programming languages. The
decisive factor is that this enables further development of the firmware.

The central goal is that all functions of the measuring laboratory can be
used simultaneously. The individual inputs and outputs can therefore be
used as if they belonged to independent devices. Later on, further functions
are to be added.

Frequency counter up to 16 MHz


Two voltmeters up to 5 V
Square wave generator up to 8 MHz

4.1 Two-channel DDS generator

The MSR lab is to be equipped with two independently adjustable DDS


generators. Especially the selection of the timers requires some preliminary
considerations, because there are several restrictions here. In particular,
timer 0 and timer 1 share the port D5. If Timer 1 is to be used later as a
frequency counter, the use of the PWM output OC0B is prohibited.
Therefore the two PWM outputs for the DDS generators now use timer 2.
OC2A is connected to PD3 and OC2B to PB3. So input T1 (at PD6) can be
used for the frequency counter. And OC0A remains usable for a square
wave generator up to 8 MHz.

Timer 2 can be initialized for PWM outputs in a similar way as timer 0


before. The PWM frequency is 62.5 kHz again. With the same frequency a
Timer 2 interrupt function is called, in which the DDS signals are generated
and the analog values for the oscilloscope are measured. However, there is
unfortunately no way to trigger the ADC start automatically from Timer 2.
So an additional start command must be inserted. But this works without
problems, because the computing time within the interrupt function is not
yet short. Later even further elements are inserted here.

In the interrupt function now two sinusoidal signals are generated via both
PWM outputs. For this there are two separate phase accumulators a1 and
a2. This time they are not increased by constants, but by the variables ph1
and ph2, which can be used to specify the frequency externally. In addition,
two square wave signals with the same frequency are generated at the
outputs D4 and D7 by copying the most significant bit of the phase
accumulator to the output in each case. Thus there are altogether four DDS
outputs and one auxiliary output:

Sine 1 (OC2A) at PB3 (D11)


Sine 2 (OC2B) at PD3 (D3)
Rectangle 1 at PD4 (D4)
Rectangle 2 at PD7 (D7)
Square wave 62.5 kHz at PB0 (D8)

The two-channel generator with low-pass filters

ISR (TIMER2_OVF_vect)
{
PORTB |= 1;
a1+=ph1;
a2+=ph2;
if (ds1) OCR2A=(dds[a1>>8]);
if (ds2) OCR2B=(dds[a2>>8]);
PORTD = (PORTD & ~128)|((a1>>8)&128);
PORTD = (PORTD & ~16)|((a2>>11)&16);
if (adn<628){
UDR0 = ADCH;
adn++;
}
ADCSRA |= 0x40; //AD Start
PORTB &= ~1;
}

Furthermore, in the interrupt function the measurement is performed via the


AD converter. Different to the last one, the measurement result is not stored
temporarily, but transferred directly to the UART ( UDR0 = ADCH; ). The time
required for this copying of a single byte is extremely low. With the write
access the UART is started at the same time. The actual sending of the data
byte takes about 10 µs at 1 Mbaud and is done by the hardware without
loading the processor. The only decisive factor is that the transmission time
is shorter than the interrupt period of 16 µs. Thus 628 bytes are measured
and sent. The user program must be able to receive and display single bytes.
To start a new series, the counter adn must be set to zero from outside.

Towards the end of the function the AD converter is retriggered via a direct
start command ( ADCSRA = 0xD2; ) because automatic triggering by timer 2 is
not possible. This command also consists of only a single byte transfer. The
AD converter then has enough time until the next interrupt.

4.2 Binary serial transmission

The firmware does completely without the transmission of text and uses
binary data in the form of single bytes instead. Therefore the Arduino
typical commands for data transmission cannot be used. For the byte
transfer there are now the functions USART_Transmit and USART_Receive . In
both directions only one byte is written to or read from UDR0. Before this,
the USART waits until it is ready or has received a byte. The byte
transmission from the interrupt function could do without this waiting time,
because with a transmission clock of 16 µs it is clear that the USART is
ready for a new byte.
In the main function first the USART, the timer 2, the AD converter and the
ports are initialized. Timer 2 provides two PWM outputs with 62.5 kHz and
triggers a timer interrupt at each overflow. The PWM pulse widths are first
initialized with 128. The AD converter operates left-adjusted, so that the
upper 8 bits can be read with a byte access in register ADCH.

The converter clock is set to the highest possible speed. The AD clock is set
to Clk/16, i.e. 1 MHz. The data sheet recommends 200 kHz for best
accuracy. However, because only 8 bits of the available resolution are used
here, the faster clock can be used without losses. The AD converter needs
13 clocks for one measurement. Therefore the conversion time of 13 µs is
shorter than the interrupt period of 16 µs. The serial transmission of the last
measured value and the measurement of the following value run
simultaneously with their separate hardware blocks without burdening the
controller's computing time.

void USART_Transmit(unsigned char data){


while ( !( UCSR0A & (1<<UDRE0)));
UDR0 = data;
}

unsigned char USART_Receive( void ){


while ( !(UCSR0A & (1<<RXC0)) );
return UDR0;
}

int main()
{
UBRR0H = 0; //USART
UBRR0L = 0; //1 MBaud
UCSR0B = 0x18; //TX, RX on
UCSR0C = 0x06; //8N1

TCCR2A = 0xA3; //Timer2 Fast PWM at PD3/PB3


TCCR2B = 0x01; //16 MHz
TIMSK2 = 0x01; //Timer0 Overflow Interrupt
OCR2A = 128;
OCR2B = 128;

ADMUX = 0x60; //Ref = VCC, Left adjusted


ADCSRA = 0xC4; //ADC Enable, Start, 1 MHz

DDRB = 255;
DDRD = 254;

for (n=0;n<256;n++) dds[n]= 128+127.9*sin(PI*n/128.0);


ph1=1049; //1 kHz
ph2=2098; //2 kHz
be();

while(true) {
c=USART_Receive();
if (c==65) adn=0; //Oszi Start}

In addition to the initialization of the controller periphery, the sine table


dds[n] with its 256 supporting values is also prepared in the main function.
And finally the two output frequencies are set to 1 kHz and 2 kHz. For 1000
Hz ph1=1049 must be set. So one has a frequency resolution of about one
hertz. Later, other frequencies are also assigned via serial commands. The
two sine and the two square wave signals appear without delay and
permanently at their outputs. Measured values, however, are sent only after
a request.

In an endless loop the program waits for commands in the form of single
bytes. In the first expansion stage only one command is recognized. If a
byte 65 was received, a measurement with 628 points is started by setting
adn=0. The command can also be sent as a single capital A. Both ways of
reading the data can be processed by the simple serial terminal program
Ternimal.exe. The received data shows the sinusoidal signal smoothed with
a RC filter. You can clearly see the maximum at 240 and the minimum at
15.
Start and reception of the measured values

The VB program triggers the measurement in a timer function, which is


repeated after every one second. In this way one gets sufficiently long
standing pictures. As soon as data is received, a new diagram with green
auxiliary lines is prepared in the drawing area Picture1. Then a total of 626
bytes are received and plotted in 625 line segments. With a sampling
frequency of 62.5 kHz, this gives a time of 10 ms on the x-axis, i.e. 1
millisecond per scale section (deflection time 1 ms/div).

Private Sub Timer2_Timer()


busy = 1
CLEARBUFFER
SENDBYTE 65
Do
n=n+1
If n > 20000 Then Exit Do
Loop Until INBUFFER > 0

Picture5.Cls
For n = 1 To 9
Picture1.Line (62.5 * n, 2)-(62.5 * n, 258), vbGreen
Next

For n = 0 To 10
Picture5.Line (0, 258 - n * 25.5)-(625, 258 - n * 25.5), vbGreen
Next n
alast = 258 - READBYTE
alast = 258 - READBYTE

For n = 0 To 625
Ain = 258 - READBYTE
Picture5.Line (n - 1, alast)-(n, Ain), vbBlack
alast = ain
Next n
End Sub

4.3 Frequency setting

The next stage of the extension concerns the setting of the DDS
frequencies. For this the contents of ph1 and ph2 must be reassigned. The
commands 67 and 68 were defined for this. Because both variables have a
width of 16 bits, two data bytes must be transmitted in each case.

while(true) {
c=USART_Receive();
//cli();
if (c==65) adn=0; //Oszi Start
if (c==80){ //DDS Freq 1
ph1 = USART_Receive()<<8;
ph1 = ph1+ USART_Receive();
}
if (c==81){ //DDS Freq 2
ph2 = USART_Receive()<<8;
ph2 = ph2+ USART_Receive();
}
}

An example: With a value of 512 one generates approx. 500 Hz. To set this
frequency for the second DDS channel, the command and its data is: 80, 2,
0. In the terminal you can see the slowed down progress of the sine
function.

Frequency assignment and start of a measurement

In the user program there are two sliders for the two DDS frequencies. Both
convert the adjustable frequency from 0 to 5000 Hz into frequency
parameters from 0 to 5242, which are then sent after the control command
66 or 67 as highbyte and lowbyte. The limit of 5 kHz is set arbitrarily. One
could also generate up to 10 kHz, But then each oscillation would have only
six support values, which would require much better low pass filters.

Private Sub HScroll1_Change()


Data = HScroll1.Value
f1 = Round(Data * 0.65536 * 1.6)
Label1.Caption = Str$(Data) + " Hz"
SENDBYTE 80
Hi = Int(f1 / 256)
Lo = f1 And 255
SENDBYTE Hi
SENDBYTE Lo
End Sub

So far there are two DDS outputs, but only one analog input. For the test it
is useful to lead both DDS outputs with 10 kΩ each or also different
resistors to the common input A0 and to smooth with 10 nF. The
oscilloscope then shows the sum of both signals. If you set slightly different
frequencies, the typical beatings appear.

Addition of both DDS channels


Superposition of two sinusoidal signals

In addition to the two sine outputs, there are two square wave outputs with
the same frequency. DDS1 supplies a signal to D7, DDS2 to D4. These
signals can also be examined directly with the oscilloscope. If they are sent
through a low-pass filter, the typical shark teeth with an exponential rise
and fall of the edges are created.
Square wave signal with 500 Hz at D7

Square wave signal with 800 Hz after low pass filtering with 10 kΩ and 10
nF

4.4 Deflection times and dual-channel operation

Previously, the sampling rate was constant at 62.5 kHz, which resulted in a
deflection factor of 1 ms/div in the oscilloscope. There are 62.5 measuring
points between two parts of the scale. Now, however, lower rates are to be
made possible. As usual, the deflection speed shall be adjustable in 1-2-5
steps.

In the interrupt function a division counter dvn is now continuously


incremented. From outside the speed is set in dv. So it can be compared
when the next measuring value is to be sent. For example, if only every
fifth interrupt is to send a measured value, dv=5 must be set via a
command. The oscilloscope then works with 5 ms/div.
ISR (TIMER2_OVF_vect)
{
PORTB |= 1;
a1+=ph1;
a2+=ph2;
if (ds1) OCR2A=(dds[a1>>8]);
if (ds2) OCR2B=(dds[a2>>8]);
PORTD = (PORTD & ~128)|((a1>>8)&128);
PORTD = (PORTD & ~16)|((a2>>11)&16);
dvn++;
if (dvn >= dv){
if (adn<628){
UDR0 = ADCH;
if (duo==1) ADMUX = 0x60+(adn & 0x0001);
adn++;
dvn=0;
}
}
ADCSRA = 0xD2; //AD Start
PORTB &= ~1;
}

In addition, a dual-channel operation is now built in. If you set duo=1 via a
command, the function switches to the other channel at each pass. For this
the least significant bit in adn is used. The multiplexer is switched
continuously in this way and is ADMUX=0x60 at one call and ADMUX=0x61 at
the next. This leads to a halved sampling rate for each of the two input
channels A0 and A1, which however is still sufficient for many
applications.

Four new commands must now be added to the command interpreter loop:

68: Deflection time


69: Channel 1
70: Dual channel, 1 and 2
71: Channel 2

while(true) {
c=USART_Receive();
//cli();
if (c==65) adn=0; //Oszi Start
if (c==80){ //DDS Freq 1
ph1 = USART_Receive()<<8;
ph1 = ph1+ USART_Receive();
ds1 = 1;
}
if (c==81){ //DDS Freq 2
ph2 = USART_Receive()<<8;
ph2 = ph2+ USART_Receive();
ds2 = 1;
}
if (c==68){ //Oszi deflection
dv = USART_Receive();
}
if (c==69){ //Oszi Ch1
ADMUX = 0x60;
duo = 0;
ch = 0x60;
}
if (c==70){ //Oszi Ch1+2
ADMUX = 0x60;
duo = 1;
ch = 0x61;
}
if (c==71){ //Oszi Ch2
ADMUX = 0x61;
duo = 0;
ch = 0x61;
}
}

The deflection speed is transmitted in one byte. The VB program allows


deflection times up to 20 ms/div, which are set by the slider Hscroll3. With
each change the command byte 68 is transmitted together with the div
factor .

Private Sub HScroll3_Change()


Select Case HScroll3.Value
Case 6
div = 1
Case 5
div = 2
Case 4
div = 5
Case 3
div = 10
Case 2
div = 20
End Select
Label3.Caption = Str$(div) + " ms/div"
SENDBYTE 68
SENDBYTE div
End Sub

The channel switching is controlled via the slider Hscoll4. Here only one
command byte must be sent at a time without additional parameters.

Private Sub HScroll4_Change()


Do
Loop Until busy = 0
Select Case HScroll4.Value
Case 0
ch = 1
SENDBYTE 69
Label4.Caption = "Ch1"
Case 1
SENDBYTE 70
ch = 3
Label4.Caption = "Ch1 + Ch2"
Case 2
SENDBYTE 71
ch = 2
Label4.Caption = "Ch2"
End Select
End Sub

The display of the measured values must also be extended for the second
channel. Channel 1 is displayed in black, channel 2 in red. In case of ch=3
both channels are plotted together.

If ch = 1 Then
alast2 = 258 - READBYTE
End If
If ch = 1 Then
For n = 0 To 625
Ain = 258 - READBYTE
Picture5.Line (n - 1, alast)-(n, Ain), vbBlack
alast = ain
Next n
End If
If ch = 2 Then
For n = 0 To 625
Ain = 258 - READBYTE
Picture5.Line (n - 1, alast)-(n, Ain), vbRed
alast = ain
Next n
End If
If ch = 3 Then
For n = 1 To 628 Step 2
Ain = 258 - READBYTE
Picture5.Line (n - 1, alast)-(n + 1, Ain), vbBlck
alast = ain
Ain = 258 - READBYTE
Picture5.Line (n - 2, alast2)-(n, Ain), vbRed
alast2 = Ain
Next n
End If
DELAY 10
CLEARBUFFER

Now both AD channels can be used simultaneously. Because there are also
two DDS channels, you can now display two different sine frequencies at
the same time. The setup must now be extended to two low pass filters.
The two-channel oscilloscope at 2 ms/div

The oscilloscope now delivers a new image once per second. If you want to
freeze an image, click Halt. This stops timer 2, i.e. further data acquisition
is suspended. Clicking again will restart the measurement.

Private Sub Command1_Click()


If Timer2.Enabled = False Then
Timer2.Enabled = True
Else: Timer2.Enabled = False
End If
End Sub

4.5 Triggering

Up to now the oscilloscope worked exclusively free running. The position


of an oscillation on the screen is random. Normally, each image is located
slightly differently. Triggering means that the start of a measurement is
triggered with a delay and is located, for example, at a certain point of the
rising edge. The user interface has a vertical slider for this purpose, with
which the trigger point can be selected. In addition, there is a vertical slider
as a step switch for the settings free running (without triggering), trigger+
(positive edge) and trigger- (negative edge).

Up to now, each measurement was initiated with command 65, which set
the counter adn to zero. Now there are the two new commands 66 and 67,
which need one byte parameter each for the trigger level. With two
interrogation loops the trigger point is reached. Only when the trigger level
is just reached, adn=0 starts the measurement.

if (c==66){ //+Trigger
level = USART_Receive();
timeout=0;
while (ADCH>=level) {timeout++; if(timeout>10000) break;}
while (ADCH<level) {timeout++; if(timeout>10000) break;}
adn=0;
}
if (c==67){ // trigger
level = USART_Receive();
timeout=0;
while (ADCH<=level) {timeout++; if(timeout>10000) break;}
while (ADCH>level) {timeout++; if(timeout>10000) break;}
adn=0;
}

When working with an oscilloscope, one knows the problem that the trigger
point has been chosen unfavorably and no image appears. To avoid this
situation, a timeout has been built in. If the searched condition is not
reached for too long, the query loop is exited.
Trigger point in the upper third

Negative trigger edge


4.6 DC voltage output

Two sliders are already on the user interface, which have not been used yet.
These are two sliders with which one can set a desired DC voltage. Here the
same PWM outputs are used, with which also the sine signals are generated.
Although one could have used timer 1 for the DC outputs, it will be needed
later as a frequency counter. In addition, the double use of the Timer2 PWM
outputs has the further advantage that one gets by with a total of two low-
pass filters.

If you press one of the DC voltage adjusters, the DDS output is stopped and
a DC voltage is output instead. It is also possible to use one of the outputs
for a sine signal and the other for a DC voltage. For the DC outputs there
are the two new commands 83 and 84. The additionally transferred
parameter is assigned directly to the PWM registers.

if (c==83){ //DC Ch1


ds1 = 0;
OCR2A = USART_Receive();
}
if (c==84){ //DC Ch2
ds2 = 0;
OCR2B = USART_Receive();
}

In addition, however, a change in the interrupt function is also necessary.


Here the sine output is only active when ds1 or ds2 is active.

ISR (TIMER2_OVF_vect)
{
PORTB |= 1;
a1+=ph1;
a2+=ph2;
if (ds1) OCR2A=(dds[a1>>8]);
if (ds2) OCR2B=(dds[a2>>8]);
PORTD = (PORTD & ~128)|((a1>>8)&128);
PORTD = (PORTD & ~16)|((a2>>11)&16);
dvn++;
if (dvn >= dv){
if (adn<628){
UDR0 = ADCH;
if (duo==1) ADMUX = 0x60+(adn & 0x0001);
adn++;
dvn=0;
}
}
ADCSRA |= 0x40; //AD Start
PORTB &= ~1;
}

The previous commands for frequency setting must also be extended so that
they can now switch on the DDS output. For this ds1 = 1 and ds2 = 1 is
inserted.

if (c==80){ //DDS Freq 1


ph1 = USART_Receive()<<8;
ph1 = ph1+ USART_Receive();
ds1 = 1;
}
if (c==81){ //DDS Freq 2
ph2 = USART_Receive()<<8;
ph2 = ph2+ USART_Receive();
ds2 = 1;
}
Output of a DC voltage of 1.35 V

Now one channel can be used for the sine output and the other for a DC
voltage. By adding both signals it is then possible to shift the average level
of the signal.
Sine signal with shifted DC level
5 Additional inputs and outputs
The Arduino Nano has a lot more to offer. Several ports, analog inputs and
timers are still free. Here we try to exhaust all possibilities that can be used
at the same time. The goal remains to use all functions as if they belonged
to independent devices. The MSR laboratory thus becomes more extensive
without the need for additional hardware.

For a good overview even with much more inputs and outputs all functions
are now named according to the pin designations on the Arduino.

Additional connections and functions


The enhancements affect the following connections and functions:

Adjustable phase shift between the two DDS outputs as long as the
same frequency is set.
Square wave generator up to 8 MHz at D6
10-bit analog inputs at A2 and A3
Frequency counter up to 8 MHz at D5
Capacitance meter 1 pF ... 10 nF at A4
Ohmmeter up to 1 MΩ also at A4
Ohmmeter 1 Ω ... 100 kΩ at A7

5.1 Phase adjustment of the DDS

The sine table of the DDS generators has a length of 256 bytes. For a
complete oscillation, the high byte in the phase accumulator must pass
through the range between 0 and 255. Thus, with the same frequency of
both channels, a phase relationship of 360 degrees in total is mapped in this
range. Accordingly, a1=0x0000 is set and a received byte parameter is shifted
into the high byte of a2. Command 82 thus triggers a phase jump at both
channels after which the desired phase relationship exists.

if (c==82){ //DDS Phase


a2= (USART_Receive())<<8;
a1=0x0000;
}

Private Sub HScroll9_Change()


phase = HScroll9.Value
Label15 = "D3 " + Str(Round(phase / 256 * 360)) + " °"
SENDBYTE 82
SENDBYTE phase
End Sub

In the user program, the desired phase difference is set with the HScroll9
slider. At each operation the command 82 is sent together with the new
phase byte.

A phase difference of 90 degrees

5.2 Signal generator up to 8 MHz

Timer 0 with a resolution of 8 bits can be used to generate a symmetrical


square wave signal. For initialization TCCR0A=0x42 is set. The following
register sets the prescaler. With TCCR0B=0x00 the generator is switched off,
with TCCR0B=0x01 it gets the full clock of 16 MHz. Further prescaler levels
reach up to a ratio of 1024. The exact frequency is set with OCR0A = 255
( /256, smallest frequency) to OCR0A = 0 (/1, largest frequency). The counter
counts up and jumps to 0 each time OCR0A is reached. At the same time
the output OC0A at port D6 is toggled. This results in the highest frequency
of 8 MHz. The lowest frequency is 16 MHz/2/1023 /256 = 30.528 Hz.

TCCR0A = 0x42; //Timer0 Toggle OC0A


TCCR0B = 0x00; //off
OCR0A = 255;
To set the frequency, two bytes must be transmitted for the prescaler and the
timer. Command 90 has been defined for this purpose.

if (c==90){ //OC0A frequency


TCCR0B = USART_Receive();
OCR0A = USART_Receive();
}

In the user program every change at the frequency control HScroll8 leads to
a new output. For the finest possible setting, five ranges with different
prescalers (1, 8, 64, 256, 1024) are used. The output frequency is calculated
and displayed on the surface.

Private Sub HScroll8_Change()


d = HScroll8.Value
If d = 0 Then pre = 0: n = 0
If d > 0 Then
pre = 5
n = 256 - d
If n > -1 Then f = 8000000 / 1024 / (n + 1)
End If
If d > 192 Then
pre = 4
n = 448 - d
If n > -1 Then f = 8000000 / 256 / (n + 1)
End If
If d > 384 Then
pre = 3
n = 640 - d
If n > -1 Then f = 8000000 / 64 / (n + 1)
End If

If d > 608 Then


pre = 2
n = 864 - d
If n > -1 Then f = 8000000 / 8 / (n + 1)
End If
If d > 832 Then
pre = 1
n = 1088 - d
If n > -1 Then f = 8000000 / (n + 1)
End If

If f < 100000 Then Label11.Caption = "D6 " + Str(Round(f))


+ " Hz"
If f >= 100000 Then Label11.Caption = "D6 " + Str(Round(f
/ 1000)) + " kHz"
SENDBYTE 90
SENDBYTE pre
SENDBYTE n
End Sub
Output and display of a signal of 1000 Hz

Many important frequencies can be set exactly, but most frequencies are
crooked parts of 16 MHz. The resolution is high at small frequencies and
becomes coarser towards the end. The four highest frequencies are 2 MHz,
2.667 MHz, 4 MHz and 8 MHz. For comparison: The DDS generator has a
resolution of about 1 Hz everywhere, but only reaches up to 5 kHz.

With the square wave generator, frequencies far above the sampling rate of
the oscilloscope can be set. However, reliable measurements with the
oscilloscope are only possible up to half the sampling rate, i.e. up to about
31 kHz. Near the sampling rate or its multiples, completely wrong images
are delivered. The double sampling rate is 125 kHz. If you set the square
wave generator to 127 kHz, an apparent signal of 2 kHz appears, i.e. the
difference frequency. In principle, this problem can be observed with any
DSO, while it never occurs with an analog oscilloscope.
Measurement of supposed 2 kHz at actual 127 kHz

Also noticeable are the sloping edges in the oscillogram despite the actual
rectangular shape. They are caused by the finite sampling time of the AD
converter. The sample-and-hold capacitor needs some time to charge up to
the actual voltage. However, at very high frequencies, the state already
changes within the sampling time. As a result, voltages between the
extreme values are measured in the transitions. At very high frequencies,
even triangular voltages are displayed.
Triangle display at 308 kHz

5.3 Frequency measurement

The digital counter uses timer 1 with a resolution of 16 bits. Because it is


only possible to count up to 65535 with this, an interrupt is triggered at each
overflow to increment an additional counter. This contradicts the principle
that there should be only one active interrupt to not disturb the running
DDS output. However, the Timer1 interrupt occurs extremely rarely and
only when frequencies above 65 kHz are measured.

ISR (TIMER1_OVF_vect)
{
fh1++;
}

...

TCCR1A = 0x00;
TCCR1B = 0x07; //Timer1 Input
TIMSK1 = 0x01; //Timer1 Overflow Interrupt
TCCR1C = 0;

For initialization the counter is connected to input T1 at port D5.


Additionally the interrupt is enabled. The Timer2 interrupt is also used to
control the gate time. A time counter t is set up here. At t = 0 the Timer1 is
reset together with its external highbyte fh1 . At t = 1 the timer is started.
And exactly one second later it is stopped and read out.

ISR (TIMER2_OVF_vect)
{
PORTB |= 1;
...
t++;
if(t==0){ TCCR1B = 0x00; TCNT1=0; fh1=0;}
if(t==1){ TCCR1B = 0x07;}
if(t==62501){ TCCR1B = 0x00;f=TCNT1; fh2=fh1;}
...
PORTB &= ~1;
}

The lower 16 bits are then in f . In addition, there are the upper 8 bits in
fh2 . Command 91 was defined for transmission to the PC.

if (c==91){ //Timer 1 frequency


USART_Transmit(fh2);
USART_Transmit(f>>8);
USART_Transmit(f & 0xFF);
}

In the user program, the frequency is displayed anew once per second. For
this purpose, the measured value must be read out within the timer
function. A total of three bytes are combined to form a 24-bit number.

CLEARBUFFER
SENDBYTE 91
f = READBYTE
f = 256 * f
f = f + READBYTE
f = 256 * f
f = f + READBYTE
Label9 = "D5 " + Str(f) + " Hz"

The frequency meter works permanently in the background without


disturbing the DDS output and the oscilloscope. If one connects the input
D5 with the output D9 (= B0), the sampling rate and the regular call of the
Timer2 interrupt function can be monitored. Here 62500 Hz are reliably
displayed. Should this frequency ever fluctuate or drop as a result of a
firmware extension, this indicates an error caused by too much time in the
interrupt.
Measurement of the sampling frequency at D8
Measurement of the DDS output frequency of 1000 Hz

The square wave output D7 or D4 is best suited for measuring the DDS
frequency. Here one can find deviations of one Hertz partly caused by
rounding errors. Usually the lowest digit of a frequency counter fluctuates
because the signal frequency is mostly completely asynchronous to the time
base of the counter.

In this case, the frequency of 1 kHz is also confirmed by the oscilloscope,


which simultaneously measures the corresponding sinusoidal signal.
However, the oscilloscope can only measure frequencies below 31 kHz.
The frequency counter, on the other hand, works up to 8 MHz.
Measurement of 8 MHz at D6

A deviation of 4 Hz is measured at the highest measuring frequency of 8


MHz. This deviation is due to calculation time in the Timer2 function,
which lead to a slight extension of the gate time. More precisely, this time
error can be narrowed down to 0.5 µs.

Overall, a frequency counter seems to have excellent accuracy. However,


one has to keep in mind that all measured signals are derived from the same
clock, namely the system clock of the Arduino. Unfortunately, the
controller does not use a quartz, but a ceramic resonator with 16 MHz.
Accurate measurements show that this can have a deviation of up to about
0.3%, which is about 50 kHz at 16 MHz. So with the displayed frequency
of 8 MHz an error up to 25 kHz is possible.

These tolerances must be taken into account in any frequency measurement.


However, there are often tasks where only relative accuracy or the
observation of frequency changes is important. In other cases, one may
consider removing the ceramic resonator and replacing it with a quartz.
5.4 Additional analog inputs

High resolution analog inputs are welcome and useful in the MSR lab. The
user interface contains two displays for external voltages at inputs A2 and
A3. They are to work with a resolution of 10 bits, which requires a
completely different initialization. The measured values shall be output
right-justified, so that the lower 8 bits are in ADL and the upper two bits are
in ADH. In addition, the converter must be clocked slower to achieve the
full accuracy.

if (c==75){ //ADC 10 bit


ADCSRA = 0x00; //Disable ADC
ADCSRA = 0x86; //ADC to Clk / 64
ADMUX = 0x40 + USART_Receive(); //0x42 for AD2
ADCSRA = 0xC2; //1. start
while((ADCSRA & 0x40));
ADCSRA = 0xC2; //2.Start
while((ADCSRA & 0x40));
adc=ADC;
USART_Transmit(adc>>8);
USART_Transmit(adc & 0xFF);
ADCSRA = 0x00; //Disable ADC
ADMUX = ch; //Ref = VCC, Left adjusted
ADCSRA = 0xC4; //ADC Enable, Start, 1, 1 MHz
}

For the measurement at any input channels first the command 75 is sent and
then the desired channel. This initializes the AD converter accordingly and
prepares it with an idle measurement. After the actual measurement, the
measurement result is sent to the PC in the range 0 to 1023 in two bytes.
Afterwards, the original setting of the AD converter is restored so that fast,
left-justified measurements can be performed for the oscilloscope.
In the timer function in the user program, two channels are measured at a
time after an oscillogram has been recorded. Thus the time sequence is clear
and there can be no conflict in the use of the AD converter.

SENDBYTE 75
SENDBYTE 2
u1 = READBYTE
u1 = 256 * u1
u1 = u1 + READBYTE
u1 = 5 * u1 / 1023
u1 = (Round(u1 * 1000)) / 1000
Label7 = "A2 " + Str(u1) + " V"
CLEARBUFFER

SENDBYTE 75
SENDBYTE 3
u2 = READBYTE
u2 = 256 * u2
u2 = u2 + READBYTE
u2 = 5 * u2 / 1023
u2 = (Round(u2 * 1000)) / 1000
Label8 = "A3 " + Str(u2) + " V"
Measurement at 3.3 V and 5 V

For testing, A2 was connected to 3V3 and A3 to 5V. VCC was apparently
measured with high accuracy, but 3.3V was displayed too high. In fact, it is
the other way around because VCC serves as a reference during the
measurement. The AD converter measures its own reference and returns the
value 1023. Assuming that Vcc = 5.0 V, the user program calculates a
measured value of 5 V from this. In fact, however, VCC can deviate from
5.0 V. In this case, the controller was operated via a USB hub without an
additional power supply. The actual voltage was measured with 4.68 V. In
contrast, the auxiliary voltage of 3.3 V was very accurate and was measured
with an external digital voltmeter as 3.30 V.

As with the frequency measurement, also with the voltage measurement


everything depends on the reference. In this case, all generated and
displayed voltages of the DDS generator and the oscilloscope are also
subject to the same error. Again, in many cases the deviation is of no
concern. However, if high accuracy of the measured voltages is important,
an external voltage of 9 V to 12 V should be connected to Vin. Then the
internal 5 V regulator comes into action and provides a much better
accuracy. Mostly the direct connection to the PC or the use of a power
supply at the USB hub is sufficient.

5.5 Capacitance measurement from 1 pF

Often a capacitance measuring device is missing in the laboratory, which


can also measure very small capacitors. The method used here uses a
reference capacitor with 1000 pF in series to the DUT Cx. Both capacitors
are first discharged to GND via port outputs on PC5 and PC4. Then PC4 is
switched as a high impedance input and PC5 is connected to VCC. This
results in a series connection of both capacitors to 5 V. The partial voltage
Ux can now be measured to determine the capacitance Cx from it.

Connection of the capacitors and two phases of measurement

If Cx also has 1000 pF, half the operating voltage should be measured. For
very small capacitors the measured voltage is close to Vcc. With the 10-bit
AD converter, a resolution of 1 pF is achieved for small capacitors.
Theoretically, 1 µF should also still be measurable, but only with very
coarse resolution. However, reasonable measurements up to 10 nF are
possible.

For the capacitance measurement the command 76 was defined. Here again
the AD converter must be reinitialized. Waiting loops were inserted
between the individual phases of the measurement, so that the capacitors
can sufficiently discharge and recharge themselves. The code is relatively
long, because with the same command also a resistance measurement is
executed. So it is also possible to check unknown components of which it is
not yet clear whether it is a capacitor or a resistor.

if (c==76){ //CR measurement


DDRC = 0x30; //C4/C5 output
PORTC = 0;
ADCSRA = 0x00; //Disable ADC
ADCSRA = 0x86; //ADC to Clk / 64
ADMUX = 0x44; //AD4, right adjust
ADCSRA = 0xC2; //1. start
while((ADCSRA & 0x40)); //discharged
for(i=1;i<2000;i++)asm ("nop");
DDRC &= ~0x10; //Hi Z
PORTC |= 0x20; //C3 at 5V
for(i=1;i<1000;i++) asm ("nop");
ADCSRA = 0xC2; // Measure C
while((ADCSRA & 0x40));
adc=ADC;
USART_Transmit(adc>>8);
USART_Transmit(adc & 0xFF);
PORTC = 0x10; //D3 Pullup, A5 GND
for(i=1;i<1000;i++) asm ("nop");
ADCSRA = 0xC2; //R measure
while((ADCSRA & 0x40));
adc=ADC;
USART_Transmit(adc>>8);
USART_Transmit(adc & 0xFF);
DDRC &= ~0x10; //Hi Z
PORTC |= 0x20; //C1, C2 at 5V
ADCSRA = 0x00; //Disable ADC
ADMUX = ch; //Ref = VCC, Left adjusted
ADCSRA = 0xC4; //ADC Enable, Start, 1, 1 MHz
}
The measurement results in two measured values for the capacitance and
the resistance. A total of four bytes are sent. The evaluation takes place
again in the timer interrupt after the display of the oscilloscope. The two
capacitances 1000 pF and Cx share the voltage in inverse ratio, so the larger
voltage is at the smaller capacitor. The measurement shows an offset of
about 30 pF because this is the capacitance of input A4 along with the
capacitances of the plug-in board. With the offset correction, the conversion
was: Cx = Int(1030 * (1023 - uc) / uc) - 30 Instead of a constant offset, one could
also perform a zero point measurement to take into account the capacitance
of a connected measuring cable at the same time.

CLEARBUFFER
SENDBYTE 76
uc = READBYTE
uc = 256 * uc
uc = uc + READBYTE
ur = READBYTE
ur = 256 * ur
ur = ur + READBYTE

If uc > 0 Then Cx = Int(1030 * (1023 - uc) / uc) - 30


Label12.Caption = "A4 " + Str(Cx) + " pF"

If ur < 1000 Then


Rx = Int(33500 * ur / (1023 - ur))
Label13.Caption = "A4 " + Str(Rx / 1000) + " k"
Else: Label13.Caption = "A4 >1 M"
End If
Measurement result 258 pF

The capacitance measurement runs without interference alongside all other


functions. In particular, the DDS generator and the oscilloscope continue to
operate unchanged.

5.6 Resistance measurement up to 1 MΩ

The measurement of a resistor also at port A4 against GND uses the internal
pullup of port PC4. This does not promise great accuracy, but is sufficient
for simple measurements up to about 1 MΩ. The unknown resistor forms a
voltage divider with the pullup resistor of about 30 kΩ. From the measured
partial voltage the searched resistance can then be calculated.
Resistance measurement

PORTC = 0x10; //D3 Pullup, A5 GND


for(i=1;i<1000;i++) asm ("nop");
ADCSRA = 0xC2; //R measure
while((ADCSRA & 0x40));
adc=ADC;
USART_Transmit(adc>>8);
USART_Transmit(adc & 0xFF);

The pullup is subject to strong specimen scatter and also depends on the
operating voltage. For the best possible accuracy, the value of 30 kΩ should
be determined more precisely and used in the calculation. Here, a resistance
of 33.5 kΩ was determined, which led to good results.

If ur < 1000 Then


Rx = Int(33500 * ur / (1023 - ur)- 460 )
Label13.Caption = "A4 " + Str(Rx / 1000) + " k"
Else: Label13.Caption = "A4 >1 M"

Another measurement error is caused by internal contact resistances close


to 500 Ω between the controller port and the external connector. This offset
error has been roughly corrected.

Measurement on a 100 kΩ resistor


5.7 Resistance measurement from 1Ω

For measurements also on small resistors, another ohmmeter has been


implemented at connection A7. This time there is an external reference
resistor of 1 kΩ. This eliminates the problem of internal contact
resistances, so that measurements can be made down to 0 Ω without offset
correction. Here no extension of the firmware is necessary, because there is
already an analog query for all available inputs.

CLEARBUFFER
SENDBYTE 75
SENDBYTE 7
ur = READBYTE
ur = 256 * ur
ur = ur + READBYTE
If ur < 1023 Then
Rx2 = Int(1000 * ur / (1023 - ur))
Label14.Caption = "A7 " + Str(Rx2) + " R"
Else: Label14.Caption = "A7 >100 k"
End If

Voltage divider for resistance measurement


Measurement of a 330-Ω resistor at A7
6 Measurements and experiments
The development of the compact measuring laboratory has reached a
preliminary end point. Now, typical examples will be used to show what
can be done with it. This also includes possible measurement errors and the
limits of the measurement methods used.

6.1 Subsampling

The following applies to every digital oscilloscope: The set deflection time
must match the measurement signal. This has already been confirmed in
many tests. Now a typical measurement error caused by undersampling
shall be provoked. The measurement is performed with a simple low-pass
filter with 10 kΩ and 10 nF between the DDS output D11 and the
oscilloscope input A0.

Low-pass filter with the cut-off frequency 1.6 kHz

The oscilloscope is set to 20 ms/div for this purpose. In this case, only one
of 20 possible measuring points is used. The sampling rate is then 62.5 kHz
/ 20 = 3125 Hz. If one now sets the DDS generator exactly to this
frequency, the oscilloscope should always sample exactly the same point of
the oscillation after every twenty oscillations. Thus, one should only see a
DC voltage.

In fact, however, one sees a section of a very slow sine wave with a
frequency below 1 Hz. This throws light on the possible frequency
deviations of the DDS generator. In fact, there are rounding errors here,
because due to the use of integer phase accumulators, the smallest
frequency step is 62500 Hz / 256 / 256 = 0.95367. If one sets one Hz
higher, i.e. 3126 Hz, an apparent frequency of 1 Hz should be measured.

Sub-sampling of 3126 Hz
Measurement at 3135 Hz

When the DDS frequency is increased to 3135 Hz, two complete sinusoidal
oscillations with a period of 100 ms become visible. The displayed
frequency is therefore 10 Hz. This is explainable because the real frequency
is now exactly 10 Hz above the sampling frequency. That the real frequency
cannot be 10 Hz but must be much higher can be seen from the lower
amplitude.

A comparison with a measurement at real 10 Hz shows the difference. The


signal now ranges from 0 V to 5 V. And another difference becomes clear.
One recognizes with an undersampling certain distortions and deviations
from the pure sine function, which are due to the fact that with the relatively
high DDS frequency of 3135 Hz only 20 support values are output to
approximate the sine function. At only 10 Hz, on the other hand, each of the
256 values of the DDS table is output several times.
Measurement at 10 Hz

6.2 Examination at higher frequencies

Undersampling can lead to measurement errors, but can also be used


deliberately to examine signals that are actually too fast for the
oscilloscope. Fast square wave signals are generated with timer 0 at D6.
Which signals are generated when a symmetrical square wave signal is sent
through a low pass filter has already been investigated for smaller
frequencies. This time a frequency of 127 kHz shall be used, which was
chosen on purpose to be close to the double sampling rate of the
oscilloscope of 125 kHz.
127 kHz over 1 kΩ at 10 nF

Cutoff frequency 16 kHz

This time the signal is filtered with 1 kΩ and 10 nF. The oscillogram shows
a symmetrical triangular signal with 1 Vpp and an apparent frequency of 2
kHz. The comparison measurement with a faster oscilloscope shows that
the waveform and the amplitude of the signal were displayed correctly even
with undersampling.
Comparison measurement

6.3 Measurement on a synchronous signal

At the output D8 (PB0) a square wave signal with 62.5 kHz appears, which
is mainly used to monitor the computing time within the interrupt function.
It is clear that one cannot observe this signal directly with the oscilloscope
with the same sampling rate. But if you try it anyway, a DC voltage with
low ripple appears, which is a little bit different at each measurement, but
always range 0 V to 0.5 V.
Measurement at D8 with 62500 Hz

Almost at the very end of the interrupt function the AD converter is


restarted. After that only the output B0 is switched off, i.e. the negative
edge of the 62.5 kHz signal is generated. After the start of the AD
converter, the sampling of the analog signal starts and lasts for a few clocks.
Therefore, most of the sampling time is after B0 is switched off, a smaller
part still captures the 1-state. Therefore the displayed voltage is usually a
little higher than 0 V. And because the AD converter has its own prescaler
for its operating clock, this operation is not quite synchronous with the
timer interrupt. This explains the observed fluctuations between 0 V and 0,
5 V. But it is crucial that the AD converter has finished its work before it is
read out at the next call.

ISR (TIMER2_OVF_vect)
{
PORTB |= 1;
...
ADCSRA |= 0x40; //AD Start
PORTB &= ~1;
}

With a faster oscilloscope you can see that the computing time is about 50%
utilized, which is about 8 µs.

The examined square wave signal

6.4 Frequency response of a low-pass filter

The most commonly used low-pass filters so far used a resistor of 10 kΩ


and a capacitor with 10 nF. The cut-off frequency is then 1600 Hz. At this
frequency the signal has dropped to -3 dB or 71%.
Frequency response in LTspice

At 62.5 kHz, the signal should be attenuated by about 32 dB. This


corresponds to a 40-fold attenuation or about 0.125 Vpp for the PWM
signal.

With the own oscilloscope in the MSR laboratory, only the frequency
response up to 5 kHz can be examined. At 5 kHz, one finds only 1.7 Vpp
compared to 5 Vpp at the lowest frequencies.
Measurement at 5 kHz

If you measure many measuring points at ascending frequencies and plot


the signal voltage against the frequency, you get the frequency response of
the filter.
Frequency response up to 5 kHz
Measurement of PWM attenuation at approx. 63 kHz

To check the achieved attenuation of the PWM frequency, a similar


frequency of approx. 63 kHz was generated with the adjustable square-
wave generator. The signal corresponds to the expected level within the
measurement accuracy. And the expected curve shape is also still clearly
visible with this undersampling.

One could assume that this ripple should affect all previous measurements
that used the same low-pass filter. However, this was not observed because
the oscilloscope runs synchronously with the PWM signal, whereby the
disturbances cancel each other out. This is an advantage of synchronous
measurement that should not be overlooked. Compared to other devices, the
measurement results appear significantly glossed over. On the other hand,
synchronous measurement allows very simple filters, which is an advantage
for small experiments.

6.5 An LC low pass


By using an additional fixed inductor, a second-order low-pass filter is
obtained. This doubles the attenuation in the upper range to 12 dB per
octave. Fixed inductors of 22 mH are readily available. To avoid resonance
overshoot, an additional resistor must be used. The simulation in LTSpice
shows for 22 mH, 100 nF and 620 Ω a straight frequency response up to 2
kHz and an attenuation of the 62.5 kHz PWM signal of about 50 dB.

An LC low pass

In the real setup, a resistor of 470 Ω was used because the fixed inductance
itself already has a certain wire resistance. The measurement shows a
straight frequency response up to approx. 2.2 kHz.
The LC low pass at 2 kHz

The LC low pass filter

At the same time, the residual ripple of the PWM signal has become so low
that it is hardly detectable. The test was again performed with the square
wave generator at D6 at approx. 63 kHz and with undersampling.
The smoothed signal at approx. 63 kHz

6.6 LC resonance

An LC circuit is often used as a bandpass filter to filter out a signal from a


frequency mixture. In the resonance case, the signal voltage oscillates to a
large amplitude. For an inductor with 22 mH and a capacitor of 100 nF, one
calculates a resonant frequency of 3.393 kHz.
Calculation with LCFR.exe

The DDS signal is reduced for the experiment with a voltage divider and an
additional electrolytic capacitor with 10 µF so that the excessive resonance
voltage still fits into the measuring range of the AD converter.

Excitation of an oscillating circuit


Resonance at about 3300 Hz

With the tuning of the sinus generator and the display in the oscilloscope,
one gets a quick overview and finds the resonance frequency very quickly.
For more detailed investigations, you can record some measuring points
more precisely and display them graphically with a spreadsheet. For
occasional investigations this manual evaluation is sufficient. But it is only
a question of software to automate such measurements. For automatic
recording of frequency responses no change in the firmware is necessary,
because all necessary measurement functions are already included.

The example measurement shows a typical resonance curve. It is noticeable


that the resonant circuit is relatively strongly damped and therefore only
brings a modest resonance rise. This also leads to a relatively large
bandwidth, with which one can determine a low quality factor. Reasons for
this are on the one hand a high internal resistance of the signal source with
about 100 Ω and the additional wire resistance of the coil, which could be
determined with the ohmmeter at A7 to 24 Ω.
In LCFR.exe the inductive resistance of the coil at the resonance frequency
was calculated with 469 Ω. From the ratio of the inductive resistance to the
ohmic resistance, the quality factor is obtained: 469 Ω / 124 Ω = 3.78. And
with the quality factor and the resonance frequency, the bandwidth can be
determined: 3.393 kHz / 3.78 = 0.898 kHz. The bandwidth of just under 1
kHz can be confirmed within the measurement accuracy.

The measured resonance curve

6.7 Transistor test circuit

A simple AF amplifier in emitter circuit with adjustable base current is


suitable for the investigation of a transistor. The working resistance was
fixed at 1 kΩ, so that voltages and currents can be read easily. An optimal
operating point of the circuit for many cases is 2.5 mA, so that a voltage of
2.5 V is at the working resistor and also 2.5 V between collector and
emitter.

The first PWM channel is used as a DDS sine wave generator with 1 kHz.
The low-pass filter was intentionally dimensioned with 10 kΩ and 100 nF
so that a relatively low AC voltage is applied. The second PWM output is
used as an adjustable voltage source to set the base current via the 470 kΩ
resistor.

Amplifier stage in common emitter circuit


Low base current
The two-channel oscillogram shows the generated sinusoidal voltage with
about 0.8 Vpp and the course of the collector voltage. You can see current
peaks up to more than 3 mA, where the collector voltage drops to below 2
V. The DC voltage is set to 0.67 V, so that only a very small base quiescent
current flows. The upper half-waves are therefore cut off, since the
transistor remains completely blocked in these phases.

At about 1.1 V a larger base current flows, which leads to a symmetrical


clipping. The transistor is completely on and completely off for somewhat
the same length of time. The amplifier works with strong overdrive, so that
the sinusoidal input voltage becomes approximately a square wave voltage
at the output. You can also clearly see that the phase is reversed. An
amplifier with these settings can be used, for example, as a preamplifier for
a frequency counter, because a digital counter expects square wave signals.
Another possible application would be a guitar amplifier and distortion.
Average operating point
Large base current

The signal looks different with a very large base quiescent current. Here a
control voltage of 2.12 V was set. The transistor switches fully in the idle
state, so that the collector current only decreases in the negative peaks of
the input voltage. This results in positive peaks of the collector voltage.

An undistorted amplification requires a smaller input voltage. This results


with the given low pass filter at a higher frequency of 2 kHz. The signal
voltage is only 0.5 Vpp and is amplified to an undistorted output voltage of
approx. 4 Vpp.
Optimum operating point and full output
7 Firmware extensions
The experiments conducted so far have shown some limitations, which are
now to be overcome by suitable extensions to the firmware and the MSR2
user program.

7.1 Alternative DDS functions

Up to now, the DDS generator could only produce sine oscillations with full
amplitude, i.e. between 0 V and 5 V. However, this can lead to problems if,
for example, an LC low-pass filter is used that partially leads to an increase
in amplitude.

The solution in this case brings a reduction of the amplitude to 50%. But
then quite different signal shapes can be realized at once. Both channels can
also generate different signals. Therefore there shall now be two separate
DDS tables, which are filled with the same sine waveform with full
amplitude for initialization.

unsigned char dds1[256];


unsigned char dds2[256];
...
ISR (TIMER2_OVF_vect)
{
PORTB |= 1;
a1+=ph1;
a2+=ph2;
if (ds1) OCR2A=(dds1[a1>>8]);
if (ds2) OCR2B=(dds2[a2>>8]);
...

for (n=0;n<256;n++){
dds1[n]= 128+127.9*sin(PI*n/128.0);
dds2[n]= 128+127.9*sin(PI*n/128.0);
}

Via own commands now also alternative table functions can be initialized
for the first DDS channel at D11.

if (c==85){ //sine
for (n=0;n<256;n++) dds1[n]= 128+127.9*sin(PI*n/128.0);
}
if (c==86){ //sine /2
for (n=0;n<256;n++) dds1[n]= 128+64*sin(PI*n/128.0);
}
if (c==87){ //triangle
for (n=0;n<128;n++) dds1[n]= 2 * n;
for (n=128;n<256;n++) dds1[n]= 255 - 2 * (n - 128);
}
if (c==88){ //sawtooth
for (n=0;n<256;n++) dds1[n]= n;
}

7.2 Reduced amplitude

A new slider was installed as selection switch for the four possible DDS
functions. Here only the single command bytes 85 to 88 are sent. The
firmware then calculates the required DDS table in each case.
Private Sub HScroll10_Change()
Select Case HScroll10.Value
Case 0
SENDBYTE 85
Label16.Caption = "D11 Sine"
Case 1
SENDBYTE 86
Label16.Caption = "D11 Sine/2"
Case 2
SENDBYTE 87
Label16.Caption = "D11 Triangle"
Case 3
SENDBYTE 88
Label16.Caption = "D11 Sawtooth"
End Select
End Sub

Half amplitude sine

The switching of the waveform works without any noticeable time delay.
The left position of the slider sets the full sine amplitude again.

7.3 Triangle and sawtooth


When outputting a triangular signal, it is important to note that the signal
can be changed by the low-pass filter. The calculated triangle shape is
therefore only seen at relatively low frequencies.

Triangular signal with 100 Hz over 10 kΩ at 10 nF

The same applies even more to the sawtooth. Especially the steep slope is
strongly changed at higher frequencies by the low pass filter.

While a sine wave contains only the fundamental frequency, square, triangle
and sawtooth have numerous even or odd harmonics. The signals therefore
differ greatly in sound when listened to directly through a piezo
loudspeaker without a low-pass filter, for example.
Sawtooth with 15 Hz.
Triangular signal over 10 kΩ at 100 nF

With sufficient filtering, every oscillation form approaches a sine wave.


This is most obvious with a triangular signal, which already contains only
small harmonics. A low pass filter with 10 kΩ and 100 nF has a cutoff
frequency of 160 Hz. At a fundamental frequency of 500 Hz, even the
fundamental is already noticeably weakened. The first harmonic at 1500 Hz
is already almost ten times smaller, so that the deviations from the pure
sinusoidal form are small.

7.4 XY representation

Until now, the x-axis of an oscillogram was always the time axis. Now,
however, both input channels A0 and A1 are plotted against each other. For
this and further representations the channel switch was extended by some
positions. The XY representation is called A1(A0) here, according to the
mathematical notation f(x). On the firmware side, only the normal two-
channel measurement is triggered, so that both channels alternate in the
data.

Private Sub HScroll4_Change()


Select Case HScroll4.Value
Case 0
SENDBYTE 69
ch = 1
Label4.Caption = "A0"
Case 1
SENDBYTE 71
ch = 2
Label4.Caption = "A1"
Case 2
SENDBYTE 70
ch = 3
Label4.Caption = "A0, A1"
Case 3
SENDBYTE 70
ch = 4
HScroll1_Change
Label4.Caption = "A1(A0)"
Case 4
ch = 5
Label4.Caption = "A0(f)"
Case 5
ch = 6
Label4.Caption = "A0(D11)"
Case 6
ch = 7
Label4.Caption = "-A0(D11)"
Case 7
ch = 8
Label4.Caption = "-A1+A0(A1)"
End Select
End Sub

In the timer function, there is a separate block for the XY representation.


The diagram is again composed of individual line elements. The different
size of the diagram in x- and y-direction had to be considered.

If ch = 4 Then
aylast = 258 - READBYTE
axlast = 2.45 * READBYTE
For n = 1 To 624 Step 2
Ay = 258 - READBYTE
Ax = 2.45 * READBYTE
Picture5.Line (axlast, aylast)-(Ax, Ay), vbBlck
aylast = ay
axlast = Ax
Next n
End If
Two phase-shifted sinusoidal signals of the same frequency

The XY plot can be used to create Lissajous figures from which frequency
relationships and phase relationships can be read. Two sinusoidal signals
with the same frequency and amplitude should result in a circle with a
phase shift of 90 degrees. Because the width and height differ here, a better
approximation to a circle is obtained with half the amplitude. In addition,
the phase was set to 90 degrees. However, the time-shifted sampling of both
channels results in an additional phase shift. Therefore, the set phase had to
be corrected to 94 degrees in this case.

With integer frequency ratios special Lissajous figures arise. With a little
experience one can recognize the ratio. Even small frequency deviations
can be recognized, because they continuously lead to a slow change of the
phase relations.
Frequency ratio 1 : 2
Frequency ratio 1 : 5
Different curve shapes can also be plotted against each other. The sampling
rate used is also important. With low sampling rates, such as a setting to 20
ms/div, additional delays occur between the x- and y-sampling. Instead of a
closed Lissajous figure, you then get complex line patterns.
Sine vs. sawtooth plotted at low sampling rate

7.5 Frequency sweep

Sweep generators, which continuously change their frequency, are used to


investigate frequency responses. In the high frequency range in particular,
these are also known as sweep generators or wobblers and are used to adjust
filters. In this case, the frequency is swept up from 0 Hz to 5 kHz. The
effect of a low-pass filter can then be read directly in the oscillogram. The
channel switch must be set to A0(f) for this purpose.
Frequency sweep from 0 Hz to 5 kHz

In the firmware there is a new start command 73 for a start of the


measurement at channel A0. After that the phase summand ph1 is increased
proportionally to the counter adn until the end of the measurement. In the
interest of a small calculation time, the conversion uses a shift of three bits,
i.e. a multiplication by a factor of 8. After 625 conversions, the product
5000 is reached, which actually leads to a frequency of 4766 Hz only. The
simplified conversion thus leads to a frequency error of 5%.

if (c==73){ //f-Sweep
ADMUX = 0x60;
duo = 0;
ds1 = 1;
ch = 0x60;
adn=0;
while (adn<629){
asm ("nop");
n = adn;
ph1 = n<<3;
}
ph1=0;
a1=0;
}
In the timer function of the user program the command 73 is now sent
instead of the start command 65. The actual display on the oscilloscope
does not differ from a simple single-channel oscillogram.

If trigger = 0 Then
If ch < 5 Then SENDBYTE 65
If ch = 5 Then SENDBYTE 73
If ch = 6 Or ch = 7 Then SENDBYTE 72
End If
...
If ch = 5 Then 'Frequency sweep
alast = 258 - READBYTE
For n = 0 To 625
Ain = 258 - READBYTE
Picture5.Line (n - 1, alast)-(n, Ain), vbBlack
alast = ain
Next n
End If
Sub-sampling of the sweep frequency

For a correct display of the sweep signal, only the fast settings with 1
ms/div and 2 ms/div are suitable. If the measurement is too slow,
undersampling will occur.

At 20 ms/div, the sampling rate is 62500 Hz / 20 = 3125 Hz. Exactly at this


frequency the display goes through an apparent zero crossing of the
frequency. The highest theoretically still representable frequency is half the
sampling rate with 1652.5 Hz. However, already far below this frequency
errors occur in the representation, because the signal course is drawn with
too few sample points.

7.6 Ramp function


The ramp function corresponds to a sawtooth shape with the difference that
there is only one slope, which is exactly matched to the duration of a
measurement independent of the sampling speed. The voltage increases
linearly from 0 V to 5 V. This allows components or circuits to be
examined.
The measurement is started with command 72, whereby the DDS signal
generation is switched off with ds1 = 0;. The ramp at the PWM output is
generated directly during the measurement.

if (c==72){
ADMUX = 0x60;
ds1 = 0;
adn = 0;
ph1 = 0;
while (adn<629){
asm ("nop");
n = adn;
OCR2A = (n<<6)/157;
}
ph1=0;
a1=0;
}
Ramp 0...5 V

The display of the ramp again corresponds to a normal single-channel


oscillogram. This allows the volatge curve on a component to be displayed.

If ch = 6 Then 'Frequency sweep


alast = 258 - READBYTE
For n = 0 To 625
Ain = 258 - READBYTE
Picture5.Line (n - 1, alast)-(n, Ain), vbBlack
alast = ain
Next n
End If

If ch = 7 Then 'Frequency sweep inverted


alast = 3 + READBYTE
For n = 0 To 625
Ain = 3 + READBYTE
Picture5.Line (n - 1, alast)-(n, Ain), vbBlack
alast = ain
Next n
End If

Additionally, there is the inverted ramp representation, where the ramp


itself remains unchanged, but the representation in the diagram is inverted.
This representation can be used if you do not want to show the voltage at a
component, but the voltage drop at a working resistor.

Ramp with inverted output

Here, for example, the collector current can be examined as a function of


the input voltage of an amplifier stage in emitter circuit. With a collector
resistance of 1 kΩ, the y-axis represents the collector current up to 5 mA. It
can be seen that at an input voltage below 0.6 V no measurable collector
current flows. Then follows an almost linear range. And from about 1.7 V
the collector current goes into saturation at about 4.9 mA. From the
measurement result, even the current amplification factor can be evaluated.
Very roughly: A change of the input voltage by 1 V changes the base
current of the transistor by 10 µA and the collector current by 5 mA. The
current amplification factor is therefore 5000 µA / 10 µA = 500.

Transfer characteristic of a transistor in common emitter circuit


A typical application of the normal ramp function is the examination of the
voltage at a diode or an LED. Here, a red LED was connected in parallel to
the low-pass capacitor. It can be seen that the current starts at about 1.7 V,
since the linear increase is left here. The voltage does not rise above 1.9 V
until the end, although the brightness increases visibly during the
measurement. The measurement shows that the LED can be used to
stabilize the voltage in a similar way to a Zener diode.

Voltage limitation with one LED


7.7 Measurement of characteristic curves

The characteristic curve of a component describes the current as a function


of its voltage. Unlike the previous measurements, this time the DDS and
oscilloscope function is not used, but the characteristic is determined via
direct control of the PWM output and direct measurements with high
resolution at A0 and A1.
The measurement is critical because the current is determined from the
difference between two voltage measurements. Rounding errors can occur
and become unpleasantly noticeable. To get a smooth curve, a resolution of
more than 10 bits is necessary. It is achieved here by an additional
averaging. Here two IIR filters are used, where each new measured value
has an effect of only 5%. Thus a resolution of about 12 bits and at the same
time a further low pass filtering of the PWM signal is achieved. Therefore,
with y=258-(u0-u1)/4 a useful voltage difference for current measurement can
be obtained. However, steep diode characteristics result in certain artifacts
which are due to the stepped input voltage.
If ch = 8 Then 'Characteristic
SENDBYTE 83
SENDBYTE 0
DELAY 50
ya = 258
xa = 0
s0 = 0
s1 = 0
For n = 0 To 1023
SENDBYTE 83
SENDBYTE n \ 4
SENDBYTE 75
SENDBYTE 0
u0 = READBYTE
u0 = 256 * u0
u0 = u0 + READBYTE
s0 = u0 + s0 * 0.95
u0 = s0 / 20
SENDBYTE 75
SENDBYTE 1
u1 = READBYTE
u1 = 256 * u1
u1 = u1 + READBYTE
s1 = u1 + s1 * 0.95
u1 = s1 / 20
y = 258 - (u0 - u1) / 4
x = u1 * 0.611
Picture5.Line (xa, ya)-(x, y), vbBlack
ya = y
xa = x
Next n
SENDBYTE 83
SENDBYTE 0
End If

Characteristic measurement with measuring object LED


Characteristic of a red LED

The silicon diode has a characteristic with a similar curve, which is,
however, shifted to lower voltages. A noticeable current flows here from
0.5 V. The same applies to the BE diode of a transistor. The characteristic
curve of a resistor, on the other hand, is straight.
Characteristic of the base-emitter diode of a transistor
Characteristic of a resistor with 10 kΩ

8 Application examples
The last chapter deals with typical measurements from the electronics
laboratory, their problems and also solutions to them. As with the previous
applications, the focus is on analog electronics. More complex circuits with
operational amplifiers are also examined here.

8.1 The emitter follower

An emitter follower is also called a common collector circuit because the


collector voltage is at a fixed potential. The emitter voltage follows the base
voltage at all times. The circuit has a large current gain, but no voltage
gain.
The test with a linear voltage ramp shows that the emitter voltage also
increases linearly, but is around 0.6 V to 0.7 V lower at any time. The lower
part of the ramp is cut off because the NPN transistor is still completely
blocked in this range.

The NPN transistor in collector circuit

The voltage curve at the emitter


8.2 Emitter follower as impedance converter

The DDS outputs with their low pass filters used to be very high
impedance, which meant no problem when connected to a high impedance
analog input. But if you connect a low impedance load, the signal voltage
will collapse. For such cases you need a buffer amplifier as impedance
converter. The usual way is to use an operational amplifier.

But also the emitter follower can be used as impedance converter. For this
purpose the signal voltage should be reduced to half, because the emitter
follower does not work at voltages close to 0 V. The measurement shows
that the output voltage is about 0.7 V below the input voltage at every
point.
Voltage curve at the base and at the emitter

The emitter follower works like a control loop. The collector and emitter
current depends strongly on the base-emitter voltage. When this increases,
the emitter current increases, which leads to a greater voltage drop across
the emitter resistor and thus reduces the base-emitter voltage. Thus, an
equilibrium is established in which each base voltage has a matching
emitter voltage. Because an increase of the base-emitter voltage by only 20
mV leads to a doubling of the emitter current, the voltage difference
between base and emitter remains almost constant.

8.3 Sallen Key filter

The first-order low-pass filters most commonly used to date have a


relatively smooth transition between the passband and the stopband. With a
second order filter a sharper transition can be achieved. A common circuit
is the Sallen-Key filter, which is usually built with an operational amplifier.
But also an emitter follower can be used.
The frequency response of the filter

You can see a relatively straight range of low frequencies up to about 1.6
kHz and a steeper drop in signal amplitude above that. If you remove the
left capacitor to the emitter terminal from the circuit, you have only a first
order filter with a cutoff frequency of 800 Hz. The transition to the
stopband is less steep, and at 5 kHz you have a higher signal amplitude.
Filter curve with only one capacitor

Because an emitter follower is used in the filter circuit, you also have a
buffered, low impedance output. Therefore you can put a dynamic
headphone in series to the emitter resistor to hear the filtered sweep signal.
Alternatively, a piezo speaker can be connected in parallel to the emitter
capacitor. Interesting are different sweep speeds and the associated sounds
between 20 ms/div and 1 ms/div.

8.4 Beat generator

If two signals with similar frequency are added, a beat with a modulation of
the amplitude occurs. The beat frequency is then the difference frequency of
the two added signals.
This experiment is about demodulating the sum signal to obtain the beat
frequency itself. The circuit is similar to an AM demodulator in radio
technology. Usually a diode is used for this purpose. Here a transistor in
common collector circuit is used, because the sum signal has a very high
impedance. At first sight the circuit looks like an emitter follower. But the
emitter resistor is very high impedance and forms with the parallel capacitor
a low pass filter with a cutoff frequency of 160 Hz. The circuit thus works
as a peak rectifier. The transistor conducts only in the short moments of the
voltage maxima at the input. After that, the emitter voltage drops only due
to the discharge of the filter capacitor.

Signal addition and peak rectifier


The sum signal at A0
The demodulated beat signal
Both signals in the two-channel measurement

In the two-channel measurement, it can be clearly seen that each voltage


peak at the base charges the output capacitor to a peak voltage that is about
0.7 V below the input voltage. The demodulated output signal has a
frequency of 200 Hz, exactly the difference of the input frequencies 5 kHz
and 4.8 kHz. You can still see remnants of the high frequencies, which
could be removed by further filtering.

8.5 Operational amplifier

An operational amplifier (OPA) contains many transistors in a complex


circuit with a differential amplifier at the input. The difference between
both input voltages is amplified about 100000 times. In real use, negative
feedback is almost always used to operate with a precisely defined gain.
Here the amplifier output is directly connected to the inverting input, which
leads to a full negative feedback. The OPA therefore works with voltage
gain 1 as a pure impedance converter. Again, this circuit can be thought of
as a fast control circuit. The output voltage is controlled in each case so that
the two input voltages are equal. In fact, with the LM358 used, there is
usually an offset voltage of up to 1 mV between the two inputs. And the fast
tracking succeeds only at not too high frequencies. In addition, control
oscillations in the HF range can occur with an unfavorable design.

OPA as impedance converter


The input is extremely high impedance and hardly loads the low-pass filter.
The output is low impedance and can be loaded up to approx. 10 mA.
Therefore, one expects the same voltage curve at the output as at the low-
pass filter. However, the measurement shows a weakness of the circuit. The
voltage does not reach the full output voltage of 5 V but remains about 1.5
V below it. Every OPA has a voltage range in which it can operate. The
LM358 works almost down to 0 V, but only up to 1.5 V below the supply
voltage. In many cases, one uses a double operating voltage up to +/-15 V.
Here it would be enough to raise the operating voltage for the OPA to +8 V.

The output signal of the OPA


8.6 Voltage doubling

An increased operating voltage for the OPA could be achieved with a


battery or a power supply. It would be enough to connect a 9V supply to
Vin and use it directly for the OPA. However, an external voltage is always
a possible source of error. You have to be very careful and never connect
directly to one of the controller terminals by mistake.
Power supply with a doubler circuit

The doubler circuit with two diodes and two capacitors requires an AC
voltage signal or a square wave signal, which in this case is available with
adjustable frequency (here 50 kHz) at port D6. To the operating voltage of 5
V the voltage of the square wave signal with 5 Vpp is added, minus the
double forward voltage of a diode. Here two Si diodes 1N4148 with an
expected forward voltage of 0.7 V were used. Thus, the output voltage
should be 10 V - 1.4 V = 8.6 V, which is sufficient for the OPA. The real
test showed a voltage of 4.5 V at A2. The operating voltage of the OPA is
therefore 9 V.

Mainly because of the internal resistance of port output D6, the doubler
circuit supplies only a limited current, which is sufficient for the OPA, but
is not a great danger in case of possible errors.

The complete output signal at 9 V operating voltage


In principle, one could also build a higher order low pass filter with the
OPA on this basis. However, attempts with a sallen key filter failed because
of unwanted RF oscillations. The circuit did not work stable enough,
possibly due to the construction on the breadboard.

8.7 Allpass filter

An all-pass filter changes only the phase as a function of frequency, but


maintains the amplitude over all frequencies. At the cutoff frequency, the
phase shift is exactly 90 °. At very low frequencies the phase shift
approaches zero, at very high frequencies it approaches 180 °. With the
proposed dimensioning, the cutoff frequency is 160 Hz. The RC element
with 100 kΩ and 10 nF is decisive.
The phase shift at the cutoff frequency can already be seen clearly in the
two-channel measurement. The phase shifts appear even more clearly in the
xy display of the oscilloscope.

The allpass filter


Phase shift at the cutoff frequency
Phase shift 90°

Near 0 ° at 10 Hz
Near 180 ° at 2 kHz

8.8 Bandpass filter

As is well known, a bandpass filter can be built with an LC resonant circuit.


Alternatively, an OPA with RC elements can be used. The presented circuit
has a resonant frequency close to 2 kHz. The function can be illustrated
clearly with the sweep generator up to 5 kHz. The sweep frequency was set
to 2 ms/div because a narrowband filter needs sufficient settling time. The
faster the frequency range is swept, the more the resonance curve blurs.
The bandpass filter
The frequency response of the filter
An alternative measurement uses a signal rectifier with a diode and an RC
element. The rectifier works like the one in chap. 8.4 but needs only a
simple diode because the OPA output has a low impedance.
Resonance measurement with a signal rectifier

The advantage of the measuring rectifier is that you can now pass through
the frequency as slowly as you like in order to give the filter sufficient time
to settle. In this case the setting 10 ms/div was chosen.
Appendix
List of components used

Arduino Nano
Breadboard SYB-46
USB cable
Piezo speaker
LM358 double OPA
LED red
Diodes: 3 x 1N4148
Transistor: BC547C
Resistors: 470 Ω, 1 kΩ, 3*10 kΩ, 27 kΩ, 2*100 kΩ, 220 kΩ, 470 kΩ
Capacitors: 3 x 10 nF, 2 x 100 nF
electrolytic capacitors: 10 µF, 100 µF
Fixed inductance 22 mH

The breadboard drawings in this book were created with Fritzing:


https://fritzing.org/

Software and more information about the book:


https://www.b-kainka.de/MeasurementLab.html

You might also like