If you’ve not built the hardware yet then see this previous article otherwise read on to do some preliminary tests on the circuit.
Testing your DAC
Hook up a voltmeter to GPIO pin 25 of the ESP32. This is the output of DAC1. The ESP32 has two DAC’s whose outputs come out on GPIO25 and GPIO26. Enter the code below and upload to your ESP32. If you’ve not set up your Arduino to talk to ESP32 modules then have a look at this article.
1 2 3 4 5 6 7 8 9 10 11 12 |
void setup() { } void loop() { for(int i=0;i<256;i+=32){ dacWrite(25,i); delay(1500); } dacWrite(25,i); } |
You should see voltages of approx (and remember this is the analogue world now so they are approx!)
0.20V
0.60V
1.00V
1.36V
1.72V
2.12V
2.52V
2.88V
3.20V
Earlier we said that the voltage should be 0V for a value of 0 and 3.3V for a value of 255. Well, that’s in an ideal “what you would expect” world. In fact we get values slightly off from these due to the circuitry. For 0 we are getting around 200mV and for 255 around 3.20V. With any DAC you should check the range you are getting for the values you put in. There may even be some variance between devices due to manufacturing tolerances.
Producing a Sine Wave
Let’s do something a little more interesting, let’s draw a nice smart sign wave on a oscilloscope. If you don’t have a scope you can still listen to the noise this sine wave makes.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
// Create a sine wave on an oscilloscope using a 8 bit DAC // (C) XTronical 2018 // Use in any way you wish! // // As we're using an 8 bit value for the DAC 0-255 (256 parts) that means for us // there are 256 'bits' to a complete circle not 360 (as in degrees) or even 2PI Radians // (There are 2*PI Radians in a circle and computers love to work in Radians!) // The computer works in radians for SIN, COSINE etc. so we must convert our 0 -255 value // to radians, the comments in the code show this. int SineValues[256]; // an array to store our values for sine void setup() { float ConversionFactor=(2*PI)/256; // convert my 0-255 bits in a circle to radians // there are 2 x PI radians in a circle hence the 2*PI // Then divide by 256 to get the value in radians // for one of my 0-255 bits. float RadAngle; // Angle in Radians // calculate sine values for(int MyAngle=0;MyAngle<256;MyAngle++) { RadAngle=MyAngle*ConversionFactor; // 8 bit angle converted to radians SineValues[MyAngle]=(sin(RadAngle)*127)+128; // get the sine of this angle and 'shift' up so // there are no negative values in the data // as the DAC does not understand them and would // convert to positive values. } } void loop() { for(int i=0;i<256;i++) dacWrite(25,SineValues[i]); } |
This should produce a nice sine wave on your scope or a simple tone on your speaker. Here’s the sine wave from my scope;
Looks super smooth doesn’t it? Well yes, it’s not bad but you’ve got to remember that this analogue signal was generated from a digital value in the range of 0-255 and that it moves up in discreet voltage “steps”. So our range as found out above was 0.2 to 3.2V. This is a range of 3V. To found out how much the voltage changes for each digital value (0-255) we divide this by 256, this gives 0.012V or around 120mV per step. If we zoom in on a part of the wave we can clearly see this stepping
A basic 1 edge saw-tooth
The code below will produce a simple 1 edged saw-tooth wave-form
1 2 3 4 5 6 7 8 9 |
void setup() { } void loop() { for(int i=0;i<256;i++) dacWrite(25,i); } |
Triangle Wave.
Another popular wave form for sound is the triangle, here’s the code for it.
1 2 3 4 5 6 7 8 9 10 11 |
void setup() { } void loop() { for(int i=0;i<256;i++) dacWrite(25,i); for(int i=254;i>0;i--) dacWrite(25,i); } |
and here’s the display from my scope, can you hear the differences that these different waves make?
Advanced Saw-tooth
To really show how we can manipulate the waveform have a look at this example which produces an almost mountain landscape for a wave-form
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
void setup() { } void loop() { for(int i=0;i<256;i+=2) dacWrite(25,i); for(int i=254;i>=0;i-=2) dacWrite(25,i); for(int i=1;i<75;i+=2) dacWrite(25,i); for(int i=74;i>0;i-=2) dacWrite(25,i); } |
Here’s the wave form produced.
That’s all for now, if you’ve not already done so pop over to the download for this library and install it ready for the next tutorials. In the next article in the DAC/sound series we look at capturing/storing and replaying some digital sound/speech!
Next Article : To be released