Mostrando entradas con la etiqueta MP3. Mostrar todas las entradas
Mostrando entradas con la etiqueta MP3. Mostrar todas las entradas

miércoles, 16 de octubre de 2013

Construcción de una caja musical con arduino V

Vamos a concluir la construcción de la caja musical con la soldadura y el montaje.En las imágenes vemos todos los componentes soldados al shield




Y el conjunto completo con el altavoz y el botón de encendido




El montaje ya dentro de la caja



Para el encendido y apagado del microcontrolador hemos usado un botón en la parte posterior de la caja, conectado a una pila por un extremo y al microcontrolador por el otro. El botón deja pasar la corriente cuando está pulsado, de forma que al abrir la tapa lo pulsa y cierra el circuito.



Y aquí tenemos la caja acabada y funcionando




Artículos relacionados

martes, 10 de septiembre de 2013

Construcción de una caja musical con arduino IV

El sketch que hemos creado hasta ahora reproduce canciones indefinidamente sin interrumpirlas en ningún momento. En este artículo vamos a añadir el mecanismo para que la música se interrumpa cuando se cierra la caja y vuelva a sonar cuando se abre. Existen varias formas de hacerlo, pero en este artículo me voy a centrar en dos.

Utilizando una fotorresistencia

Una fotorresistencia funciona igual que el potenciómetro del artículo anterior, pero la resistencia varía con la cantidad de luz que detecta. La idea es que al cerrar la caja la fotorresistencia detecte la variación de luz al abrir y cerrar la caja para interrumpir o reanudar la música. En la foto podemos ver una fotorresistencia y una resistencia


El fotorresistor está conectado en serie con una resistencia de 10 KΩ. El valor devuelto por el fotoresistor lo leeremos por el pin analógico 2. El esquema es el siguiente



Y por último el montaje del prototipo


En el siguiente vídeo podemos ver el prototipo en funcionamiento.





El sketch

En el sketch hemos definido un umbral mínimo de luz por debajo del cual la música se interrumpirá. Cuando la luz vuelva a estar por encima del valor mínimo se volverá a elegir una nueva canción y se reproducirá. 

#include <SPI.h>
#include <Adafruit_VS1053.h>
#include <SD.h>

#define MP3_XCS 6   // CS Registros
#define MP3_XDCS 7  // CS Datos (BSYNC)
#define MP3_DREQ 2  // Interrupción chip disponible
#define MP3_RESET 5 // Reset activo bajo
#define VOLUME_PIN A1
#define PHOTO_PIN A2
#define MIN_VOLUME 70

#define MIN_LIGHT_LEVEL 900


bool isSdOpened=false;
File root;
File entry;
long fileCount;


unsigned long totalBytes;
int currentVolume=MIN_VOLUME-map(analogRead(VOLUME_PIN),0,1023,0,MIN_VOLUME);
int oldVolume=currentVolume;
int currentLightLevel=analogRead(PHOTO_PIN);
bool active=currentLightLevel>=MIN_LIGHT_LEVEL;

Adafruit_VS1053_FilePlayer musicPlayer = Adafruit_VS1053_FilePlayer(MP3_RESET, MP3_XCS, MP3_XDCS, MP3_DREQ, 10);

void setup(){
  pinMode(10,OUTPUT);
  Serial.begin(115200);

  musicPlayer.begin();
  
  while(!isSdOpened){
    isSdOpened=SD.begin(10);
  
    Serial.print("SD.begin ");
    Serial.println(isSdOpened);
  }

   musicPlayer.useInterrupt(VS1053_FILEPLAYER_PIN_INT); 
   musicPlayer.setVolume(currentVolume,currentVolume);
  
  root=SD.open("/");
  root.rewindDirectory();
  fileCount=0;
  entry=root.openNextFile();
  while(entry){
    fileCount++;
    Serial.print(entry.name());
    Serial.print("\t");
    if(entry.isDirectory()){
      Serial.println("Directorio");
    }
    else{
      Serial.println(entry.size(), DEC);
    }
    entry.close();
    entry=root.openNextFile();
  }
  root.rewindDirectory();
  Serial.print("Numero de ficheros: ");
  Serial.println(fileCount);
  randomSeed(analogRead(0));
  
  Serial.print("Volumen: ");
  Serial.println(currentVolume);
  Serial.println("Reset finalizado");
  
}


