Some Arduino boards, like the MKR Vidor 4000, come with built-in digital-to-analog converters (also often simply abbreviated to DACs). With other popular development boards, for example, the Arduino UNO, you’ll have to live with a PWM pseudo-analog output. Or do you? This short article investigates the difference between true analog outputs and PWM pseudo-analog signals, and what you can do to get a true analog signal without having to own one of the more expensive Arduino boards.
Digital vs. Analog Signals
Let’s start with some basic terminology. Digital signals typically switch between two states. This type of signal can either be HIGH (on) or LOW (off). Often, a threshold function determines what counts as HIGH or LOW. In the case of TTL electronics, a voltage level below 0.7V can be considered low, and any value above 3.5V represents a HIGH state. Voltages between the threshold values are considered invalid, and the device’s behavior might be undefined in those cases. Note that these numbers serve as examples. You can find the exact values in the datasheet of a specific digital component:
In contrast to digital signals, ideal analog signals can take any value within a given voltage range. Therefore, you can not only output two states, but theoretically, you can represent an infinite number of values using a single output. Note that in reality, the electronic components are limited by various factors such as the resolution.
To my knowledge, every Arduino board comes with a built-in ADC (analog-to-digital converter) that allows the MCU to read analog signals and convert them to a digital value (often represented as a number). Note that microprocessors are digital machines. They can’t deal with analog signals unless you convert them to digital values. Let’s suppose you set your Arduino’s ADC to a resolution of 10 bits. This allows the ADC to convert the analog signal to one of 1024 values (2^10 = 1024). This number is not quite infinite, but good enough for most use-cases.
The Problem with Modulated Pseudo-Analog Signals
Now, we’ve established that most (if not all) Arduino boards can read analog signals and convert them to digital values without needing additional hardware. How about analog outputs? Most of you might be familiar with the following Arduino function:
This function compiles and runs on all official Arduino boards. It converts a number that represents an analog value, such as 127 in this example, and outputs the resulting analog voltage value on the given pin (A0 in this case). So what’s the problem, you might ask. Well, if we take a look at the official API documentation, you can read the following:
Writes an analog value (PWM wave) to a pin. Can be used to light a LED at varying brightnesses or drive a motor at various speeds. After a call to
analogWrite(), the pin will generate a steady rectangular wave of the specified duty cycle until the next call to
analogWrite()(…) on the same pin.
The text states that the software calculates how long it needs to pull the output pin high to reach a PWM duty cycle that represents the value you want to output. So, for example, assume that you set the resolution to 10 bits. This means that you can output 1024 values. So, if you instruct the Arduino to output 512 using the analogWrite function, you’d expect it to output a signal with a steady voltage of 2.5V (assuming you use a 5V Arduino). Since 512 is half of 1024, you’d expect the output to be 2.5V, which is half of 5V. However, in reality, the hardware will output a HIGH signal for half the time. In the other half, the board outputs 0V. On average, you could say that the output voltage will be 2.5V. However, that’s not true as we can clearly see with an oscilloscope:
As you can see, the output is clearly digital (either HIGH or LOW), and there are no values between the two extremes. However, some external components might expect a true analog signal and they won’t work correctly if you feed them the modulated pseudo-analog output created by the analogWrite()-function.
Anyway, note that the API documentation also states that:
In addition to PWM capabilities on the pins noted above, the MKR, Nano 33 IoT, and Zero boards have true analog output when using
Which we can also make visible using an oscilloscope:
A Quick and Dirty Solution
So, what can you do in a pinch? Well, the easiest option is to use an Arduino that’s capable of producing a true analog output. As mentioned, those are:
- The MKR range
- The Nano 33 IoT
- The Zero range
However, some Arduino-compatibles, such as the Seeedstudio XIAO, are also equipped with built-in DACs for outputting true analog signals.
More Elaborate Solutions
You can also build a custom digital-to-analog converter and connect your Arduino board to it. I’ll have a look at the simplest common DAC design (the R-2R resistor ladder) in the upcoming shorts #5 article. In addition to that, you can often also employ a readily-available DAC integrated circuit such as the MAX1043. I’ll also take a look at DAC ICs in an upcoming project where I’m going to design a simple DAC shield for the Arduino UNO.
Most original Arduino development boards are incapable of outputting true analog signals. Instead, the development board translates an analogRead-call to an appropriate digital PWM signal. However, some Arduinos and compatible clone development boards include a digital to analog converter (DAC), and these devices can output voltages between HIGH and LOW. You can always add an external DAC if your project requires true analog output.
Table of Contents
This article is part of the DAC mini-series:
A Brief Introduction to Analog Signals on the Arduino (You are here)
What is a Digital-To-Analog Converter (DAC) (TBA)
An Introduction to the R-2R Resistor Ladder (TBA)
A Short Overview of DAC Options for Hobby Projects (TBA)
How To Design a DAC Shield for the Arduino UNO (TBA)