-3

I would like to play two frequencies (522 and 660) at the same time on a buzzer using an esp32.

I have tried these different methods:

void loop()
{
  unsigned long t = micros();
  if(t % 261 <= 10) //for approximation
  {
     firstWave = !firstWave;
  }
  if(t % 330 <= 10)
  {
     secondWave = !secondWave;
  }
  if(firstWave && secondWave)
  {
    digitalWrite(13, HIGH);
  }
  else
  {
    digitalWrite(13, LOW);
  }
}

This one resulted in absolutely no sound at all. Then I tried forcing it with FreeRTOS without thinking too much...

void secondWave(void* p)
{
  while(true)
  {
    delayMicroseconds(330);
    digitalWrite(13, HIGH);
    delayMicroseconds(330);
    digitalWrite(13, LOW);
  } 
  return;
}
void setup()
{
  xTaskCreate(secondWave, "wave", 10000, NULL, 1, NULL);
}
void loop()
{
    delayMicroseconds(261);
    digitalWrite(13, HIGH);
    delayMicroseconds(261);
    digitalWrite(13, LOW);
}

This didn't work... but who is watchdog and why is he getting triggered.

I do not want to buy a second buzzer. I do not want to buy a different card.

please help, thanks

2 Answers2

1

What you are trying to do is virtually impossible with only one buzzer.

A buzzer works by vibrating a metal plate at certain frequencies. A piezo buzzer can only ever play one frequency at a time. I know that you don't want to buy another buzzer but that would mean you would be stuck with only one note being played at a time

If you want to play a chord you might even need up to three. What you can do is try to make a speaker or recycle one. These can usually play multiple frequencies at once.

This is a crude, yet good way to make a speaker: Guide

I am sorry about the bad news, I hope that you might find this useful - have a good day!

James Barnett
  • 561
  • 5
  • 18
  • 1
    Besides suitable hardware, you need some analog output to produce something recognizable as an overlay of two frequencies. – datafiddler Jul 21 '21 at 14:18
0

If anyone was wondering, the answer is a lot easier than what I thought. No maths involved.

Basically it's just all the samples from a wav file (16000 Hz) and I just shoved those into a timer and write to the buzzer using the dac.

#include <driver/dac.h>

#include "sound.h"

hw_timer_t * timer = NULL;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;

volatile uint32_t isrCounter = 0;
volatile uint32_t lastIsrAt = 0;

void IRAM_ATTR onTimer() {
  portENTER_CRITICAL_ISR(&timerMux);
  isrCounter++;
  lastIsrAt = millis();
  portEXIT_CRITICAL_ISR(&timerMux);
  if (isrCounter > samplesLen) {
    isrCounter = 0;
  }
  dac_output_voltage(DAC_CHANNEL_1, samples[isrCounter]);
}

void setup() {
  pinMode(25, OUTPUT);
  dac_output_enable(DAC_CHANNEL_1);
  timer = timerBegin(0, 80, true);
  timerAttachInterrupt(timer, &onTimer, true);
  timerAlarmWrite(timer, 62, true);
  timerAlarmEnable(timer);
}

void loop()
{

}

sound.h looks like this but way way longer (about 67923 times longer):

const int samplesLen = 12;

const unsigned char samples[12] = {
  0x8B, 0x91, 0x91, 0x91, 0x93, 0x94, 0x94, 0x95, 0x97, 0x8E, 0x77, 0x7C,
};

!!! the const keyword is super important !!!