Download PDF Parts List View on YouTube Download Code

Today we will use one of the lesser-known features of the ESP32, the Digital to Analog Converter or DAC.  We’ll see how it works, and then we will use it to create some Oscilloscope “Art” and an edible musical instrument!

Introduction

You are likely very familiar with the analog-to-digital converters, or ADCs, that are packaged in just about every microcontroller.  Commonly referred to as “analog inputs,” these converters allow you to input analog voltages and retrieve a digital representation of their level.

But the ESP32 has a couple of other analog pins, DAC, or Digital to Analog Converters. As the name implies, these pins will OUTPUT an analog voltage.

Today we will see how we can incorporate the ESP32 DAC into our projects.

Digital to Analog Converters

Converting a digital number into an analog signal is a pretty standard application; audio is an obvious application, as it is stored and transmitted in a digital format and is converted to an analog format during playback.

DACs also have applications in telecommunications and instrumentation. And a DAC can also be used as a “digital potentiometer”.

ESP32 DAC

There are two identical DACs in the ESP32, and unlike many other ESP32 features, these have their outputs hardwired to dedicated pins.  We will refer to them as “Channel 1” and Channel 2”.

On most ESP32 modules, you will find Channel 1 on GPIO pin 25, and Channel 2 on GPIO 26. But if you have an ESP32-S2 module, then Channel 1 is on GPIO 17, and Channel 2 is on GPIO 18.

The ESP32 DACs are 8-bit devices, which are unsuitable for high-end audio. They can be used for “telephone quality” audio, but you would be better off using I2S for ESP32 audio applications in most cases.

The output of each DAC ranges from zero volts to the reference voltage. 

By default, the ESP32 DAC uses the 3.3-volt ESP32 power supply as its reference voltage. It can also use the AREF (Analog Reference) input with an external voltage reference, assuming that your ESP32 board exposes this pin (many do not).

One known issue with the ESP32 DAC is that it does not go down to zero volts when the input is set to 0 or up to 3.3 volts when the input is 255. You should factor this in when using it to control something that requires zero or 3.3 volts.

ESP32 DAC Modes

The DAC can be operated in three different modes:

Direct Voltage Output

This is the simplest mode, in Direct Output mode, you simply write a value from 0 to 255 to the DAC channel, and the corresponding voltage will appear on the output. The voltage will remain there until the DAC is called again.

Cosine Wave Generator

The ESP32 DAC has a single Cosine Wave Generator, whose output can be sent to one or both DAC channels.  The user has control over the frequency, amplitude, and phase of the cosine wave.

Continuous Output by DMA

In this mode, the DAC is fed by the DMA (Direct Memory Access) buffer. It can handle the buffer data using three methods:

  • Normal or Synchronous Writing – The data in the DMA buffer is continually written to the DAC.
  • Cyclical Writing – The DMA buffer is loaded with data, and that data is looped in the DAC. This is an efficient method of generating complex waveforms.
  • Asynchronous Writing – The DMA data is sent to the DAC in response to an external callback.

DAC Experiments

Now it’s time to start working with the ESP32 DAC.

To be able to follow along, you will need some test equipment.  If you don’t own, or don’t have access to some of it, you can watch me perform the experiments in the video accompanying this article.

Test Equipment

You’ll need a way of measuring DC voltage, DC voltage from between zero and 3.3 volts.

I’m guessing that you likely have a multimeter, and any multimeter will work. Digital, analog, auto-ranging, or manual ranging, all will be fine!

An oscilloscope with at least two channels will be very handy when working with waveforms, as you’ll be able to see them.  Obviously, the scope will be required for the Oscilloscope Art experiment!

If you don’t have access to a scope, you can do the waveform experiments with an audio amplifier. Any small audio amp module will do, actually any amplifier will do, although I would be hesitant to feed it into your 500-watt sound system!

Otherwise, the only part required is an ESP32 module, and pretty well any ESP32 module with GPIO 25 and 26 will suffice.  I used an ESP32 Dev Kit module for my experiments.

Direct Voltage Output – Producing Voltages

For our first experiment, we will just write to the DAC and measure the output voltages. It’s very easy to do with the Arduino IDE.

Direct Voltage Output Hookup

Here is how we will hook up a multimeter (or voltmeter) to the ESP32 DAC:

Click on the wiring diagram to open a larger image

You’ll need to measure voltages between zero and 3.3 volts, so adjust your meter accordingly.

I will assume that your Arduino IDE is installed and configured with the ESP32 Boards Manager.  You can read my article about using the ESP32 if you are not yet set up.

Direct Voltage Output Basic Code

Here is some very simple code that will write a series of numbers to the DAC on Channel 1. The DAC output can then be measured.

It is a straightforward sketch, centering around the dacWrite function, which accepts two parameters:

  • The DAC Pin. In this case, we are using DAC Channel 1, so the value is 25.
  • The DAC Value. An integer between 0 and 255.

