# Control para dimer de 8 canales individuales con el micro controlador PIC16f877a



## Saint_ (Abr 14, 2014)

Control para dimer de 8 canales individuales con el micro controlador PIC16f877a
“Un buen día” recordé que en un video del youtube presentaban un proyecto el cual consistía en un juego de luces tipo auto fantástico, es decir que el led encendido iba de izquierda a derecha dejando una estela como la de un cometa, en ese momento solo me llamo la atención como algo curioso, también leí por ahí que debería estar hecho en base a salidas PWM (esto para generar la impresión de la estela dejada al paso del led principal). Ahora que “no sé qué hacer (me estoy aburriendo de mí mismo)… jajajajajajaj”, me dije “que tal si haces uno de esos, así te distraes un poco”, fue así que empecé con este pequeño proyecto.
 ************************************************** ****************************
1 Condiciones base del proyecto.

 El proyecto constara de 8 salidas PWM (modulación por ancho de pulso) para el control de potencia para aplicaciones DC (corriente directa) que pueden ser manipuladas independientemente una de otra.
 El proyecto costara de 8 salidas PPM (modulación por posición de pulso) para el disparo de triac, esto para el control de potencia por fase para aplicaciones de AC (corriente alterna) que puedan ser manipuladas independientemente una de otra.
 Tanto las señales PWM y PPM serán controladas simultáneamente por los 8 canales conversores analógicos a digitales (ADC) disponibles en un PIC 16f877a.
 El proyecto deberá ser flexible en el sentido de poder modificarlo fácilmente en caso de usar otro medio de control de las señales PWM y PPM distinto de los canales ADC del microcontrolador, adicionalmente poder cambiar los pines de las salidas PWM y PPM a gusto.
2 Tips para el diseño del proyecto.

2.1 Modulación por ancho de pulso (PWM).

 La modulación por ancho de pulso consiste en un tren de pulsos de onda rectangular con frecuencia constante cuyo parámetro a variar es el ancho de pulso o ciclo de servicio.
 El ciclo de servicio es está definido por la relación entre el tiempo de nivel alto y el periodo de la onda rectangular.

​Para generar la onda rectangular se definirá una frecuencia de 100 Hz (T=10ms), para el cual se empleara el temporizador 0 del microcontrolador.
  La interrupción temporizada se disparara cada 100us para obtener una resolución del 1% 
  La variable _ciclo_ guardara el valor del ciclo de servicio de la señal PWM y la variable _n_ hará de contador para verificar si se llegó al valor del ciclo de servicio.
*2.2 Modulación por posición de pulso (PPM).*

  La modulación por posición de pulso conste en un tren de pulsos de onda rectangular con frecuencia constante y ancho de pulso constante, el parámetro a variar es posición de pulso.

​ 
Para generar la señal PPM (modulación por ancho de pulso) se utilizara el temporizador 1, su interrupción se disparara cada 100us para obtener una resolución de 1%.
  La variable ángulo es la encargada de guardar el momento en el que se generara el pulso. El pulso tendrá una duración de 100us.
  Para sincronizarlo con la red eléctrica se utilizara la interrupción externa disparada por flancos.
*3        Código y esquema básico.*
  El programa está realizado en CCS PIC 

```
/*********************************************************************
  Este programa hace la lectura de los 8 canales del ADC del pic, según
  el valor de cada canal y mediante un  factor de escala genera 8 señales
  PWM(pensado para dimer DC) individuales por el puerto D y 8 señales 
  PPM(pensado para dimer AC) individuales por el puerto C, cada salida
  PWM y PPM están en función del valor capturado por cada canal del ADC.
  La frecuencia del PWM es 100Hz
  *********************************************************************/
  #include <16f877a.h>
  #fuses   xt,nowdt
  #device  adc=10
  #use     delay(clock=20M)
  /****************************************************/
  #define  ppm0  pin_c0
  #define  ppm1  pin_c1
  #define  ppm2  pin_c2
  #define  ppm3  pin_c3
  #define  ppm4  pin_c4
  #define  ppm5  pin_c5
  #define  ppm6  pin_c6
  #define  ppm7  pin_c7
  /****************************************************/
  #define  pwm0  pin_d0
  #define  pwm1  pin_d1
  #define  pwm2  pin_d2
  #define  pwm3  pin_d3
  #define  pwm4  pin_d4
  #define  pwm5  pin_d5
  #define  pwm6  pin_d6
  #define  pwm7  pin_d7
  /*****************************************************
  Variables para guardar los valores leídos por el ADC
  /****************************************************/
  unsigned int16 dato_adc0;
  unsigned int16 dato_adc1;
  unsigned int16 dato_adc2;
  unsigned int16 dato_adc3;
  unsigned int16 dato_adc4;
  unsigned int16 dato_adc5;
  unsigned int16 dato_adc6;
  unsigned int16 dato_adc7;
  /*****************************************************
  Variables para el ciclo de servicio del PWM (0-100%)
  /****************************************************/
  unsigned int8  ciclo0=0;
  unsigned int8  ciclo1=0;
  unsigned int8  ciclo2=0;
  unsigned int8  ciclo3=0;
  unsigned int8  ciclo4=0;
  unsigned int8  ciclo5=0;
  unsigned int8  ciclo6=0;
  unsigned int8  ciclo7=0;
  /*****************************************************
  Variables para el posición de pulso de PPM (Angulo de disparo para el TRIAC de 0-97%)
  *****************************************************/
  unsigned int8  angulo0=97;
  unsigned int8  angulo1=97;
  unsigned int8  angulo2=97;
  unsigned int8  angulo3=97;
  unsigned int8  angulo4=97;
  unsigned int8  angulo5=97;
  unsigned int8  angulo6=97;
  unsigned int8  angulo7=97;
  /***************************************************/
  unsigned int8  n=0;  //contador para la señal PWM
  unsigned int8  m;    //contador para la señal PPM
  /***************************************************/
  #int_ext
  void detector_cruce_por_cero()
  {
     if(input_state(pin_b0))
     {
        ext_int_edge(h_to_l);
     }
     else
     {
        ext_int_edge(l_to_h);
     }
  
     set_timer1(65085);
     setup_timer_1(t1_internal|t1_div_by_1);
     m=0;
     if(angulo0==0)
     {
        output_high(ppm0);
     }
     if(angulo1==0)
     {
        output_high(ppm1);
     }
     if(angulo2==0)
     {
        output_high(ppm2);
     }
     if(angulo3==0)
     {
        output_high(ppm3);
     }
     if(angulo4==0)
     {
        output_high(ppm4);
     }
     if(angulo5==0)
     {
        output_high(ppm5);
     }
     if(angulo6==0)
     {
        output_high(ppm6);
     }
     if(angulo7==0)
     {
        output_high(ppm7);
     }
  }
  #int_timer1
  void ppm()
  {
     set_timer1(65077);
     if(input_state(ppm0))
     {
        output_low(ppm0);
     }
     else
     {
        if(m==angulo0)
        {
           output_high(ppm0);
        }
     }
  
     if(input_state(ppm1))
     {
        output_low(ppm1);
     }
     else
     {
        if(m==angulo1)
        {
           output_high(ppm1);
        }
     }
  
     if(input_state(ppm2))
     {
        output_low(ppm2);
     }
     else
     {
        if(m==angulo2)
        {
           output_high(ppm2);
        }
     }
  
     if(input_state(ppm3))
     {
        output_low(ppm3);
     }
     else
     {
        if(m==angulo3)
        {
           output_high(ppm3);
        }
     }
  
     if(input_state(ppm4))
     {
        output_low(ppm4);
     }
     else
     {
        if(m==angulo4)
        {
           output_high(ppm4);
        }
     }
  
     if(input_state(ppm5))
     {
        output_low(ppm5);
     }
     else
     {
        if(m==angulo5)
        {
           output_high(ppm5);
        }
     }
  
     if(input_state(ppm6))
     {
        output_low(ppm6);
     }
     else
     {
        if(m==angulo6)
        {
           output_high(ppm6);
        }
     }
  
     if(input_state(ppm7))
     {
        output_low(ppm7);
     }
     else
     {
        if(m==angulo7)
        {
           output_high(ppm7);
        }
     }
  
     m++;
  }
  #int_timer0
  void generar_pwm()
  {
     delay_cycles(1);
     set_timer0(28);
     if(n>=ciclo0)
     {
        output_low(pwm0);
     }
     else
     {
        output_high(pwm0);
     }
  
     if(n>=ciclo1)
     {
        output_low(pwm1);
     }
     else
     {
        output_high(pwm1);
     }
  
     if(n>=ciclo2)
     {
        output_low(pwm2);
     }
     else
     {
        output_high(pwm2);
     }
  
     if(n>=ciclo3)
     {
        output_low(pwm3);
     }
     else
     {
        output_high(pwm3);
     }
  
     if(n>=ciclo4)
     {
        output_low(pwm4);
     }
     else
     {
        output_high(pwm4);
     }
  
     if(n>=ciclo5)
     {
        output_low(pwm5);
     }
     else
     {
        output_high(pwm5);
     }
  
     if(n>=ciclo6)
     {
        output_low(pwm6);
     }
     else
     {
        output_high(pwm6);
     }
  
     if(n>=ciclo7)
     {
        output_low(pwm7);
     }
     else
     {
        output_high(pwm7);
     }
  
     if(n==100)
     {
        n=0;
     }
     else
     {
        n++;
     }
  }
  void main()
  {
     setup_adc(adc_clock_internal);
     setup_adc_ports(all_analog);
     output_d(0);
     enable_interrupts(global);
     enable_interrupts(int_ext_l2h);
     enable_interrupts(int_timer1);
     enable_interrupts(int_timer0);
     setup_timer_0(t0_internal|t0_div_2);
     while(true)
     {
        set_adc_channel(0);
        delay_ms(1);
        dato_adc0=read_adc(adc_start_and_read);
  
        set_adc_channel(1);
        delay_ms(1);
        dato_adc1=read_adc(adc_start_and_read);
  
        set_adc_channel(2);
        delay_ms(1);
        dato_adc2=read_adc(adc_start_and_read);
  
        set_adc_channel(3);
        delay_ms(1);
        dato_adc3=read_adc(adc_start_and_read);
  
        set_adc_channel(4);
        delay_ms(1);
        dato_adc4=read_adc(adc_start_and_read);
  
        set_adc_channel(5);
        delay_ms(1);
        dato_adc5=read_adc(adc_start_and_read);
  
        set_adc_channel(6);
        delay_ms(1);
        dato_adc6=read_adc(adc_start_and_read);
  
        set_adc_channel(7);
        delay_ms(1);
        dato_adc7=read_adc(adc_start_and_read);
  
        ciclo0=dato_adc0/10;
        ciclo1=dato_adc1/10;
        ciclo2=dato_adc2/10;
        ciclo3=dato_adc3/10;
        ciclo4=dato_adc4/10;
        ciclo5=dato_adc5/10;
        ciclo6=dato_adc6/10;
        ciclo7=dato_adc7/10;
  
        angulo0=102-ciclo0;
        angulo1=102-ciclo1;
        angulo2=102-ciclo2;
        angulo3=102-ciclo3;
        angulo4=102-ciclo4;
        angulo5=102-ciclo5;
        angulo6=102-ciclo6;
        angulo7=102-ciclo7;
        if(angulo0>97)
        {
           angulo0=97;
        }
        if(angulo1>97)
        {
           angulo1=97;
        }
        if(angulo2>97)
        {
           angulo2=97;
        }
        if(angulo3>97)
        {
           angulo3=97;
        }
        if(angulo4>97)
        {
           angulo4=97;
        }
        if(angulo5>97)
        {
           angulo5=97;
        }
        if(angulo6>97)
        {
           angulo6=97;
        }
        if(angulo7>97)
        {
           angulo7=97;
        }
     }
  }
```

********************************************************************
​


----------

