Está en la 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 artículo es explicar la manera de reproducir sonidos usando un microcontrolador PIC y la salida PWM que muchos llevan incorporada como DAC (conversor digital a analógico). El origen del sonido será un fichero .wav que ya tendremos más o menos tratado con algún programa de edición de sonido y que será introducido en la memoria del PIC previo tratamiento de los datos usando MATLAB.

La principal preocupación no es la calidad de sonido, ya que  limitaciones como la memoria del PIC o la resolución de la salida PWM hacen imposible obtener una calidad buena de sonido, pero para voces habladas y sonidos concretos será más 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

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-. Para este ejemplo. Esto es conocido como tasa de Nyquist.a 44100hz. las frecuencias para que se entienda el mensaje no suelen superar los 2000Hz. 16 bits y mono. se usan 16 bits. Pero el segundo si sería más o menos posible dependiendo de la gama del PIC! Crear la tabla de datos para la ROM del PIC usando Matlab. Para el que no esté demasiado familiarizado con estos términos esto quiere decir que 44100 veces cada segundo se toma el valor de la señal analogica original (el sonido) y que el valor que se lee. 8 bits son: (320000 bits) 40k Se puede ver. Se podría intentar con un par de memorias 24xx1025 usando el bus I2C.a 4000hz. 2/9 . Así se evita la aparición de "alias". al pasarlo a un numero binario. Básicamente lo que nos dice es que para muestrear una señal de frecuencia "f" y poder reconstruirla correctamente después. es un archivo muestreado a 44100hz. si lo que quieres es reproducir sonidos audibles (1-20000hz) necesitarás al menos el doble de frecuencia de muestreo que la máxima frecuencia que quieras oir. suponiendo que el microcontrolador fuera capaz de leer del bus y reproducir en tiempo real. es necesario que la frecuencia de muestreo sea al menos "2 x f". Vamos a calcular ahora el tamaño que tendrá dependiendo de la tasa de muestreo: . Básicamente.WAV con PIC usando PWM [CCS+18F4550+MATLAB] El archivo original es bocina3.  señales a frecuencias que no existen en la señal original. ¿que importancia tiene esto? El tamaño del fichero! Imagina que tienes un sonido de 10 segundos que quieres meter en el microcontrolador. reduzcas el muestreo lo máximo posible (ahora recordaremos las limitaciones). De ahí sale el habitual 44100Hz. por lo que podrás muestrear a 4000Hz. que el primer fichero no va a ser muy fácil de meter en la memoria del PIC. La norma para remuestrear (resample) para reducir la cantidad de datos esta controlada por la teoría del muestreo. Si lo que quieres es producir un sonido de voz humana.Reproducir sonidos . 8 bits son: (3528000 bits) 441k .wav .

No apto para melómanos.[datos. . de sólo lectura en tiempo de ejecución.csv'. Esto quiere decir.datos=datos*127 El valor 127 es suponiendo que el máximo o mínimo valor del vector de datos es 1 o -1. Es el número de datos dentro del vector "datos" que hemos generado con nuestro sonido. vamos a tener 2 8 =256 tonos de sonido diferentes..datos=datos+127 . Lo vamos a necesitar más adelante en el compilador de C para definir el tamaño del  vector estático . este valor puede ser un poco mayor para maximizar la resolución de la conversión.Opts]=wavread('d:bocina3. Si no sabes o no te apetece saber de lo que hablo.csvwrite('d:datos. Usaremos para este ejemplo una variable de 8 bits. Abrimos Matlab y cargamos en un vector los datos del muestreo. Básicamente introduces el vector de datos destino. .  Anota la dimensión de la variable datos en MATLAB antes de cerrar. el número de bits a utilizar.datos=fix (datos) Ahora grabamos el fichero de valores (0-255) en formato CSV (valores separados por comas). . 3/9 .NBits.WAV con PIC usando PWM [CCS+18F4550+MATLAB] Lo que vamos a hacer ahora es obtener los datos que vamos a cargar como variables estáticas en el controlador.datos). Recomentado ejecutar "help wavread" en Matlab si no sabes lo que significa nada de lo que hay entre corchetes. Si no lo es. Esta variable o variables contendrán el sonido.Reproducir sonidos . Así que ejecutamos las siguientes instrucciones: .Fs.wav') El único problema es que los datos varían entre -1 y 1 y no nos sirve.. es decir. serán datos en ROM. usa 127. los queremos entre 0 y 255 (8 bits). la frecuencia de muestreo.

125. el editor de texto del CCS se puede quedar colgado!! Programa ejemplo y configuración del PIC main." y crea un texto que debería ser más o menos así: Const char datos[X]={127. pero normalmente esta memoria es mucho más pequeña que la ROM y que el fichero a guardar. no podrás modificarla en tiempo de ejecución!! Puedes descargarte el ejemplo de como debería quedar antes de copiarlo y pegarlo en el CCS PICC .Reproducir sonidos ... Ese es el sonido con sus valores en digital. así que debes usar "const" para que se guarde como datos de ROM..WAV con PIC usando PWM [CCS+18F4550+MATLAB] Ya está! Ahora sólo hace falta abrirlo con un procesador de textos y hacer un apaño!. Para comprobar que no nos hemos equivocado en el proceso puedes ver que los valores oscilan entre 0-255.csv y con la opción de reemplazar sustituye los saltos de linea por ". Ya puedes copiar la linea en el CCS-PICC.127.127.tus datos. Abre el fichero . algo has hecho mal. * El valor de X es el valor que anotaste del tamaño de la variable "datos" en Matlab Esto que hacemos aquí es definir como variable "datos" estática "const". ya que sino. Sino...127.. Ojo. el sonido en formato digital.54}. Hay que copiarlo con un valor por linea. es decir se guardará como sólo lectura en ROM que tiene generalmente más capacidad que la RAM-.c 4/9 . Si el sonido es muy muy pequeño puedes definir la variable sin el "const" y guardarla en RAM. Verás que hay un montón de numeros..

..h  (configuración): #include <18F4550. void main() { setup_adc_ports(NO_ANALOGS|VSS_VDD). int16 i.54}. SETUP_CCP1(CCP_PWM_HALF_BRIDGE|CCP_PWM_L_L|CCP_SHUTDOWN_AC_F).110.i++) {set_pwm1_duty(datos[i]).127.rcv=PIN_C7. for (i=0. while(1==1){ setup_ccp1(CCP_CAPTURE_FE).xmit=PIN_C6. setup_comparator(NC_NC_NC_NC).h> #device adc=8 5/9 . delay_ms(3000).parity=N..i++) {set_pwm1_duty(datos[i]).i<1000. setup_timer_2(T2_DIV_BY_1.bits=8) #use delay(clock=8000000) Const char datos[1000]={127.i<1000.WAV con PIC usando PWM [CCS+18F4550+MATLAB] #USE RS232(baud=9600. setup_vref(FALSE).127. setup_wdt(WDT_OFF).} for (i=0.1).127..125.tus datos. setup_spi(SPI_SS_DISABLED)...} } } main. SETUP_CCP1(CCP_PWM_HALF_BRIDGE|CCP_PWM_L_L|CCP_SHUTDOWN_AC_F).} for (i=0.Reproducir sonidos ..i++) {set_pwm1_duty(datos[i]).i<1000. setup_adc(ADC_OFF). setup_timer_1(T1_DISABLED).

Reproducir sonidos .c 6/9 .h main. 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.xmit=PIN_C6.rcv=PIN_C7.bits=8) Si quieres puedes descargarlos aquí: main.parity=N. 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.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.

Ahora usamos: 7/9 . así que yo le he puesto un amplificador operacional no-inversor. pero el volumen es muy bajo. Este punto. es necesaria como mínimo una red RC a la salida del PIC. No te fies del valor en el esquema. La salida de esa red ya se podría conectar a un pequeño altavoz. En ella se explica que valor hay que darle a la resistencia y condensador del filtro paso baja -formulas clásicas. Puede que incluso sea poco dependiendo de la aplicación que busques.y también los valores para configurar el Timer2 y los requisitos de resolución y frecuencia del conversor PWM. Para una f=20khz. explicado.WAV con PIC usando PWM [CCS+18F4550+MATLAB] Esquema electrónico Para convertir una señal PWM (Modulación de ancho de pulso) en una señal analógica variable y así tener funcionando un DAC. justificado y demás. También se recomienda usar un filtro paso baja de orden mayor al de una red RC simple.Reproducir sonidos .01uF. C=0. C=10nF tendríamos una resistencia de 795 Ohm. con ganancia 10 para amplificarlo. pero para esta aplicación no lo veo muy necesario. Pongamos por ejemplo. Nos damos cuenta. a la vista del esquema que tenemos una red RC (filtro paso baja) que calcularemos más adelante. Elige un valor de C. se puede encontrar en la nota de aplicación AN538 de Microchip .

Sólo queda configurar el timer2 del PIC para obtener una velocidad de reproducción acorde con la velocidad de muestreado que hubiesemos elegido.Reproducir sonidos . velocidad del micro. 1). aunque a veces es fácil ajustarlo a ojo. Monta la red RC tal y como se muestra en el esquema. Afortunadamente hay una ecuación para todo esto. Ahí es nada. Prueba con setup_timer_2(T2_DIV_BY_16. R=795 Ohm.WAV con PIC usando PWM [CCS+18F4550+MATLAB] Siendo f la frecuencia máxima del sonido que queremos oir. Ya tienes R y C. Timer2(Div_by_1. x.1). velocidad del reloj del timer. Evidentemente esto dependerá de la velocidad de muestreo. valor de desbordamiento y número de veces que se debe desbordar. Donde x es: ***Valores habituales: Para sonidos muestreados a 22050Hz: Oscilador a 4 Mhz. C=10nF 8/9 .125. que puedes verlo a más resolución al final de la página.

125.WAV con PIC usando PWM [CCS+18F4550+MATLAB] Para sonidos muestreados a 44100Hz: Oscilador a 8 Mhz. R=1.1). Timer2(Div_by_1. C=10nF {youtube}8AUEa6c0Zts {/youtube} {gallery}circuitos/PWM/{/gallery} 9/9 .Reproducir sonidos .5KOhm.