Você está na página 1de 9

Reproducir sonidos .

WAV con PIC usando PWM [CCS+18F4550+MATLAB]

Revision 1. Septiembre 2011. English version here added

El objetivo de este artculo es explicar la manera de reproducir sonidos usando un microcontrolador PIC y la salida PWM que muchos llevan incorporada como DAC (conversor digital a analgico). El origen del sonido ser un fichero .wav que ya tendremos ms o menos tratado con algn programa de edicin de sonido y que ser introducido en la memoria del PIC previo tratamiento de los datos usando MATLAB.

La principal preocupacin no es la calidad de sonido, ya que limitaciones como la memoria del PIC o la resolucin de la salida PWM hacen imposible obtener una calidad buena de sonido, pero para voces habladas y sonidos concretos ser ms que suficiente.

Yo he usado lo siguiente y est probado de esta forma:

PIC 18F4550 CCS PICC (compilador de C para PICs) MATLAB Procesador de textos Un fichero .wav (16bits / 44100Hz)

El archivo de sonido .wav

1/9

Reproducir sonidos .WAV con PIC usando PWM [CCS+18F4550+MATLAB]

El archivo original es bocina3.wav , es un archivo muestreado a 44100hz, 16 bits y mono. Para el que no est demasiado familiarizado con estos trminos esto quiere decir que 44100 veces cada segundo se toma el valor de la seal analogica original (el sonido) y que el valor que se lee, al pasarlo a un numero binario, se usan 16 bits.

Para este ejemplo, te recomiendo que con un programa de edicion de sonido pases a mono el fichero -salvo que seas un machote y quieras usar dos salidas PWM-, reduzcas el muestreo lo mximo posible (ahora recordaremos las limitaciones).

La norma para remuestrear (resample) para reducir la cantidad de datos esta controlada por la teora del muestreo. Bsicamente, si lo que quieres es reproducir sonidos audibles (1-20000hz) necesitars al menos el doble de frecuencia de muestreo que la mxima frecuencia que quieras oir.

Esto es conocido como tasa de Nyquist. Bsicamente lo que nos dice es que para muestrear una seal de frecuencia "f" y poder reconstruirla correctamente despus, es necesario que la frecuencia de muestreo sea al menos "2 x f". De ah sale el habitual 44100Hz. As se evita la aparicin de "alias", seales a frecuencias que no existen en la seal original.

Si lo que quieres es producir un sonido de voz humana, las frecuencias para que se entienda el mensaje no suelen superar los 2000Hz, por lo que podrs muestrear a 4000Hz. que importancia tiene esto? El tamao del fichero! Imagina que tienes un sonido de 10 segundos que quieres meter en el microcontrolador. Vamos a calcular ahora el tamao que tendr dependiendo de la tasa de muestreo: - a 44100hz, 8 bits son: (3528000 bits) 441k - a 4000hz, 8 bits son: (320000 bits) 40k

Se puede ver, que el primer fichero no va a ser muy fcil de meter en la memoria del PIC. Se podra intentar con un par de memorias 24xx1025 usando el bus I2C, suponiendo que el microcontrolador fuera capaz de leer del bus y reproducir en tiempo real. Pero el segundo si sera ms o menos posible dependiendo de la gama del PIC!

Crear la tabla de datos para la ROM del PIC usando Matlab.

2/9

Reproducir sonidos .WAV con PIC usando PWM [CCS+18F4550+MATLAB]

Lo que vamos a hacer ahora es obtener los datos que vamos a cargar como variables estticas en el controlador. Esto quiere decir, sern datos en ROM, de slo lectura en tiempo de ejecucin. Esta variable o variables contendrn el sonido. Usaremos para este ejemplo una variable de 8 bits, es decir, vamos a tener 2 8 =256 tonos de sonido diferentes. No apto para melmanos.

Abrimos Matlab y cargamos en un vector los datos del muestreo. Recomentado ejecutar "help wavread" en Matlab si no sabes lo que significa nada de lo que hay entre corchetes. Bsicamente introduces el vector de datos destino, la frecuencia de muestreo, el nmero de bits a utilizar... - [datos,Fs,NBits,Opts]=wavread('d:bocina3.wav')

