Documentos de Académico
Documentos de Profesional
Documentos de Cultura
07 PWM
07 PWM
En la Figura 6-2 se muesta un pulso con un ciclo de trabajo del 10%; Ton/T = 0.1.
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.
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%.
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.
La Figura 6-6 muestra un diagrama a bloques simplificado del módulo CCP en modo
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).
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.
#include <p18f4550.h>
#include <timers.h>
#include <pwm.h>
#pragma code
void main()
{
// Configura pines como digitales
ADCON1 = 0x0f;
// 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)
{
}
}
#include <p18f4550.h>
#include <timers.h>
#include <pwm.h>
// Seccion de codigo
#pragma code
void main()
{
// Configura pines como digitales
ADCON1 = 0x0f;
// 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)
{
}
}
cont++;
if (cont > 10)
cont = 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?
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.
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.
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?
#include <p18f4550.h>
#include <timers.h>
#include <pwm.h>
#include <math.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;
// 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)
{
}
}
cont++;
if(cont >= 50)
cont = 0;