Música con ARDUINO Education

/

Descripción

En este proyecto vamos a aprender cómo hacer música y mucho más con ARDUINO. Pensado para personas que se están iniciando en electrónica y programación y mediante la experimentación iremos paso a paso desgranando todos los conceptos necesarios para realizar este reto. ¡Comenzamos!

Aprenderemos acerca de:

  • Notas musicales
  • Tipos de notas
  • Tempo
  • Escala
  • Timbre y sonido
  • Frecuencia de las notas
  • Programar el buzzer
  • Constantes
  • Monitor en serie
  • Funciones
  • Programar Leds

 

Materiales

PARA EL MECANISMO

Arduino Student Kit (individual o de aula). Componentes del kit que necesitaremos:

  • Placa Arduino Uno
  • Cable USB
  • Base de montaje de la placa
  • 5 resistencias 220 Ohmios
  • Una placa de pruebas de 400 puntos
  • Cables de conexión
  • Un cable de puente macho a macho

Leds extra: en total necesitaremos 8 leds blancos.

Cables extra: 16 cables de conexión macho hembra de 15cm ó 30cm.

Resistencias extra de 220 Ohm, necesitaremos 3 unidades extra (en total necesitaremos 8 resistencias)

Etiquetas: para identificar los cables.

PARA LA ESTRUCTURA (A de STEAM):

  • Cartón pluma de 5mm de espesor y tamaño A4.
  • Soporte para la plancha de cartón pluma: más cartón pluma, una caja,…
  • Adhesivo (pistola de silicona…)

Consejos:

Fijar a la estructura la placa Arduino Uno para evitar que se suelten los cables.

Etiquetar los cables para facilitar su correcta conexión.

Proceso

El buzzer o timbre con el que trabajamos nos permite variar la frecuencia, es decir, jugar con las distintas notas y la duración de las mismas, pero no podemos jugar con la amplitud, volumen de sonido ni con el timbre (Tienes información adicional sobre timbre y sonido en los archivos adjuntos).

La membrana del buzzer sólo permite una frecuencia de vibración cada vez. No podemos superponer distintas frecuencias con un sólo buzzer. Es decir, no podemos hacer que suenen dos notas a la vez con un sólo buzzer.

NOTAS MUSICALES

La nota, gracias a su aspecto y su posición, permite definir simultáneamente tres parámetros:

Notas musicales

  • La posición vertical de la nota define su altura (aguda o grave). Cuanto más arriba se sitúe la nota sobre las líneas o los espacios del pentagrama, más aguda será.
  • La posición horizontal de la nota define cuándo es emitida. Así, el eje horizontal del pentagrama define una escala de tiempo creciente desde la izquierda hacia la derecha. Si existiesen dos notas en la misma columna, estarían emitidas simultáneamente.

Duración de las notas

  • La forma de la nota define su duración. Duraciones estándar de notas están definidas en solfeo; cada una dura la mitad que la anterior.

Un ejemplo de pentagrama en clave de Sol:

Las 7 notas

Nuestro sistema musical tiene doce notas, y no siete, distanciadas entre sí por semitonos. De Do a Do# hay un semitono, de Do# a RE hay un semitono,…

Tonos y semitonos

Es decir, de Do a Do hay 12 semitonos.

FRECUENCIA DE UNA NOTA

Sabemos que la relación entre octavas es de 2:1. Es decir, si la frecuencia de la nota La es 440Hz, la frecuencia de la nota La una octava más arriba será 880 Hz y una octava más abajo será 220 Hz.

Esta proporción 2:1 es la única que necesitamos para saber las frecuencias de cada una de las notas de nuestro proyecto.

Para calcular la frecuencia de cualquier nota:

frecuencia de las notas

Si:

La = 440 Hz

Siguiente nota:  La# = 440*r

Siguiente nota: Si = 440*r*r = 440*r2

.

.

Y así sucesivamente, hasta llegar a: La = 880 Hz = 440*r12 

Por lo tanto el valor de r será:

  Fórmula de la frecuencia de una nota   

r = 1,059463

De esta manera, la forma de calcular la frecuencia de culaquier nota será multiplicar la frecuencia de la nota anterior (un seminotno) por 1,059463.

Así pues, las frecuencias en hercios para una escala quedan así:

  • Do1 = 261.63
  • Re = 293.66
  • Mi = 329.63
  • Fa = 349.23
  • Sol = 392.00
  • La = 440.00
  • Si = 493.88
  • Do2 = 523.63

Dado que la diferencia al oído entre, por ejemplo, 261.63 Hz y 261 Hz no es apreciable, vamos a redondear estas cifras para que sean más manejables.

  • Do1 = 261
  • Re = 294
  • Mi = 330
  • Fa = 349
  • Sol = 392
  • La = 440
  • Si = 494
  • Do2 = 524

*Más adelante asignaremos estas frecuencias a unas constantes. Si los números que manejamos son con coma deberemos utilizar float y si son sin comas podemos utilizar int. En el primer caso la placa reserva más memoria para estos datos que en el segundo. En nuestro caso, dado que la diferencia de sonido es inapreciable, redondearemos para no utilizar comas y utilizaremos int.

PROGRAMAR EL BUZZER

Estas funciones son las que vienen por defecto en la librería de la placa Arduino UNO sin tener que instalar librerías adicionales:

  • tone(pin, frecHz): para hacer sonar el timbre.
  • tone(pin, frecHz, tiempo): para hacer sonar el timbre durante un tiempo determinado.
  • noTone(pin): para que deje de sonar el timbre.

Argumentos de estas funciones:

  • pin: pin de conexión a la placa Arduino.
  • frecHz: frecuencia de la onda sonora en Hercios, cuyo valor está relacionado con la nota musical.
  • tiempo: tiempo, medido en milisegundos (ms), que está el timbre sonando.

Formas de hacer sonar una nota:

Así pues, si queremos reproducir una nota basta con programar:

tone(2,440,1000);

Es decir, reproduce en el buzzer (que está conectado al pin 2) la nota La (440 Hz) durante 1 segundo (1000 ms)

Si queremos reproducir varias notas seguidas (hacer una melodía), podríamos pensar en programar algo así:

tone(2, 440, 1000);
tone(2, 524, 500);
tone(2, 494, 500);

Es decir, La negra, Do corchea, Si corchea.

Si probamos esta programación comprobaremos que no se reproduce la melodía correctamente ya que, la ejecución del segundo tone no espera a que pase el tiempo del primero (1 segundo), y lo mismo ocurre con el tercero. Lo más probable es que escuchemos únicamente el tercer tone.

Es decir, la función tone no espera hasta terminar para seguir a la siguiente.

Esto nos es muy útil si queremos que se encienda un led al mismo tiempo que comienza un sonido, pero debemos encontrar otra manera de hacer esperar al tone antes de reproducir la siguiente nota.

Para ello utilizaremos la función delay(tiempo). Por ejemplo:

tone(2, 440);
delay(1000);
tone(2, 524);
delay(500);
tone(2, 494);
delay(500);

PROGRAMAR UNA CANCIÓN

Proponemos una serie de programaciones progresivas para que, mediante la experimentación, poder integrar los conceptos de programación necesarios para desarrollar este proyecto.

*En función del dominio o no de estos conceptos es posible avanzar paso a paso o saltar al paso que consideres más decuado.

Monta tu dispositivo musical

Para comprender bien cómo se programa la placa ARDUINO UNO con un buzzer que reproduzca canciones vamos a comenzar montando únicamente el buzzer. Más adelante incorporaremos los leds y aprenderemos a programar para que suene y luzca al mismo tiempo.

El montaje necesario en esta parte es el siguiente: 

Esquema buzer en placa arduino.     Diagrama buzer en placa arduino

PASO 1. Programa una escala

Hasta ahora sabemos:

  • Calcular las frecuencias de las notas
  • Utilizar las funciones tone y noTone
  • Utilizar la función delay

Programa tu ARDUINO UNO para que se reproduzca una escala Do-Re-Mi-Fa-Sol-La-Si-Do. Cada nota sonará durante medio segundo. Al final de la escala habrá un silencio de un segundo.