void loop(){
  
  currentLightLevel=analogRead(PHOTO_PIN);
  
  delay(1000);
  
  if(currentLightLevel>=MIN_LIGHT_LEVEL){
    active=true;
    if(!musicPlayer.playingMusic){
     
      
      Serial.print("currentLightLevel: ");
      Serial.print(currentLightLevel);
      Serial.print(" MIN_LIGHT_LEVEL: ");
      Serial.println(MIN_LIGHT_LEVEL);
     root.rewindDirectory();
  
     int randNumber = random(1,fileCount+1);
  
     Serial.print("Numero aleatorio: ");
     Serial.println(randNumber);
  
     for(int i=0;i<randNumber;i++){
       entry=root.openNextFile();
       entry.close();
    
      }
      Serial.print("Fichero: ");
      Serial.println(entry.name());
      
      musicPlayer.startPlayingFile(entry.name());
    }
    else{
      delay(500);
      currentVolume=MIN_VOLUME-map(analogRead(VOLUME_PIN),0,1023,0,MIN_VOLUME);
      if(currentVolume!=oldVolume){
        musicPlayer.setVolume(currentVolume,currentVolume);
        oldVolume=currentVolume;
        Serial.print("Volumen: ");
        Serial.println(currentVolume);
     }
   }
  }
  else if(active){
    Serial.print("currentLightLevel: ");
      Serial.print(currentLightLevel);
      Serial.print(" MIN_LIGHT_LEVEL: ");
      Serial.println(MIN_LIGHT_LEVEL);
      active=false;
      asm volatile ("  jmp 0");
      
     
    }
  }

Comentarios al código fuente

Hemos definido dos nuevas variables, PHOTO_PIN y MIN_LIGHT_LEVEL para definir el pin al que hemos conectado el fotorresistor y el umbral mínimo de luz para reproducir una canción. En la función loop() verificamos si la luz detectada por el fotoresistor es mayor que el umbral mínimo y si es mayor ejecutamos el mismo código que en el sketch anterior. En caso contrario comprobamos la variable active que determina si al leer un valor por debajo del umbral mínimo de luz la música estaba activa, lo cual significa que acabamos de bajar del umbral y por lo tanto hay que interrumpir la música. La forma más fácil de interrumpir la música es reiniciar el programa con la instrucción asm volatile ("  jmp 0").

Utilizando una pila

El problema del enfoque anterior es que el microcontrolador necesita estar siempre activo, es decir, consumiendo energía para poder detectar los cambios de luz. Esto nos lleva al problema de cómo proveer de energía a nuestra caja. El microcontrolador Arduino Uno puede alimentarse por USB, con un adaptador de corriente (según la documentación necesita entre 7 y 12 Voltios, pero puede soportar hasta 20) y a través del pin VIN. Las posibles opciones son:

  • Cable USB. Es poco práctico tener la caja siempre conectada a un ordenador en marcha.
  • Adaptador de corriente. Es una buena opción si vamos a tener la caja siempre en el mismo sitio, pero hay que tener en cuenta que siempre que la enchufemos estará consumiendo energía a menos que el adaptador tenga un interruptor que habría que conectar antes de abrir la caja.
  • Pilas. Se puede conectar uno de los varios adaptadores que existen para alimentarlo mediante pilas. Los hay que se conectan a la entrada DC y también que se conectan al pin VIN. Dado que el microcontrolador estará siempre consumiendo energía es poco práctico a menos que añadamos un un interruptor, o quitar la pila cuando no la usemos para que no la consuma.
  • Panel solar. El panel solar sólo estará alimentando en microcontrolador cuando reciba luz. Esta sería la solución ideal si siempre fuésemos a tener suficiente luz, ya que nos permite proveer de energía sin cables y si la ponemos en el interior de la caja solo recibirá luz cuando se abra. La ventaja adicional es que no tenemos que modificar el sketch que hemos programado en el artículo anterior.
