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.

Módulo de audio DFRobot

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

Esquema de conexión del módulo de audio proporcionado por el fabricante

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:

Prueba del módulo de audio

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.

Pintura eléctrica sobre una tecla

El esquema para conectar las teclas responde al siguiente circuito:

Esquema de conexiones de las teclas (no se toma en cuenta el zumbador)

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).

Prueba de las teclas con el módulo de audio

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.

Prueba de la función de multiplexión de escalas en Tinkercad

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.

Circuito terminado

Piano digital Yeah-Maha

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;
  }
}

También te podría gustar...

Deja una respuesta

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