Experimenting with audio tones using the ESP32 for use in projects

A reader alerted me to the Tone function for Arduino. When I was making my WordPress hit counter I wanted to add in an audio alert. I preferred something other than a constant tone but thought I would have a go using the tone function. It turns out that the tone function is not implemented with the ESP32.

After a bit of searching, I found a couple of useful pages:

They explain a workaround using PWM functionality. It’s quite simple and only requires a few lines of code. To avoid having a constant tone, I tried a few combinations of loops and changing the frequency for each loop. I ended up with one, that while fairly simple, I am happy with. The code is below and the comments should be enough to see what is going on. The pages above have a lot more detail and more options.

One part that I am not too sure about is connecting this to a speaker. In the linked articles they use a buzzer module that I think is just a piezo module. Using a regular speaker instead by itself is probably a bad idea. It could result in a higher current flow than the ESP32 and maybe the speaker can handle and I’ve also read that the ESP32 doesn’t like to drive inductive loads. let me know if you have a good and simple solution for this. In the WordPress stats counter I used a 130 ohm speaker from a phone with a 330 ohm resistor and 220uF capacitor all in series. It works and the volume is about right but I could be taking a risk. Another option is to drive a small amplifier. I’ve tried an LM386 and that works ok, but I prefer not using an amplifier if there is a simpler solution.

Here is a recording of the sketch below so you can hear the sound of each part.

// Audio alert example using PWM
// Connections: Output connected between pin 26 and ground

// Output pin
const int TONE_OUTPUT_PIN = 26;

// The ESP32 has 16 channels which can generate 16 independent waveforms. We will use PWM channel 0 here
const int TONE_PWM_CHANNEL = 0; 

void setup() {

  ledcAttachPin(TONE_OUTPUT_PIN, TONE_PWM_CHANNEL);

}

void loop() {
  // 100Hz tone for 1 second
  ledcWriteTone(TONE_PWM_CHANNEL, 100);
  delay(1000);    
  ledcWrite(TONE_PWM_CHANNEL, 0); // Stop tone 

  delay(2000); // Delay before starting the next example

  // 1000Hz tone for 1 second
  ledcWriteTone(TONE_PWM_CHANNEL, 1000);
  delay(1000);    
  ledcWrite(TONE_PWM_CHANNEL, 0); // Stop tone 

  delay(2000); // Delay before starting the next example

  // Short rising tone (100 to 2000Hz for 200ms)
  for (int i=1; i<20; i++) {
    ledcWriteTone(TONE_PWM_CHANNEL, i * 100);
    delay(10);    
  }
  ledcWrite(TONE_PWM_CHANNEL, 0); // Stop tone 

  delay(2000); // Delay before starting the next example

  // Short rise and fall
  for (int i=1; i<20; i++) {
    ledcWriteTone(TONE_PWM_CHANNEL, i * 100);
    delay(10);    
  }
  for (int i=10; i>0; i--) {
    ledcWriteTone(TONE_PWM_CHANNEL, i * 100);
    delay(10);    
  }
  ledcWrite(TONE_PWM_CHANNEL, 0); // Stop tone 

  delay(2000);

  // Slow fall (500 to 50 Hz 1800 ms)
    for (int i=500; i>50; i--) {
    ledcWriteTone(TONE_PWM_CHANNEL, i);
    delay(4);    
  }
  ledcWrite(TONE_PWM_CHANNEL, 0); // Stop tone 

  delay(2000); // Delay before starting loop again

}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Website Powered by WordPress.com.

Up ↑

%d bloggers like this: