Tabla de contenido:

Reproducción de archivos de sonido de audio (WAV) con un Arduino y un DAC: 9 pasos
Reproducción de archivos de sonido de audio (WAV) con un Arduino y un DAC: 9 pasos

Video: Reproducción de archivos de sonido de audio (WAV) con un Arduino y un DAC: 9 pasos

Video: Reproducción de archivos de sonido de audio (WAV) con un Arduino y un DAC: 9 pasos
Video: Como REPRODUCIR MÚSICA, AUDIOS y GRABACIONES con ARDUINO y MODULO SD LVC125A || Bien Explicado 2020 2024, Noviembre
Anonim
Reproducción de archivos de sonido de audio (WAV) con un Arduino y un DAC
Reproducción de archivos de sonido de audio (WAV) con un Arduino y un DAC
Reproducción de archivos de sonido de audio (WAV) con un Arduino y un DAC
Reproducción de archivos de sonido de audio (WAV) con un Arduino y un DAC
Reproducción de archivos de sonido de audio (WAV) con un Arduino y un DAC
Reproducción de archivos de sonido de audio (WAV) con un Arduino y un DAC

Reproduzca audio de archivo wav desde su tarjeta SD Audino. Este Instructable le mostrará cómo se puede reproducir un archivo wav en su SdCard a través de un circuito simple a un altavoz.

El archivo wav debe ser mono de 8 bits. No he tenido problemas para reproducir archivos de 44 KHz.

Aunque no es de alta fidelidad, la calidad del sonido es muy satisfactoria.

El monitor de serie se utiliza para seleccionar el archivo. Los archivos deben estar en una carpeta llamada adlog.

Este instructivo se deriva de un proyecto anterior en el que guardé grabaciones wav en la SdCard:

El circuito utiliza un convertidor de digital a analógico (DAC) económico de 8 bits y un amplificador de audio de un solo chip.

Las secciones clave para configurar interrupciones fueron tomadas del excelente artículo de Amanda Ghassaei:

Paso 1: requisitos

Requisitos
Requisitos
Requisitos
Requisitos

Arduino: uso el Mega, sin embargo, no hay ninguna razón por la que el Uno no debería funcionar.

Lector de tarjetas SdCard: el programa está configurado para: Placa de conexión MicroSD regulada con conversión lógica V2

Consulte este instructivo para obtener detalles de configuración de SdCard:

DAC0832 LCN: un excelente conversor de digital a analógico de 8 bits: unas pocas libras.

Amplificador operacional LM386 N-1 - barato como chips

Toma de chip de 20 vías

Toma de chip de 8 vías

Fuente de alimentación de 9 voltios: una batería servirá.

Referencia de voltaje LM336 2.5 V

Condensador de 10 uF * 3 (cualquier voltaje superior a 9 V)

Resistencia de 10 ohmios

Condensador de 50nF- (O en algún lugar cercano a -47nF, 56nf, 68nf- servirá)

Condensador 220uF

Altavoz de 64 ohmios

Potenciómetro lineal de 10K

Cable para conectar las 8 líneas de datos entre el Arduino y el circuito-

En el Uno, las 8 conexiones están en línea, en el Mega están en pares.

En el Mega utilicé un cable plano de 10 vías con un encabezado IDC de 10 vías. (2 cables son de repuesto)

Conectores de enchufe para salida 0V, 9V y DAC

Tablero de tiras de cobre, soldadura, alambre, cortadores, etc.

Paso 2: las especificaciones

Las especificaciones
Las especificaciones

Serie fijada a 115200 baudios.

Se cuenta con soporte para la placa de conexión MicroSD de Hobbytronics usando un Mega. La selección de chip y otros puertos cambiarán entre Mega y Uno.

Los archivos Wav deben existir en un directorio llamado adlog. Siéntase libre de nombrarlo de otra manera y reorganizar la codificación necesaria.

El archivo wav debe ser mono de 8 bits. He probado hasta 44 KHz.

El monitor serial muestra los archivos wav en la carpeta adlog. Los nombres de archivo se envían desde la línea de salida del monitor.

El tamaño del archivo solo está limitado por el tamaño de la tarjeta SdCard.

Paso 3: Comenzando

Empezando
Empezando

Conecte el lector de tarjetas SD. Estas son las conexiones del Mega.

