09 – Generando señales PWM con el PIC18F4550

Inicialmente, no profundizaré respecto a que es una señal PWM y sus utilidades ya que considero que hay una amplia bibliografía al respecto. Nos concentraremos en la puesta en marcha del módulo PWM.

Típicamente, los microcontroladores utilizan  temporizadores para generar señales PWM. En los PIC de 8 bits, el módulo encargado de proveer la señal PWM se llama Capture/Compare/PWM. En el PIC18F4550 hay dos salidas PWM: CCP1 y CCP2.

CCP

CCP1, se encuentra conectado a RC2 y CCP2 a RC1, aunque RB3 puede utilizarse como una salida CCP2 alternativa.
Cuando el módulo Capture/Compare/PWM funciona en modo PWM los pines CCPX pueden producir una salida PWM con una resolución 10 bits, siempre que se utilice el TRIS apropiado para PORTC y PORTB.

Librerías especiales XC8 para Timer y PWM

Para generar señales PWM se requiere de una base de tiempos que es proporcionada por el Timer2 del PIC, por lo que se requiere de:

OpenTimer2(): este método inicializa el Timer 2 del microcontrolador. Se le debe especificar como argumento el prescaler que puede ser:

prescaler_tm2.png

Por lo general, se utiliza el prescaler 1:16. Una vez configurado Timer2, se requiere de la librería pwm.h para poder utilizar los siguientes métodos:

OpenPWMx(): Inicializa el módulo PWM 1 o 2. Se le debe especificar como argumento el período (en hexadecimal) de la señal PWM que se desea generar.

SetDCPWMx(): Establece el ciclo de trabajo de la señal PWM. Se debe especificar como argumento el ciclo de trabajo deseado (debe ser un número entero).

Cálculo del período y del ciclo de trabajo.

Ecuación para encontrar el período de la señal PWM que será el argumento de OpenPWMx():

periodoPWM.png

Ecuación para calcular el ciclo de trabajo del 100% de la señal PWM, servirá como argumento de SetDCPWMx():

cicloTPWM

Ejemplo de aplicación:

EjemploPWM

 

El código del programa sería el siguiente:

#include <xc.h>
#include <plib/timers.h>
#include <plib/pwm.h>

//BITS DE CONFIGURACION...
#pragma config PLLDIV = 5, CPUDIV = OSC1_PLL2, USBDIV = 2
#pragma config FOSC = HSPLL_HS, FCMEN = OFF, IESO = OFF
#pragma config PWRT = OFF, BOR = OFF, VREGEN = OFF
#pragma config WDT = OFF, WDTPS = 32768
#pragma config MCLRE = ON, LPT1OSC = OFF, PBADEN = OFF
#pragma config STVREN = ON, LVP = OFF, ICPRT = OFF, XINST = OFF

#define _XTAL_FREQ 48000000

void main(){
TRISCbits.TRISC2 = 0;
unsigned char prescaler = T2_PS_1_16;
OpenTimer2(prescaler);
OpenPWM1(0x95);
while(1){
SetDCPWM1(300);
}
}

Simulamos y observamos con el osciloscopio la señal generada:

simulacionPWM

Variación de ciclo de trabajo PWM + Timer

Como se puede apreciar, la generación de señales PWM es muy simple. Sin embargo, la técnica PWM requiere de la variación del ciclo de trabajo para “regular” la energía que se entrega a una carga. En el siguiente ejemplo, observaremos como generar un ciclo de aumento y disminución del CT de la señal PWM anteriormente generada.

Según los cálculos PWM realizados, el argumento para SetDCPWM1 es de 600 para un CT del 100%, de esta manera necesitamos incrementar de uno en uno desde 0 hasta 600 y posteriormente decrementar de uno en uno hasta llegar a 0, esto se repetirá infinitamente.

Como ya hemos aprendido a utilizar temporizadores, trabajaremos con el Timer0 para proveer una base de tiempo de 0.1 segundos para efectuar los incrementos/decrementos (ya no debemos utilizar delays). El código sería el siguiente:

#include <xc.h>
#include <plib/timers.h>
#include <plib/pwm.h>

#pragma config PLLDIV = 5, CPUDIV = OSC1_PLL2, USBDIV = 2
#pragma config FOSC = HSPLL_HS, FCMEN = OFF, IESO = OFF
#pragma config PWRT = OFF, BOR = OFF, VREGEN = OFF
#pragma config WDT = OFF, WDTPS = 32768
#pragma config MCLRE = ON, LPT1OSC = OFF, PBADEN = OFF
#pragma config STVREN = ON, LVP = OFF, ICPRT = OFF, XINST = OFF

#define _XTAL_FREQ 48000000

int dutyCicle;
unsigned int accion;

void main(){
accion = 0; //Aumentar
dutyCicle = 0;
TRISCbits.TRISC1 = 0;
unsigned char Timer0Config;
unsigned char prescaler = T2_PS_1_16;
Timer0Config = TIMER_INT_ON &amp; T0_16BIT &amp; T0_SOURCE_INT &amp; T0_PS_1_256;
OpenTimer0(Timer0Config);
WriteTimer0(0xEDAF);
TMR0IF = 0;
OpenTimer2(prescaler);
OpenPWM1(0x95);
ei();
while(1){}
}

void interrupt high_isr(){
if(TMR0IF){
if(accion == 0){
dutyCicle++;
SetDCPWM1(dutyCicle);
if(dutyCicle == 600){
accion = 1;
}
}
else if(accion == 1){
dutyCicle--;
SetDCPWM1(dutyCicle);
if(dutyCicle == 0){
accion = 0;
}
}
TMR0IF = 0;
WriteTimer0(0xEDAF);
}
}

Los invito a comprobar el funcionamiento del módulo PWM y probar distintos escenarios.

Un saludo,

Acerca de jjguevara09

Me gusta la electrónica
Esta entrada fue publicada en Microcontroladores PIC y etiquetada , , , . Guarda el enlace permanente.

2 respuestas a 09 – Generando señales PWM con el PIC18F4550

  1. Carlos Rodriguez dijo:

    Hola amigo primero que nada Gracias por compartir tus conocimientos y tu blog esta super bueno. Bueno estoy implementando el segundo codigo que das para crear la rutina sin los delays pero no me compila el primer codigo compila bien sin problemas pero al segundo no me deja sabes a que se debe uso el xc8 v1.34 pro. y el ultimo ide de mplabx. De antemano gracias por su ayuda.

    Me gusta

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión /  Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión /  Cambiar )

Conectando a %s