SOLUCIÓN:

void setup()
{    
  pinMode(2, OUTPUT);
}
void loop()
{
  tone(2,261);
  delay(500);
  tone(2,294);
  delay(500);
  tone(2,330);
  delay(500);
  tone(2,349);
  delay(500);
  tone(2,392);
  delay(500);
  tone(2,440);
  delay(500);
  tone(2,494);
  delay(500);
  tone(2,524);
  delay(500);
  noTone(2);
  delay(1000);
}

PASO 2. Programa una escala con un bucle

¿Podemos programar una escala de un modo más eficiente aún? Sin duda. Para ello utilizaremos un bucle, es decir, la función for.

Uso de constantes:

Definimos una constante para almacenar los valores de las frecuencias de las 8 notas que necesitamos. Es como un cajón con 8 compartimentos. El cajón se llama nota[8] y cada uno de los compartimentos se reconoce por su número de orden. Así cuando durante el programa llamemos por ejemplo a nota[5] nos devolverá el valor que está en ese compartimento; la frecuencia de la nota La.

*Aprender a utilizar constantes en programación es fundamental. Con ellas podremos hacer cambios en los valores de forma cómoda, bastará con cambiar su valor en la definición de la constante. De otra manera, cada vez que queramos variar uno de estos valores tendremos que hacerlo en muchos lugares a lo largo de la programación, lo que nos llevará a cometer olvidos y errores.

constantes en programación

const int nota[8]={261,294,330,349,392,440,494,524};

Y programaremos un bucle (for) así:

const int nota[8]={261,294,330,349,392,440,494,524};
void setup()
{    
  pinMode(2, OUTPUT);
}
void loop()
{
  for(int i=0; i<8 ;i++) //corre un contador i de 0 a 7
  {
   tone(2,nota[i]); //la frecuencia que encuentra en la posición i de nota
   delay(500); //suena durante medio segundo
  }
  noTone(2);
  delay(1000); 
}

PASO 3. Monitoriza las notas

Veamos qué está pasando mientras se ejecuta el programa. Para ello utilizaremos el monitor en serie (salida de texto) del ARDUINO IDE (en él podemos mostrar el estado de las variables en cada momento).

Para ello definimos una constante de tipo texto de esta manera:

char *notaEsc[8]={"Do","Re","Mi","Fa","Sol","La","Si"};

Y modificamos la programación para que nos enseñe ese valor en el monitor en serie:

const int nota[8]={261,294,330,349,392,440,494,524}; //frecuencias de las notas
char *notaEsc[8]={"Do","Re","Mi","Fa","Sol","La","Si","Do"};
void setup()
{    
  pinMode(2, OUTPUT);
  Serial.begin(9600); //necesario para utilizar el monitor en serie
}
void loop()
{
  for(int i=0; i<8 ;i++)
  {
   tone(2,nota[i]);
   Serial.println(notaEsc[i]); //texto de la posición i de notaEsc
   delay(500);
  }
  noTone(2);
  delay(1000); 
}

PASO 4. Programa una canción sencilla

Programa tu ARDUINO UNO para que se reproduzca una melodía sencilla. Al final de la melodía habrá un silencio de un segundo. Vamos a practicar con la melodía de “Cumpleaños feliz”.

Cumpleaños feliz

Definir la duración de cada nota:

¿Cómo determinamos la duración de las notas? Si tenemos el valor del tempo en la partitura podemos transformarlo en milisegundos, que es lo que necesitamos para programar.

tempo

En este caso el tempo es 99, esto quiere decir que en 1 minuto (60 segundos) entran 99 negras. Con una sencilla regla de tres podemos deducir que una negra dura 600 milisegundos.

Así pues, damos un valor de 600 ms para la negra, por lo tanto:

  • Negra 600ms
  • Blanca (negrax2) 1200ms
  • Corchea (negra/2) 300ms

Si nos ponemos a programar esta melodía, a pesar de ser sencilla y corta, comprobaremos que es muy laborioso ir consultando la frecuencia de cada nota para incluirla en la función Tone.

