Hey Everyone, we're back with another video about the ESP32 and audio output.
In previous videos, we've covered using the ESP32's I2S peripherals
along with the built-in Analogue to Digital Converters for reading audio data.
We've also looked at using the I2S peripherals for directly outputting digital audio signals.
In this video, we're going to take a look at using the built-in Digital to Analogue Converters.
We'll use these to output analogue signals directly from the ESP32.
So, there are a few things to note about the Digital to Analogue Converters on the ESP32.
There are two channels available DAC-1 and DAC-2.
Both these channels support 8-bit resolution so we can set them to a value between 0 and 255.
The range of the output voltage is from 0v volts to Vdd.
So, typically a range of 0 volts to 3.3 volts.
And one big difference from what you may be used to is that the GPIO pins are fixed.
Channel 1 will output on GPIO25 and channel 2 will output on GPIO26.
Basic output using Arduino code is pretty straightforward.
We just use the "dacWrite" function specifying pins 25 or 26
along with the value that you would like to send.
If you want to stick to the IDF functions this is also very straightforward.
You just need to enable the DAC channel and then call "dac_output_voltage".
DAC channel 1 will output on pin 25 and DAC channel 2 will output on pin 26.
Let's have a look at this in action.
I've hooked up my multimeter to one of my esp32 dev boards and I'm slowly stepping up the voltage
on the output of the DAC channel.
Here you can see a chart of the expected values versus the measured values.
There's a couple of things to note:
We don't get zero volts when the output is set to zero we get around four millivolts.
There is a reasonably linear range up to about 1.5 volts where the error is fairly small.
And then we increasingly get
differing values from what we expect as we approach the maximum output voltage.
If you're doing anything that requires any accuracy it's probably worth calibrating
your own device to see what values you get.
So, using direct output is pretty good if you just want to output a slowly changing value.
But what If you want to play audio or generate high-frequency signals.
For this, we can use the I2S peripheral to transfer data using DMA.
This will let us queue up samples to be
output letting the CPU get on with doing other processing.
We need to configure the I2S peripheral to use the built-in Digital to Analog Converters.
We need to tell it the sample rate we want to use and bits per sample.
This is slightly strange as only the top eight bits will be used by the DACs.
Initializing the I2S peripheral is the same as usual.
We install the driver - there is one important note here: we can only use I2S0 with the built-in DACs.
We also need to set the I2S peripheral into DAC mode and enable both the DAC channels.
Sending data to the I2S peripheral is straightforward
and follows the same pattern as we've used before.
We create a task and within our task wait for the peripheral to request more data.
We can then write more data to the peripheral for output.
Now the output from the DAC's won't be powerful enough to drive a speaker directly
so you'll need an amplifier.
I'm using a small breakout board with an audio amplifier but you can easily
build a simple amplifier from discrete components.
Let's have a listen to see how well this works.
🎵Music🎵
There's a bit of noise but that's probably to be expected when building up a circuit
on a breadboard - we're not dealing with high-end audio here.
What about outputting arbitrary signals and higher frequencies?
I've tried a few experiments outputting a simple sawtooth
waveform and this is the highest frequency I was able to achieve.
This works out at a sample rate of around 2 MHz so you can output at fairly high frequencies.
So, what have we learned?
We can use the built-in Digital to Analog Converters
to output analogue signals directly from the ESP32.
We can output audio data and we can output arbitrary signals at reasonably high frequencies.
The outputs are reasonably linear over a range of values
but we are limited to 8-bit resolution so high-end audio is probably not an option.
Apart from that, this is a pretty simple way to get analogue data out of the esp32.
So thanks for watching all the source code is on GitHub - the link is in the description.
If you found this video useful then please hit the subscribe button.
There are more videos in the pipeline and I'm working on an interesting project
which will hopefully use some of what we've learned in this video.
So thanks again and I'll see you in the next video!