Con un circuito muy sencillo de un Arduino o un ESP32, podemos generar sonidos de forma simple y barata, la calidad de sonido es baja pero suficiente para alertas, podemos incluso crear pequeñas piezas musicales, claro esta con baja calidad recordando al antiguo ZX-Spectrum con su sentencia “BEEP”.
El funcionamiento es muy simple conectaremos el positivo a una de las entradas PWM y la otra a GND, lo que nos permitirá realizar ondas de alto a bajo que generaran el zumbido. Debemos tener cuidado pues la corriente de salida de Arduino no podrá pasar de 40mA. También podemos colocar un altavoz pero en este caso sera necesaria más potencia y ademas proteger las salidas de nuestro Arduino o ESP32 (Placa de desarrollo desde ahora) con alguna resistencia.
En Arduino disponemos de la función “tone” que nos genera una onda cuadrada de una frecuencia especifica en el pin que indiquemos. Debemos tener en cuenta que solo podremos generar un tono a la vez, aunque sean en diferentes pines, y debemos saber también que solo producirá tonos mayores de 31Hz.
tone(Pin,frecuencia);
tone(Pin,frecuencia,duración);
noTone(Pin); // Para la generación de onda
En el ESP32 no disponemos de la función tone pero tenemos otra similar, ledcWriteTone, incluso alguna otra función que nos ayuda a generar notas musicales.
// Antes de usar Tonos deberemos definir el Pin y canal a utilizar como en PWM,
ledcAttachPin(GPIO, Canal)
ledcWriteTone(GPIOx, Frecuencia)
delay(duración)
// Silenciamos noTone()
ledcDetachPin(GPIOx)
ledcWrite(Canal,0)
// Especial Notas musicales de ESP32
ledcWriteTone(Canal,frecuencia);
ledcWriteNote(Canal, Nota, Octava); Genera una nota de la octava elegida.
En este POST no usaremos las funciones de notas musicales del ESP32 ya que generaremos la nuestra propia para compatibilizar Arduino & ESP32 en uno solo de la forma más sencilla posible.
El Circuito es muy simple conectaremos la masa de nuestra plataforma a un pin del Buzzer y el otro pin al PWM que elijamos.
Las notas musicales son frecuencias lo único que deberemos conocer la frecuencia que corresponde a cada nota y generarla con la salida PWM conectada al Buzzer.
Conociendo que el DO de la 4ª Octava tiene una frecuencia de 261,63 Hz, que tomaremos como nota 0, para octavas inferiores generaremos ordenes negativos como se puede ver en la tabla siguiente.
Nota | Frecuencia Hz | Orden | Octava |
La | 220,00 | -3 | Octava 3ª |
La# / Sib | 233,08 | -2 | Octava 3ª |
Si | 246,94 | -1 | Octava 3ª |
Do | 261,63 | 0 | Octava 4ª |
Do# / Reb | 277,18 | 1 | Octava 4ª |
Re | 293,66 | 2 | Octava 4ª |
Re# /Mib | 311,13 | 3 | Octava 4ª |
Mi | 329,63 | 4 | Octava 4ª |
Fa | 349,23 | 5 | Octava 4ª |
Fa# /Solb | 369,99 | 6 | Octava 4ª |
Sol | 391,99 | 7 | Octava 4ª |
Sol# / Lab | 415,30 | 8 | Octava 4ª |
La | 440,00 | 9 | Octava 4ª |
La# / Sib | 466,16 | 10 | Octava 4ª |
Si | 493,88 | 11 | Octava 4ª |
Do | 523,25 | 12 | Octava 5ª |
Do# / Reb | 554,36 | 13 | Octava 5ª |
Re | 587,33 | 14 | Octava 5ª |
Pero como seguro que nos interesan tener más octavas diremos que esta tabla se puede completar fácilmente con la siguiente formula:
// Recordemos empezamos desde el DO de la 4ªOctava que corresponde al orden 0 y frecuencia 261.63
Frecuencia = 261,625 * pow(1,0594630943593, Orden)
Ahora debemos tener un valor de duración aproximado para cada nota
Nombre | Valor Musical | Tiempo |
Redonda | 4/4 | 4 segundos |
Blanca | 2/4 | 2 segundos |
Negra | 1/4 | 1 segundo |
Corchea | 1/8 | ½ Segundos |
Semicorchea | 1/16 | ¼ Segundo |
Fusa | 1/32 | ⅛ Segundo |
Y ya podemos generar nuestra función «beep» en recuerdo del ZX-Spectrum.
/************************************************************
* Funciones para generar sonido
*
* void beep(float, unsigned int tono)
* Genera una nota indexada como 0 el DO de la 4ª Octava
* de una duración.
* La Nota 100 Indica silencio
************************************************************/
void beep(float duracion, unsigned int nota)
{
int frecuencia;
if(nota < 100)
{
// Calculamos la frecuencia a tocar, indice 0 Do4
frecuencia = (int) 261.625 * pow(1.0594630943593,nota);
}
else frecuencia =0;
// Codigo Arduino
#if defined(PLAT_ARDUINO)
// Codigo Arduino
tone(BZ, frecuencia);
delay(duracion*500);
noTone(BZ);
#else
ledcWriteTone(0, frecuencia); //Toca Tono definido en la frecuencia con su duración
delay(duracion*500);
ledcWrite(0,0);
#endif
}
Tenemos el codigo completo, compatible con Arduino y ESP32 en GITHUB «https://github.com/pinguytaz/Arduino/blob/master/CuadernoTecnico/PWM/Musica/Musica.ino»
de esta forma si se decide actualizar o mejorar el código siempre lo tendremos actualizado, así como si añadimos nuevas músicas en los fichero .h ya que de momento solo tenemos dos FrereJacwues y La Guerra de las Galaxias.