This is only a preview of the August 2022 issue of Practical Electronics. You can view 0 of the 72 pages in the full issue. Articles in this series:
|
KickStart
b y M ike Tooley
Part 9: Exploring microcontroller digital-to-analogue conversion
in no more than a couple of hours using
‘off-the-shelf’ parts. As well as briefly
explaining the underlying principles
and technology used, the series will
provide you with a variety of solutions
and examples, along with just enough
information to be able to adapt and
extend them for your own use.
This ninth instalment explores ways
of adding (and improving) analogue
output capability from a wide range of
popular microcontrollers.
to-analogue converters (ADC and
DAC respectively) provide a
means of interfacing the digital world
of a microcontroller to the outside
analogue world. Unfortunately, while
most microcontrollers incorporate
reasonable ADC hardware, the same
cannot be said of their DAC counterparts.
We’ve put this into context in Tables
9.1 and 9.2, comparing the on-board
ADC/DAC capabilities of three of the
most popular microcontrollers.
that’s 25% of its maximum, while in
Fig.9.2(c) a pulse wave with 75% duty
cycle will exhibit a long-term average
value which is 75% of its maximum.
This leads us to the notion that we can
produce a continuous range of analogue
voltages by simply varying the duty cycle
of a train of rectangular pulses.
PWM is a useful technique for noncritical applications, and it can be easily
implemented on devices that don’t
have a built-in DAC capability. All that
is required is a handful of additional
components that will average the output,
as shown in Fig.9.3.
In Fig.9.3, R1 and C1 form a simple RC
low-pass filter, while IC1 acts as a unitygain buffer (exhibiting a very high input
impedance and capable of tolerating a
relatively low resistance at the output).
The PWM pulse train at the GP16 output of
the Raspberry Pi Pico has an amplitude of
3.3V, hence the output at pin-6 of IC1 can
be made to vary over the range 0 to +3.3V.
The analogue output voltage from
Fig.9.3 can be easily set using just a few
Enter PWM
Table 9.1 Comparison of microcontroller ADC capability
Our occasional KickStart series aims to
show readers how to use readily available
low-cost components and devices to
solve a wide range of common problems
in the shortest possible time. Each of the
examples and projects can be completed
A
nalogue-to-digital and digital-
As noted in Table 9.2, most low-cost
microcontrollers don’t incorporate true
DAC; instead, they use pulse-width
modulation (PWM), where the average
value of a train of rectangular pulses is
used to represent an analogue voltage.
This process is illustrated in Fig.9.2.
Fig.9.2(a) shows a perfect square wave
(ie, a rectangular wave with a 50%
duty cycle). The average value of this
waveform will be exactly 50% of its
maximum (peak) value. In Fig.9.2(b) a
repetitive pulse having a duty cycle of
25% will have a long-term average value
Microcontroller
ADC capability
Notes
Arduino Nano
Six 10-bit ADC channels. Input
voltages can range from 0 to 5V.
The ADC channels are labelled A0
to A5 on the board.
ESP32 NodeMCU
(Fig.9.1)
Up to 18 12-bit ADC channels. The
measurement range is limited by
the 1.1V internal voltage reference.
Larger inputs can be measured
by applying one of four input
attenuation options.
The ADC resolution is configurable
(typical values are 9, 10, 11 and
12-bits). Some boards have a
restricted number of ADC pins
accessible. ADC2 cannot be used
concurrently with Wi-Fi.
Raspberry Pi
Pico
Four 12-bit ADC channels. Input
voltages can range 0 to 3.3V.
One ADC channel is dedicated to
the internal temperature sensor. The
three remaining ADCs are available
at GPIO26, GPIO27, and GPIO28.
Table 9.2 Comparison of microcontroller DAC capability
Fig.9.1. Unlike the Raspberry Pi Pico and
Arduino Uno microcontrollers, this ESP32
NodeMCU development board offers
a true DAC capability. Unfortunately, its
two on-board DACs only provide 8-bit
resolution (so only 256 unique output
voltage levels are possible).
Practical Electronics | August | 2022
Microcontroller
DAC capability
Notes
Arduino Nano
No true DAC hardware present, but
pulse-width modulation (PWM) can
be used. Maximum PWM output is
5V with 8-bit resolution.
Digital I/O pins 3,5,6,9,10 and
11 support PWM (these pins are
marked with a ‘~’ symbol on the
board).
ESP32 NodeMCU
(Fig.9.1)
Two on-board 8-bit DACs with an
output range from 0 to 3.3V.
GPIO pins 25 and 26 are available
for DAC.
Raspberry Pi
Pico
No true DAC hardware present, but
PWM can be used. Maximum PWM
output is 3.3V with 16-bit resolution.
16 PWM output channels available
simultaneously; each GPIO pin can
be configured as a PWM output
(see text).
47
Arduino analogue output
lines of Python code. For example, the following code will
produce an analogue output voltage of 1V:
On an Arduino Uno, pins 3, 5, 6, 9,
10 and 11 are available for PWM and
from machine import Pin, PWM # import from the library module
the somewhat misleadingly named
out_pin = PWM(Pin(16))
# use GP16 for PWM
analogWrite() function used to
out_pin.freq(100000)
# set the PWM frequency to 100kHz
generate an analogue output voltage.
out_pin.duty_u16(19859)
# set the duty cycle for 1V output
At this point it is worth noting that
analogWrite() does not actually
write a value to a DAC register. Instead,
It’s possible to condense the last three lines of code into a
it performs in the same way as the
single instruction, as follows:
Raspberry Pi’s out_pin.duty_u16()
out_pin = PWM(Pin(16), freq=100000, duty=19859) # GP16, 100kHz, 1V
function, which just sets the duty cycle
that will be used for PWM waveform
generation. It is also worth being aware that the Uno’s low
Note that the duty cycle is represented by an integer (n) in
pulse-repetition frequency (PRF) is approximately 490Hz
the range 0 to 65535, where a value of 65535 represents a
on pins 3, 9, 10 and 11, increasing to around 980Hz on
maximum possible duty cycle of 100%.
pins 5 and 6.
The following formula can be used to determine the required
The range of values that can be used in the analogWrite()
value for use with the out_pin.duty_u16(n) function:
function is constrained by the use of 8-bit data and
consequently they range from 0 to 255. Thus, a maximum
n = Vout × 19859
analogue output corresponding to a 100% duty cycle will
result from analogWrite(255). Half full-scale output voltage
The 3.3V maximum output voltage from the circuit in Fig.9.3
will be produced by a square wave (50% duty cycle) using
can sometimes be a limitation, but this problem can be easily
analogWrite(128). With a 5V logic supply, the maximum
overcome by incorporating some gain in the buffer stage, as
and half-scale output voltages will amount to 5V and 2.5V
shown in Fig.9.4. This circuit can produce output voltages of
respectively, with the output voltage adjustable from 0V to
up to about 6V.
5V in 256 steps, each of around 20mV.
In the circuit of Fig.9.4 (which has a gain of 2) the duty cycle
As an example, let’s assume that you need to produce an
required for a given output voltage can be calculated from:
analogue output voltage of 4.5V. As with the previous example,
you will first need to determine the required value for use
n = Vout × 9930 or n ≈ Vout × 10000
with the analogWrite(n) function. This can be calculated
from the relationship:
The approximate relationship can help make life easy. For
example, an output of 2.5V will result from a value of 25000,
n = Vout × 51
an output of 5V from a value of 50000, and so on.
As a further example, the following line of code will produce
an analogue output voltage of 4.5V:
So, for 4.5V output you will need: analogWrite(230)
out_pin = PWM(Pin(16), freq=100000, duty=45000) # GP16, 100kHz, 4.5V
Fig.9.3. Obtaining an analogue output voltage from a Raspberry
Pi Pico.
Fig.9.2. Generating an analogue voltage using PWM techniques.
48
Fig.9.4. Increasing the output voltage range of Fig.9.3.
Practical Electronics | August | 2022
PWM can be a cost-effective solution for many simple DAC
applications, but the technique has quite a few limitations,
including relatively low bit resolution, slow settling time, poor
power efficiency, reduced accuracy (when supply rail voltages
are used as voltage references), unwanted noise generation,
and the need for averaging and filtering circuitry. As a result,
it often makes better sense to add a dedicated DAC module
to a host microcontroller using either the I2C or SPI bus (the
latter is more suitable for high-speed applications).
Before going further, it is worth explaining some of the
terminology associated with DACs, including the important
relationship between resolution and number of bits used in
the conversion process.
DAC resolution
The resolution of a DAC can be quoted in terms of the smallest
increment of output that the DAC can produce. This small
change in output voltage is that which results from a change
in the least-significant bit (LSB) of the data that’s written to
the DAC. An alternative way of expressing DAC resolution
is the number of bits used in the conversion process. As this
Part 9: Exploring
increases,
the stepmicrocontroller
size in outputdigital-to-analogue
voltage becomesconversion
smaller. The
Part 9: Exploring
microcontroller
digital-to-analogue conversion
relationship
is given
by:
Vstep =
Vref
n
V2
Vstep = refn
Where V2ref is the DAC reference voltage (often 3.3V or 5V) and
n is the number of bits. To put this into context, an 8-bit DAC
with a 5V
will have a step increment of:
5 reference
5
Vstep = 8 =
= 0.01953V or 19.53mV
25 256
5
Vstep = 8 =
= 0.01953V or 19.53mV
2
256
As the number of bits increases the number of steps will increase
and the step size decrease, as shown as shown in Table 9.3.
Table 9.3 DAC resolution
Number Number of
of bits
discrete steps
8
28 = 256
10
210 = 1024
12
212 = 4096
14
214 = 16384
16
216 = 65536
Values
range
0 to 255
0 to 1023
0 to 4095
0 to 16383
0 to 65535
Approx resolution
with 5V reference
20mV
5mV
1.2mV
0.3mV
0.08mV
DAC linearity
Linearity is the maximum allowable deviation from the straight
line drawn between 0V and the DAC’s full-scale output.
Linearity can be expressed as a percentage or in terms of a
fraction of the LSB. Note that the linearity of a DAC may be
significantly reduced for very low (near zero) or very high
(near full-scale) values.
DAC settling time
The output of a DAC cannot respond instantaneously to a
change in its digital input. The delay in response is specified
in terms of the time taken for the analogue output to reach its
new value within specified limits. As you might expect, the
worst-case settling time usually corresponds to the time taken
to reach full-scale from zero.
DAC operation
A simple form of DAC is shown in Fig.9.5(a). This uses a
set of binary-weighted resistors to define the voltage gain of
an operational summing amplifier (IC2). A four-bit binary
latch (IC1) is used to store the binary input while it is being
converted. Note that, since the amplifier is used in inverting
mode, the analogue output voltage will be negative rather
than positive, so a second inverting amplifier (IC3) is often
1
connected at the output.
Practical Electronics | August | 2022
1
Fig.9.5. DAC ladder networks.
The voltage gains for the four inputs to IC2 are 1, 0.5,
0.25 and 0.125 for bit-3 (MSB), bit-2, bit-1 and bit-0 (LSB),
respectively. If we assume that the logic levels produced by
the four-bit data latch are ‘ideal’ (such that logic 1 corresponds
to +5V and logic 0 corresponds to 0V) we can determine the
output voltage corresponding to the eight possible input states
by simply summing the voltages that will result from each of
the four inputs taken independently. For example, when the
output of the latch takes the binary value 1010 the output
voltage can be calculated from:
Vout = (1 × 5) + (0.5 × 0) + (0.25 × 5) + (0.125 × 0) = 6.25V
Similarly, when the output of the latch takes the binary
value 1111 (the maximum possible) the output voltage can
be determined from:
Vout = (1 × 5) + (0.5 × 5) + (0.25 × 5) + (0.125 × 5) = 9.375V
In this simple 4-bit DAC there are only 16 output voltage steps,
ranging from 0V to 9.375V in steps of 0.625V.
An improved binary-weighted DAC is shown in Fig.9.5(b). This
circuit operates on a similar principle to that shown in Fig.9.5(a)
but uses four analogue switches (IC1) instead of a four-bit data
latch. The analogue switches are controlled by the logic inputs
so that the respective output is connected to the reference voltage
(Vref) when the respective logic input is at logic 1, and to 0V when
the corresponding logic input is at logic 0. When compared with
the previous arrangement, this circuit offers the advantage that
the reference voltage is considerably more accurate and stable
than using the logic level to define the analogue output voltage.
49
Fig.9.8. Connecting an external DAC to a microcontroller.
values are required and that they can be
any convenient value provided that one
value is double the other (it is relatively
easy to manufacture matched resistances
of close tolerance and high stability on
an integrated circuit chip).
Fig.9.6 shows how a varying analogue
output voltage can be produced by
the DAC arrangements in Fig.9.5. The
presence of discrete voltage steps
in Fig.9.6(b) (rather than a smooth
waveform) is undesirable for many
applications, but this can be resolved
by passing the output signal through an
appropriately designed low-pass filter,
as shown in Fig.9.7.
Fig.9.8 shows how an external DAC
can be connected to a microcontroller.
The bus interface can be based on the
I2C bus or on the faster SPI bus – most
microcontrollers support both.
Fig.9.6. DAC input and output waveforms.
A practical add-on DAC
Fortunately, it is easy to add true DAC
capability to any popular microcontroller
board (including the Arduino or Raspberry
Pi Pico boards that we met earlier). This
is made even easier by using a low-cost
DAC module based on an IC like the
MCP4725 from Microchip (see Fig.9.9).
This high-accuracy, single-channel, 12bit buffered output DAC incorporates a
non-volatile memory that will allow you
to ‘set and forget’ the data sent to it. The
chip’s on-board precision output amplifier
allows it to achieve a full-range (rail-torail) analogue output voltage swing. The
Fig.9.9. A low-cost DAC module based
on the MCP4725.
chip incorporates an I2C-compatible serial
interface which can operate in standard
(100kHz), fast (400kHz), or high-speed
(3.4MHz) modes.
The simplified internal architecture
of the MCP4725 is shown in Fig.9.10.
The chip’s internal non-volatile memory
retains the digital input value during
power-off time, and the previously
set DAC output will become available
immediately after power-up. The network
address selection pin (A0) can be taken
high or low to facilitate address selection.
Fig.9.11 shows the circuit schematic of
a simple buffered MCP4725 that can be
used with an Arduino microcontroller.
The output voltage of the 12-bit DAC
can be set over the range 0 to +5V with
Fig.9.7. Using a low-pass filter with a DAC.
Unfortunately, because of the range of
resistance values required, the binaryweighted DAC becomes increasingly
impractical for higher-resolution
applications in intefrated circuits. Taking
a 10-bit circuit as an example, and assuming
that the basic value of R is 1k , the binary
weighted values would range from 1k
(bit-0) to 256k (bit-9). To ensure high
accuracy, these resistors will need to be
close-tolerance types (±1%, or better).
A more practical arrangement uses a
summing amplifier in which the input
voltage to the operational amplifier is
derived from an R-2R ladder, as shown in
Fig.9.5(c). Note that only two resistance
50
Fig.9.10. Simplified internal architecture of an MCP4725 DAC.
Practical Electronics | August | 2022
that the currently generated voltage is echoed back to the host
computer using the serial monitor facility.
Listing 9.1 Code for the positive staircase function
// Positive staircase function generator
// 0 to 5V in 1V steps using the MCP4725
// Rob Tillaart's MCP4725 library is available from
// https://github.com/RobTillaart/MSP4725
Fig.9.11. A simple buffered MCP4725 DAC with positive output.
4096 steps of 1.22mV. It is worth noting that the chip uses the
positive supply voltage (VDD) as its voltage reference. This is
expedient but it means the supply rail should be accurate,
stable and noise and hum free. For this reason, it is important
to ensure that the 5V supply is well regulated and has suitably
rated capacitors to reduce supply noise and ripple.
Coding the MCP4725
Pre-made library modules make DAC coding very
straightforward, but before entering and testing your code you
will need to locate and install the required library module (see
Fig.9.12). To check the DAC’s accuracy and linearity, the circuit
in Fig.9.11 was tested by sending a series of data values (from 0
to 4095) to the chip and measuring the output voltage with an
accurate bench voltmeter. The results are shown in Table 9.4.
Table 9.4 Measured output voltages for Fig.9.10
Binary code
Hex
Denary
Output
(base 2)
(base 16) (base 10) voltage (V)
000000000000
000
0
0
000000000001
001
1
0.00122
000000000010
002
2
0.00244
000000000011
003
3
0.00366
000000000100
004
4
0.00488
….
….
….
….
001100110010
332
818
0.99854
001100110011
333
819
1.00000
001100110100
334
820
1.00098
….
….
….
….
111111111101
FFD
4093
4.99634
111111111110
FFE
4094
4.99756
111111111111
FFF
4095
4.99878
#include "Wire.h"
// Libraries required
#include "MCP4725.h"
MCP4725 MCP(0x60);
// Can be 0x62 or 0x63
void setup()
{
Serial.begin(115200);
Serial.println("0 to 5V in 1V steps:");
MCP.begin();
MCP.powerOnWakeUp();
MCP.setValue(0);
}
void loop()
{
for (uint16_t i = 0; i < 6; i++)
{
// Rising steps
Serial.print(i);
Serial.println(" V");
MCP.setValue(i * 819);
delay(4000); // 4s delay between steps
}
}
Listing 9.1 is a complete sketch showing the code required
to generate a simple staircase waveform based on the circuit
in Fig.9.11. The code generates six voltage steps, from 0V to
5V, over a period of 24 seconds, as depicted in Fig.9.13. Note
Fig.9.13. Positive staircase waveform
produced by Fig.9.11 and Listing 9.1.
Producing a negative
output voltage
Fig.9.12. Using the Arduino’s Library Manager to locate and install the MCP4725 library.
Practical Electronics | August | 2022
If a negative output voltage is required,
the circuit can be easily modified, as
shown in Fig.9.14. The required code
is shown in Listing 9.2 and the code
generates six voltage steps, from 0V
to –5V, over a period of 24 seconds, as
shown in Fig.9.15. As with the previous
listing, the currently generated voltage
is echoed back to the host computer
using the serial monitor facility.
51
Listing 9.2 Code for the negative staircase function
// Negative staircase function generator
// 0 to -5V in -1V steps using the MCP4725
// Rob Tillaart's MCP4725 library is available
// from https://github.com/RobTillaart/MSP4725
#include "Wire.h"
// Libraries required
#include "MCP4725.h"
MCP4725 MCP(0x60);
// Can be 0x62 or 0x63
void setup()
{
Serial.begin(115200);
Serial.println("0 to -5V in 1V steps:");
MCP.begin();
MCP.powerOnWakeUp();
MCP.setValue(0);
}
void loop()
{
for (uint16_t i = 0; i < 6; i++)
{
// Falling steps
Serial.print(i);
Serial.println(" V");
MCP.setValue(4095 – (i * 819));
delay(4000); // 4s delay between steps
}
}
Fig.9.14. Buffered MCP4725 DAC with negative output.
Fig.9.16. Dual output DAC (positive and negative outputs are
simultaneously available).
Fig.9.17. Current-boosted DAC with positive output.
Fig.9.15. Negative staircase waveform produced
by Fig.9.14 and Listing 9.2.
Dual output arrangement
Fig.9.18. Current-boosted DAC with negative output.
If both positive and negative voltages are required, the
dual output circuit shown in Fig.9.16 can be employed.
Here, IC1 operates as a unity-gain inverter (note that the
positive output remains unbuffered in this arrangement).
Boosting the output current
In the simple buffered arrangements shown in Fig.9.11
and 9.14, the output current supplied to a load should
be limited to 20mA. Where necessary, the current
drive capability can be increased by adding an emitterfollower stage (TR1), as shown in Fig.9.17 and Fig.9.18
for positive and negative outputs respectively. Both
circuits can deliver load currents of up to about 0.25A,
but a small heatsink may be required for load currents
of more than 100mA.
52
Fig.9.19. Basis of the author’s digitally controlled low-voltage 0.25A
DC power supply.
Practical Electronics | August | 2022
Table 9.5. Going Further with Exploring microcontroller digital-to-analogue conversion
Topic
Source
Notes
Introduction to PWM: https://bit.ly/pe-aug22-pwm
PWM
MCP4725 DAC
This Texas Instruments application report – https://bit.ly/pe-aug22-ti
– describes a method for using PWM as a DAC for its series
of digital signal controllers; includes a detailed explanation of
analogue filter design.
The website provides links to a number of practical
projects that use PWM techniques.
The MCP4725’s datasheet can be downloaded from Microchip’s
website by going to: https://bit.ly/pe-aug22-mcp
Useful guide to the MCP4725: https://bit.ly/pe-aug22-best
Electronics Teach-In 8 from PE / Electron Publishing: http://bit.ly/
pe-apr21-ks2-7
Arduino
Arduino IDE
Raspberry Pi
Pico
Comprehensive guide to the Arduino – this popular series
introduces hardware and software and also features a range of
practical projects with different levels of complexity.
The Arduino’s integrated development environment (IDE) can be
downloaded from: https://bit.ly/pe-dec21-ard2
Versions available for Windows, Linux and macOS
The official Raspberry Pi Pico guide is Get Started with Micropython
on Raspberry Pi Pico by Gareth Halfacre and Ben Everard (ISBN
978-1-912-04786-4). Provides an introduction to the Pico and
using Thonny, describes simple beginner projects.
Programming the Pico – Learn Coding and Electronics with
the Raspberry Pi Pico (ISBN 979-8-464-88217-1) an excellent
introductory book from respected author Simon Monk.
These two books are intended for complete beginners
and they both assume little previous knowledge of
electronics and coding.
Your best bet since MAPLIN
Chock-a-Block with Stock
Fig.9.20. Semiconductor pin connections.
Visit: www.cricklewoodelectronics.com
Or phone our friendly knowledgeable staff on 020 8452 0161
Increasing the output voltage
If more than 5V is required from the DAC, the output voltage
can be increased by incorporating gain in the buffer stage, as
shown in Fig.9.19. This circuit forms the basis of the author’s
digitally controlled low-voltage power supply. Note the use
of +12V and –12V supply rails (the positive rail should be
rated at about 1A while the negative rail is less demanding
at 100mA, or so). Pin connections for the semiconductors
are shown in Fig.9.20.
Components • Audio • Video • Connectors • Cables
Arduino • Test Equipment etc, etc
Going further
Table 9.5 in this section details a variety of sources (books and
online links) that will help you locate the component parts
and further information that will enable you to understand
the use of PWM, as well conventional DAC devices. It also
provides links to underpinning knowledge and manufacturers’
data sheets.
Visit our Shop, Call or Buy online at:
www.cricklewoodelectronics.com
020 8452 0161
Practical Electronics | August | 2022
Visit our shop at:
40-42 Cricklewood Broadway
London NW2 3ET
53
|