PWM POR SOFTWARE : CONTROL DE 8 LEDS.

Como están amigos en este post que hemos llamado ” PWM POR SOFTWARE : Control de 8 leds. ” continuamos con la parte final de este interesante tema. Vamos a ver como logramos implementar un programa para controlar hasta 8 salidas digitales PWM.

Te recuerdo que previo a este tema puedes revisar los 2 post anteriores:

  1. INTRODUCCION AL PWM
  2. PWM POR HARDWARE

Bueno, vemos a continuación como funciona este modo de control PWM por SOFTWARE:

FRECUENCIA PERIODO Y ANCHO DE PULSO BASADO EN EL TIMER 0.

Habíamos mencionado ya que en el caso del PWM por SOFTWARE no existía un único criterio para controlar estas variables, ya que depende básicamente del enfoque que cada programador le puede dar.

Lo que presentamos a continuación es nuestra forma de controlar hasta 8 salidas PWM basados en las interrupciones que se generan a través del TIMER 0 del PIC 16f628.

Recordemos este modelo :

Como controlar el brillo de un LED : Introducción al PWM.

Lo que podemos ver es que utilizando las interrupciones del TIMER 0 podemos tranquilamente realizar el control tanto del ancho de pulso como de la amplitud del periodo.

Para llevar a cabo esta idea seguiremos los siguientes pasos:

PASO 1. Establecer la frecuencia que tendrá la señal PWM en todas la salidas del PIC.

PASO 2. Establecer el tiempo de duración del PERIODO de la frecuencia seleccionada.

PASO 3. Dividir el periodo entre el numero de anchos de pulsos que queremos que tenga nuestra señal PWM esto sera la RESOLUCION el resultado sera el TIEMPO de INTERRUOCION del TIMER 0.

PASO 4. Con el tiempo de interrupción encontrado utilizar la formula del TIMER 0 para hallar el VALOR de PRECARGA DEL TIMER, probando con todos los valores posibles de PRESCALER : 1-2-4-8-16-32-64-128 y 256, seleccionado cualquiera que arroje un valor de PRECARGA entre 0 y 255.

PASO 5. Finalmente, programar el TIMER 0 con los datos encontrados y generar el código habilitando todas las salidas por los puertos correspondientes.

CASO PRACTICO PWM POR SOFTWARE CON 8 SALIDAS PWM.

Veamos como aplicamos estos criterios con un ejemplo practico:

Tenemos un PIC 16f628 con un cristal de 4MHZ y necesitamos implementar 8 salidas PWM con una señal de 5 Kilo Hertz por cada una de las salidas con una resolución de 5 BITS es decir 32 TONS. El efecto sera de incrementar y decrementar el brillo en todas las salidas de forma automática.

Veamos como seguimos cada uno de los pasos establecidos.

PASO 1:

La frecuencia requerida es de 5 Kilo Hertz.

PASO 2:

El tiempo de duración del periodo lo obtenemos con la formula :

PASO 3:

Ahora dividimos el Periodo entre el numero de la resolución requerida de 5 BITS es decir 32 TONS para hallar el tiempo de interrupción del TIMER 0 :

El resultado del tiempo de interrupción seria de 6.25 microsegundos.

PASO 4:

Ahora aplicamos la formula del tiempo de interrupción del TIMER 0 para hallar el valor de PRECARGA que corresponde al tiempo de interrupción.

Recuerda como funciona el valor de PRECARGA:

Como controlar el brillo de un LED : Introducción al PWM.

La formula:

En este caso fue suficiente probar con el PRESCALER 1 para obtener un valor de PRECARGA entre 0 y 255. Quedando entonces como resultado el valor redondeado de:

PRECARGA = 250

PASO 5.

Finalmente te presentamos nuestro código de programación :

PWM POR SOFTWARE CODIGO PARA 8 SALIDAS PWM.

