Fade LED RGB

Basándonos en el post de múltiples PWM sin CCP http://electgpl.blogspot.com.ar/2014/10/multiple-pwm-sin-ccp.html realizaremos un paneo o fade del espectro de colores de forma automática, si bien existen leds RGB automáticos que solo hay que alimentarlos para que produzcan este efecto, la idea es dar el pie para luego realizar trabajos mas elaborados.
Primero que nada debemos saber que un LED RGB es en realidad tres leds en un solo package, un led Rojo, un led Verde y un led Azul, el método para formar colores o tonos depende de cuanto se encienda cada color, cuando digo cuanto se encienda estamos hablando del ciclo de trabajo PWM, es decir un led al que lo excitamos con PWM a un ciclo de trabajo del 20% brillara menos que si lo excitamos al 80%, de esta forma con el PWM logramos controlar el brillo. 
Al tratarse de 3 LEDs podremos controlar el brillo de cada uno por individual, lo que nos permitirá no solo encender el led de color Rojo, Verde o Azul, sino también todas sus variantes intermedias hasta lograr una graduación del color.
Esto lo vamos a entender mejor en el Gif que se encuentra abajo, donde podemos ver como varia el valor de 0 a 255 o de 0 a 100% de cada uno de los colores al pasar por todo el espectro.



Ahora que tenemos en claro que debemos variar el valor del ciclo de trabajo de cada color, procedemos a explicar mejor el programa.
Como el post mencionado anteriormente donde se enseña a manipular múltiples canales PWM sin el modulo CCP, se le agregaran lazos for que realizaran la tarea que muestra el gif animado que se encuentra arriba.
Como podremos ver en el firmware estamos manejando los valores de 0 a 15, esto nos dará 16 niveles de cada color, claramente podrían ser mas niveles para una mayor resolución pero en la practica podrán ver que no se nota la diferencia y con 16 niveles tendremos un programa mas rápido.
Ahora la parte del fade de colores.
como vemos en el gif, los pasos serán los siguientes

 R  , G  , B
100%, 0% ,Inc
Dec , 0% ,100%
 0% ,Inc ,100%
 0% ,100%,Dec
Inc ,100%, 0%
100%,Dec , 0%

Ahora que tenemos en claro la secuencia realizaremos un lazo for por cada una de ellas quedando los seis lazos independientes.
Se incluye una demora de 50ms por cada lazo para dar tiempo a ver el incremento o decremento de la variable. El tiempo sera 50ms por 16 ya que se repetirá 16 veces, nos dará un valor de 800ms en cada lazo for, una secuencia de aproximadamente 5s.


#include <16F628A.h>
#FUSES NOWDT, HS, NOMCLR 
#use delay(clock=4000000)
#int_timer0 
void pwm_duty(int pwm0, int pwm1, int pwm2){
   int cont;
   if(cont>15)
      cont=0;
   else
      cont++; 
   if(cont>0&&cont<pwm0)
      output_high(PIN_B0);
   else
      output_low(PIN_B0);
   if(cont>0&&cont<pwm1)
      output_high(PIN_B1);
   else
      output_low(PIN_B1);
   if(cont>0&&cont<pwm2)
      output_high(PIN_B2);
   else
      output_low(PIN_B2);
   set_timer0(0);      
}
void main(){
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1); 
   set_timer0(0); 
   enable_interrupts(INT_TIMER0); 
   enable_interrupts(GLOBAL); 
   while(true){
      int r, g, b;
      for(b=0;b<16;b++){
         pwm_duty(16,0,b);
         delay_ms(50);
      }
      for(r=16;r>1;r--){
         pwm_duty(r,0,16);
         delay_ms(50);
      }
      for(g=0;g<16;g++){
         pwm_duty(0,g,16);
         delay_ms(50);
      }
      for(b=16;b>1;b--){
         pwm_duty(0,16,b);
         delay_ms(50);
      }      
      for(r=0;r<16;r++){
         pwm_duty(r,16,0);
         delay_ms(50);
      }
      for(g=16;g>1;g--){
         pwm_duty(16,g,0);
         delay_ms(50);
      }
   }
}