¿Cómo podemos programar de forma más eficiente?

Asignando cada frecuencia a una constante que llamaremos como la nota correspondiente. De esta manera, en vez de escribir tone(2, 440) pondremos tone(2,  La).

Una constante para cada nota

 

SOLUCIÓN:

const int Do1 = 261;
const int Re = 294;
const int Mi = 330;
const int Fa = 349;
const int Sol = 392;
const int La = 440;
const int Si = 494;
const int Do2 = 524;
const int Re2 = 588;
const int Mi2 = 660;
const int Fa2 = 699;
const int Sol2 = 785;
void setup()
{    
  pinMode(2, OUTPUT);
}
void loop()
{
  tone(2,Sol);
  delay(300);
  noTone(2);
  tone(2,Sol);
  delay(300);
  tone(2,La);
  delay(600);
  tone(2,Sol);
  delay(600);
  tone(2,Do2);
  delay(600);
  tone(2,Si);
  delay(1200);
  tone(2,Sol);
  delay(300);
  noTone(2);
  tone(2,Sol);
  delay(300);
  tone(2,La);
  delay(600);
  tone(2,Sol);
  delay(600);
  tone(2,Re2);
  delay(600);
  tone(2,Do2);
  delay(1200);
  noTone(2);
  tone(2,Sol);
  delay(300);
  noTone(2);
  tone(2,Sol);
  delay(300);
  tone(2,Sol2);
  delay(600);
  tone(2,Mi2);
  delay(600);
  tone(2,Do2);
  delay(600);
  tone(2,Si);
  delay(600);
  tone(2,La);
  delay(600);
  tone(2,Fa2);
  delay(300);
  noTone(2);
  tone(2,Fa2);
  delay(300);
  tone(2,Mi2);
  delay(600);
  tone(2,Do2);
  delay(600);
  tone(2,Re2);
  delay(600);
  tone(2,Do2);
  delay(1200);
  noTone(2);
  delay(1000);
}

Si lo probamos, escucharemos que las notas suenan bien pero los tiempos no del todo. Cuando dos notas iguales suenan consecutivamente no se aprecia. Es decir, si tenemos  Sol corchea (150ms) y Sol corchea (150ms) lo escucharemos como si fuera Sol negra (300ms). Para solucionarlo hemos puesto entre estas dos notas una función noTone. A partir de ahora, para evitar estar pendiente de las notas que se repiten, pondremos noTone en todas las notas.

PASO 5. Una función para cada nota

Así como hemos asociado las frecuencias de las notas a una constante para facilitar la programación, podemos hacer lo mismo con la duración de las notas de esta manera:

const int n = 600;  //Duración en ms de las notas negras
const int b = n*2;  //Duración en ms de las notas blancas, relativo al valor de una negra
const int c = n/2;  //Duración en ms de las notas  corchea, relativo al valor de una negra

Esta constante es la que asignaremos a delay, en vez de:

tone(2,Do2);
delay(1200); //Duración en ms de la blanca
noTone(2);

Pondremos:

tone(2,Do2);
delay(b); //b=n*2=600ms
noTone(2);

Por último y para mejorar al máximo la programación, convertiremos esto en una función para cada nota.

*En este momento hemos decidido cambiar los nombres de las constantes de las frecuencias, en vez de Do, le llamamos FDo (frecuencia de Do), para poder llamar Do a la función que llamará a esa nota.

Función La

void La(int t)
{
  tone(2,FLa); //suena la frecuencia almacenada en FLa
  delay(t); //espera t milisegundos
  noTone(2); //deja de sonar
}

Cuando queramos que esta nota suene, únicamente tendremos que llamarla y darle el valor de la duración:

La(n); //ejecula la función La con el valor de n (300ms)

Tienes el programa para la canción de cumpleaños feliz en el archivo adjunto MelodiaV2

PASO 6. Programar más de una canción

Este programa será suficiente para reproducir una sola canción pero, ¿y si queremos reproducir varias canciones? Podríamos programarlas una detrás de otra pero hay una manera mucho más eficiente que nos premitiría modificar el orden fácilmente. Cada una de las canciones será una función, por ejemplo:

Función cumpleañosfeliz

void cumpleanosfeliz()
{
Sol(c);
Sol(c);
La(n);
Sol(n);
Do2(n);
Si(b);
Sol(c);
Sol(c);
La(n);
Sol(n);
Re2(n);
Do2(b);
Sol(c);
Sol(c);
Sol2(n);
Mi2(n);
Do2(n);
Si(n);
La(n);
Fa2(c);
Fa2(c);
Mi2(n);
Do2(n);
Re2(n);
Do2(b);
}

Así, desde el módulo principal llamamos a la función cumpleañosfeliz de esta manera:

void loop()
{
cumpleanosfeliz();
}

ILUMINAR LAS NOTAS

Con todo lo visto hasta ahora ya somos capaces de programar cualquier melodía con nuestra placa ARDUINO UNO y un zumbador o buzzer. Ahora lo que queremos es montar una estructura musical en la que a la vez que suenen las notas se iluminen.

Para ello, comenzamos con un montaje sencillo de un buzzer y dos leds como este: 

Diagrama de 2 leds con buzzer con arduino Esquema de 2 leds con buzzer con arduino

Vamos a partir de la última programación. Analicemos:

  • Tenemos una función para cada nota
  • Estas funciones leen dos tipos de constantes: la frecuencia y el tiempo
  • Queremos que SIEMPRE que suene la nota se encienda su led correspondiente
  • Debemos definir qué tipo de pins son los nuevos, donde están conectados los leds

*Cuando en nuestro mecanismo necesitamos utilizar varios pins es aconsejable renombrarlos para programar con más facilidad. Es decir, si conectamos el led de la nota Fa al pin 8, por ejemplo, declararemos al principio del programa:

#define LFa 8  //el pin 8 es el led de la nota Fa

Así, cada vez que tenemos que teclear este pin, pondremos LFa en vez de 8.

PROGRAMAR UN LED

Esta función es la que viene por defecto en la librería de la placa Arduino UNO sin tener que instalar librerías adicionales:

  • digitalWrite(pin, HIGH/LOW): enciende o apaga un led

Argumentos de esta función:

  • pin: pin de conexión a la placa Arduino.
  • HIGH: da energía, es decir, led encendido
  • LOW: NO da energía, es decir, led apagado

Así pues, si queremos encender el led mientras suena una nota, basta con programar:

Función La

void La(int t)
{
  tone(2,FLa); //Comienza a sonar la nota Do1 a la frecuencia fijada
  digitalWrite(4,HIGH); //se enciende el led correspondiente al La
  delay(t); //Permanece encendido t milisegundos
  digitalWrite(4,LOW); //Se apaga el led correspondiente al La
  noTone(2); //se apaga el sonido. Ha estado sonando t milisegundos
}

Vamos ahora a probar con dos notas y dos leds:

Funciones Sol y La

void Sol(int t)
{
  tone(2,FSol); //Comienza a sonar la nota Sol a la frecuencia fijada
  digitalWrite(5,HIGH); //se enciende el led correspondiente al Sol
  delay(t); //Permanece encendido t milisegundos
  digitalWrite(5,LOW); //Se apaga el led correspondiente al Sol
  noTone(2); //se apaga el sonido. Ha estado sonando t milisegundos
}
void La(int t)
{
  tone(2,FLa); //Comienza a sonar la nota La a la frecuencia fijada
  digitalWrite(4,HIGH); //se enciende el led correspondiente al La
  delay(t); //Permanece encendido t milisegundos
  digitalWrite(4,LOW); //Se apaga el led correspondiente al La
  noTone(2); //se apaga el sonido. Ha estado sonando t milisegundos
}

En la canción cumpleaños feliz algunas notas se repiten, como los dos primeros Sol. ¿Te has fijado qué ocurre con el led? Al ejecutarse dos veces seguidas la función Sol nuestro ojo no es capaz de apreciar que el led se apaga entre una y otra. Para resolver esto vamos a intentar que el tiempo de encendido del led sea algo menor que el tiempo de sonido.

Hemos determinado que un tiempo en milisegundos adecuado para que nuestro ojo pueda percibir que el led se ha apagado es de 75 milisegundos.

Vamos a modificar la programación para que el sonido dure t y el led t-75. De esta manera se apagará un poco antes de acabar el sonido y esto nos permitirá verlo cuando haya dos notas seguidas.

Funciones Sol y La

void Sol(int t)
{
  tone(2,FSol); //Comienza a sonar la nota Sol a la frecuencia fijada
  digitalWrite(5,HIGH); //se enciende el led correspondiente al Sol
  delay(t-75); //Permanece encendido t-75 milisegundos
  digitalWrite(5,LOW); //Se apaga el led correspondiente al Sol
  delay(75); //Permanece sonando 75 milisegundos más
  noTone(2); //se apaga el sonido. Ha estado sonando t milisegundos
}
void La(int t)
{
  tone(2,FLa); //Comienza a sonar la nota Do1 a la frecuencia fijada
  digitalWrite(4,HIGH); //se enciende el led correspondiente al La
  delay(t-75); //Permanece encendido t-75 milisegundos
  digitalWrite(4,LOW); //Se apaga el led correspondiente al La
  delay(75); //Permanece sonando 75 milisegundos más
  noTone(2); //se apaga el sonido. Ha estado sonando t milisegundos
}

*Posibles mejoras: podríamos asignar este valor de 75 a una constante z, al igual que hemos hecho con las frecuencias de las notas o con los tiempos.

PROYECTO FINAL

Este es el proyecto final que hemos realizado.

Puedes imitarlo o, ¡poner en marcha tu creatividad y diseñar el tuyo propio!

Hemos diseñado y construido una estructura decorativa en la que se verá representado un pentagrama y cuyas notas se iluminarán en el momento en que suenan.

Programaremos nuestra Arduino UNO para que reproduzca canciones, de forma tal, que cuando suenen se encienda el led correspondiente a la nota del pentagrama que esté sonando y que el tiempo que permanezca el led encendido  sea proporcional al de la duración de la nota musical.

Hemos seleccionado canciones navideñas que únicamente contengan las notas Do-Re-Mi-Fa-Sol-La-Si-Do.

Este es el diseño de pentagrama que hemos hecho:

Imprimible del pentagrama para el proyecto con arduino

Puedes descargarlo en los archivos adjuntos.

Las canciones seleccionadas son «Jingle bells» y «Joy to the world» (partituras en los archivos adjuntos)

En la galería dejamos los diagramas y fotos del proyecto final, y en los archivos adjuntos el programa completo.

 

Esperamos que disfrutes tanto el proceso de creación y aprendizaje como lo hemos hecho nosotros. 

Archivos adjuntos

Lorem ipsum dolor sit amet consectetur adipisicing elit.

Documento
Descripción
Versión
Fecha
Descargar
Anexo Timbre y sonido
Información adicional sobre timbre y sonido
Versión:1.0
Fecha:19/10/2023
MelodiaV2
Cumpleaños feliz con funciones para cada nota
Versión:1.0
Fecha:19/10/2023
Pentagrama imprimible
Pentagrama imprimible en A4
Versión:1.0
Fecha:19/10/2023
Partitura de Jingle bells
Partitura de la melodía Jingle bells
Versión:1.0
Fecha:19/10/2023
Partitura de Joy to the world
Partitura de la melodía Joy to the world
Versión:1.0
Fecha:19/10/2023
Programa final
Programa completo del proyecto de pentagrama con ARDUINO Education
Versión:1.0
Fecha:19/10/2023

Deja tu Comentario

Un Comentario “Música con ARDUINO Education”

  • Luismar Canelon

    dice:

    Tu articulo me ayudo a entender el calculo de para sacar las frecuencias, quisiera saber si tienes a disposición otros archivos como el de feliz cumpleaños para dar practicas a unos chicos que quieren seguir aprendiendo

    Responder

Deja un Comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

To top