#include <16f628mks.h>  // Define el PIC16f628
#FUSES INTRC_IO   // HABILITA el OSCILADOR INTERNO debe ir acompñado de #use delay(clock = X000000 , INTERNAL)
#USE DELAY(clock = 4000000, INTERNAL) // COMPLEMENTA EL FUSE INTRC_IO DEFINIENDO LA FRECUENCIA DEL RELOJ INTERNO.
#fuses NOMCLR         // DESABILITA EL PIN DE RESET EVITA TENER QUE CONECTARLO A POSITIVO (RA5)
#fuses NOWDT          // DESABILITA EL AUTO RESET DEL PIC CUANDO SE CUELGA
#fuses NOPROTECT      // ENABLE O DISABLE LA LECTURA DEL CODIGO DEL PROGRAMA
#fuses NOLVP          // DESABILITA QUE EL PIN RB4 SE CONVIERTA EN TERMINAL DE PROGRAMACION.
#fuses NOBROWNOUT     // EL MAS IMPORTANTE HABILITA AL PIC PARA TRABAJAR EN BAJO VOLTAGE CON LA PILA DE 3.7 VOLTIOS FUNCIONA GENIAL.

INT16 CONTINT=0;            // CONTADOR DE INTERRUPCIONES SIRVE PARA MARCAR EL ANCHO DE PULSO Y EL FLANCO DE SUBIDA DEL PERIODO
signed char PWMX=0;         // VARIABLE QUE CONTROLA EL ANCHO DE PULSO ASCENDENTE AL COMPARARSE CON EL CONTADOR DE INTERRUPCIONES CONTINT
int1 FLAG=0;                // VARIABLE BOLEANA QUE NOS AYUDA A AUMENTAR O DISMINUIR PWMX O PWMY
int1 REPOSA=0;              // VARIABLE BOLEANA QUE MANTIENE APAGADO  LOS LEDS UN RATITO UNA VEZ QUE PWMX LLEGO A CERO
    

// AQUI COMIENZA LA INTERRUPCION DEL TIMER 0 

#int_RTCC

void  RTCC_isr(void) 
   {

//************************* EL EFECTO  ENCIENDE TODOS LOS 8 LEDS AL MISMO TIEMPO Y LUEGO LOS APAGA TAMBIEN AL MISMO TIEMPO .       
 //   if (efecto==0) {      COMO ES EL UNICO EFECTO NO SE REQUIERE DE ESTE IF

    
    IF (REPOSA == 0)        // CUANDO REPOSA NO ESTA ACTIVADO EL PWMX AVANZA DESDE 0 HASTA 120 Y LUEGO REGRESA DE 120 A 0 CUANDO RETORNA A 0 REPOSA SE ACTIVA A UNO.
    {
    if (CONTINT==PWMX)      // COMPARADOR DEL CONTADOR DE INTERRUPCIONES CON EL ANCHO DE PULSO, AL COINCIDIR AL COINCIDIR SE MARCA EL FLANCO DE BAJADA DEL PULSO DEL PWMX
    {
    rb0=0;
    rb1=0;
    rb2=0;
    rb3=0;
    rb4=0;
    rb5=0;
    rb6=0;
    rb7=0;
    }
    CONTINT++;             // CADA VEZ QUE SE REALIZA EL FLANCO DE BAJADA DEL ANCHO DE PULSO CONTINT AUMENTA HAZTA LLAGAR A 120
    IF (CONTINT==31)      // AL LLEGAR A LOS 32 ANCHOS DE PULSO SE LEVANTA EL FLANCO DEL PERIODO 
    {
    rb0=1;
    rb1=1;
    rb2=1;
    rb3=1;
    rb4=1;
    rb5=1;
    rb6=1;
    rb7=1;
    
    CONTINT=0;                 // UNA VEZ QUE SE LEVANTA EL FLANCO DEL PERIODO EL CONTADOR DE INTERRUPCIONES VUELVE A CERO
    
    if (FLAG==0)               // FLAG SIEMPRE INICIA EN 0 Y ESO NOS PERMITE CONTROLAR PWMX HAZTA QUE LLEGA A 120
    {
    PWMX++;                    // PWMX SE INCREMENTA EN UNO CON CADA FLANCO DE SUBIDA DE FIN DE PERIODO
    IF (PWMX==31) {FLAG++;}   // AL LLEGAR PWMX A 32, FLAG CAMBIA A 1 PARA QUE ENTRE EL SIGUIENTE IF Y PWMX AHORA PUEDA DISMINUIR
    }
    
    if (FLAG==1)               // CUANDO FLAG ES UNO NOS PERMITE REDUCIR EL VALOR DE PWMX DESDE 120 HAZTA 0
    {
    PWMX--;                    // PWM DISMINUYE EN UNO CON CADA FLANCO DE SUBIDA DE FIN DE PERIODO
    IF (PWMX==0)               // IF DE CONTROL CUANDO PWMX RETROCEDE HAZTA LLEGAR A CERO
    {
    FLAG++;                    // PWMX AL LLEGAR A CERO EL FLAG VUELVE A SER 0
    REPOSA++;                  // PWMX AL LLEGAR A CERO ACTIVA EL CONTROL REPOSA
    }
    }
    

    }
    set_timer0(250);             // VOLVEMOS A CARGAR EL TIMER O CON EL VALOR SELECCIONADO
    break;                       // SALIMOS DEL IF
    }
    
    ELSE IF (REPOSA == 1)        // SI REPOSA ESTA ACTIVADO SIGNIFICA QUE PWMX ES CERO Y HAREMOS UNA PAUSA DE 2500 INTERRUPCIONES PARA OBSERVAR EL APAGADO DEL EFECTO
    {
    rb0=0;
    rb1=0;
    rb2=0;
    rb3=0;
    rb4=0;
    rb5=0;
    rb6=0;
    rb7=0;
    CONTINT++;                   // EL CONTADOR DE INTERRUPCIONES SIGUE CONTANDO
    IF (CONTINT ==2500)          // AL LLEGAR A LAS 2500 INTERRUPCIONES
    {REPOSA=0; CONTINT=0;}       // SALIMOS DE REPOSA Y REINICIAMOS A CERO EL VALOR DEL CONTADOR DE INTERRUCIONES
    
    set_timer0(250);             // RECARGAMOS EL VALOR DEL TIMER 
    BREAK;                       // SALIMOS DE ESTE IF
    }

 // }
    
    }

//***********************************************************************************************************************

// ESTA ES LA CONFIGURACION DEL TIMER Y DE LOS PUERTOS DEL PIC EL RESTO SE EJECUTA EN LA INTERRUPCION.
void main()
   {
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);    // CONFIGURAR EL TIMER 0 COMO TEMPORIZADOR Y SIN PREESCALER
   set_timer0(250);                            // EL TIMER 0 ES PRECARGADO CON EL VALOR DE 250.
   clear_interrupt(INT_TIMER0);                // LIMPIAMOS LA BANDERA DE LA INTERRUPCION DEL TIMER 0
   enable_interrupts(INT_RTCC);                // HABILITAMOS LA INTERRUPCION DEL TIMER 0
   enable_interrupts(GLOBAL);                  // HABILITAMOS INTERRUPCIONES GLOBALES 
 
   TRISA = 0X00;                               // CONFIGURAMOS TODO EL PUERTO A COMO SALIDA
   TRISB = 0x00;                               // CONFIGURAMOS TODO EL PUERTO B COMO SALIDA
   PORTB = 0b00000000;                         // INICIA EL PUERTO B COMPLETO COMO SALIDA
   PWMX=0;                                     // PWMX INICIALIZA EN CERO
   CONTINT=0;                                  // EL CONTADOR DE INTERRUPCIONES SE INICIA EN 0
   
   while(1)
     {
     // LOS EFECTOS SON AUTOMATICOS EN SECUENCIA Y SE REPITEN.  SI QUIERES QUE SEA MANUAL AQUI DEBES PONER LOS IF DE LOS PULSADORES Y ELIMINAR LA VARIABLE 
     // EFECTO AL FINAL DE CADA UNO DE LOS EFECTOS PARA QUE EL CAMBIO DE EFECTO NO SEA AUTOMATICO SINO MANUAL
     }
        
   }

Este programa nos dará 8 salidas PWM con un efecto básico, a partir de este puedes crear muchas otras combinaciones de efectos y salidas a tu gusto y antojo.

El video que hemos colocado en YOUTUBE muestra una secuencia de efectos un poco mas compleja pero con el mismo principio de funcionamiento.

Te invito a ver el video:

Agregue un comentario

Su dirección de correo no se hará público. Los campos requeridos están marcados *