You are on page 1of 13

9- PWM

9 MODULACIN DE ANCHO DE PULSO (PWM)


La tcnica de PWM consiste en producir un pulso rectangular con un ciclo de trabajo determinado, este ciclo de trabajo puede variar de 0 a 100%. En la Figura 9-1 se muestra un pulso con un ciclo de trabajo del 50%, es decir Ton/T = 0.5.

Figura 9-1. Ciclo de trabajo de 50% [16]

En la Figura 9-2 se muesta un pulso con un ciclo de trabajo del 10%; Ton/T = 0.1.

Figura 9-2. Ciclo de trabajo del 10% [16]

Un ciclo de trabajo del 0% significa que la seal siempre est nivel bajo; y un ciclo de trabajo del 100% significa la seal siempre en nivel alto, el nmero de casos intermedios posibles es un nmero finito llamado resolucin del PWM y se expresa como Log2(nmero de casos). Por ejemplo si puede haber 256 ciclos de trabajo posibles se dice que el PWM tiene una resolucin de 8 bits.

Si conectamos una seal rectangular a un analizador de espectros para ver su contenido de frecuencias, veramos que est formada por tres partes (Figura 9-3): Una componente de DC, cuya amplitud es proporcional al ciclo de trabajo. Una sinusoide en la frecuencia fundamental (f=1/T). Un nmero infinito de armnicas cuyas frecuencias son mltiplos de la fundamental (2f, 3f, 4f, 5f, 6f, ).

Ing. Juan Ramon Terven Salinas

139

9- PWM

Figura 9-3. Espectro de la seal PWM

De tal forma que si conectamos un filtro ideal pasa bajas a la salida del PWM para remover todas las frecuencias de la fundamental para arriba, obtendramos un seal de CD limpia, cuya amplitud sera directamente proporcional al ciclo de trabajo. Aqu radica la importancia del PWM. Podemos aproximar este filtro pasabajas con un simple filtro pasivo RC (de primer orden) o un filtro activo de un orden superior. En la Figura 9-4 se muestra la componente de CD (lnea punteada) para una seal con un ciclo de trabajo de 50% y otra con un ciclo de trabajo de 10%.

Figura 9-4. Salida analogica del PWM y el filtro pasa bajas

Ing. Juan Ramon Terven Salinas

140

9- PWM

Mdulo Output Compare (OC)


La familia PIC32 posee un mdulo llamada Output Compare, el cual es usado para generar un pulso o un tren de pulsos en respuesta a eventos seleccionados [10] . Este mdulo tiene varios modos de funcionamiento, entre ellos uno llamado Modo PWM en el cual el PIC32 genera un pulso rectangular con un ciclo de trabajo establecido por nuestro cdigo.

9.1.1 Pasos para configurar el modo PWM


1. Ajuste el periodo del PWM escribiendo en el registro de periodo del timer seleccionado (PRx). (se puede usar el Timer2 o el Timer3) 2. Ajuste el ciclo de trabajo del PWM escribiendo en el registro OCxRS. 3. Escriba el registro OCxR con el ciclo de trabajo inicial. 4. Habilite las interrupciones para el timer usado y el mdulo OCx usado (en caso de ser necesarias). La interrupcin del mdulo OC es necesaria para el modo PWM con proteccin de falla. 5. Configure el mdulo Output Compare para algn modo de operacin de PWM escribiendo en los bits OCM (OCxCON<2:0>). 6. Seleccione el Timer a usar en el bit OCTSEL (OCxCON<3>). Si OCTSEL = 0, se usa el Timer2, si OCTSEL = 1 se usa el Timer3. 7. Ajuste el prescaler del TMRx y habilitelo activando el bit TON (TxCON<15>).

Tome en cuenta lo siguiente:

El registro OCxR debe ser inicializado antes de que el mdulo Output Compare sea habilitado.

El registro OCxR se convierte de solo-lectura cuando el mdulo Output Compare opera en modo PWM.

El valor en OCxR se convierte en el ciclo de trabajo del primer periodo del PWM.

El contenido del registro OCxRS se transfiere a OCxR cuando ocurre una coincidencia del Timer.

En la Figura 9-5 se muestra el funcionamiento del PWM del mdulo Output Compare.

Ing. Juan Ramon Terven Salinas

141

9- PWM

Figura 9-5. Funcionamiento del PWM [10]

1) El Timerx es puesto en 0 y se carga un nuevo ciclo de trabajo de OCxRS a OCxR. 2) El valor del Timer iguala al valor de OCxR, el pin OCx pasa a nivel bajo. 3) El Timerx termina de contar (iguala a PRx), se carga el valor de OCxRS a OCxR, el pin OCx pasa a nivel alto. Se genera una interrupcin del Timerx.