El nico problema es que los datos varan entre -1 y 1 y no nos sirve, los queremos entre 0 y 255 (8 bits). As que ejecutamos las siguientes instrucciones: - datos=datos*127

El valor 127 es suponiendo que el mximo o mnimo valor del vector de datos es 1 o -1. Si no lo es, este valor puede ser un poco mayor para maximizar la resolucin de la conversin. Si no sabes o no te apetece saber de lo que hablo, usa 127. - datos=datos+127 - datos=fix (datos)

Ahora grabamos el fichero de valores (0-255) en formato CSV (valores separados por comas). Anota la dimensin de la variable datos en MATLAB antes de cerrar. Es el nmero de datos dentro del vector "datos" que hemos generado con nuestro sonido. Lo vamos a necesitar ms adelante en el compilador de C para definir el tamao del vector esttico .

- csvwrite('d:datos.csv',datos);

3/9

Reproducir sonidos .WAV con PIC usando PWM [CCS+18F4550+MATLAB]

Ya est! Ahora slo hace falta abrirlo con un procesador de textos y hacer un apao!. Vers que hay un montn de numeros. Ese es el sonido con sus valores en digital. Para comprobar que no nos hemos equivocado en el proceso puedes ver que los valores oscilan entre 0-255. Sino, algo has hecho mal.

Abre el fichero .csv y con la opcin de reemplazar sustituye los saltos de linea por "," y crea un texto que debera ser ms o menos as:

Const char datos[X]={127,127,127,127,....tus datos...,125,54};

* El valor de X es el valor que anotaste del tamao de la variable "datos" en Matlab

Esto que hacemos aqu es definir como variable "datos" esttica "const", es decir se guardar como slo lectura en ROM que tiene generalmente ms capacidad que la RAM-, el sonido en formato digital.

Ya puedes copiar la linea en el CCS-PICC. Si el sonido es muy muy pequeo puedes definir la variable sin el "const" y guardarla en RAM, pero normalmente esta memoria es mucho ms pequea que la ROM y que el fichero a guardar, as que debes usar "const" para que se guarde como datos de ROM. Ojo, no podrs modificarla en tiempo de ejecucin!!

Puedes descargarte el ejemplo de como debera quedar antes de copiarlo y pegarlo en el CCS PICC . Hay que copiarlo con un valor por linea, ya que sino, el editor de texto del CCS se puede quedar colgado!!

Programa ejemplo y configuracin del PIC


main.c

4/9

Reproducir sonidos .WAV con PIC usando PWM [CCS+18F4550+MATLAB]

#USE RS232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8) #use delay(clock=8000000)

Const char datos[1000]={127,127,127,127,....tus datos...,125,54};

int16 i; void main() { setup_adc_ports(NO_ANALOGS|VSS_VDD); setup_adc(ADC_OFF); setup_spi(SPI_SS_DISABLED); setup_timer_1(T1_DISABLED); SETUP_CCP1(CCP_PWM_HALF_BRIDGE|CCP_PWM_L_L|CCP_SHUTDOWN_AC_F); setup_wdt(WDT_OFF); setup_timer_2(T2_DIV_BY_1,110,1); setup_comparator(NC_NC_NC_NC); setup_vref(FALSE); while(1==1){ setup_ccp1(CCP_CAPTURE_FE); delay_ms(3000); SETUP_CCP1(CCP_PWM_HALF_BRIDGE|CCP_PWM_L_L|CCP_SHUTDOWN_AC_F); for (i=0;i<1000;i++) {set_pwm1_duty(datos[i]);} for (i=0;i<1000;i++) {set_pwm1_duty(datos[i]);} for (i=0;i<1000;i++) {set_pwm1_duty(datos[i]);} } }

main.h (configuracin):

#include <18F4550.h> #device adc=8

5/9

Reproducir sonidos .WAV con PIC usando PWM [CCS+18F4550+MATLAB]