Para terminar el diseño de la caja me he decantado por alimentarlo con la pila, que sólo alimentará el circuito se accione un pequeño interruptor que pondremos en la tapa de la caja de forma que se accione cuando la tapa se abra o se cierre. Conectaremos el pulsador de forma que cuando se presione abra el circuito, y lo cierre cuando se libere, es decir, lo presionará la tapa cuando se cierre la caja y se liberará cuando se abra. Aquí tenemos el interruptor:


Lo vamos a conectar en la entrada de corriente del circuito, que será una pila de 9 voltios


La ventaja de este montaje es que no hay que modificar el sketch del artículo anterior para que funcione y además sólo consumirá energía cuando reproduzca la música. Este es pues el diseño definitivo de nuestra caja. En el próximo artículo soldaremos los componentes a un shield para conectarlo al microcontrolador y atornillarlo a la caja.

Artículos relacionados

viernes, 30 de agosto de 2013

Construcción de una caja musical con arduino III

En este artículo vamos a añadir un potenciómetro a nuestro prototipo para ajustar el volumen del decodificador MP3. Un potenciómetro es un resistor variable que normalmente posee algún tipo de control que nos permite ajustar su resistencia y por lo tanto el voltaje que leeremos por unos de los pins analógicos del microcontrolador. En la foto vemos dos tipos de potenciómetros. En uno el ajuste de la resistencia se hace mediante una rueda que se puede girar fácilmente los dedos. En el otro se hace mediante un pequeño tornillo. Obviamente para nuestra caja usaremos el primero, ya que no queremos que el usuario tenga que ajustar el volumen con un destornillador ;-)



El potenciómetro tiene tres pines, dos de ellos van a corriente y tierra, y el tercero va conectado a uno de los pines analógicos del microcontrolador. El esquema de conexión es el siguiente


Y aquí está montado en la placa de prototipo


El sketch

El código fuente modificado para que al girar la rueda del potenciómetro se ajuste el volumen es el siguiente:

#include <SPI.h>
#include <Adafruit_VS1053.h>
#include <SD.h>

#define MP3_XCS 6   // CS Registros
#define MP3_XDCS 7  // CS Datos (BSYNC)
#define MP3_DREQ 2  // Interrupción chip disponible
#define MP3_RESET 5 // Reset activo bajo
#define VOLUME_PIN A1
#define MIN_VOLUME 70


bool isSdOpened=false;
File root;
File entry;
long fileCount;
unsigned long totalBytes;
int currentVolume=MIN_VOLUME-map(analogRead(VOLUME_PIN),0,1023,0,MIN_VOLUME);
int oldVolume=currentVolume;

Adafruit_VS1053_FilePlayer musicPlayer = Adafruit_VS1053_FilePlayer(MP3_RESET, MP3_XCS, MP3_XDCS, MP3_DREQ, 10);


void setup(){
  pinMode(10,OUTPUT);
  Serial.begin(115200);

  musicPlayer.begin();

  while(!isSdOpened){
    isSdOpened=SD.begin(10);

    Serial.print("SD.begin ");
    Serial.println(isSdOpened);
  }

   musicPlayer.useInterrupt(VS1053_FILEPLAYER_PIN_INT);
   musicPlayer.setVolume(currentVolume,currentVolume);

  root=SD.open("/");
  root.rewindDirectory();
  fileCount=0;
  entry=root.openNextFile();
  while(entry){
    fileCount++;
    Serial.print(entry.name());
    Serial.print("\t");
    if(entry.isDirectory()){
      Serial.println("Directorio");
    }
    else{
      Serial.println(entry.size(), DEC);
    }
    entry.close();
    entry=root.openNextFile();
  }
  root.rewindDirectory();
  Serial.print("Numero de ficheros: ");
  Serial.println(fileCount);
  randomSeed(analogRead(0));

  Serial.print("Volumen: ");
  Serial.println(currentVolume);

}


