Reproductor de archivos WAVE LPCM usando microcontrolador AVR y librería Petit FAT

Herramientas necesarias:

(FREE) AVR Studio 4.19 --> para compilar código del AVR
(FREE) Free MP3 WMA Converter -> para convertir archivos .MP3 a .WAV
(NO FREE) WinHex 16.0 -> Para analizar los archivos WAV

(NO FREE) Proteus 7.9 -> para simular el reproductor
(NO FREE) WinImage 8.50 --> para crear imagen necesaria para poder simular mmc en proteus, en esta imagen se almacena los archivos WAV

OTROS (opcional)
EditPlus TEXT editor v3.31 --> para explorar fuentes

Notas:
1- Así como esta solo reproduce archivos de 8 bits stereo… dará error en caso de usar un archivo wav mono.
2- En caso de recompilar el proyecto, les recomiendo usar el archivo delay.h para los retardos contenido en el proyecto, ya que no se por qué el que viene por default <util/delay.h> no me funciona.
3- En mis pruebas use una SDC Kingston de 2GB, formateada en FAT16 Para reproducir audio, no he probado la calidad usando FAT32 la verdad no lo he comprobado con el reproductor, pero si he comprobado que lee archivos cuando esta formateada en FAT32.
4- Este código ya lo he probado funciona de maravilla, usando un filtro pasa bajo de primer orden, no pude eliminar un pequeño ruido de fondo, pero he leído que usando R2R la señal resultante tendría mejor calidad.
5- Tambien va una simulación en proteus, aunque esta necesita una imagen conteniendo archivos WAV y una buena PC para simularse en tiempo real.
6- Soporta solo archivos en 8:3, es decir 8 caracteres de nombre, sin espacios y 3 de extensión, ejemplo: (PLAYLIST.WAV).
7- La idea final era dejar un reproductor completo funcionando con el lcd rotando el nombre de artista y nombre de canción (usando ID3v1 o ID3v2 con Free MP3 WMA Converter), duración total y progreso de tiempo con actualización pero para esto debemos usar otro mcu, yo tenía pensado un PIC16F84 el cual se encargaría del lcd, también seria genial usar R2R para una mejor calidad de señal.
8- El archivo Sine_Wave_Generator.pdf explica la lógica del PWM timer, en este pdf se basa la función ini_timers.


Inicialmente estaba usando el MCU AVR ATmega328P pero lo termine dañando, y no pude conseguir otro, así que termine usando un ATmega644. El proyecto trabaja con una frecuencia de 16 MHZ pero ustedes pueden recompilarlo para trabajar con una frecuencia de 20 MHZ.
Este reproductor usa la librería petit FAT de ELM-CHAN. En caso de no tener el ATMEGA644 ustedes pueden recompilarlo fácilmente para usar un ATMEGA32 u otro ATMEGA pero considerando la frecuencia de reloj permitida por el dispositivo a usar.

¿Cómo usar?:

Con las funciones de petitFAT tenemos acceso a una SD card formateada en FAT16 ó FAT32, así que demos formato a nuestra SDCy usando Free MP3 WMA Converter convertimos nuestra música en archivo WAV stereo con sample rate de 44100 Hz muestra de 8 bits, estos archivos WAV no están en LNF (long file name) así que deben de tener la forma 8:3 dicho de otra forma 8 caracteres de nombre y 3 de extensión ejemplo; PLAYLIST.WAV.

Luego debemos almacenar los archivos WAV en raíz de la SDC ya que el reproductor empezara a reproducir todos los archivos WAV encontrados en raíz.

El LCD es mas para depuración, en caso de que una función falle en el display se visualizaran qué función fallo, si todo sale bien al final se muestra el nombre del archivo el sample rate y la duración en minutos de la canción.

Principio de funcionamiento:
Básicamente se usan 2 buffers de audio de 512 bytes.
Usando el timer 1 (interrupción) se consigue la frecuencia de reproducción es decir el sample rate de la canción y usando el timer 0 con fast PWM las muestras extraídas del archivo son moduladas en PWM para salir por los pines OC0B y OC0A.

El AVR lee 512 bytes del archivo y los almacena en uno de los buffers, mientras un buffer está siendo usado por el timer 1, el MCU estará llenando el otro buffer.


En el Archivo lcd.h // configuramos los pines para el LCD con controlador HD44780 de hasta 16x2, 20x2, 20x4, etc.

CONFIGURACIÓN DE LOS PINES DE INTERFACE
/*Si lcd_data_nibble = 0 se utilizará el nible bajo del puerto escogido (ejem. PB0-DB4,...,PB4-DB7)*/
/*Si lcd_data_nibble = 1 se utilizará el nible alto del puerto escogido (ejem. PB4-DB4,...,PB7-DB7)*/

