Caja Musical orientada a bebés.

Autores: Daniel Francisco Pandolfo Mendoza, Fernando Sanz Zambrana, Mohamed El Kanboui Bouaacha.

Explicación del Proyecto.

La idea de nuestro proyecto es una caja musical orientada para bebés con el fin de facilitar su sueño. Esta caja es controlada por medio de una aplicación móvil con la que el usuario es capaz de :

  • Abrir y cerrar la caja.
  • Reproducir una canción concreta.
  • Para la reproducción de la canción.
  • Cambiar el volumen de la música.
  • Reproducir en bucle todas las canciones.
  • Encender y apagar la luz.
  • Poner un color concreto a la luz.
  • Habilitar un cambio automático del color de las luces.
  • Activar un temporizador que permita cerrar por completo la caja (apagando la luz y parando la música).

Componentes Utilizados.

Componente/ProductoPrecio
Altavoz2,17 €
Módulo Bluetooth5,10 €
Tarjeta SD6,42 €
Pila2 €
Pegamento Instantáneo1,90 €
DFPlayer6 €
2 Rollos de Plástico1,2 €
Caja de cartón0 €
Kit de Arduino0 €
Total24,79 €

Problemas encontrados.

Problema 1. Incompatibilidad entre las comunicaciones seriales del reproductor y el módulo bluetooth.

Al juntar en el prototipo estos dos componentes, se apreciaba un comportamiento indeseado. Al investigar se averiguó que se debía a la librería SoftwareSerial, que no permitía el uso simultáneo de dos comunicaciones con el microcontrolador.

Solución al problema 1.

Con un análisis del funcionamiento del sistema, se llegó a la conclusión de que no se necesitaba un uso simultáneo de las comunicaciones. Así que se hizo uso de la función .listen(), provista por la librería y que permite dar prioridad a unas comunicaciones seriales frente a otras.

Problema 2. El amplificador requería de una librería especial.

El amplificador se compró con el objetivo de reproducir audios de tipo .wav y .mp3, sin embargo, no cumplía con su propósito.

Solución del problema 2.

Para solucionar el problema se instaló la librería “DFplayermini.h”. Esta librería ya permitía conectarse con el amplificador y reproducir los archivos con las extensiones anteriormente mencionada.

Problema 3. La caja contenía material defectuoso

Concretamente, la pila estaba agotada.

Solución al problema 3.

Se optó por comprar un repuesto para dicho material.

Problema 4. Potencia lumínica insuficiente.

La intensidad de la fuente lumínica de la caja, en este caso 2 leds RGB, era insuficiente para proyectar en el techo el patrón del papel trasparente que se situaba en la tapa de la caja.

Solución al problema 4.

No se ha conseguido proyectar el patrón en el techo con las herramientas de las que se disponían.

Problema 5. Pin PWM

La placa cuenta con 6 pines PWM, sin embargo, necesitábamos 7 para el sistema: 3 para el LED, 2 para el DFPlayer, 1 para el módulo bluetooth y otro para el servomotor.

Solución al problema 5. Los colores que emite el LED siempre tienen el componente rojo en 0 o 255, por lo que no se necesitaba una escritura analógica, bastaba con una digital.

Vídeo demostración.

Código.

A continuación, se muestra el código que implementa la parte software del proyecto.

// LIBRERIAS NECESARIAS
#include <Servo.h>
#include <SoftwareSerial.h>
#include "DFRobotDFPlayerMini.h"


//===== CONSTANTES =====
//  bluetooth:
#define RX_BT 9 // PWM
#define TX_BT 8 // No PWM
//  DFPlayer:
#define RX_DFP 6 // PWM
#define TX_DFP 5 // PWM
//  led:
#define LED_ROJO 12
#define LED_VERDE 10
#define LED_AZUL 11
//  servo:
#define PIN_SERVO 3
Servo motor;
// Variables de estado
int colorActual = 1;
bool cerrada;

// VARIABLES GLOBALES
SoftwareSerial BTSerial(RX_BT,TX_BT);
SoftwareSerial DFPlayerSerial(RX_DFP,TX_DFP); // Comunicacion entre placa y DFPlayer.
DFRobotDFPlayerMini moduloDFP;   // Componente DFPlayer

// FUNCIONES AUXILIARES
String decodificarEntrada(String, int*);
void darColorRGB(int, int, int);
void abrirTapa(bool);
void actualizarColor(int);

//________________________________________________________