We simply write to the DAC with different values and delay for three seconds. We also write to the serial monitor at the same time.

Run the sketch and observe your multimeter. You will see the voltage change with each different DAC value.

You’ll probably notice two things:

  • The DAC doesn’t go to zero when the value is 0.
  • The DAC doesn’t go to 3.3 volts when the value is 255.

This is a known issue with the ESP32 DAC, here are the results I received when I ran the experiment, along with the desired results (based on a 3.3-volt power supply):

You should, however, notice that the values you get are pretty consistent. So if you need repeatable results, you can rely on the ESP32 DAC to give them to you.

Making Waves

One common use of a DAC is generating waveforms, which is a good use for the ESP32 DAC. While it won’t be capable of laboratory-quality waveforms, it can be handy for simple waves and for creating sounds.

Wave Hookup

The best way to do these experiments is to use an oscilloscope.  A scope will let you see the waveform, and most modern scopes will also measure its parameters.

You can also use an audio amplifier to listen to the resulting waveforms, which are all within audible range. If you do use an audio amplifier, make sure that it either has a volume control or that you have a speedy way of silencing it, as the tones we will be creating are not very pleasant to listen to!

The following hookup diagram illustrates using both a scope and amplifier; you’ll need at least one of them.

Click on the wiring diagram to open a larger image

Once again, we are only using DAC Channel 1. If you wish, you can repeat the experiments with the second channel.

Sine Wave Basic Code

Here is a very basic way of generating a sine wave using the ESP32 DAC:

This method uses the dacWrite function again, which isn’t really the best way to make a waveform as you are limited in frequency.  It is really just for demonstration purposes.

As you can see, all the action is in the loop, and one iteration of the loop is one cycle of the sine wave. We cycle through the sine wave steps and write them to the DAC.

This is really best seen on an oscilloscope, as shown here.:

As it is a very low frequency (I got about 86Hz), it will require a speaker with some bass response to hear it properly. The tiny breadboard speaker I used broke into convulsions trying to play it!

Sine Wave with Table Code

Another way of generating a low-frequency waveform is to use a table to hold the waveform values. These are waveform level values, and using this method, you can generate a pretty complex waveform.

Again, this sketch is more of a demonstration, but it could be adapted for practical purposes.  

Once again, we are generating a sine wave, whose levels are contained in a 112-element array.  This array is our “table”.

We cycle through the array and use our friend dacWrite to write the level to the DAC.

As with the last sketch, a scope is the best way to monitor the results. Try changing some of the array values and note the effect on the display. You can also try changing the number of elements in the array, which will also alter the output frequency.

You can actually create some pretty complex waveforms with this method. 

Cosine Generator

The ESP32 DAC has a single Cosine Waveform Generator. You can use this to generate a cosine wave (which is a lot like a sine wave in shape) over a wide range of frequencies and amplitudes.

Cosine Generator Library Code

When working with the Arduino IDE, it is much easier to use a library to use the cosine generator functions.  I will use the DacESP32 Library, and you can install this library using your Arduino IDE Library Manager.

Here is a sketch to generate a 1KHz tone at several different levels:

As you can see, the library really simplifies things. The outputCW method has just one parameter, the cosine wave frequency.  You can also see how we use setCwScale to set the amplitude.

Oscilloscope Art

I have to admit, “art” is a bit of a stretch here! 

What we are going to do is use both ESP32 DAC channels to draw an ellipse on our oscilloscope. You can expand upon this to make something more artistic.

Oscilloscope Settings

Obviously we will need a scope for this experiment, and this time we will need to use two channels.

In addition, we will need to have our scope set to “X-Y Mode”. In “X-Y Mode,” the X-axis of the display is modulated by one channel, and the Y-axis is modulated by a second channel. This is a feature that you should be able to find on any multichannel oscilloscope, both digital and analog.

The video accompanying this article shows you how I set my Rigol DS1054Z scope for X-Y Mode. 

Each channel will be measuring about 3.3 volts, so set the probe and channel sensitivity accordingly.

Oscilloscope Art Hookup

The hookup for our scope art project is pretty simple, you probably guessed it already! For those of you who didn’t guess, here it is:

Click on the wiring diagram to open a larger image

Note that although I show both scope probe grounds connected to an ESP32 ground, it is really only necessary to connect one.

Oscilloscope Art Code

I can’t in any way take credit for the code here; it comes from a very talented author who goes by the name of Bitluni. You can see more of his code on his GitHub repository, and YouTube Channel.

The code uses a couple of internal ESP32 libraries, these were installed with the ESP32 Boards Manager in your IDE, so no extra installation is required.

Basically, we generate the “art” by creating a sine wave in one channel and a cosine wave in the other one. We do this while changing the value of a float that represents the position in a circle.

It also sends a pulse at the end of each iteration, this is to sync the scope.