Ejemplo 1. Generacin de voltaje analgico usando el mdulo OC en modo PWM.


En este ejemplo se configura el registro de periodo del Timer3 con un valor de 2000, este valor a su vez representa la resolucin del PWM, ya que podemos tener 2000 valores de voltajes diferentes. Si nuestro PBCLK es de 80MHz, entonces tendremos un pulso rectangular de 5kHz, podemos conectar un filtro pasabajas a la salida del PWM como se muestra en la Figura 9-6. El filtro pasabajas de la figura tiene una frecuencia de corte de 15.9 Hz atenuando de manera efectiva los componentes armnicos del PWM.

Figura 9-6. Filtro Pasa bajas a la salida del PWM

De esta manera podemos usar el PWM como un convertidor digital-anlogo o DAC.

Ing. Juan Ramon Terven Salinas

142

9- PWM

Programa 9-1. Salida de voltaje analgico /* * Uso del modulo Output Compare en modo PWM * Utiliza el OC1, sale por el pin RD0 */ #include <p32xxxx.h> #include <plib.h> //Bits de configuracion #pragma config POSCMOD = HS, FNOSC = PRIPLL, FPLLMUL = MUL_20 #pragma config FPLLIDIV = DIV_2, FPLLODIV = DIV_1 #pragma config FPBDIV = DIV_1, FWDTEN = OFF, UPLLEN = ON #pragma config UPLLIDIV = DIV_2, FVBUSONIO = ON, FUSBIDIO = ON #pragma config FSOSCEN = OFF, CP = OFF, FCKSM = CSECMD //PBCLK = 80MHz #define FPB 80000000L int main(void) { //Frecuencia del PWM int freqPWM = 10000; // inicializa el modulo OC1 con Timer2 OpenOC1( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0); // inicializa Timer2 y PR2 //La siguiente funcin inicializa el valor de PR2 = FPB/freqPWM //en este ejemplo PR2 = 80,000,000/10,000 = 8000 //Esto quiere decir que tenemos 8000 ciclos de trabajo distintos OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT,FPB/freqPWM); //Ajusta el ciclo de trabajo al 50%, es decir OC1RS = 4000 OC1RS = PR2/2; while(1); return 0; }

Ing. Juan Ramon Terven Salinas

143

9- PWM

Ejemplo 2. Generacin de una seal diente de sierra


El ejemplo anterior provoca un voltaje fijo por el pin RD0, sin embargo podemos hacer que este voltaje cambie con el tiempo. Podemos aprovechar la rutina de interrupcin del Timer usado para cambiar el ciclo de trabajo del PWM como se muestra en el siguiente ejemplo.

Programa 9-2. Generacin de seal diente de sierra /* * Uso del modulo Output Compare en modo PWM * para generar una seal diente de sierra * Utiliza el OC1, sale por el pin RD0 */ #include <p32xxxx.h> #include <plib.h> //Bits de configuracion #pragma config POSCMOD = HS, FNOSC = PRIPLL, FPLLMUL = MUL_20 #pragma config FPLLIDIV = DIV_2, FPLLODIV = DIV_1 #pragma config FPBDIV = DIV_1, FWDTEN = OFF, UPLLEN = ON #pragma config UPLLIDIV = DIV_2, FVBUSONIO = ON, FUSBIDIO = ON #pragma config FSOSCEN = OFF, CP = OFF, FCKSM = CSECMD //PBCLK = 80MHz #define FPB 80000000L //Frecuencia del PWM #define freqPWM 10000 // VARIABLES GLOBALES //Periodo del PWM (FPB/freqPWM = 8000) short valorMax = FPB/freqPWM; //Contador usado para generar el diente de sierra short count = 0; int main(void) { // inicializa el modulo OC1 con Timer2 OpenOC1( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0); // inicializa Timer2 y PR2 //La siguiente funcin inicializa el valor de PR2 = FPB/freqPWM //en este ejemplo PR2 = 80,000,000/10,000 = 8000 //Esto quiere decir que el diente de sierra subira //desde 0 hasta 8000 (valorMax) OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT,valorMax); //Ajusta la interrupcin de Timer2 con prioridad de 2 IPC2bits.T2IP = 2; //prioridad 2 IPC2bits.T2IS = 1; //subprioridad 1 IFS0bits.T2IF = 0; //Limpia la bandera de interrupcion // Activa el modo MultiVectored INTEnableSystemMultiVectoredInt();

Ing. Juan Ramon Terven Salinas

144

9- PWM
IEC0bits.T2IE = 1; //Activa la interrupcion del Timer2

