Voltimetro 3 led rgb

Hola, necesito de su ayuda nuevamente, arme el físico y funciona correctamente pero tiene un parpadeo molesto los led y probé subiendo la frecuencia o bajando y no veo cambio alguno, como hago para que parpadee menos?
 
Hola, no medí pero funciona mejor a 8 mhz, voy a tener que usar un cristal de 20 mhz y probar este pic 12f683 interno solo llega a 8mhz, por timer no se bien como hacer que desborde mas rápido , pero non se si me serviría mucho.
 
Última edición:
Con esta librería controlo los led, si divido por 4 el preescaler obtengo una mayor frecuencia?
Código:
long contador;
long red, green, blue;

#define COMMON_CATHODE 1
#define COMMON_ANODE 0
#define RGB_HARDWARE

#ifdef RGB_HARDWARE
#int_timer0                                                              // Interrupcion en el timer 0
void timer0_isr()
{
   contador = contador + 5;
   if(contador > 256)
   {contador = 0;}
   if(contador < red) output_high(led_r); else output_low(led_r);        // Pulsos del led rojo
   if(contador < green) output_high(led_g); else output_low(led_g);      // Pulsos del led verde
   if(contador < blue) output_high(led_b); else output_low(led_b);       // Pulsos del led azul
   set_timer0(0);
}
#endif

long map_int(int16 valor, int16 entradaMin, int16 entradaMax, int16 salidaMin, int16 salidaMax)
{
   return((((valor-entradaMin)*(salidaMax-salidaMin))/(entradaMax-entradaMin))+salidaMin);
}

void rgb_init()
{
   setup_timer_0(rtcc_internal | rtcc_div_1 | rtcc_8_bit);               // Configuracion del timer 0
   enable_interrupts(int_rtcc);                                          // Habilitacion del la interrupcion en el timer 0
   enable_interrupts(global);                                            // Habilitacion de las interrupciones globales
   set_timer0(0);                                                        // Carga el valor del timer 0
}

void rgb_write_value(int value_r, int value_g, int value_b, int1 t_led)
{
   switch(t_led)
   {
      case 0:
      int ta_led_r = map_int(value_r, 0, 255, 255, 0);                // Conversion del valor red
      int ta_led_g = map_int(value_g, 0, 255, 255, 0);                // Conversion del valor green
      int ta_led_b = map_int(value_b, 0, 255, 255, 0);                // Conversion del valor blue
      if(ta_led_r > 254){
         red = 256;
      }else{
         red = ta_led_r;
      }
      if(ta_led_g > 254){
         green = 256;
      }else{
         green = ta_led_g;
      }
      if(ta_led_b > 254){
         blue = 256;
      }else{
         blue = ta_led_b;
      }
      break;
     
      case 1:
      int tc_led_r = map_int(value_r, 0, 255, 0, 255);                // Conversion del valor red
      int tc_led_g = map_int(value_g, 0, 255, 0, 255);                // Conversion del valor green
      int tc_led_b = map_int(value_b, 0, 255, 0, 255);                // Conversion del valor blue
      red = tc_led_r;
      green = tc_led_g;
      blue = tc_led_b;
      break;
   }
}

void red_channel_write(int data_red, int1 trg_led_r)
{
   switch(trg_led_r)
   {
      case 0:
      int da_red = map_int(data_red, 0, 255, 255, 0);                    // Conversion del valor red
      if(da_red > 254){
         red = 256;
      }else{
         red = da_red;
      }
      break;

      case 1:
      int dc_red = map_int(data_red, 0, 255, 0, 255);                    // Conversion del valor red
      red = dc_red;
      break;
   }
}

void green_channel_write(int data_green, int1 trg_led_g)
{
   switch(trg_led_g)
   {
      case 0:
      int da_green = map_int(data_green, 0, 255, 255, 0);                // Conversion del valor green
      if(da_green > 254){
         green = 256;
      }else{
         green = da_green;
      }
      break;

      case 1:
      int dc_green = map_int(data_green, 0, 255, 0, 255);                // Conversion del valor green
      green = dc_green;
      break;
   }
}

void blue_channel_write(int data_blue, int1 trg_led_b)
{
   switch(trg_led_b)
   {
      case 0:
      int da_blue = map_int(data_blue, 0, 255, 255, 0);                  // Conversion del valor blue
      if(da_blue > 254){
         blue = 256;
      }else{
         blue = da_blue;
      }
      break;

      case 1:
      int dc_blue = map_int(data_blue, 0, 255, 0, 255);                  // Conversion del valor blue
      blue = dc_blue;
      break;
   }
}
controlo los led
 
Última edición:
Por eso te dije que lo ideal es que primero hagas encender un led, para que entiendas el funcionamiento del timer.