void loop(){

  if (! musicPlayer.playingMusic) {
    musicPlayer.softReset();
    delay(1000);
    root.rewindDirectory();

    int randNumber = random(1,fileCount+1);

    Serial.print("Numero aleatorio: ");
    Serial.println(randNumber);

    for(int i=0;i<randNumber;i++){
      entry=root.openNextFile();
      entry.close();
 
    }
    Serial.print("Fichero: ");
    Serial.println(entry.name());
    musicPlayer.startPlayingFile(entry.name());
  }
  else{
    currentVolume=MIN_VOLUME-map(analogRead(VOLUME_PIN),0,1023,0,MIN_VOLUME);
    if(currentVolume!=oldVolume){
      musicPlayer.setVolume(currentVolume,currentVolume);
      oldVolume=currentVolume;
      Serial.print("Volumen: ");
      Serial.println(currentVolume);
    }
  }
}

Comentarios al código fuente

En la instrucción currentVolume=MIN_VOLUME-map(analogRead(VOLUME_PIN),0,1023,0,MIN_VOLUME) leemos el valor de la entrada analógica y lo adaptamos al rango de valores que vamos a pasarle a la funcion setVolume(). La función analogRead(VOLUME_PIN) devuelve un valor entre 0 y 1023, pero a setVolume() le vamos a pasar un valor entre 0 y 70. La función map() devuelve un valor extrapolado de un rango a otro. En nuestro caso le pasamos un valor entre 0 y 1023 y devuelve su valor proporcional en el rango 0 a 70. Y por último restamos el valor devuelto por map() a 70 porque cuanto menor es el valor que le pasamos a setVolume() mayor es el volumen de la canción, es decir, el valor cero es el máximo volumen.
En la función loop(), cuando no se está reproduciendo la canción leemos el valor del potenciómetro y si ha cambiado ajustamos el valor con setVolume().

Con esto ya tenemos las funcionalidades básicas de nuestra caja. En la próxima entrada veremos cómo hacer que la música se reproduzca o pare cuando se abre o cierra la caja.

Artículos relacionados

 

sábado, 24 de agosto de 2013

Construcción de una caja musical con arduino II

Seguimos con la construcción de la caja musical que empezamos en Construcción de una caja musical con arduino I. Esta vez vamos a conectar el decodificador MP3 para que lea el fichero de la tarjeta SD que hemos seleccionado aleatoriamente y lo reproduzca. Para ello vamos a usar un módulo decodificador de MP3 basado en el chip VS1003/VS1053.




El esquema es el siguiente:



Y aquí lo tenemos montado en la placa de prototipo:



Como hemos visto en el esquema, el lector de tarjetas y el decodificador MP3 comparten algunas conexiones. Esto es consecuencia del uso del protocolo SPI  para la comunicación del microcontrolador con ambos dispositivos. De esta forma necesitamos menos pines para conectar varios dispositivos. Básicamente la idea es que haya un dispositivo master (el microcontrolador) y varios dispositivos esclavos (el lector de tarjetas y el decodificador MP3). El controlador elige con qué dispositivo se comunica desactivando los demás y usando las vías de comunicación comunes a todas ellas. El decodificador MP3 usa además otros cuatro pines además de los de corriente (5V y GND). La entrada XCS conectada al pin digital 6 del microcontrolador es la de Chip Select, que ha de ponerse a LOW para seleccionar el dispositivo. La entrada XDCS conectada al pin digital 7 es la de Data Chip Select, que ha de ponerse a LOW para enviar datos. La entrada DREQ conectada al pin digital 2 es la de Data Request, que estará a HIGH cuando el buffer de datos está vacío y por lo tanto podemos enviarle más. Y por último la entrada XRST conectada al pin digital 5 es la de reset, para reiniciar el dispositivo. Como veremos en el sketch, todo esto no debe preocuparnos ya que vamos a usar una biblioteca que nos permite obviar todos los detalles del protocolo SPI.