//Ajusta el ciclo de trabajo incial a 0%, es decir OC1RS = 0 OC1RS = 0; while(1); return 0; } //RUTINA DE INTERRUPCIN DE TIMER2 //Cambia el ciclo de trabajo del PWM para generar un diente de sierra //de 125Hz (1/8ms) //Esta interrupcin se ejecuta cada 100us, y el voltaje //sube linealmente desde 0 hasta el mximo en 80 interrupciones //por lo tanto el periodo del diente de sierra es de 8ms (80 x 100us) void __ISR(_TIMER_2_VECTOR, ipl2) Timer2Handler(void) { //Ajusta el Nuevo ciclo de trabajo OC1RS = count; count+=100; //Si el contador llega a valorMax, regresa a 0 if (count >= valorMax) count = 0; //Limpia la bandera de interrupcion del Timer2 IFS0bits.T2IF = 0; }

Esta rutina producir una seal diente de sierra de aproximadamente VDD de amplitud con una rampa gradual del ciclo de trabajo de 0 a 100% en 80 pasos, seguida de una caida abrupta a 0. Esta seal tendr una frecuencia de 125 Hz.

Ing. Juan Ramon Terven Salinas

145

9- PWM

Ejemplo 3. Generacin de un Senoidal


El siguiente ejemplo es idntico al anterior solo cambia la rutina de interrupcin en la cual se usa la funcin sin de la librera math.h para generar cada valor de voltaje de una seal senoidal.
Programa 9-3. Generacin de una seal senoidal usando PWM /* * Uso del modulo Output Compare en modo PWM * para generar una seal senoidal * Utiliza el OC1, sale por el pin RD0 */ #include <p32xxxx.h> #include <plib.h> #include <math.h> //Bits de configuracion #pragma config POSCMOD = HS, FNOSC = PRIPLL, FPLLMUL = MUL_20 #pragma config FPLLIDIV = DIV_2, FPLLODIV = DIV_1 #pragma config FPBDIV = DIV_1, FWDTEN = OFF, UPLLEN = ON #pragma config UPLLIDIV = DIV_2, FVBUSONIO = ON, FUSBIDIO = ON #pragma config FSOSCEN = OFF, CP = OFF, FCKSM = CSECMD //PBCLK = 80MHz #define FPB 80000000L //Frecuencia del PWM #define freqPWM 10000; //Periodo del PWM (FPB/freqPWM = 8000) short valorMax = FPB/freqPWM; //Contador usado para generar la seal senoidal short count = 0; int main(void) { // inicializa el modulo OC1 con Timer2 OpenOC1( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0); // inicializa Timer2 y PR2 //La siguiente funcin inicializa el valor de PR2 = FPB/freqPWM //en este ejemplo PR2 = 80,000,000/10,000 = 8000 OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT,valorMax); //Ajusta la interrupcin de Timer2 con prioridad de 2 IPC2bits.T2IP = 2; //prioridad 2 IPC2bits.T2IS = 1; //subprioridad 1 IFS0bits.T2IF = 0; //Limpia la bandera de interrupcion // Activa el modo MultiVectored INTEnableSystemMultiVectoredInt(); IEC0bits.T2IE = 1; //Activa la interrupcion del Timer2 //Ajusta el ciclo de trabajo incial a 0%, es decir OC1RS = 0 OC1RS = 0 ; while(1);

Ing. Juan Ramon Terven Salinas

146

9- PWM
return 0; } //RUTINA DE INTERRUPCIN DE TIMER2 //Cambia el ciclo de trabajo del PWM para generar una senoidal //de 100Hz (1/10ms) //Esta interrupcin se ejecuta cada 100us, y el voltaje //cambia senoidalmente generando un periodo completo cada //100 interrupciones (2pi/100 = pi/50) //por lo tanto el periodo de la senoidal 10ms (100 x 100us) void __ISR(_TIMER_2_VECTOR, ipl2) Timer2Handler(void) { // calcula el nuevo valor de la senoidal OC1RS = PR2/2 + PR2/2 * sin(M_PI/50*count); count++; //Limpia la bandera de interrupcion del Timer2 IFS0bits.T2IF = 0; }

La funcin seno de la librera math.h tarda bastante tiempo en ser calculada (unos cuantos milisegundos), de tal manera que si se desea generar una senoidal de alta frecuencia no es recomendable usar la funcin de la librera. En su lugar, podramos generar un arreglo con los valores del seno y simplemente mandarlos llamar.

Ing. Juan Ramon Terven Salinas

147

9- PWM

Ejemplo 4. Generacin de una seal senoidal usando una tabla de datos


Para el siguiente ejemplo se uso una hoja de clculo para generar una tabla de 100 valores que representan 1 ciclo de una seal senoidal. Estos valores se mapearon a un rango de 0 a 160, en donde 160 ser el valor del 100% del ciclo de trabajo (PR1 = 160).

Figura 9-7. Generacin de datos