Once you get the circle (or ellipse) displaying on your scope, you can experiment by changing the sensitivity and horizontal time base for each channel, this will distort the waveform.

This “art” is just perfect for your next science fiction movie!

Musical Fruit

This is definitely one of the tastiest experiments we have ever worked on here in the DroneBot Workshop!

We will use one of the ESP32 DAC channels along with another ESP32 feature – its touch switch capability.

The ESP32 has 10 GPIO ports that can be used as touch switches. And while you can use them with any conductive surface, I have chosen to use fruit!

I’m pairing up (or should that be “pearing up”?) some oranges with a few rather tiny Granny Smith apples to create a fruity keyboard whose output will go to the ESP32 DAC.  

Musical Fruit Hookup

Here is how I hooked up a fruit basket to an ESP32! You’ll also need an amplifier module or an external audio amplifier.  I would hold off on using a guitar amplifier until after you have mastered the fruity instrument!

Click on the wiring diagram to open a larger image

There is a potentiometer shown in the diagram. I used a 100k linear-taper pot, but an audio taper would be a better choice (I didn’t have one), as what we have here is basically a volume control. If your amplifier already has a volume control, then you can just connect its input directly to GPIO pin 25 and eliminate the pot.

Of course, you aren’t obliged to use fruit, or any sort of produce as a touch switch. Anything conductive will work fine, and you can “fine-tune” each sensor in the code.

Musical Fruit Code

Here is the code I used to turn a bunch of apples and oranges into a musical instrument:

As you can see, the code is based upon the DacESP32 Library to provide a simple way of outputting tones.

Each touch switch has a threshold defined; by default, it is 200. You may need to experiment with this value, as it sets the sensitivity of your fruity sensor.

The frequencies are for the 5th (and part of the 6th) octave, but you can substitute other ones.

We print the value of the touch switch sensors to the serial monitor, this can be useful when adjusting the touch switch sensitivity.

In the loop, we check the status of each switch. If we see it as being touched, then we play the corresponding tone. If we don’t see any switch (i.e., fruit) being touched, then we turn off the DAC.

Hooke it up and get prepared to serenade the world. And when you get tired of it, you can eat your creation!

Conclusion

The DAC is one of those many features of the ESP32 that you don’t think of often, but that doesn’t mean it isn’t useful.

Consider using it to drive analog panel meters for a “retro project”, or to create cool tones for a toy or robot. Or to create an orchestra with a bowl of fruit!

 

Parts List

Here are some components that you might need to complete the experiments in this article. Please note that some of these links may be affiliate links, and the DroneBot Workshop may receive a commission on your purchases. This does not increase the cost to you and is a method of supporting this ad-free website.

ESP32 DEVKIT C – Digikey

 

Resources

Code Used – All of the code USD in this article, inside a nice ZIP file!

ESP32 DAC – Espressif documentation for the ESP32 DAC.

 

 

Using the ESP32 DAC (and making a Fruity Instrument)
Summary
ESP32 DAC - Analog Output & Musical Fruit
Article Name
ESP32 DAC - Analog Output & Musical Fruit
Description
Learn to use the Digital to Analog Converters or DACs in the ESP32. I'll show you how to program the DAC to produce output voltages and waveforms. We will;l also make oscilloscope art and some musical fruit!
Author
Publisher Name
DroneBot Workshop
Publisher Logo
Tagged on:
Subscribe
Notify of

6 Comments
Oldest
Newest
Inline Feedbacks
View all comments
Dave
1 year ago

Another well made and very interesting tutorial !
Thanks Bill

Joe S
1 year ago

Great tutorial. I don’t have an amplifier. Is there a way to send the signal to a blue tooth speaker?

Jerry S
11 months ago
Reply to  Joe S

Great tutorial, however I am getting a strange error when compiling caused by the DACESP32 routine:

libraries/DacESP32/src/DacESP32.cpp:298:11: error: variable ‘stepSize’ set but not used [-Werror=unused-but-set-variable]
 float  stepSize, stepSizeTemp;

I see that stepSize is defined and appears to be used in line 325:
    stepSize = stepSizeTemp;

I am using version 1.0.10.

Can you suggest a reason why this is happening?

10 months ago
Reply to  Jerry S

You have 3 possible solutions to prevent above build error:
1) don’t compile with build flag ‘Werror=unused-but-set-variable’ but instead use ‘-Wno-error=unused-but-set-variable’,
2) build with CORE_DEBUG_LEVEL set to >= 4 (DEBUG/VERBOSE) or
3) use latest version of DacESP32 lib. I just released V1.0.11 on Github.
Have fun & thx for using the lib.
Cheers Thomas

summer
6 months ago

Great! do you have a TFT display to show the waves? Thanks.

J H
2 months ago

Hi and thanks for the article. How would I go about playing several fruit tones simultaneously? Would need to combine the waves, right..?