El sketch

Vamos a modificar el sketch del primer artículo de la serie para enviar el fichero seleccionado de la tarjeta al decodificador MP3. Para ello vamos a usar la biblioteca Adafruit VS1053 que se puede descargar aquí, ya que no viene por defecto en el IDE de arduino. Para instalarla hay que copiar los dos ficheros, Adafruit_VS1053.h y Adafruit_VS1053.cpp en una carpeta que crearemos donde están el resto de bibliotecas de nuestro IDE. O bien los podemos importar desde cualquier otra carpeta con la opción Sketch/Importa biblioteca.../Añadir del propio IDE de arduino. El código fuente del sketch es el siguiente:

#include <SPI.h>
#include <Adafruit_VS1053.h>
#include <SD.h>

#define MP3_XCS 6   // CS Registros
#define MP3_XDCS 7  // CS Datos (BSYNC)
#define MP3_DREQ 2  // Interrupción chip disponible
#define MP3_RESET 5 // Reset activo bajo


bool isSdOpened=false;
File root;
File entry;
long fileCount;
unsigned long totalBytes;

Adafruit_VS1053_FilePlayer musicPlayer = Adafruit_VS1053_FilePlayer(MP3_RESET, MP3_XCS, MP3_XDCS, MP3_DREQ, 10);


void setup(){
  pinMode(10,OUTPUT);
  Serial.begin(115200);

  musicPlayer.begin();

  while(!isSdOpened){
    isSdOpened=SD.begin(10);

    Serial.print("SD.begin ");
    Serial.println(isSdOpened);
  }

  musicPlayer.setVolume(10,10);

   musicPlayer.useInterrupt(VS1053_FILEPLAYER_PIN_INT);

  root=SD.open("/");
  root.rewindDirectory();
  fileCount=0;
  entry=root.openNextFile();
  while(entry){
    fileCount++;
    Serial.print(entry.name());
    Serial.print("\t");
    if(entry.isDirectory()){
      Serial.println("Directorio");
    }
    else{
      Serial.println(entry.size(), DEC);
    }
    entry.close();
    entry=root.openNextFile();
  }
  root.rewindDirectory();
  Serial.print("Numero de ficheros: ");
  Serial.println(fileCount);
  randomSeed(analogRead(0));

}


void loop(){

  if (! musicPlayer.playingMusic) {
    musicPlayer.softReset();
    delay(1000);
    root.rewindDirectory();

    int randNumber = random(1,fileCount+1);

    Serial.print("Numero aleatorio: ");
    Serial.println(randNumber);

    for(int i=0;i<randNumber;i++){
      entry=root.openNextFile();
      entry.close();
 
    }
    Serial.print("Fichero: ");
    Serial.println(entry.name());
    musicPlayer.startPlayingFile(entry.name());
  }

}

Comentarios al código fuente

La primera línea que hemos añadido es #include <Adafruit_VS1053.h> para poder usar las funciones de acceso al decodificador MP3. En la instrucción Adafruit_VS1053_FilePlayer musicPlayer = Adafruit_VS1053_FilePlayer(MP3_RESET, MP3_XCS, MP3_XDCS, MP3_DREQ, 10) estamos inicializando el decodificador MP3 con los valores de los pines a los que lo hemos conectado. Y finalmente musicPlayer.startPlayingFile(entry.name()) reproduce el fichero. Hemos añadido el if (! musicPlayer.playingMusic) porque la función de reproducción devuelve el control al programa inmediatamente, lo cual es importante si queremos hacer más cosas mientras se reproduce la canción como es nuestro caso. Pero esto ya lo veremos en la tercera entrega donde conectaremos un potenciómetro para controlar el volumen al que se reproducirá la canción.

Artículos relacionados