Al aumentar el valor de preescaler, más lenta es la cuenta y por ende menor la frecuencia de tu señal. Por ej. un preescaler x4 implica que necesitás 4 clks para completar una cuenta.

Vos estás configurando el preescaler en 1 y el contador con 256 cuentas. Es decir que después de 256 clks, se genera una interrupción. Ahora bien, la frecuencia de clk que le llega al timer es la del cristal/4, por lo tanto:

f_timer=fsoc/(4*256)

Y a eso le tenés que agregar 51 cuentas más que hacés en la rutina de interrupción. Supongo que con 8MHz te dá una frecuencia de:

f_timer=8MHz/(4*256*51)=153 Hz aproximadamente.

Si querés aumentar la frecuencia, bajá la cuenta del contador:

C:
set_timer0(127);   // Carga el valor del timer 127

f_timer=8MHz/(4*128*51)=306 Hz aproximadamente.

Eso lo tenés que hacer tanto en "void rgb_init()" como en la rutina de interrupción.
 
Si es tal cual como me indicaste!

Ahora entendí mejor como confirmación el timer, te agradezco un montón.

Probé todas las configuraciones y sigue el parpadeo, que pic de la línea 12f tiene oscilador interno de 20mhz creo que ahí funcionaria mejor, gracias
 
Es raro, pero probá a ver que pasa.

Particularmente creo que el problema puede estar en otro lado, como arranque tendrías que poder comprobar que los tiempos del PWM son los correctos. Si te interesa después te subo un código sencillo para probar y ver que pasa con eso.
 
Probá con esto:

C:
#include <12f683.H>
#device ADC=10
#use delay(clock=8mhz)
#fuses intrc_io,nomclr,nowdt, PROTECT

#define led_r        PIN_A1                    // Pin del canal rojo
#define TIEMPO_MS    (unsigned int16)1000    // 1000mS = 1S

unsigned int16 contador_ms=0;

#int_timer0                    // Interrupcion en el timer 0
void timer0_isr()
{
    contador_ms++;

    if(contador_ms>=TIEMPO_MS)    //Cuenta 1000 mS= 1Seg
    {
        contador_ms=0;
        if(input(PIN_A1))
            output_low(led_r);
        else
            output_high(led_r);
    }
   
    set_timer0(6); // Tiempo deseado por interrupción=1mS => Carga Timer= 256-[(Tiempo deseado*fosc)/(4*Preescaler)]= 256-[(1mS*8MHz)/(4*8)]= 6
}
#endif

void IniciarTimer0()
{
    setup_timer_0(rtcc_internal | rtcc_div_8 | rtcc_8_bit);               // Configuracion del timer 0
    enable_interrupts(int_rtcc);                                          // Habilitacion del la interrupcion en el timer 0
    enable_interrupts(global);                                            // Habilitacion de las interrupciones globales <--- No sé de donde sale la variable "global"
    set_timer0(6);                                                          // Tiempo deseado por interrupción=1mS => Carga Timer= 256-[(Tiempo deseado*fosc)/(4*Preescaler)]= 256-[(1mS*8MHz)/(4*8)]= 6
}

void main()
{
    IniciarTimer0()                
    set_tris_a(0xfD);    //Acá puede haber algo mal, en algún punto tenés que definir que vas a usar un puerto como salida (en este caso, puse el puerto 1 y el resto como entrada), en tu uC se usa el registro TRISIO, pero en CCS no existe y al parecer se usa el "TRIS A".
    while(true)
    {
        //Se puede agregar algo... por ej. un sleep
    }   
}

La idea es que te encienda y apague un led cada un segundo. Si eso funciona, cambiá el valor de TIEMPO_MS por 10, para que obtengas una señal PWM al 50% a una frecuencia de 50Hz y fijate como se ve el led.

PD: puede haber errores en las funciones y declaraciones propias del CCS, no suelo usar PICS.
 
Ahora lo veo, estaba haciéndolo
Código:
  #include <12f683.H>
#device ADC=10
#use delay(clock=8mhz)
#fuses intrc_io,nomclr,nowdt, PROTECT

#define led_r PIN_a1                                // Pin del canal rojo
#define led_g PIN_a2                                    // Pin del canal verde
#define led_b PIN_a4                            // Libreria para el manejo del led RGB



int16 analogico;

