Autor Tema: Timer0 - LEDs RGB  (Leído 4069 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado elfrancho

  • PIC16
  • ***
  • Mensajes: 101
Timer0 - LEDs RGB
« en: 17 de Agosto de 2010, 02:04:42 »
EDITO:


Esta foto es de una duty teoricamente de 50% y miren como que se saltea pasos.. mas abajo esta el codigo a ver si me pueden ayudar !!!


Código: CSS
  1. //      LOS LED PRENDEN TODOS JUNTOS
  2. //  CUANDO SE CUMPLE EL DUTY DEL PRIMERO, SE APAGA
  3. //  CUANDO SE CUMPLE EL DUTY DEL SEGUNDO, SE APAGA
  4. //  CUANDO SE CUMPLE EL DUTY DEL TERCERO, SE APAGA
  5. //  CUANDO SE CUMPLE SE CUMPLE EL PERIODO, REINICIA
  6. //
  7.  
  8. #include <18F4620.h>
  9. #device adc=8
  10. //CONFIGURACIÓN DE BITS
  11. #FUSES NOWDT                    //No Watch Dog Timer
  12. #FUSES XT                       //Crystal osc <= 4mhz
  13. #FUSES NOPUT                    //No Power Up Timer
  14. #FUSES NOPROTECT                //Code not protected from reading
  15. #FUSES BROWNOUT                 //Reset when brownout detected
  16. #FUSES NOLVP                      //Low Voltage Programming on B3(PIC16) or B5(PIC18)
  17. #FUSES NOCPD                    //No EE protection
  18. #FUSES NOWRT                    //Program memory not write protected
  19. #FUSES NODEBUG                  //No Debug mode for ICD
  20.  
  21. #use delay(clock=4000000)
  22. #use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
  23. #use fast_io(A)
  24. #use fast_io(B)
  25. #use fast_io(C)
  26. #use fast_io(D)
  27.  
  28. //LIBRERIAS INCLUIDAS
  29. #include "flex_lcd.c"
  30.  
  31. //DEFINICIONES
  32. #DEFINE TECLA1 PIN_A0
  33. #DEFINE TECLA2 PIN_A1
  34. #DEFINE TECLA3 PIN_A2
  35. #DEFINE ROJO PIN_D2
  36. #DEFINE VERDE PIN_D1
  37. #DEFINE AZUL PIN_D3
  38.  
  39. //DECLARACION DE FUNCIONES
  40. void fin_fin(void);                                                                     //FIN PROGRAMA
  41. void menu(void);                                                                //MENU
  42. void boton_ok(void);
  43. void antirebote(void);
  44. void leds(void);
  45. void display7(void);
  46. void ad(void);
  47. void rs232_in(void);
  48. void pwm_led(void);
  49.  
  50.  
  51. ///DECLARACION DE VARIABLES GLOBALES
  52. char dutyR=0;
  53. char dutyG=0;
  54. char dutyB=0;
  55.  
  56. char opcion=0;                                                                          //MENU
  57. char valor;
  58.  
  59.  
  60. //INTERRUPCIONES
  61. #int_TIMER0
  62. TIMER0_isr() {
  63.         if(dutyR>0){
  64.                 output_high(ROJO);
  65.         }
  66.         if(dutyG>0){
  67.                 output_high(VERDE);
  68.         }
  69.         if(dutyB>0){
  70.                 output_high(AZUL);
  71.         }
  72.         //set_timer0(1);        
  73. }
  74.  
  75.  
  76. ///PROGRAMA
  77.  
  78. void main(void){
  79.    setup_adc_ports(NO_ANALOGS);
  80.    setup_adc(ADC_OFF);
  81.    setup_psp(PSP_DISABLED);
  82.    setup_spi(FALSE);
  83.    setup_wdt(WDT_OFF);
  84.    setup_timer_0(RTCC_INTERNAL|RTCC_DIV_16|RTCC_8_BIT);
  85.    setup_timer_1(T1_DISABLED);
  86.    setup_timer_2(T2_DISABLED,0,1);
  87.  
  88.    enable_interrupts(INT_TIMER0);
  89.    enable_interrupts(GLOBAL);   //ENABLE
  90.  
  91.         set_tris_a(0b00000111);         //PULSADORES
  92.         set_tris_b(0b00000000);         //PORTB SALIDA
  93.         set_tris_c(0b00000000);         //PORTC SALIDA
  94.         set_tris_d(0b00000000);         //PORTD SALIDA
  95.         output_a(0b00000000);
  96.         output_b(0b00000000);
  97.         output_c(0b00000000);
  98.         output_d(0b00000000);
  99.  
  100.         lcd_init();
  101.         delay_ms(20);
  102.         printf(lcd_putc("\f RJ    VD    AZ"));
  103.         //printf(lcd_putc,"\n%i  %i    %i  ",dutyR,dutyG,dutyB);
  104.         //menu();
  105.  
  106.         dutyR=0;
  107.         dutyG=128;
  108.         dutyB=28;
  109. //      printf(lcd_putc,"\n%3u   %3u    %3u  ",dutyR,dutyG,dutyB);
  110. while(1){
  111.         valor=(get_timer0() & 0xff);
  112.         if (valor>dutyR){
  113.                 output_low(ROJO);
  114.         }
  115.         if (valor>dutyG){
  116.                 output_low(VERDE);
  117.         }
  118.         if (valor>dutyB){
  119.                 output_low(AZUL);
  120.         }
  121.         //printf(lcd_putc,"\n%3u   %3u    %3u  ",dutyR,dutyG,dutyB);
  122.        
  123. }
  124. }
  125.  
  126.        
  127.  
  128. //FUNCIONES
  129.  
  130. void antirebote(void) {
  131.         delay_ms(500);
  132. }

Saludos !!!
PD: estoy usando CCS
« Última modificación: 17 de Agosto de 2010, 14:28:03 por elfrancho »

Desconectado MarkKnopfler81

  • PIC12
  • **
  • Mensajes: 64
    • PICs, Electrónica y Robótica
Re: Timer0 - LEDs RGB
« Respuesta #1 en: 17 de Agosto de 2010, 08:32:44 »
Hola.
Para leer la parte menos significativa de una variable debes hacer un and con la mascara 0x0F del siguiente modo:

Código: CSS
  1. x=get_timer0()&0x0F;

Pero ¿a que variables de 4 bits te refieres?

saludos.

Desconectado willynovi

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 546
Re: Timer0 - LEDs RGB
« Respuesta #2 en: 17 de Agosto de 2010, 08:40:27 »
hola elfrancho, pues no he entendido bien, todas las variables quenombras son de 8 bits, cuales serian las de 4bit?

En todo caso la de 4 bits no vas a poder manejarla como de 4 bits, ya que el C la unidad es el byte.

Si solo te importa el nibble bajo lo que puedes hacer es una máscara poniendo todo el nibble alto a ceros usando la función &.

variable4bits = variable8bits & 0x0F;

Y si necesitas el nibble alto,

variable4bits = variable8bits & 0xF0;
variable4bits = variable4bits >> 4;

Espero te sirva,
Saludos
Intento enseñarte a pescar, si solo quieres pescados, espera que un pescador te regale los suyos.

Desconectado elfrancho

  • PIC16
  • ***
  • Mensajes: 101
Re: Timer0 - LEDs RGB
« Respuesta #3 en: 17 de Agosto de 2010, 10:14:18 »
DISCULPEN ARME UNA ENSALADA, ACA VA DE NUEVO

Hola estoy haciendo un control de 3 PWM para leds RGB con el timer0 del PIC18F4620

tengo 3 variables de 8 bits (una para cada color) DutyRojo DutyVerde DutyAzul

el problema es que get_timer0() me devuelve una variable de 16 bits y las tengo que comparar con las de 8 bits

Como puedo obtener la parte menos significativa (que es la que me intereza) del get_timer0()??????


Saludos !!!
PD: estoy usando CCS

Desconectado MarkKnopfler81

  • PIC12
  • **
  • Mensajes: 64
    • PICs, Electrónica y Robótica
Re: Timer0 - LEDs RGB
« Respuesta #4 en: 17 de Agosto de 2010, 10:43:56 »
A, ok entonces para eso tienes que declarar las variables como int16 del siguiente modo:

int16 DutyRojo;
int16 DutyVerde;
int16 DutyAzul;

A partir de ahi se manejan igual que las int8

saludos.

Desconectado elfrancho

  • PIC16
  • ***
  • Mensajes: 101
Re: Timer0 - LEDs RGB
« Respuesta #5 en: 17 de Agosto de 2010, 10:53:50 »
A, ok entonces para eso tienes que declarar las variables como int16 del siguiente modo:

int16 DutyRojo;
int16 DutyVerde;
int16 DutyAzul;

A partir de ahi se manejan igual que las int8

saludos.

Muchas gracias, pero la idea es trabajar todo con 8 bits, para ahorrar CPU..  se podrà  tomar solamente la parte menos significativa del timer0?

Desconectado MarkKnopfler81

  • PIC12
  • **
  • Mensajes: 64
    • PICs, Electrónica y Robótica
Re: Timer0 - LEDs RGB
« Respuesta #6 en: 17 de Agosto de 2010, 11:49:19 »
Hola de nuevo:

Para obtener los 8bits menos significativos solo necesitas hacer lo mismo que decia antes solo que tomas los 8 bits en lugar de 4 o sea asi:

Código: CSS
  1. x=get_timer0() & 0xFF;

Recuerda que si tienes el valor del timer como 16 bits y deseas comprobarlo con un int8 en un if debes usar parentesis de esta forma:

Código: CSS
  1. x=get_timer0()
  2. if((x & 0xFF)==DutyRojo) Tal cosa;

saludos.
« Última modificación: 17 de Agosto de 2010, 11:54:17 por MarkKnopfler81 »

Desconectado elfrancho

  • PIC16
  • ***
  • Mensajes: 101
Re: Timer0 - LEDs RGB
« Respuesta #7 en: 17 de Agosto de 2010, 14:05:11 »
Buenisimo muchas gracias, voy a probar, si no anda, voy a postear el codigo y una imagen del osciloscopio para q vean lo que me pasa....

saludos !!!! y gracias !!!!

Desconectado elfrancho

  • PIC16
  • ***
  • Mensajes: 101
Re: Timer0 - LEDs RGB
« Respuesta #8 en: 17 de Agosto de 2010, 14:24:28 »


Vean, midiendo el color Verde con un duty de 128...  miren como trabaja..  pareceria como que se salta algunos pasos!!!

que puede ser??  les dejo el codigo!!!

Saludos !!!


Código: C
  1. //      LOS LED PRENDEN TODOS JUNTOS EN LA INTERRUPCIÓN
  2. //             DURANTE EL PROGRAMA COMPARA CONSTANTEMENTE EL "DUTY" de cada color con T0, en caso de ser necesario, apaga los leds
  3.  
  4. #include <18F4620.h>
  5. #device adc=8
  6. //CONFIGURACIÓN DE BITS
  7. #FUSES NOWDT                    //No Watch Dog Timer
  8. #FUSES XT                       //Crystal osc <= 4mhz
  9. #FUSES NOPUT                    //No Power Up Timer
  10. #FUSES NOPROTECT                //Code not protected from reading
  11. #FUSES BROWNOUT                 //Reset when brownout detected
  12. #FUSES NOLVP                      //Low Voltage Programming on B3(PIC16) or B5(PIC18)
  13. #FUSES NOCPD                    //No EE protection
  14. #FUSES NOWRT                    //Program memory not write protected
  15. #FUSES NODEBUG                  //No Debug mode for ICD
  16.  
  17. #use delay(clock=4000000)
  18. #use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
  19. #use fast_io(A)
  20. #use fast_io(B)
  21. #use fast_io(C)
  22. #use fast_io(D)
  23.  
  24. //LIBRERIAS INCLUIDAS
  25. #include "flex_lcd.c"
  26.  
  27. //DEFINICIONES
  28. #DEFINE TECLA1 PIN_A0
  29. #DEFINE TECLA2 PIN_A1
  30. #DEFINE TECLA3 PIN_A2
  31. #DEFINE ROJO PIN_D2
  32. #DEFINE VERDE PIN_D1
  33. #DEFINE AZUL PIN_D3
  34.  
  35. //DECLARACION DE FUNCIONES
  36. void fin_fin(void);                                                                     //FIN PROGRAMA
  37. void menu(void);                                                                //MENU
  38. void boton_ok(void);
  39. void antirebote(void);
  40. void leds(void);
  41. void display7(void);
  42. void ad(void);
  43. void rs232_in(void);
  44. void pwm_led(void);
  45.  
  46.  
  47. ///DECLARACION DE VARIABLES GLOBALES
  48. char dutyR=0;
  49. char dutyG=0;
  50. char dutyB=0;
  51.  
  52. char opcion=0;                                                                          //MENU
  53. char valor;
  54.  
  55.  
  56. //INTERRUPCIONES
  57. #int_TIMER0
  58. TIMER0_isr() {
  59.         if(dutyR>0){
  60.                 output_high(ROJO);
  61.         }
  62.         if(dutyG>0){
  63.                 output_high(VERDE);
  64.         }
  65.         if(dutyB>0){
  66.                 output_high(AZUL);
  67.         }
  68.         //set_timer0(1);        
  69. }
  70.  
  71.  
  72. ///PROGRAMA
  73.  
  74. void main(void){
  75.    setup_adc_ports(NO_ANALOGS);
  76.    setup_adc(ADC_OFF);
  77.    setup_psp(PSP_DISABLED);
  78.    setup_spi(FALSE);
  79.    setup_wdt(WDT_OFF);
  80.    setup_timer_0(RTCC_INTERNAL|RTCC_DIV_16|RTCC_8_BIT);
  81.    setup_timer_1(T1_DISABLED);
  82.    setup_timer_2(T2_DISABLED,0,1);
  83.  
  84.    enable_interrupts(INT_TIMER0);
  85.    enable_interrupts(GLOBAL);   //ENABLE
  86.  
  87.         set_tris_a(0b00000111);         //PULSADORES
  88.         set_tris_b(0b00000000);         //PORTB SALIDA
  89.         set_tris_c(0b00000000);         //PORTC SALIDA
  90.         set_tris_d(0b00000000);         //PORTD SALIDA
  91.         output_a(0b00000000);
  92.         output_b(0b00000000);
  93.         output_c(0b00000000);
  94.         output_d(0b00000000);
  95.  
  96.         lcd_init();
  97.         delay_ms(20);
  98.         printf(lcd_putc("\f RJ    VD    AZ"));
  99.         dutyR=0;
  100.         dutyG=128;
  101.         dutyB=28;
  102.         printf(lcd_putc,"\n%3u   %3u    %3u  ",dutyR,dutyG,dutyB);
  103. while(1){
  104.         valor=(get_timer0() & 0xff);
  105.         if (valor>dutyR){
  106.                 output_low(ROJO);
  107.         }
  108.         if (valor>dutyG){
  109.                 output_low(VERDE);
  110.         }
  111.         if (valor>dutyB){
  112.                 output_low(AZUL);
  113.         }
  114.         //printf(lcd_putc,"\n%3u   %3u    %3u  ",dutyR,dutyG,dutyB);
  115.        
  116. }
  117. }
  118.  
  119.        
  120.  
  121. //FUNCIONES
  122.  
  123. void antirebote(void) {
  124.         delay_ms(500);
  125. }

Desconectado MarkKnopfler81

  • PIC12
  • **
  • Mensajes: 64
    • PICs, Electrónica y Robótica
Re: Timer0 - LEDs RGB
« Respuesta #9 en: 17 de Agosto de 2010, 14:47:26 »
No olvides que la interrupcion salta cada 65536 cuentas, o sea que cuando llega a 0 el LED se enciende y luego mas o menos a 128 se apaga y no vuelve a encender hasta que no pase de 65535 a 0, Digo masomenos porque la funcion que se encarga de apagarlos esta dentro del main....

Lo mejor es gestionarlo todo desde dentro de la interrupcion, puedes hacer que la interrupcion salte cada 200Us y en cada llamada de interrupcion incremente un contador, cuando este llegue a cero enciendes los leds y en cada interrupcion (dentro de la interrupcion) compruebas si se ha llegado a el valor deseado, es mas o menos lo mismo que estas haciendo, con la diferencia que los saltos son mas grandes, pero precisos, se usa esa tecnica para controlar servos...

saludos.

Desconectado elfrancho

  • PIC16
  • ***
  • Mensajes: 101
Re: Timer0 - LEDs RGB
« Respuesta #10 en: 17 de Agosto de 2010, 15:45:34 »
No olvides que la interrupcion salta cada 65536 cuentas, o sea que cuando llega a 0 el LED se enciende y luego mas o menos a 128 se apaga y no vuelve a encender hasta que no pase de 65535 a 0, Digo masomenos porque la funcion que se encarga de apagarlos esta dentro del main....

Lo mejor es gestionarlo todo desde dentro de la interrupcion, puedes hacer que la interrupcion salte cada 200Us y en cada llamada de interrupcion incremente un contador, cuando este llegue a cero enciendes los leds y en cada interrupcion (dentro de la interrupcion) compruebas si se ha llegado a el valor deseado, es mas o menos lo mismo que estas haciendo, con la diferencia que los saltos son mas grandes, pero precisos, se usa esa tecnica para controlar servos...

saludos.

Estimado MarkKnopfler81:

Fijate que el timer lo seteé en 8 bits con un preescaler de 16

setup_timer_0(RTCC_INTERNAL|RTCC_DIV_16|RTCC_8_BIT);

Segun mi cuenta me da una interrupciòn cada 4mS  por lo tanto una frecuencia de 250Hz....

No entiendo porque el programa falla de esta manera... :S


Saludos y gracias!

Desconectado willynovi

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 546
Re: Timer0 - LEDs RGB
« Respuesta #11 en: 17 de Agosto de 2010, 15:58:03 »
creo que podria hacerlo de otra forma, si solo manejas un led es simple.
Deberias ordenar por valor los tres % PWM y luego hacer las diferencias entre cada uno para ir cargando en el regstro del TIMER0 y así te van saltando las interrupciones en distintos tiempos y segun cual es el que corresponde enciendes el LED. Luego completas el ciclo para ajustar la frecuencia desea.
Así vuelves a repetir.

Creo que el problema surge porque usas el TIMER0 en modo interrupción y en modo polling a la ves, deberias usarlo de una sola forma.

Saludos,
Intento enseñarte a pescar, si solo quieres pescados, espera que un pescador te regale los suyos.

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Timer0 - LEDs RGB
« Respuesta #12 en: 17 de Agosto de 2010, 19:28:22 »
Si cambias a:
Código: C
  1. #int_TIMER0
  2. TIMER0_isr(){
  3.    if(dutyR>0){
  4.       output_high(ROJO);
  5.    }
  6.    if(dutyG>0){
  7.       output_high(VERDE);
  8.    }
  9.    if(dutyB>0){
  10.       output_high(AZUL);
  11.    }
  12.    valor=(get_timer0());
  13. }

y:
Código: C
  1. while(1){
  2.       valor=(get_timer0());
  3.       if ((valor>dutyR) && (input(ROJO)==1)){
  4.          output_low(ROJO);
  5.       }
  6.       if ((valor>dutyG)  && (input(VERDE)==1)){
  7.          output_low(VERDE);
  8.       }
  9.       if ((valor>dutyB)  && (input(AZUL)==1)){
  10.          output_low(AZUL);
  11.       }
  12.    }

Seguramente va a funcionar adecuadamente. Lo que pasa es que al ocurrir la interrupción puede estar dentro de un if o a punto de ejecutar alguno, y si no se actualiza el la variable valor, tomará una decisión errónea, y además debemos impedir que entre al if si ya ha sido ejecutado anteriormente.

Estas encuestas deben ser bastante regulares, por lo que se debe pensar bien como realizarlo si le vas a agregar LCD y esas cosas que demoran mucho tiempo en ejecutarse.


Saludos!

No contesto mensajes privados, las consultas en el foro

Desconectado elfrancho

  • PIC16
  • ***
  • Mensajes: 101
Re: Timer0 - LEDs RGB
« Respuesta #13 en: 18 de Agosto de 2010, 15:24:37 »
Gracias Suky, tienes razón, ese código anda, pero estoy limitado a poner LCD, comunicaciones, etc..
Por eso, como dice el amigo willynovi voy a implementar los timers...

La idea es tener 3 variables (dutyR dutyG dutyB)
Me gustaría saber cómo ordenarlas en forma ascendente...

Y que pasaría si dos o 3 de ellas con iguales....

Muchas gracias, saludos....

Desconectado MarkKnopfler81

  • PIC12
  • **
  • Mensajes: 64
    • PICs, Electrónica y Robótica
Re: Timer0 - LEDs RGB
« Respuesta #14 en: 18 de Agosto de 2010, 19:04:01 »
Mira yo lo implementaría de esta forma, no se cuales son tus necesidades, pero puedes ponerle un cristal mas veloz, y hacer lo que quieras en el main.

Código: CSS
  1. #int_TIMER0
  2. void TIMER0_isr() {
  3.    set_timer0(220);
  4.    cnt++;
  5.    if(cnt==0){
  6.       output_high(ROJO);
  7.       output_high(VERDE);
  8.       output_high(AZUL);      
  9.    }
  10.    if (cnt>=dutyR)output_low(ROJO);
  11.    if (cnt>=dutyG)output_low(VERDE);
  12.    if (cnt>=dutyB)output_low(AZUL);        
  13.    
  14. }

saludos.