#FUSES NOWDT //No Watch Dog Timer #FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale #FUSES INTRC_IO //Internal RC Osc, no CLKOUT #FUSES NOPROTECT //Code not protected from reading #FUSES NOBROWNOUT //No brownout reset #FUSES NOPUT //No Power Up Timer #FUSES NOCPD //No EE protection #FUSES STVREN //Stack full/underflow will cause reset #FUSES NODEBUG //No Debug mode for ICD #FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O #FUSES NOWRT //Program memory not write protected #FUSES NOWRTD //Data EEPROM not write protected #FUSES IESO //Internal External Switch Over mode enabled #FUSES FCMEN //Fail-safe clock monitor enabled #FUSES PBADEN //PORTB pins are configured as analog input channels on RESET #FUSES NOWRTC //configuration not registers write protected #FUSES NOWRTB //Boot block not write protected #FUSES NOEBTR //Memory not protected from table reads #FUSES NOEBTRB //Boot block not protected from table reads #FUSES NOCPB //No Boot Block code protection #FUSES NOMCLR //Master Clear pin NOT enabled #FUSES LPT1OSC //Timer1 configured for low-power operation #FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)

#FUSES ICPRT //ICPRT enabled #use delay(clock=8000000) #use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)

Si quieres puedes descargarlos aqu: main.h main.c

6/9

Reproducir sonidos .WAV con PIC usando PWM [CCS+18F4550+MATLAB]

Esquema electrnico
Para convertir una seal PWM (Modulacin de ancho de pulso) en una seal analgica variable y as tener funcionando un DAC, es necesaria como mnimo una red RC a la salida del PIC. Este punto, explicado, justificado y dems, se puede encontrar en la nota de aplicacin AN538 de Microchip . En ella se explica que valor hay que darle a la resistencia y condensador del filtro paso baja -formulas clsicas- y tambin los valores para configurar el Timer2 y los requisitos de resolucin y frecuencia del conversor PWM. Tambin se recomienda usar un filtro paso baja de orden mayor al de una red RC simple, pero para esta aplicacin no lo veo muy necesario.

Nos damos cuenta, a la vista del esquema que tenemos una red RC (filtro paso baja) que calcularemos ms adelante. La salida de esa red ya se podra conectar a un pequeo altavoz, pero el volumen es muy bajo, as que yo le he puesto un amplificador operacional no-inversor, con ganancia 10 para amplificarlo. Puede que incluso sea poco dependiendo de la aplicacin que busques.

Elige un valor de C. Pongamos por ejemplo, C=0.01uF. No te fies del valor en el esquema. Para una f=20khz, C=10nF tendramos una resistencia de 795 Ohm. Ahora usamos:

7/9

Reproducir sonidos .WAV con PIC usando PWM [CCS+18F4550+MATLAB]

Siendo f la frecuencia mxima del sonido que queremos oir. Ya tienes R y C. Monta la red RC tal y como se muestra en el esquema, que puedes verlo a ms resolucin al final de la pgina.

Slo queda configurar el timer2 del PIC para obtener una velocidad de reproduccin acorde con la velocidad de muestreado que hubiesemos elegido. Evidentemente esto depender de la velocidad de muestreo, velocidad del micro, velocidad del reloj del timer, valor de desbordamiento y nmero de veces que se debe desbordar. Ah es nada. Afortunadamente hay una ecuacin para todo esto, aunque a veces es fcil ajustarlo a ojo.

Prueba con setup_timer_2(T2_DIV_BY_16, x, 1); Donde x es:

***Valores habituales:

Para sonidos muestreados a 22050Hz: Oscilador a 4 Mhz, Timer2(Div_by_1,125,1), R=795 Ohm, C=10nF

8/9

Reproducir sonidos .WAV con PIC usando PWM [CCS+18F4550+MATLAB]

Para sonidos muestreados a 44100Hz: Oscilador a 8 Mhz, Timer2(Div_by_1,125,1), R=1,5KOhm, C=10nF

{youtube}8AUEa6c0Zts {/youtube}

{gallery}circuitos/PWM/{/gallery}

9/9

Você também pode gostar