#int_timer0
void pwm_duty(long pwm0, long pwm1, long pwm2){
   long cont;
   if(cont>256)
      cont=0;
   else
      cont++;
   if(cont>0&&cont<pwm0)
     output_low(PIN_a1);
   else
      output_high(PIN_a1);
      
   if(cont>0&&cont<pwm1)
     output_low(PIN_a2);
   else
    output_high (PIN_a2);
      
   if(cont>0&&cont<pwm2)
       output_low (PIN_a4);
   else
     output_high (PIN_a4);
      
   set_timer0(0);     
}
void main(){
   setup_adc_ports( AN0_ANALOG );
 setup_adc( ADC_CLOCK_INTERNAL );
 set_adc_channel( 0 );
   set_timer0(0);
   enable_interrupts(INT_TIMER0);
   enable_interrupts(GLOBAL);
   while(true){
 
         analogico= read_adc();
delay_ms(15);

if (analogico > 0){
  pwm_duty(0, 0, 0); 
}

  if (analogico > 100){
      pwm_duty (255, 0, 0);       // Color rojo     
  }
       if (analogico > 200){
      pwm_duty(0, 255, 0);  // Color verde
    
         }
        
      if (analogico > 300){
       pwm_duty(0, 0, 255);       // Color azul
    }
  
      if (analogico > 400){
     pwm_duty (0, 240, 255);     // Color cyan
      }
      
       if (analogico > 500){
    pwm_duty  (255, 0, 125);     // Color rosa
    }
      if (analogico > 600){
    pwm_duty (100, 0, 255);     // Color morado
      }
         if (analogico > 700){
    pwm_duty (255, 220, 0);     // Color amarillo
     }
       if (analogico > 800){
    pwm_duty(255, 80, 0);      // Color naranja
     }
    
      if (analogico > 900){
     pwm_duty (255, 255, 255);   // Color blanco
          }
            
          
   }

}
asi
 
En lugar de una cadena de comparaciones te conviene usar una tabla.

Este ejemplo parte de un copypaste de tu código original al que no me quedó otra opción que sacarle casi todo.


C:
#include <12f683.H>
#device ADC=8
#use delay(internal=8MHz)
#fuses intrc_io,nomclr,nowdt, PROTECT

#use FIXED_IO( A_outputs=PIN_A4,PIN_A2,PIN_A1 )

#define led_r PIN_a1       // Pin del canal rojo
#define led_g PIN_a2       // Pin del canal verde
#define led_b PIN_a4       // Pin del canal azul

//--------------------------------------------------
struct RGB {int8 r, g, b ;} ;

const struct RGB rgb[]={{  0,  0,  0},  // 0   la nada
                        {255,  0,  0},  // 1   rojo
                        {  0,255,  0},  // 2   verde
                        {  0,  0,255},  // 3   azul
                        {  0,240,255},  // 4   cyan
                        {255,  0,125},  // 5   rosa
                        {100,  0,255},  // 6   morado
                        {255,220,  0},  // 7   amarillo
                        {255, 80,  0},  // 8   naranja
                        {255,255,255},  // 9   blanco
                        {255,255,255}}; // 10  blanco

//--------------------------------------------------
struct RGB pwm = {0,0,0} ;

#INT_TIMER2
void  TIMER2_isr(void)
{
static int8 contador=0x00;

    if(contador==0x00)      output_a(0xFF)    ;
    else {
        if(contador==pwm.r) output_low(led_r) ;

        if(contador==pwm.g) output_low(led_g) ;

        if(contador==pwm.b) output_low(led_b) ;
    }
    contador-- ;
}
//--------------------------------------------------
int8 analogico;
void main()
{
    setup_adc_ports(sAN0, VSS_VDD);
    setup_adc(ADC_CLOCK_INTERNAL);

    set_adc_channel( 0 );

    output_a(0xFF) ;
    setup_timer_2(T2_DIV_BY_1,129,1);    // 65.0 us overflow,
                                        // 65.0 us interrupt

    enable_interrupts(INT_TIMER2);
    enable_interrupts(GLOBAL);

    while(true)
    {
        delay_ms(20);
        analogico= read_adc()/25;
        pwm = rgb[analogico] ;
   }
}

Tengo una duda... Al led RGB le estás poniendo las debidas resistencias (diferentes para cada color) o lo mandás derecho al pic como en uno de tus últimos .rars ?
 
Solamente hay que tocar la interrupcion. Podés usar directivas condicionales.

Al principio definís si es AC
C:
#define ANODO_COMUN
Si es CC la marcás como comentario o borrás esa línea.

Dentro de la interrupción
C:
#IFDEF ANODO_COMUN
    if(contador==0x00)      output_a(0xFF)    ;
    else {
        if(contador==pwm.r) output_low(led_r) ;
        if(contador==pwm.g) output_low(led_g) ;
        if(contador==pwm.b) output_low(led_b) ;
    }
#ELSE             // Es CC
    if(contador==0x00)      output_a(0x00)    ;
    else {
        if(contador==pwm.r) output_high(led_r) ;
        if(contador==pwm.g) output_high(led_g) ;
        if(contador==pwm.b) output_high(led_b) ;
    }
#ENDIF

Y se compilará el bloque que corresponda.
 
Atrás
Arriba