Paso 3: Salida de Audio Mono con DAC de 8 bits y frecuencia de muestreo de 44,1 kHz
El diagrama esquemático para la configuración del CAD se muestra en la figura 2. AGND y DGND (pines 1 y 5) conectan a masa de Arduino. VDD (pin 17), OUTA (pin 2), número (pin 20). RFBA (pin 3) y RFBB (pin 19) conectan a 5V de Arduino. WR (pin 16) se conecta al pin digital 10 CS (pin 15) se conecta al pin digital 9 y DACA/DACB (pin 6) se conecta al pin digital 8. DB0-DB7 (pines 14-7) conectar a los pines digitales 0-7. Las salidas de la DAC son pernos 4 (DACA) y 18 (DACB).
En el siguiente código de pieza utilizo una interrupción de temporizador para enviar datos a la DAC a una velocidad de unos 44,1 kHz (frecuencia de muestreo de audio estándar). Las interrupciones son rutinas que se ejecutan en intervalos de tiempo específicamente. Mientras que el Arduino ejecuta comandos en el loop() principal función pausa para ejecutar el contenido de {} ISR(TIMER1_COMPA_vect) a una tasa de 44.1 kHz. Una vez que se ejecutaron los comandos dentro de la función, el Arduino reanuda lo que estaba haciendo en la función loop(). Así que fácilmente podemos añadir código a la función de bucle (Revise sensores, encender leds, etc.) y no tener que preocuparse por la sincronización de la salida de audio. Las siguientes líneas configuración la interrupción:
CLI (); //stop interrupciones
interrupción timer1 set en ~44.1kHz
TCCR1A = 0; / / todo registro TCCR1A para 0
TCCR1B = 0; / / única para TCCR1B
TCNT1 = 0; //initialize valor de contador a 0
compara Set match registrarse en incrementos de 1hz
OCR1A = 361; / / = (16 * 10 ^ 6) / (44100 * 1) - 1 (debe ser < 65536)
Activar modo de CTC
TCCR1B | = (1 << WGM12);
Establezca el bit CS10 para 1 prescaler
TCCR1B | = (1 << CS10);
habilitar interrupción de timer en comparación
TIMSK1 | = (1 << OCIE1A);
SEI (); //enable interrupciones
Se da una explicación completa de estas líneas en mi tutorial de interrupción del temporizador de Arduino. Dentro de la rutina de interrupción nos encontramos las siguientes líneas:
PORTD = Sierra; //send serrar a la DAC a través de los pines digitales 0-7
Sierra ++; //increment Sierra valor por uno
Si (VI == 256) {//reset vio si llega a 256 (salida mantiene dentro siempre de 0-255)
VI = 0;
}
Así que cada vez que la rutina de interrupción ejecuta envía el valor de la variable "vio" a la DAC. Luego la sierra variable se incrementa en uno para la próxima vez que se ejecuta la rutina de interrupción. Si es de la Sierra > 255 se restablece a cero. Esencialmente el Arduino envía los números de 0-255 a la DAC y luego reiniciar a 0 una vez que alcanza 255. Esto producirá una onda de Sierra de la DAC (fig 7).
He observado en los comentarios del código que no se está ejecutando la rutina de interrupción en exactamente 44,1 kHz, pero tan cerca como pude conseguir. La tasa de muestreo actual es 44,199 kHz (que es en realidad un poco mejor que 44.1). Esto era debido a algunas limitaciones en la configuración de las interrupciones de temporizador. Usaremos este número para calcular cierta información sobre la salida DAC:
duración de cada muestra = velocidad de muestreo de 1
duración de cada muestra = 1/44199 Hz = 22.6us
Figura 8 muestra que un zoom a la vista de la DAC vieron salida en un osciloscopio. Se puede ver el 22.6us individual pasos de la onda, tan calculada. El período de la onda (la longitud de la sierra completa un ciclo) es:
período = duración de cada muestra * muestras por ciclo
periodo = 22.6us * 256 = 5.8ms
y la frecuencia:
frecuencia = 1/periodo
frecuencia = 1/0.0058s = 172 Hz
Estos pueden verse en la figura 6.
<pre>//mono saw out with 44.1kHz sampling rate //by Amanda Ghassaei //Nov 2012
El código siguiente salidas una onda sinusoidal utilizando la misma interrupción establecido anteriormente. Arduino ha construido en función del seno, pero es demasiado lento para ejecutar a 44,1 kHz, por lo que almacena un conjunto de valores del seno para tirar de durante cada interrupción. Corrí un simple script en Python (abajo) para generar 100 valores de 127+127*sin(2*3.14*t/100):
importación matemáticas
para x en el rango (0, 100):
imprimir str(int(127+127*math.sin(2*math.pi*x*0.01)),)+str(","),
I estos números almacenados en un array llamado "seno" y luego ponga la siguiente línea en la rutina de interrupción:
PORTD = seno [índice]; //send un valor almacenado en el seno de la matriz hacia fuera a la DAC a través de digital pins 0-7
Índice ++; Índice de //increment por uno
Si (índice == 100) {índice de //reset si llega a 100
índice = 0;
}
estas líneas envían un valor de la matriz "seno", especificado por el valor de la variable "index", a PORTD. Entonces "índice" se incrementa en uno para el siguiente ciclo. Si Índice > 99 consigue poner a cero. La salida de este código se muestra en la figura 9.
Desde que utilicé la misma configuración de interrupción como el código de la sierra, la duración de cada muestra es el mismo: 22.6us (fig 10). Puesto que sólo hay 100 muestras por ciclo para este seno (muestras vs 255 por ciclo para la sierra) el periodo es:
período = duración de cada muestra * muestras por ciclo
periodo = 22.6us * 100 = 2.3ms
frecuencia = 1/periodo
frecuencia = 1/0.0023s = 442 Hz
Estos pueden verse en la fig 9
<pre>//mono sine out with 44.1kHz sampling rate //by Amanda Ghassaei //Nov 2012