void setup() {
 
  // Inicializar leds y servo
  pinMode(LED_ROJO, OUTPUT);
  pinMode(LED_VERDE, OUTPUT);
  pinMode(LED_AZUL, OUTPUT);
  
  motor.attach(PIN_SERVO);
  motor.write(0);
  cerrada = true;
  
  darColorRGB(0, 0, 0);

  // Inicializar comunicaciones seriales  
  BTSerial.begin(9600);
  DFPlayerSerial.begin(9600);

  //-----------------------------
  // Inicializacion de DFPlayer
  if (!moduloDFP.begin(DFPlayerSerial)) {  //Usar softwareSerial para comunicarse con la placa
    while (true){ // Fallo en la conexion al DFP
      actualizarColor(0);
      actualizarColor(2);
    }
  }

  moduloDFP.setTimeOut(500); // Tiempo de comunicacion DFP-placa

  //----Ajustar volumen----
  moduloDFP.volume(30);  // Volumen (0~30).

  //----Ajustar ecualizador----
  moduloDFP.EQ(DFPLAYER_EQ_NORMAL);

  //----Ajustar dispositivo del que leer. SD como predeterminado----
  moduloDFP.outputDevice(DFPLAYER_DEVICE_SD);

}

void loop() {
  
  // Atender la comunicacion bluetooth
  BTSerial.listen();
  
  if (BTSerial.available())
  {
    String mensaje = BTSerial.readStringUntil('/');
    int valor;
    String componenteID = decodificarEntrada(mensaje, &valor);
    if(componenteID.equals("CJT")){         // Cerrar el sistema
      abrirTapa(false);
      moduloDFP.pause();
      darColorRGB(0,0,0);
    }
    else if (componenteID.equals("CJ")) {        // Abrir/Cerrar caja
      abrirTapa(valor);
    }

    else if(componenteID.equals("REPCAN")){  
      if(!cerrada){
        DFPlayerSerial.listen();
        moduloDFP.play(valor);
      }
    }
    else if(componenteID.equals("PAUCAN")){   // Parar cancion
      if(!cerrada){
        DFPlayerSerial.listen();
        moduloDFP.pause();
      }
    }
    else if(componenteID.equals("ALLCAN")){   // Reproducir todas las canciones
      if(!cerrada){
        DFPlayerSerial.listen();
        moduloDFP.enableLoopAll();
      }
    }
    else if(componenteID.equals("ONECAN")){   // Reproducir en bucle la misma cancion
      if(!cerrada){
        DFPlayerSerial.listen();
        moduloDFP.disableLoopAll();
        moduloDFP.loop(moduloDFP.readCurrentFileNumber());
      }
    }
    else if(componenteID.equals("VOL")){      // Ajustar volumen
      if(!cerrada){
        DFPlayerSerial.listen();
        int volumen = valor*30 / 100;
        moduloDFP.volume(volumen);
      }
    }

    else if(componenteID.equals("L") ||     // Apaga/Enciende luces
          componenteID.equals("COL")){      // Cambia a color concreto
      if(valor==0)darColorRGB(0,0,0);
      else{
        actualizarColor(valor);
      }
    }
    else if(componenteID.equals("NEXTCOL")){    // Pasar al siguiente color
      colorActual = (colorActual%9) + 1;
      actualizarColor(colorActual);
    }
  }
}

void actualizarColor(int colorID) {
  switch (colorID) {
    case 0:
      darColorRGB(0, 0, 0);
    case 1:
      darColorRGB(255, 255, 255);
      break;
    case 2:
      darColorRGB(255, 0, 0);
      break;
    case 3:
      darColorRGB(0, 0, 255);
      break;
    case 4:
      darColorRGB(0, 255, 255);
      break;
    case 5:
      darColorRGB(0, 255, 0);
      break;
    case 6:
      darColorRGB(255, 0, 255);
      break;
    case 7:
      darColorRGB(255, 165, 0);
      break;
    case 8:
      darColorRGB(255, 51, 249);
      break;
    case 9:
      darColorRGB(255, 255, 0);
      break;
    default:
      darColorRGB(0, 0, 0);
      
      break;
  }
}


//________________________________________________________

void darColorRGB(int r, int g, int b) {
  if(r>0)digitalWrite(LED_ROJO, HIGH);
  else digitalWrite(LED_ROJO, LOW);
  analogWrite(LED_VERDE, g);
  analogWrite(LED_AZUL, b);
}

void abrirTapa(bool abrir) {
  
  for (int i = 0; i <= 100; i++) {
    if (abrir) motor.write(i);
    else motor.write(100 - i);
    delay(15);
  }
  cerrada = !abrir;
}

String decodificarEntrada(String mensaje, int* valor) {
  // Descomponer el mensaje entrante
  int indiceSeparador = mensaje.indexOf('_');
  
  if(indiceSeparador != -1){
    *valor = mensaje.substring(indiceSeparador + 1, mensaje.length()).toInt();
    return mensaje.substring(0, indiceSeparador);
  }else{
    *valor = -1;
    return mensaje.substring(0, mensaje.length());
  }
}

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 *