Está en la página 1de 12

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 <4:5> 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) 2930 11719 46875 187500 375000 500000


Prescaler TMR2 (1,4,16) 16 4 1 1 1 1
PR2 255 255 255 63 31 23
Resolución Máxima: 10 10 10 8 7 6.6

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


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 <p18f4550.h>
#include <timers.h>
#include <pwm.h>

//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; // pin CCP1 salida
OpenPWM1(0xFF); // Activa PWM1 con PR2 = 255
SetDCPWM1(512); // 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 Digital-
Aná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 <p18f4550.h>
#include <timers.h>
#include <pwm.h>

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; // 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
}

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 <p18f4550.h>
#include <timers.h>
#include <pwm.h>
#include <math.h>

void rsi_tmr (void);

Ing. Juan Ramon Terven Salinas


PWM 80

/*
//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

También podría gustarte