ESP32 and Mozzi

I’ve been meaning to do something with the ESP32 for some time. I have some general ESP32-C3 devices, and a range of XIAO ESP32 (S2 and C3) devices too, but what I was particularly interested in was the original ESP32 as it includes two 8-bit DACs.

This is my first set of experiments using a cheap ESP32-WROOM-32D devkit available from various online sites.

Warning! I strongly recommend using old or second hand equipment for your experiments.  I am not responsible for any damage to expensive instruments!

If you are new to microcontrollers, see the Getting Started pages.

ESP32 WROOM DevKit

The ESP32 is a whole range of powerful 32-bit microcontrollers that include Wi-Fi and Bluetooth. They can be programmed via the Arduino IDE using an ESP32 core from Espressif.

I was particularly after the original ESP32, so not one qualified with a S2, S3, C3, or similar reference. This is based on the dual-core Xtensa 32-bit LX6, running between 80 and 240 MHz. As well as Wi-Fi and Bluetooth there is a full range of embedded peripherals, including two 8-bit DAC outputs alongside a number of ADC inputs, and built-in 4Mb SPI flash.

Note: these are not recommended for new designs now, as updated and more powerful devices are available, but they are still readily available in a range of formats.

It should also be noted that 8-bit isn’t particularly great for a DAC for audio. For a more useful audio quality resolution really an I2S peripheral and higher resolution DAC would be much better, but for my messing around, having no additional components is worth it for me.

Here are the basic references required to get going:

To install via the Arduino board manager, add in the board URL as described in the installation guide, then when searching for ESP32 the Espressif core should be listed.

There are a range of devkits around and not all the pinouts are the same. There is an official Espressif DevKit (V4 at the time of writing), but I ended up with one including a ESP32-WROOM-32D module which the listing suggests has the following pinout:

Warning: I’m not convinced of the accuracy of that pinout! For one thing, there are two sets of pins apparently linked to ADC 1.4 and 1.5. From other pinout diagrams I’ve seen, and going back to the datasheet for the ESP32, the labels for ADC 1.4 to 1.9 on the bottom left should read ADC 2.4 to 2.9.

I’m now wondering if the one here is more accurate: https://mischianti.org/doit-esp32-dev-kit-v1-high-resolution-pinout-and-specs/. Basically, the GPIO numbers should be checked off against the datasheet when it comes to additional functions. The DAC does appear to be on GPIO 25 and 26 though.

As a test, once the ESP32 core is installed, select the ESP32-WROOM-DA module from the Arduino board menu, open the blink application and add the following line at the top of the file:

#define LED_BUILTIN 2

This is because my DevKit has an LED on D2 (there are two surface mount LEDs labelled PWR and D2 as per the diagram above) but LED_BUILTIN is generally undefined by default.

The code should build, download, and run and result in the on-board LED flashing as expected.

Parts list

  • ESP32-WROOM-32D DevKit
  • 1x 10uF electrolytic or non-polar capacitor
  • 2x 1KΩ resistors
  • 1x TRS breakout
  • Breadboard and jumper wires
  • Optional: Several 10KΩ potentiometers

The Circuit

These modules are pretty wide, so only just fit onto a solderless breadboard and then only with one row of holes down one side exposed, so they aren’t particularly practical on that front! But that is enough for some simple tests.

The DAC outputs can be found on GPIO25 and 26. Mozzi treats them both the same when in mono mode. The output of the DAC will be just over 0V to just under 3.3V. Using a coupling capacitor to remove the DC bias could get this to be approx +/- 1.6V. That is a little high for a line level signal so I use a 1K/1K potential divider to half that to around +/- 800mV.

I believe the current limit for GPIO pins on the ESP32 is 40mA, but a line input should be fairly high impedance anyway so that shouldn’t be an issue as I understand things.

Pretty much every audio circuit I’ve seen hanging off the DAC pins, pipes them into a small audio amplifier, but with the above circuit, I feel relatively happy plugging it into my sacrificial line-level mini amplifier.

As an additional test, potentiometers can be connected up to 3V3 and GND and with the wiper easily connected to any of the following pins: GPIO 13, 12, 14, 27. Connecting to 3V3 is a bit more of a challenge, but I used a jumper wire from beneath the ESP32 to connect round to the breadboard’s power rails.

Note: they must NOT be connected to VIN which is sitting at the USB 5V level.