0, 5 V

CLK al pin 52

D0 al pin 50

D1 al pin 51

CS al pin 53

(Consulte el sitio web de los proveedores para conocer la conexión del puerto Uno)

Querrá probar que su tarjeta funciona en esta etapa; use los scripts proporcionados por el proveedor.

Necesitamos hacer un pequeño circuito

Vamos a enviar un flujo de bytes de audio desde Arduino.

Estos números están entre 0 y 255. Representan el voltaje.

El silencio es 127-128.

255 es un cono de altavoz duro en un sentido.

0 es el cono del altavoz duro al revés.

Por lo tanto, el audio se graba como números guardados, que crean voltajes variables, que crean conos de altavoz en movimiento.

Podemos enviar los números de 8 líneas en el Arduino, simultáneamente, usando un "puerto".

Si alimentamos las 8 líneas en un convertidor de digital a analógico, hace lo que dice en la lata y produce un voltaje analógico que es proporcional al número digital.

Todo lo que tenemos que hacer entonces es empacar el voltaje en un pequeño amplificador operacional y luego en un altavoz.

Paso 4: el circuito pequeño

El circuito pequeño
El circuito pequeño
El circuito pequeño
El circuito pequeño
El circuito pequeño
El circuito pequeño
El circuito pequeño
El circuito pequeño

El DAC0832 LCN

Este es un conversor digital a analógico de 8 bits excelente y económico. (DAC)

Se puede controlar por completo con una serie de retenciones de datos y líneas de muestreo de datos.

O se puede configurar para que lo haga todo automáticamente en "Funcionamiento continuo".

Para citar el manual:

Simplemente conectar a tierra CS, WR1, WR2 y XFER y atar ILE alto permite que ambos registros internos sigan las entradas digitales aplicadas (flujo continuo) y afecten directamente a la salida analógica DAC.

De acuerdo, son cuatro conexiones al conjunto de chips bajo y una a 9V, fácil.

No queremos que salga ningún voltaje negativo, por lo que el manual dice que debemos usar el "modo de conmutación de voltaje" y ellos proporcionan el diagrama.

Todo lo que tenemos que hacer es sustituir un pequeño amplificador de audio en lugar del que sugieren.

El amplificador de audio LM386-N

El manual del amplificador proporciona un diagrama de partes mínimas, que proporciona una ganancia de 20 (demasiado para nosotros, pero tiene un control de volumen).

Todo lo que tenemos que hacer es agregar un capacitor entre el DAC y el amplificador para que solo amplifiquemos las señales de CA.

También debemos agregar un par de condensadores cerca del pin de suministro de cada uno de nuestros chips, de lo contrario obtendremos zumbidos de nuestro suministro de 9V.

Paso 5: saca el soldador

Saca el soldador
Saca el soldador
Saca el soldador
Saca el soldador
Saca el soldador
Saca el soldador

Como el circuito es sencillo no pretendo dar una cuenta golpe a golpe.

A continuación, se muestran algunos consejos:

  • Prepare un trozo de tablero de tiras de cobre de al menos 28 por 28 agujeros. (Sí, sé que los neurocirujanos pueden hacerlo más pequeño)
  • Si tiene la intención de montarlo con tornillos, ¡déjelos al principio!
  • Monte los chips en los zócalos. Inserte las fichas solo cuando todo haya sido verificado.
  • Mantenga los cables de entrada alejados de la salida.
  • Observe la polaridad correcta de los condensadores.
  • Consulte el diagrama para ver la vista base de la referencia de voltaje del LM336. La pata de ajuste no se usa y se puede cortar.
  • Tenga en cuenta la conexión directa al pin 8 del DAC: es muy útil para realizar pruebas.
  • Me conecté al Audino con un cable plano y un conector IDC de 10 vías.
  • En el Uno, las conexiones están en línea recta; puede encontrar que organizar las 8 conexiones de entrada en una sola línea recta le permite conectarse al Arduino con un conector de 8 vías comprado y listo para usar.

Cuando termine, verifique la soldadura y verifique los espacios entre las pistas de cobre.

Encuentro una hoja de sierra de corte junior de 36 tpi muy útil para limpiar escombros. Quito los pasadores de ubicación de la hoja y deslizo la punta de la hoja en la pista. Obviamente, la hoja no está en un marco.