Una vez teniendo los datos se pasan a una tabla que se almacena en la memoria Flash del PIC32 y dentro de la RSI del TMR2 se usa cada uno de estos valores para generar una senoidal de aproximadamente 1kHz. Observe que podemos usar la memoria de programa (Flash) para almacenar datos constantes y asi no malgastar la preciada memoria RAM. Para hacer esto simplemente declare su variable de tipo constante con el modificador const y el compilador automticamente la guarda en memoria Flash.

Ing. Juan Ramon Terven Salinas

148

9- PWM
Programa 9-4. Generacin de senoidal a partir de una tabla de datos /* * Uso del modulo Output Compare en modo PWM * para generar una seal senoidal a partir de * una tabla de datos * Utiliza el OC1, sale por el pin RD0 */ #include <p32xxxx.h> #include <plib.h> #include <math.h> //Bits de configuracion #pragma config POSCMOD = HS, FNOSC = PRIPLL, FPLLMUL = MUL_20 #pragma config FPLLIDIV = DIV_2, FPLLODIV = DIV_1 #pragma config FPBDIV = DIV_1, FWDTEN = OFF, UPLLEN = ON #pragma config UPLLIDIV = DIV_2, FVBUSONIO = ON, FUSBIDIO = ON #pragma config FSOSCEN = OFF, CP = OFF, FCKSM = CSECMD //PBCLK = 80MHz #define FPB 80000000L //Contador usado para generar la seal senoidal short count = 0; //Tabla de datos, representa 1 ciclo completo de una seal senoidal const short tabla[100] = { 80,85,90,95,100,105,109,114,119,123,127,131,135,138,142,145,148,150,15 2,154,156,157,159,159,160,160,160,159,159,157,156,154,152,150,148,145, 142,138,135,131,127,123,119,114,109,105,100,95,90,85,80,75,70,65,60,55 ,51,46,41,37,33,29,25,22,18,15,12,10,8,6,4,3,1,1,0,0,0,1,1,3,4,6,8,10, 12,15,18,22,25,29,33,37,41,46,51,55,60,65,70,75}; int main(void) { // inicializa el modulo OC1 con Timer2 OpenOC1( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0); // inicializa Timer2 y PR2 //La siguiente funcin inicializa el valor de PR2 = 160 OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT,160); //Ajusta la interrupcin de Timer2 con prioridad de 2 IPC2bits.T2IP = 2; //prioridad 2 IPC2bits.T2IS = 1; //subprioridad 1 IFS0bits.T2IF = 0; //Limpia la bandera de interrupcion // Activa el modo MultiVectored INTEnableSystemMultiVectoredInt(); IEC0bits.T2IE = 1; //Activa la interrupcion del Timer2 //Ajusta el ciclo de trabajo incial a 0%, es decir OC1RS = 0 OC1RS = 0; while(1); return 0; } //RUTINA DE INTERRUPCIN DE TIMER2 //Cambia el ciclo de trabajo del PWM para generar una senoidal

Ing. Juan Ramon Terven Salinas

149

9- PWM
//de 5kHz (1/200us) //Esta interrupcin se ejecuta cada 2us, y el voltaje //cambia senoidalmente generando un periodo completo cada //100 interrupciones //por lo tanto el periodo de la senoidal es de 200us (2us x 100) void __ISR(_TIMER_2_VECTOR, ipl2) Timer2Handler(void) { // Obtiene el nuevo valor de la senoidal // de la tabla de datos OC1RS = tabla[count]; count++; //Si llega al final del arreglo, reinicia if (count > 99) count = 0; //Limpia la bandera de interrupcion del Timer2 IFS0bits.T2IF = 0; }

Generacin de Audio
Podemos aprovechar el ejemplo anterior y conectar una bocina a la salida del PWM para escuchar el tono lmpio de una senoidal de 5kHz. Podriamos agregarle amplificador operacional y un potencimetro que varie la ganancia para que funcione como control de volumen. Sin embargo un amplificador operacional no es capaz por si solo de entregar corrientes muy grandes por la salida, por lo que no podemos conectarles directamente un altavoz y oir el tono; necesitamos entonces aadir algn dispositivo que sea capaz de ampliar esa corriente. Podemos usar el arreglo que se muestra en la Figura 9-8. El amplificador operacional empleado es un LM833, especial para audio. La etapa de transistores formada por Q1 y Q2 tiene como nica finalidad suministrar la corriente que el operacional no puede. Los transistores empleados son los BC547 y BC557, Estos no son de gran potencia por lo que se deber usar una bocina pequea.

Ing. Juan Ramon Terven Salinas

150

9- PWM

Figura 9-8. Amplificador sencillo de Audio

Ing. Juan Ramon Terven Salinas

151

You might also like