#define lcd_data_nibble 1

/* Define el puerto a donde se conectará el bus de datos del LCD
*/
#define lcd_DATAout PORTA // Registro PORT del puerto
#define lcd_DATAin PINA // Registro PIN del puerto
#define lcd_DATAddr DDRA // Registro DDR del puerto

/* Define los ó el puerto a donde se conectarán las líneas de control del LCD
* E, RW y RS. Puede ser el mismo puerto del bus de datos.
*/
#define lcd_RSout PORTA // Registro PORT del puerto
#define lcd_RSin PINA // Registro PIN del puerto
#define lcd_RSddr DDRA // Registro DDR del puerto

#define lcd_RWout PORTA // Registro PORT del puerto
#define lcd_RWin PINA // Registro PIN del puerto
#define lcd_RWddr DDRA // Registro DDR del puerto

#define lcd_Eout PORTA // Registro PORT del puerto
#define lcd_Ein PINA // Registro PIN del puerto
#define lcd_Eddr DDRA // Registro DDR del puerto
/* Define los números de los pines del puerto anterior que corresponderán a
* las líneas E, RW y RS del LCD.
*/
#define lcd_E 3 // Pin Enable
#define lcd_RW 2 // Pin Read/Write
#define lcd_RS 1 // Pin Register Select

En el Archivo main.c
ini_timers() : al cambiar de MCU se debe configurar esta función para que este acorde al MCU seleccionado.

En el Archivo spi.c
Hay 2 funciones init_spi() y spi_high_clk()
init_spi() : Sirve para inicializar el spi del avr que hemos seleccionado (si se usa otro MCU revisar esta función y configurar los pines adecuadamente)


spi_high_clk() : configure la máxima frecuencia para el spi, es decir la mitad de la frecuencia de reloj (fck/2)


En el Archivo mmc.c
#include "spi.h"
(si se usa otro MCU revisar esta parte y poner el pin y el puerto adecuado, aquí se especifica CS (chip select))

/* Port Controls (Platform dependent) PB2 -> SS*/
#define SELECT() PORTB &= ~_BV(2) /* MMC CS = L */
#define DESELECT() PORTB |= _BV(2) /* MMC CS = H */
#define MMC_SEL !(PORTB & (1<<2)) /* MMC CS status (true:selected) */

En el Archivo mmc.c
#define _USE_READ 1 /* pf_read(): 0:Remove ,1:Enable */

#define _USE_DIR 1 /* pf_opendir() and pf_readdir(): 0:Remove ,1:Enable */

#define _USE_LSEEK 1 /* pf_lseek(): 0:Remove ,1:Enable */

#define _USE_WRITE 0 /* pf_write(): 0:Remove ,1:Enable */

#define _FS_FAT32 1 /* 0:Supports FAT12/16 only, 1:Enable FAT32 supprt */


#define _CODE_PAGE 1 // (1 es para usar solo ASCII)

#define _WORD_ACCESS 1
/ 0: Byte-by-byte access. Always compatible with all platforms.
/ 1: Word access. Do not choose this unless following condition is met.


Acá dejó el código fuente y otros archivos útiles:
 

Adjuntos

  • sdc1.jpg
    sdc1.jpg
    55.2 KB · Visitas: 25
  • fuses.png
    fuses.png
    64.4 KB · Visitas: 22
  • Sin título.png
    Sin título.png
    135.6 KB · Visitas: 19
  • atmega644 play.png
    atmega644 play.png
    50.6 KB · Visitas: 24
  • Sine_Wave_Generator.pdf
    209.4 KB · Visitas: 21
  • player.jpg
    player.jpg
    64.3 KB · Visitas: 18
  • wave-bytes.gif
    wave-bytes.gif
    14.5 KB · Visitas: 21
  • avr_player_ATmega644.rar
    174.4 KB · Visitas: 26
Última edición:
Si, se puede abrir un archivo .mot pero no en LFN, ahora tendríamos que ver la capacidad de procesamiento que se necesite para procesar la información de este.
Interesante eso de los archivos .mot, no lo sabía, investigare un poco más sobre esto. gracias por la información.
 
bueno aca te subo una aplicacion gratuita no nesesita intalacion pasa de una imagen de bimap o bmp a mot y es facil de usar...es simple se crea una secuencia de imagenes...... con la animacion de color o movimiento parecida a un .GIF
 

Adjuntos

  • bmp2mot.rar
    318.3 KB · Visitas: 6
Atrás
Arriba