Paso 6: probar el DAC

Probando el DAC
Probando el DAC

Deje la conexión entre el circuito y el Arduino apagada.

Ajuste el control de volumen de su circuito a la mitad.

Encienda la alimentación de 9 V CC a su nuevo circuito.

Compruebe que el circuito esté bien. ¡No puedo aceptar ninguna responsabilidad por su circuito!

Apagado

Conecte su circuito al Arduino.

En el Mega use los pines 22-29. (PORTA) ¡No confunda los dos pines de 5V anteriores!

En el Uno use los pines 0-7. Esto es PORTD

Conecte el 0V de su fuente de alimentación al 0V en el Arduino.

Encender.

Abra este programa de prueba DAC_TEST

Para UNO, reemplace todas las referencias a PORTA por PORTD

Reemplace DDRA con DDRD: esta instrucción establece que las 8 líneas se emitan de una vez. Este es el registro de dirección de datos.

Configure su monitor serial en 115200.

Conecte un voltímetro entre la salida DAC y OV

El programa establecerá la salida en 255, todas las líneas encendidas, voltaje máximo.

Salida 128- mitad de voltaje máximo.

Salida 0- voltaje cero (o probablemente casi cero).

Luego, avanzará a nivel de bits: 1, 2, 4, 8, 16, 32, 64, 128

El voltaje debe aumentar de manera constante.

Si el voltaje cae mientras el número aumenta, probablemente tenga dos de los cables de interconexión invertidos.

También debería escuchar el clic silencioso del altavoz a medida que cambia el voltaje

Paso 7: leer el encabezado de Wav

Leer el encabezado de Wav
Leer el encabezado de Wav

Los archivos WAV se guardan con una frecuencia y un tamaño de datos específicos.

Esta información está contenida en un encabezado de 44 bytes al comienzo de un archivo wav.

Aunque algunos programas amplían el encabezado (después del byte 35), lo que dificulta la ubicación del tamaño de los datos.

Para leer el encabezado creamos un búfer y copiamos el inicio del archivo.

La frecuencia se almacena en 4 bytes comenzando 24 bytes en el archivo.

// leer la frecuencia especificada en el encabezado del archivo wav

byte headbuf [60]

tempfile.seek (0);

tempfile.read (headbuf, 60);

retval = headbuf [27];

retval = (retval << 8) | headbuf [26];

retval = (retval << 8) | headbuf [25];

retval = (retval << 8) | headbuf [24];

Serial.print (F ("Frecuencia de archivo"));

Serial.print (retval);

La mejor manera de encontrar la información del tamaño de los datos es buscar la palabra "datos" en el encabezado.

Luego extrae los 4 bytes que le siguen, que componen el valor largo

retiro largo sin firmar;

int mypos = 40;

para (int i = 36; i <60; i ++) {

if (headbuf == 'd') {

if (headbuf [i + 1] == 'a') {

if (headbuf [i + 2] == 't') {

if (headbuf [i + 3] == 'a') {

// por fin lo tenemos

mypos = i + 4;

i = 60;

}

}

}

}

}

tempfile.seek (mypos);

retval = headbuf [mypos + 3];

retval = (retval << 8) | headbuf [mypos + 2];

retval = (retval << 8) | headbuf [mypos + 1];

retval = (retval << 8) | headbuf [mypos];

¡Bien, tenemos la longitud y frecuencia de los datos!

Los datos de audio siguen los 4 bytes que componen el valor de longitud de los datos.

Paso 8: interrumpir, interrumpir…

Interrumpir, interrumpir…
Interrumpir, interrumpir…

Usamos la información de frecuencia para crear una interrupción de software en o cerca de la frecuencia requerida.

La interrupción no siempre se puede establecer con precisión, pero es suficiente. La frecuencia leída del archivo se pasa a la subrutina setintrupt.

