Piano Digital y Reproductor MP3 Yeah-Maha
Proyecto final SEyTR Grupo 02
Autores:
- Alejandro Mateos Domínguez
- Iván Bonilla Morante
- Gustavo Andrés Marrero Tovar
Introducción
Desde el primer momento queríamos realizar un proyecto relacionado con música, pues es algo que los tres tenemos en común, así que luego de reunirnos para concretar una idea, dimos con la de construir un piano, por lo que desde un primer momento nos pusimos a investigar.
Nos hemos dado cuenta que en muchos proyectos musicales se deja la labor de reproducir los sonidos a componentes como zumbadores, los cuales nos parece que tienen un sonido bastante deficiente y difícil de distinguir. Del mismo modo, las librerías nativas que se suelen utilizar para estos proyectos no eran de nuestro agrado, por razones similares.
Por lo tanto, para lograr un sonido más realista, decidimos separar la función del audio de la parte mecánica de las teclas. De igual forma, se ha hecho con las funcionalidades adicionales, dando lugar a tres módulos bien diferenciados.
- Control y reproducción del audio.
- Conexión y circuitería de las teclas.
- Lógica de control y funcionalidades adicionales.
Componentes utilizados y coste
- 1 Arduino Uno. Proporcionado por la Universidad
- 5 Resistencias de 1K ohm. Proporcionadas por la Universidad
- Protoboard pequeño. Proporcionado por la Universidad
- 8 Resistencias de 1M ohm. Proporcionadas por la Universidad
- 2 Altavoces ZHITING2 9 €.
- Cables Jumper cortos. Proporcionados por la Universidad
- Cables Jumper (20 cm) 1,5 €.
- Polvo de grafito 4 €/envase.
- Pintura acrílica 8€/envase.
- Innovateking-EU2 (2 Módulos reproductores) 13 €.
- Un módulo original DFRobot 12 €.
- 1 Tarjeta MicroSD Proporcionado por los miembros.
- Materiales de decoración Proporcionado por los miembros.
- Componentes varios (interruptores, botones y placa pequeña) 4 €.
- Total de 51,5 €.
Descripción y proceso de desarrollo
Como hemos indicado antes, el proyecto se constituye de tres partes, cada una con su parte Hardware y componentes Software que se detallan a continuación.
Control y reproducción de audio
Lo primero que decidimos implementar fue la gestión de los sonidos, pues es el elemento diferenciador del proyecto y en un principio lo más complicado de los tres subsistemas.
Para la gestión del sonido hemos decidido utilizar un módulo de audio, el cual es un dispositivo capaz de almacenar y reproducir archivos de sonido en formato MP3 utilizando Arduino.
Por lo tanto, el primer paso consiste en realizar las conexiones del módulo con el microprocesador de Arduino e implementar el código necesario para su correcto funcionamiento. A continuación se muestra el esquema de conexión mínimo necesario para enlazar el Arduino UNO y el módulo
Se puede apreciar que se conectan 5V y tierra a los respectivos pines del módulo, y que los altavoces van conectados directamente al módulo, los cuales también había que tener de antemano. Los puertos 10 y 11 se usan para la comunicación entre los dispositivos. Cabe destacar que también podían utilizarse los puertos 0 y 1, pero hacerlo produce un pequeño retraso que en nuestro proyecto, no es aceptable, la tecla debe sonar lo antes posible una vez tocada.
Luego de eso, tuvimos que insertar una SD con las notas grabadas y configuradas de modo que el módulo pudiese reconocerlas (necesitan un orden y un nombre específico).
Al utilizar el código de prueba del fabricante para realizar comprobaciones. Ha sido necesario instalar la librería DFRobotDFPlayerMini, el resultado fue el siguiente:
Circuitería y conexión de las teclas
Al terminar la configuración y conexión del módulo de audio procedimos a implementar el teclado, para el cual utilizamos la librería CapacitiveSensor, que mide la caída de tensión entre dos puertos, a los cuales se conecta un elemento conductor (en este caso las teclas).
Las teclas las hicimos nosotros mismos usando paletas de madera y pintura eléctrica, también fabricada por nosotros a partir de pintura acrílica y polvo de grafito.
El esquema para conectar las teclas responde al siguiente circuito:
Cada línea marrón va conectada a una tecla, se puede ver como en todos los casos hay un cable conectado directamente al puerto asignado a esa tecla (que será el reciever, el que recibirá el valor de tensión que cambie en la tecla) y que a su vez, conectados con una resistencia de 1M ohm, todos se conectan a un puerto común (que será el sender).
Lógica de control y funcionalidades adicionales
Dado que al terminar nos quedaban muy pocos puertos digitales para poder generar escalas nuevas (solo quedaban tres, si se restan los 8 de las teclas y los 2 del módulo), tuvimos que ser creativos a la hora de generar nuestras funcionalidades adicionales. Queríamos añadir más escalas, además de una modalidad de reproducción de canciones, para lo que queríamos usar uno o dos puertos para cada una, lo cual no era posible.
La solución fue maximizar el uso de esos tres puertos, como si fuesen una especie de multiplexor. Dependiendo de los valores de tensión que llegaran a ellos, se tocaría una escala u otra. Dado que los valores pueden ser 1 y 0 y nos quedaban tres puertos, pues disponemos de un total de 8 combinaciones, 7 que corresponden a escalas y 1 para el modo de reproducción en MP3.
Una vez pudimos combinar estos tres módulos, solo era cuestión de trabajar en la estética del proyecto, por lo que decoramos una caja para el circuito, pegamos las teclas y otros componentes fijos y conectamos todo dentro de la misma.
Código utilizado
//Las librerias de arduino, la de comunicación en serie, la del modulo de audio, y la del sensor para las teclas. #include "Arduino.h" #include "SoftwareSerial.h" #include "DFRobotDFPlayerMini.h" #include "CapacitiveSensor.h" SoftwareSerial mySoftwareSerial(10, 11); // RX, TX. Iniciamos el modulo de audio DFRobotDFPlayerMini myDFPlayer; void printDetail(uint8_t type, int value); //Se inicializan los valores que vendrán de los switches y nos dirán la escala que se toque, escala1 es el menos significativo, escala3 es el más significativo int escala1 = 0; int escala2 = 0; int escala3 = 0; //Se inician los puertos que estarán conectados a las teclas, entre los puertos estará el sensor capacitivo CapacitiveSensor do_1 = CapacitiveSensor(2,3); CapacitiveSensor re_1 = CapacitiveSensor(2,4); CapacitiveSensor mi_1 = CapacitiveSensor(2,5); CapacitiveSensor fa_1 = CapacitiveSensor(2,6); CapacitiveSensor sol_1 = CapacitiveSensor(2,7); CapacitiveSensor la_1 = CapacitiveSensor(2,8); CapacitiveSensor si_1 = CapacitiveSensor(2,9); CapacitiveSensor do_2 = CapacitiveSensor(2,12); void setup() {//Definimos los pines 13, 14 y 15 (los dos ultimos analogicos) que recibirán información de los switches, como pines de entrada pinMode(13, INPUT); pinMode(14, INPUT); pinMode(15, INPUT); //Configuración de las notas do_1.set_CS_AutocaL_Millis(0xFFFFFFFF); re_1.set_CS_AutocaL_Millis(0xFFFFFFFF); mi_1.set_CS_AutocaL_Millis(0xFFFFFFFF); fa_1.set_CS_AutocaL_Millis(0xFFFFFFFF); sol_1.set_CS_AutocaL_Millis(0xFFFFFFFF); la_1.set_CS_AutocaL_Millis(0xFFFFFFFF); si_1.set_CS_AutocaL_Millis(0xFFFFFFFF); do_2.set_CS_AutocaL_Millis(0xFFFFFFFF); //Iniciamos el puerto serie y la comunicación con el módulo de audio mySoftwareSerial.begin(9600); Serial.begin(115200); Serial.println(F("DFRobot DFPlayer Mini Demo")); Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)")); if (!myDFPlayer.begin(mySoftwareSerial)) { //Uso de softwareSerial para comunicacion con el modulo. Serial.println(F("Unable to begin:")); Serial.println(F("1.Please recheck the connection!")); Serial.println(F("2.Please insert the SD card!")); while(true); } Serial.println(F("DFPlayer Mini online.")); //Definimos el volumen myDFPlayer.volume(10); } void loop() { //Leemos los valores de los switches y los guardamos en las variables escala escala1 = digitalRead(13); escala2 = digitalRead(14); escala3 = digitalRead(15); //Leemos los valores de capacitancia del sensor para saber que tecla se está pulsando long tocandoTecla_1 = do_1.capacitiveSensor(1000); long tocandoTecla_2 = re_1.capacitiveSensor(1000); long tocandoTecla_3 = mi_1.capacitiveSensor(1000); long tocandoTecla_4 = fa_1.capacitiveSensor(1000); long tocandoTecla_5 = sol_1.capacitiveSensor(1000); long tocandoTecla_6 = la_1.capacitiveSensor(1000); long tocandoTecla_7 = si_1.capacitiveSensor(1000); long tocandoTecla_8 = do_2.capacitiveSensor(1000); //Dependiendo de los valores que haya en los switches, se meterá por uno de los ifs, al ser 3 switches, son 8 valores, 7 de ellos son escalas, y 1 es el modo MP3 if (escala3==LOW && escala2 == LOW && escala1 == LOW){ //Escala 1 la mas baja if (tocandoTecla_1 > 1000){ myDFPlayer.play(1); } if (tocandoTecla_2 > 1000){ myDFPlayer.play(2); } if (tocandoTecla_3 > 1000){ myDFPlayer.play(3); } if (tocandoTecla_4 > 1000){ myDFPlayer.play(4); } if (tocandoTecla_5 > 1000){ myDFPlayer.play(5); } if (tocandoTecla_6 > 1000) myDFPlayer.play(6); } if (tocandoTecla_7 > 1000){ myDFPlayer.play(7); } if (tocandoTecla_8 > 1000){ myDFPlayer.play(8); } } if (escala3==LOW && escala2 == LOW && escala1 == HIGH){ //Escala 2 if (tocandoTecla_1 > 1000){ myDFPlayer.play(8); } if (tocandoTecla_2 > 1000){ myDFPlayer.play(9); } if (tocandoTecla_3 > 1000){ myDFPlayer.play(10); } if (tocandoTecla_4 > 1000){ myDFPlayer.play(11); } if (tocandoTecla_5 > 1000){ myDFPlayer.play(12); } if (tocandoTecla_6 > 1000){ myDFPlayer.play(13); } if (tocandoTecla_7 > 1000){ myDFPlayer.play(14); } if (tocandoTecla_8 > 1000){ myDFPlayer.play(15); } } if (escala3==LOW && escala2 == HIGH && escala1 == LOW){ //Escala 3 if (tocandoTecla_1 > 1000){ myDFPlayer.play(15); } if (tocandoTecla_2 > 1000){ myDFPlayer.play(16); } if (tocandoTecla_3 > 1000){ myDFPlayer.play(17); } if (tocandoTecla_4 > 1000){ myDFPlayer.play(18); } if (tocandoTecla_5 > 1000){ myDFPlayer.play(19); } if (tocandoTecla_6 > 1000){ myDFPlayer.play(20); } if (tocandoTecla_7 > 1000){ myDFPlayer.play(21); } if (tocandoTecla_8 > 1000){ myDFPlayer.play(22); } } if (escala3==LOW && escala2 == HIGH && escala1 == HIGH){ //Escala 4 if (tocandoTecla_1 > 1000){ myDFPlayer.play(22); } if (tocandoTecla_2 > 1000) myDFPlayer.play(23); } if (tocandoTecla_3 > 1000){ myDFPlayer.play(24); } if (tocandoTecla_4 > 1000){ myDFPlayer.play(25); } if (tocandoTecla_5 > 1000) myDFPlayer.play(26); } if (tocandoTecla_6 > 1000){ myDFPlayer.play(27); } if (tocandoTecla_7 > 1000){ myDFPlayer.play(28); } if (tocandoTecla_8 > 1000){ myDFPlayer.play(29); } } if (escala3==HIGH && escala2 == LOW && escala1 == LOW){ //Escala 5 if (tocandoTecla_1 > 1000){ myDFPlayer.play(29); } if (tocandoTecla_2 > 1000){ myDFPlayer.play(30); } if (tocandoTecla_3 > 1000){ myDFPlayer.play(31); } if (tocandoTecla_4 > 1000){ myDFPlayer.play(32); } if (tocandoTecla_5 > 1000){ myDFPlayer.play(33); } if (tocandoTecla_6 > 1000){ myDFPlayer.play(34); } if (tocandoTecla_7 > 1000){ myDFPlayer.play(35); } if (tocandoTecla_8 > 1000){ myDFPlayer.play(36); } } if (escala3==HIGH && escala2 == LOW && escala1 == HIGH){ //Escala 6 if (tocandoTecla_1 > 1000){ myDFPlayer.play(36); } if (tocandoTecla_2 > 1000){ myDFPlayer.play(37); } if (tocandoTecla_3 > 1000){ myDFPlayer.play(38); } if (tocandoTecla_4 > 1000){ myDFPlayer.play(39); } if (tocandoTecla_5 > 1000){ myDFPlayer.play(40); } if (tocandoTecla_6 > 1000){ myDFPlayer.play(41); } if (tocandoTecla_7 > 1000){ myDFPlayer.play(42); } if (tocandoTecla_8 > 1000){ myDFPlayer.play(43); } } if (escala3==HIGH && escala2 == HIGH && escala1 == LOW){ //Escala 7 if (tocandoTecla_1 > 1000){ myDFPlayer.play(43); } if (tocandoTecla_2 > 1000){ myDFPlayer.play(44); } if (tocandoTecla_3 > 1000){ myDFPlayer.play(45); } if (tocandoTecla_4 > 1000){ myDFPlayer.play(46); } if (tocandoTecla_5 > 1000){ myDFPlayer.play(47); } if (tocandoTecla_6 > 1000){ myDFPlayer.play(48); } if (tocandoTecla_7 > 1000){ myDFPlayer.play(49); } if (tocandoTecla_8 > 1000){ myDFPlayer.play(50); } } if (escala3==HIGH && escala2 == HIGH && escala1 == HIGH){ //Modo MP3 if (tocandoTecla_1 > 1000){ myDFPlayer.play(51); } if (tocandoTecla_2 > 1000){ myDFPlayer.play(52); } if (tocandoTecla_3 > 1000){ myDFPlayer.play(53); } if (tocandoTecla_4 > 1000){ myDFPlayer.play(54); } if (tocandoTecla_5 > 1000){ myDFPlayer.play(55); } if (tocandoTecla_6 > 1000){ myDFPlayer.play(56); } if (tocandoTecla_7 > 1000){ myDFPlayer.play(57); } if (tocandoTecla_8 > 1000){ myDFPlayer.play(58); } } //Codigo de gestion de errores, proporcionado por el fabricante if (myDFPlayer.available()) { printDetail(myDFPlayer.readType(), myDFPlayer.read()); //Print the detail message from DFPlayer to handle different errors and states. } } void printDetail(uint8_t type, int value){ switch (type) { case TimeOut: Serial.println(F("Time Out!")); break; case WrongStack: Serial.println(F("Stack Wrong!")); break; case DFPlayerCardInserted: Serial.println(F("Card Inserted!")); break; case DFPlayerCardRemoved: Serial.println(F("Card Removed!")); break; case DFPlayerCardOnline: Serial.println(F("Card Online!")); break; case DFPlayerPlayFinished: Serial.print(F("Number:")); Serial.print(value); Serial.println(F(" Play Finished!")); break; case DFPlayerError: Serial.print(F("DFPlayerError:")); switch (value) { case Busy: Serial.println(F("Card not found")); break; case Sleeping: Serial.println(F("Sleeping")); break; case SerialWrongStack: Serial.println(F("Get Wrong Stack")); break; case CheckSumNotMatch: Serial.println(F("Check Sum Not Match")); break; case FileIndexOut: Serial.println(F("File Index Out of Bound")); break; case FileMismatch: Serial.println(F("Cannot Find File")); break; case Advertise: Serial.println(F("In Advertise")); break; default: break; } break; default: break; } }