The following diagram shows one potentiometer connected to GPIO 13, with extension wires for other pots on 12, 14 and 27.

The Code

Once the blink test is successful, then a simple Mozzi test can be performed. By default, Mozzi will output to the DAC with a mono feed going to both pins, so the starting point would be to try the following:

  • Examples/Mozzi/01.Basics/Sinewave
  • Examples/Mozzi/06.Synthesis/FMSynth

Note that there are a whole lot of additional Arduino examples to explore the capabilities of the ESP32 before getting to Mozzi if required. These are found under the “Examples for ESP32” sub-menu once the core is installed, as detailed here: https://github.com/espressif/arduino-esp32/tree/master/libraries

To run a potentiometer test requires the use of analogRead with the GPIO pin number. So if the easily accessible GPIOs are used as described previously, then the following code could test that.

#define NUM_POTS 4
int potpins[NUM_POTS] = {
13, 12, 14, 27 // ADC 2.4, 2.5, 2.6, 2.7
};

void setup() {
Serial.begin(9600);
}

void loop() {
for (int i=0; i<NUM_POTS; i++) {
int aval = analogRead(potpins[i]);

Serial.print(aval);
Serial.print("\t");
}
Serial.print("\n");
delay(100);
}

The analog to digital converters are 12-bit compared to the Arduino Uno’s 10-bit. This means that the values range from 0..4095 rather than 0..1023.

Assuming everything is successful so far then it should be possible to use the code from Arduino Multi-pot Mozzi FM Synthesis – Revisited and related projects, but the scaling of the potentiometer will have to reflect the additional range of values.

One example configuration could be:

//#define WAVT_PIN 1  // Wavetable
#define INTS_PIN 13 // FM intensity
#define RATE_PIN 12 // Modulation Rate
#define MODR_PIN 14 // Modulation Ratio
//#define AD_A_PIN 5 // ADSR Attack
//#define AD_D_PIN 8 // ADSR Delay
#define FREQ_PIN 27 // Optional Frequency Control

As mentioned, all the calls to analogRead will need to be shifted down by an extra 2, but as in later versions of the code I’ve used a myAnalogRead function, I can do this all in one place with the following implementation for the ESP32:

int myAnalogRead (int pot) {
#ifdef POT_REVERSE
return 1023 - (mozziAnalogRead(pot)>>2);
#else
return mozziAnalogRead(pot)>>2;
#endif
}

One final update once again is to define the MIDI LED to use D2 rather than LED_BUILTIN.

Adding MIDI

To add serial MIDI (USB MIDI is not supported on the original ESP32) requires a 3V3 compatible MIDI module (see here, here or here for some options).

Once again I’ve made connections beneath the ESP32 board for GND, RXD and TXD.

I’ve used GPIO 3 and 1 which are RXD0 and TXD0 respectively. These are shared with the USB interface, so links here must be removed when reprogramming the ESP32 (just like with an Arduino Uno or Nano). There is a second hardware UART on GPIO 16 and 17 (RXD, TXD) which could be used instead (or in addition to) if required.

I’ve also highlighted above where additional potentiometers could be added – a further six on GPIO 33, 32, 35, 34, 39 and 36. Consequently an alternative pot configuration using six pots for a fuller synth with MIDI could be:

#define WAVT_PIN 33  // Wavetable
#define INTS_PIN 32 // FM intensity
#define RATE_PIN 35 // Modulation Rate
#define MODR_PIN 34 // Modulation Ratio
#define AD_A_PIN 39 // ADSR Attack
#define AD_D_PIN 36 // ADSR Delay

The photo at the top of this post shows my Analog IO Board and 3V3 MIDI Module hooked up to provide a nice little MIDI FM synth.

Find it on GitHub here.

Closing Thoughts

This is a really good starting point with a relatively new (to me) architecture. There is a lot of potential use here, with so many ADC inputs, two DAC outputs and even the Wi-Fi for future use. It will also be interesting to see how the dual cores could be used too.

To really do some more complex experiments though I think I’ll need a ESP32 audio/mozzi experimenter PCB along the lines of my Nano and XIAO boards, especially as these modules are quite wide. If I was feeling really brave, I could even design around the actual EP32-WROOM module itself rather than one of these DevKits…

But this all proved relatively straight forward to get set up and running so far.

Kevin

Leave a comment