void setintrupt (float freq) {float bitval = 8; // 8 para temporizadores de 8 bits 0 y 2, 1024 para temporizadores de 1 byte

setocroa = (16000000 / (frecuencia * bitval)) - 0.5;

// El valor de setocroa requiere una resta de -1. Sin embargo, agregando 0.5 rondas al 0.5 más cercano

// La resolución del temporizador es limitada

// Determinado en última instancia por la magnitud de bitval

cli (); // deshabilita las interrupciones // establece la interrupción del temporizador2

TCCR2A = 0; // establece todo el registro TCCR2A en 0

TCCR2B = 0; // lo mismo para TCCR2B

TCNT2 = 0; // inicializar el valor del contador a 0

// establece el registro de comparación de coincidencias para incrementos de frecuencia (hz)

OCR2A = setocroa; // = (16 * 10 ^ 6) / (frecuencia * 8) - 1 (debe ser <256)

// activa el modo CTC

TCCR2A | = (1 << WGM21); // Establecer el bit CS21 para 8 prescaler

TCCR2B | = (1 << CS21); // habilitar la interrupción de la comparación del temporizador

// TIMSK2 | = (1 << OCIE2A); // esto funciona, al igual que la siguiente línea

sbi (TIMSK2, OCIE2A); // habilita la interrupción en el temporizador 2

sei (); // habilitar interrupciones

Los lectores exigentes habrán detectado sbi (TIMSK2, OCIE2A)

Configuré un par de funciones (adquiridas por Internet) para configurar y borrar bits de registro:

// Define para borrar los bits de registro # ifndef cbi

# definir cbi (sfr, bit) (_SFR_BYTE (sfr) & = ~ _BV (bit))

#terminara si

// Define para configurar bits de registro

#ifndef sbi

#define sbi (sfr, bit) (_SFR_BYTE (sfr) | = _BV (bit))

#terminara si

Estas funciones proporcionan una llamada fácil para establecer o borrar la interrupción.

Entonces la interrupción se está ejecutando, ¿qué podemos hacer que haga?

Paso 9: interrupciones y almacenamiento en búfer doble

Interrupciones y doble búfer
Interrupciones y doble búfer
Interrupciones y doble búfer
Interrupciones y doble búfer

A 22 Khz, se emite un byte de datos de audio cada 0,045 ms

512 bytes (el tamaño del búfer) se leen en 2,08 ms.

Por lo tanto, el búfer no se puede leer desde la SDCard en un ciclo de escritura.

Sin embargo, se escriben 512 bytes en el puerto en 23,22 ms.

Así que todo lo que tenemos que hacer es configurar un nuevo archivo leído cada vez que el búfer se vacía y tenemos tiempo suficiente para obtener los datos antes de que se requiera un nuevo bloque de datos … Suponiendo que usamos dos búferes, vaciando uno mientras llenamos otro.

Esto es doble búfer.

La lectura del archivo se ralentizará por la interrupción repetida, pero se completará.

He configurado dos búferes de 512 bytes llamados bufa y bufb.

Si la bandera ya es verdadera, leemos desde porta; de lo contrario, leemos desde portb

Cuando la posición del búfer (búfer) alcanza el tamaño del búfer (BUF_SIZE 512), establecemos un indicador llamado readit en verdadero.

La rutina de bucle vacío busca este indicador e inicia una lectura de bloque:

if (readit) {if (! aready) {

// iniciar la lectura del bloque SDCard en bufa

tempfile.read (bufa, BUF_SIZE);

} demás {

// inicia la lectura del bloque SDCard en bufb

tempfile.read (bufb, BUF_SIZE);

}

readit = false;

}

Cuando ha terminado, la rutina marca readit = false.

Dentro de la rutina de interrupción debemos comprobar que el bucle void ha finalizado comprobando si readit == false.

Siendo este el caso, indicamos que se requiere otra lectura y cambiamos la bandera de listo para cambiar de búfer.

Si la tarjeta SD todavía está leyendo, tenemos que retroceder una lectura (contador--; búfer--;) y salir de la interrupción para volver a intentarlo más tarde. (Los clics en la señal de salida de audio implican que esto ha ocurrido).

Cuando se leen todos los datos, la interrupción se cancela, el puerto se restablece al valor de voltaje medio de 128 y el archivo de audio se cierra.

Antes de ejecutar el script dac2.ino por primera vez, configure su volumen al 50%. Esto será demasiado alto, ¡pero es mejor que el 100%!

Si su control de volumen funciona a la inversa, cambie los cables en los extremos opuestos del potenciómetro de 10K.

Déjame saber cómo suena.

Recomendado: