Story Transcript
PWM
69
6 MODULACIÓN DE ANCHO DE PULSO (PWM) En el PWM, se produce un pulso rectangular con un ciclo de trabajo determinado (comúnmente producido por un Timer), este ciclo de trabajo puede variar de 0 a 100%. En la Figura 6-1 se muestra un pulso con un ciclo de trabajo del 50%, es decir Ton/T = 0.5.
Figura 6-1. Ciclo de trabajo de 50%
En la Figura 6-2 se muesta un pulso con un ciclo de trabajo del 10%; Ton/T = 0.1.
Figura 6-2. Ciclo de trabajo del 10%
Un ciclo de trabajo del 0% significa que la señal siempre está nivel bajo; y un ciclo de trabajo del 100% significa la señal siempre en nivel alto, el número de casos intermedios posibles comúnmente es un número finito llamado resolución del PWM y se expresa como Logaritmo base 2. Por ejemplo si puede haber 256 ciclos de trabajo posibles se dice que el PWM tiene una resolución de 8 bits.
Ing. Juan Ramon Terven Salinas
PWM
70
Si conectamos una señal rectangular a un analizador de espectros para ver su contenido de frecuencias, veríamos que está formado por tres partes (Figura 6-3): -
Una componente de DC, cuya amplitud es proporcional al ciclo de trabajo.
-
Una sinusoide en la frecuencia fundamental (f=1/T).
-
Un número infinito de armónicas cuyas frecuencias son múltiplos de la fundamental (2f, 3f, 4f, 5f, 6f, …).
Figura 6-3. Espectro de la señal 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, obtendríamos un señal de CD limpia, cuya amplitud sería 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 6-4 se muestra la componente de CD (línea punteada) para una señal con un ciclo de trabajo de 50% y otra con un ciclo de trabajo de 10%.
Ing. Juan Ramon Terven Salinas
PWM
71
Figura 6-4. Salida analogica del PWM y el filtro pasa bajas
Ing. Juan Ramon Terven Salinas
PWM
72
6.1 PWM Estándar PIC18 Todos los PIC18 poseen dos módulos CCP (capture/Compare/PWM) denominados CCP1 y CCP2; los cuales se pueden usar para capturar entradas, comparar entradas o generar patrones de PWM. En el modo PWM los pines CCPx producen una salida PWM de hasta 10 bits de resolución. La Figura 6-5 muestra los pines usados para generar los patrones PWM.
Figura 6-5. Pines PWM
La Figura 6-6 muestra un diagrama a bloques simplificado del módulo CCP en modo PWM.
Ing. Juan Ramon Terven Salinas
PWM
73
Figura 6-6. Modulo PWM
La Figura 6-7 muestra la salida del módulo PWM. El Periodo esta dado por el registro PR2, el Ciclo de trabajo (Duty Cycle) esta dado por el valor de 2 registros CCPRxL (parte alta) y los bits del registro CCPxCON (parta baja).
Figura 6-7. Salida PWM
El periodo del PWM esta dado por la siguiente fórmula:
Ing. Juan Ramon Terven Salinas
PWM
74
La resolución del PWM depende de la frecuencia del PWM y la frecuencia del oscilador. Podemos obtener la resolución máxima con la siguiente formula.
Donde log indica log10. La siguiente tabla muestra algunos valores de Frecuencia y resolución del PWM en función del valor de PR2 y el prescaler del Timer2.
Frecuencia de Oscilador:
48000000
Frecuencia PWM (Hz) Prescaler TMR2 (1,4,16) PR2 Resolución Máxima:
2930 16 255 10
11719 4 255 10
46875 1 255 10
187500 1 63 8
375000 1 31 7
6.2 Librería PWM.H La librería pwm.h ofrece funciones para configurar y controlar el módulo PWM:
OpenPWMx(char periodo) – Configura y activa el modulo PWMx ClosePWMx(void) – Desactiva el módulo PWMx SetDCPWMx(unsigned int ciclo_de_trabajo) – Ajusta un nuevo ciclo de trabajo. El ciclo de trabajo es un valor de 10 bits. Cabe destacar que el nuevo ciclo de trabajo ocurre hasta que termina el ciclo actual, es decir hasta que TMR2 = PR2.
Ing. Juan Ramon Terven Salinas
500000 1 23 6.6
PWM
75
Ejemplo 6-1.Generación de PWM El siguiente ejemplo configura el módulo para generar un patrón PWM fijo. Programa 6-1. Salida de voltaje analógico /* Configuración de Módulos PWM Estándar */ #include #include #include //Código para bootloader extern void _startup (void); #pragma code REMAPPED_RESET_VECTOR = 0x1000 void _reset (void) { _asm goto _startup _endasm } #pragma code void main() { // Configura pines como digitales ADCON1 = 0x0f; // Activa Timer2 para ser usado por los módulos PMW OpenTimer2( TIMER_INT_OFF & T2_PS_1_1 & T2_POST_1_1); // Configura el PWM1 TRISCbits.TRISC2 = 0; OpenPWM1(0xFF); SetDCPWM1(512);
// pin CCP1 salida // Activa PWM1 con PR2 = 255 // Ciclo de trabajo al 50%
// Configura el PWM2 TRISCbits.TRISC1 = 0; // pin CCP2 salida OpenPWM2(0xFF); // Activa PWM1 con PR2 = 255 SetDCPWM2(256); // Ciclo de trabajo al 25% // Ciclo principal while(1) { } }
En este ejemplo se configura el registro de periodo PR2 con un valor de 255 y un prescaler de 1:1 por lo tanto la resolución del PWM es de 10 bits y la frecuencia del PWM es de 46.8kHz.
Ing. Juan Ramon Terven Salinas
PWM
76
Si colocamos un filtro pasabajas con una frecuencia de corte aproximada de 400Hz en la salida del pulso PWM como se muestra en la Figura 6-8 podemos atenuar los componentes armónicos del pulso cuadrado en -40dB y dejar sólo la componente de corriente directa. De esta manera podemos usar el módulo PWM como un Convertidor DigitalAnálogo (D/A).
Figura 6-8. Filtro Pasa bajas a la salida del PWM
Ing. Juan Ramon Terven Salinas
PWM
77
Ejemplo 6-2. Generación de señales Analógicas El ejemplo anterior provoca un voltaje fijo por los pines del PWM, sin embargo podemos hacer que este voltaje cambie con el tiempo. Podemos aprovechar la interrupción del Timer 2 para cambiar el ciclo de trabajo del PWM como se muestra en el siguiente ejemplo.
Programa 6-2. Generación de diente de sierra /* Generación de diente de sierra usando PWM */ #include #include #include void rsi_tmr (void);
//Código para bootloader extern void _startup (void); #pragma code REMAPPED_RESET_VECTOR = 0x1000 void _reset (void) { _asm goto _startup _endasm } // Declara contador para generar patron analógico #pragma udata int cont; // Seccion de codigo #pragma code void main() { // Configura pines como digitales ADCON1 = 0x0f; // Activa Timer2 para ser usado por los módulos PMW // Habilita la interrupción del TMR2, prescaler de 1:1 OpenTimer2( TIMER_INT_ON & T2_PS_1_1 & T2_POST_1_1); // Habilitacion global de interrupciones INTCONbits.GIE = 1; INTCONbits.PEIE = 1; // Configura el PWM1 TRISCbits.TRISC2 = 0; OpenPWM1(0xFF); SetDCPWM1(0);
// pin CCP1 salida // Activa PWM1 con PR2 = 255 // Ciclo de trabajo al 0%
while(1) { } } // Vector de Interrupción modo compatibilidad #pragma code high_vector=0x1008 void high_interrupt (void) { _asm GOTO rsi_tmr _endasm }
Ing. Juan Ramon Terven Salinas
PWM
78
/****** RSI de TIMER2 *****/ #pragma code #pragma interrupt rsi_tmr void rsi_tmr (void) { SetDCPWM1(cont*100); cont++; if (cont > 10) cont = 0; // Limpia la bandera de interrupción PIR1bits.TMR2IF = 0; }
Esta rutina producirá una señal diente de sierra de con una amplitud máxima cercana a VDD con una rampa gradual del ciclo de trabajo de 0 a 100% en 10 pasos, seguida de una caida abrupta a 0. ¿Cuál es la frecuencia de esta señal?
Ejemplo 6-3. Generación de un Senoidal usando la función sin Si sustituimos la RSI del TMR2 por la siguiente podemos obtener una señal senoidal. #pragma interrupt rsi_tmr void rsi_tmr (void) { //2pi * f * n (f=0.1) SetDCPWM1(512 + ( 511* sin(0.62832 * count))); count++; PIR1bits.TMR2IF = 0; }
Sin embargo la función seno de la librería math.h tarda bastante tiempo en ser calculada (poco más de 1ms), de tal manera que si se desea generar una senoidal de alta frecuencia no es recomendable usar la función de la librería. En su lugar, podríamos generar un arreglo con los valores del seno y simplemente mandarlos llamar.
Ing. Juan Ramon Terven Salinas
PWM
79
Ejemplo 6-4. Generación de una señal senoidal usando una tabla de datos Para el siguiente ejemplo se generó una tabla de 50 datos que representa un periodo de una onda senoidal con valores de 0 a 1023. La figura siguiente muestra los datos generados.
Figura 6-9. Generación de datos
Una vez teniendo los datos se pasan a un arreglo y dentro de la RSI del TMR2 se usa cada uno de estos valores para generar una senoidal, enviando un dato diferente cada 21.2µs. ¿Cuál es la frecuencia de la senoidal?
Programa 6-3. Generación de Senoidal usando tabla de datos /* Generación de Senoidal usando tabla de datoss y PWM */ #include #include #include #include
void rsi_tmr (void);
Ing. Juan Ramon Terven Salinas
PWM /* //Código para bootloader extern void _startup (void); #pragma code REMAPPED_RESET_VECTOR = 0x1000 void _reset (void) { _asm goto _startup _endasm } */ // Declara contador para usar como índice del arreglo #pragma udata int cont; // Arreglo de 50 datos que representan 1 ciclo senoidal #pragma idata int senoidal[50]={512, 576, 639, 700, 758, 812, 862, 906, 943, 974, 998, 1014, 1022, 1022, 1014, 998, 974, 943, 906, 862, 812, 758, 700, 639, 576, 512, 447, 384, 323, 265, 211, 161, 117, 80, 49, 25, 9, 1, 1, 9, 25, 49, 80, 117, 161, 211, 265, 323, 384, 447}; #pragma code void main() { // Configura pines como digitales ADCON1 = 0x0f; // Activa Timer2 para ser usado por los módulos PMW // Habilita la interrupción del TMR2, prescaler de 1:1 OpenTimer2( TIMER_INT_ON & T2_PS_1_1 & T2_POST_1_1); cont = 0; // Habilitacion global de interrupciones INTCONbits.GIE = 1; INTCONbits.PEIE = 1; // Configura el PWM1 TRISCbits.TRISC2 = 0; // pin CCP1 salida OpenPWM1(0xFF); // Activa PWM1 con PR2 = 255 SetDCPWM1(0); // Ciclo de trabajo al 0% while(1) { } } // Vector de Interrupción modo compatibilidad #pragma code high_vector=0x1008 void high_interrupt (void) { _asm GOTO rsi_tmr _endasm } /****** RSI de TIMER2 *****/ // Genera una senoidal usando los datos de la tabla #pragma code #pragma interrupt rsi_tmr void rsi_tmr (void) { SetDCPWM1(senoidal[cont]); cont++; if(cont >= 50) cont = 0; // Limpia la bandera de interrupción PIR1bits.TMR2IF = 0; }
Ing. Juan Ramon Terven Salinas
80