Autor Tema: Problema Tacometro con CCP  (Leído 3675 veces)

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

Desconectado elvaron

  • PIC10
  • *
  • Mensajes: 3
Problema Tacometro con CCP
« en: 30 de Mayo de 2008, 00:51:12 »
SALUDOS MAESTROS....

les escribo pues estoy implementando un tacometro usando una pic16f628a , con algunas rutinas que he encontrado en este foro, y estoy a punto de lograrlo, pero tengo un problema con el multiplexeo con los displays de 7 segmentos.

Mi traba es que cuando entro en el while(1) del main, una funcion me saca las revoluciones por minuto, y luego tira al multiplexeo, es decir, se me apagan los displays cuando entra en la interrupcion, y es molesto, pues trabajo con pocas rmps, (60 a 600 aproximandamente), entonces se demora

Este es el codigo que estoy ocupando:


Código: [Seleccionar]

#include <16f628a.h> //pic a utilizar
#include <MATH.h>
#fuses NOWDT,NOPROTECT,PUT,NOLVP,NOMCLR,HS //ordenes para el programador

#define COMENZAR  0
#define CONTANDO  1
#define TERMINO   2
#define VECES 2

#use delay (clock=10000000) //Fosc=4Mhz
#use standard_io(B)
#use standard_io(A)

//Variables Globales

float dato;
char cEstado;
int32 int32Cont;
float fRpm;
char i;
char j;
long int unidad,decena,centena;
int display_on[3]={0b1110,0b1101,0b1011}; //tabla display on
int Digito[3];


//INTERRUPCION POR RB3 CCP1//

#INT_CCP1

void CCP1__isr(void) {

    if (cEstado == CONTANDO) {       // Segundo Pulso
        int32Cont += CCP_1;           // Toma el valor de captura
        cEstado = TERMINO;           // Evito que vuelva a procesarse durante esta interrupcion
    }

    if (cEstado == COMENZAR)  {      // Primer Pulso
        set_timer1(0);               // Restaura el timer1 en este pulso
        cEstado = CONTANDO;
        int32Cont = 0;

    }
}

//velocidad//

float velocidad(void){

    char cCnt;
    int32 int32Suma;
    long tiempo;

    cEstado = TERMINO;
    while (TRUE) {
      int32Suma = 0;
      int32Cont = 0;
      for (cCnt = 0; cCnt < VECES; cCnt++) {       // Acumula VECES lecturas
        cEstado = COMENZAR;                        // Permite comenzar a la interrupcion
        while (cEstado != TERMINO) {               // Espera hasta que se activa la interrupcion
          tiempo =  get_timer1();
          if (tiempo > 65500) {                    // Controla si el contador excedio el tiempo. Valor Original = 60000
            set_timer1(0);                         // Restaura el timer1 para seguir sumando el tiempo de este pulso
            int32Cont += tiempo;                   // Acumula para velocidades de viento bajas

          }                                        // Fin if
        }                                          // Fin if
        int32Suma += int32Cont;                    // Acumula los tiempos
      }                                            // fin for


      int32Suma /= VECES;                          // Saca el promedio de las VECES que se tomo la medicion

      fRpm = 1 / ( float ) int32Suma / 8 * 2.5;    // Periodo en uS
      fRpm *= 1000000;                             // Periodo en segundos
      fRpm *= 60;                                 // Periodo en minutos

      dato = fRpm;

      centena=dato/100;
      decena=(dato-centena*100)/10;
      unidad=dato-(centena*100)-(decena*10);;
  return centena, decena, unidad;
    }

}

//Display
//   Conexiones:                        a
//               B0 -> a 7seg          ____
//               B1 -> b 7seg      f  |    | b
//               B2 -> c 7seg         | g  |
//               B4 -> d 7seg          ----
//               B5 -> e 7seg      e  |    | c
//               B6 -> f 7seg         |____|
//               B7 -> g 7seg            d
//////////////////////////////////////////////////////////////////////////////////

void display7seg(int j){

switch (j) {

    case 0:  output_high(pin_b0);
             output_high(pin_b1);
             output_high(pin_b2);
             output_high(pin_b4);
             output_high(pin_b5);
             output_high(pin_b6);
             output_low(pin_b7);
            break;

    case 1: output_low(pin_b0);
            output_high(pin_b1);
            output_high(pin_b2);
            output_low(pin_b4);
            output_low(pin_b5);
            output_low(pin_b6);
            output_low(pin_b7);
            break;

    case 2: output_high(pin_b0);
            output_high(pin_b1);
            output_low(pin_b2);
            output_high(pin_b4);
            output_high(pin_b5);
            output_low(pin_b6);
            output_high(pin_b7);
            break;

    case 3: output_high(pin_b0);
            output_high(pin_b1);
            output_high(pin_b2);
            output_high(pin_b4);
            output_low(pin_b5);
            output_low(pin_b6);
            output_high(pin_b7);
           break;


    case 4: output_low(pin_b0);
            output_high(pin_b1);
            output_high(pin_b2);
            output_low(pin_b4);
            output_low(pin_b5);
            output_high(pin_b6);
            output_high(pin_b7);
            break;


    case 5: output_high(pin_b0);
            output_low(pin_b1);
            output_high(pin_b2);
            output_high(pin_b4);
            output_low(pin_b5);
            output_high(pin_b6);
            output_high(pin_b7);
            break;

    case 6: output_high(pin_b0);
            output_low(pin_b1);
            output_high(pin_b2);
            output_high(pin_b4);
            output_high(pin_b5);
            output_high(pin_b6);
            output_high(pin_b7);
            break;

    case 7: output_high(pin_b0);
            output_high(pin_b1);
            output_high(pin_b2);
            output_low(pin_b4);
            output_low(pin_b5);
            output_low(pin_b6);
            output_low(pin_b7);
            break;

    case 8: output_high(pin_b0);
            output_high(pin_b1);
            output_high(pin_b2);
            output_high(pin_b4);
            output_high(pin_b5);
            output_high(pin_b6);
            output_high(pin_b7);
           break;

    case 9: output_high(pin_b0);
            output_high(pin_b1);
            output_high(pin_b2);
            output_low(pin_b4);
            output_low(pin_b5);
            output_high(pin_b6);
            output_high(pin_b7);
            break;

   }
}
//MAIN//

void main (void){

    setup_timer_1 (T1_INTERNAL | T1_DIV_BY_8 );
    setup_ccp1 (CCP_CAPTURE_FE);                    // Captura cada pulso = 0 (0v)

    delay_ms (200);

    enable_interrupts (INT_CCP1);
    enable_interrupts (GLOBAL);

    while(1){
   
      velocidad();
     

      Digito[0]=centena;
      Digito[1]=decena;
      Digito[2]=unidad;

      for(i=0;i<3;i++){ //multiplex

                  delay_ms(10);
                  output_a(display_on[i]);
                  display7seg(Digito[i]);

       
}
      }

    }                                                //Fin While



Si pudieran darme ideas para solucionar este problema... estaria muy agradecido, bueno les adjunto los archivos para simular en proteus, y vean como es el comportamiento.

De antemano Gracias.

Desconectado MLO__

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4581
Re: Problema Tacometro con CCP
« Respuesta #1 en: 30 de Mayo de 2008, 14:27:24 »
Hola

Porque no le hechas un vistaso al ejemplo que postee aqui, en la cual el multiplexado de los displays es independiente de las funciones del main, de pronto puede servirte

Saludos
El papel lo aguanta todo

Desconectado elvaron

  • PIC10
  • *
  • Mensajes: 3
Re: Problema Tacometro con CCP
« Respuesta #2 en: 31 de Mayo de 2008, 14:03:48 »
sabes, recien estoy empezando con esto de las interrupciones... y no se si puedo usar una interrupcion del timer junto con la del ccp....


¿se puede?

Desconectado MLO__

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4581
Re: Problema Tacometro con CCP
« Respuesta #3 en: 31 de Mayo de 2008, 14:26:14 »
Hola.

Por supuesto que si se puede, no hay ningun problema. Mira este link en donde he usado varias interrupciones.

Saludos
El papel lo aguanta todo

Desconectado pikman

  • Moderador Local
  • PIC24F
  • *****
  • Mensajes: 679
Re: Problema Tacometro con CCP
« Respuesta #4 en: 31 de Mayo de 2008, 22:10:07 »
elvaron, el problema del parpadeo creo que no va aa ser posible que lo soluciones porque la frecuencia de las interrupciones del CCP es fijada por una variable externa que es la frecuencia del contador/2, el parpadeo se nota porque la frecuencia a medir es muy baja, es decir 10hz por segundo en el caso de 600 revoluviones, entonces no superas los 33 hz minimos para 'engañar' al ojo, o la persistencia retinal.

La sugerencia mas economica y sencilla es, usar una pantalla LCD para presentar el dato, debido a que la pantalla LCD es inteligente y no depende del clock de la maquina, solo tenes que ponerle el dato en el bus y listo.

La segunda sugerencia es usar algun circuito integrado decodificador de bcd a 7 segmentos con lacht, que se encargue de la presentacion y pasaria lo mismo que en el caso anterior, esto lo tuve que hacer en un caso en donde como era un tacometro de un equipo industrial requerian que si o si fuesen display LED de alta eficiencia, porque se pueden observar con mucha mas facilidad a la distancia y desde cualquier angulo.


La tercera sugerencia que tengo es un poco mas compleja pero estoy seguro que funcionara, y es multiplicar por 10x (por ejemplo)  los pulsos en la entrada y luego dividir el resultado para corregir la lectura, lo que no se es como implementarlo pero seguro debe haber por ahi algun IC que oficie de multiplicador, o mas simple que genere 10 pulsos cada vez que reciba uno, de esta manera la frecuencia de la interrupcion seria mas alta, multiplicando por 10 la minima frecuencia sera 100 HZ, y ya no tendras parpadeo, de cualquier modo si optas por un driver BCD a 7 segmentos te olvidas del problema, incusive creo que hay uno que es I2C, por lo que con 2 lineas tendrias el LCD, y el costo no se elevaria tanto.





saludos
PikMan

Desconectado elvaron

  • PIC10
  • *
  • Mensajes: 3
Re: Problema Tacometro con CCP
« Respuesta #5 en: 01 de Junio de 2008, 16:38:07 »
Bueno amigos... al final me decidi por un panel de 16x2, por la ayuda de pikman.

Les dejo el codigo y las simulaciones por si les ayuda alguna vez..

Código: [Seleccionar]
#include <16f628a.h> //pic a utilizar
#include <MATH.h>
#fuses NOWDT,NOPROTECT,PUT,NOLVP,NOMCLR,HS //ordenes para el programador

#define COMENZAR  0
#define CONTANDO  1
#define TERMINO   2
#define VECES 1




#use delay (clock=10000000) //Fosc=10Mhz
#define use_portb_lcd TRUE          //definir portb lcd
#include<lcd.c>                     //libreria manejo lcd
//Variables Globales



char cEstado;
int32 int32Cont;
float fRpm;
char i;
char j;
long int dato;


//INTERRUPCION POR RB3 CCP1//

#INT_CCP1

void CCP1__isr(void) {

    if (cEstado == CONTANDO) {       // Segundo Pulso
        int32Cont += CCP_1;           // Toma el valor de captura
        cEstado = TERMINO;           // Evito que vuelva a procesarse durante esta interrupcion
    }

    if (cEstado == COMENZAR)  {      // Primer Pulso
        set_timer1(0);               // Restaura el timer1 en este pulso
        cEstado = CONTANDO;
        int32Cont = 0;

    }
}

//velocidad//

float velocidad(void){

    char cCnt;
    int32 int32Suma;
    long tiempo;

    cEstado = TERMINO;
    while (TRUE) {
      int32Suma = 0;
      int32Cont = 0;
      for (cCnt = 0; cCnt < VECES; cCnt++) {       // Acumula VECES lecturas
        cEstado = COMENZAR;                        // Permite comenzar a la interrupcion
        while (cEstado != TERMINO) {               // Espera hasta que se activa la interrupcion
          tiempo =  get_timer1();
          if (tiempo > 65500) {                    // Controla si el contador excedio el tiempo. Valor Original = 60000
            set_timer1(0);                         // Restaura el timer1 para seguir sumando el tiempo de este pulso
            int32Cont += tiempo;                   // Acumula para velocidades de viento bajas

          }                                        // Fin if
        }                                          // Fin if
        int32Suma += int32Cont;                    // Acumula los tiempos
      }                                            // fin for


      int32Suma /= VECES;                          // Saca el promedio de las VECES que se tomo la medicion

      fRpm = 1 / ( float ) int32Suma / 8 * 2.5;    // Periodo en uS
      fRpm *= 1000000;                             // Periodo en segundos
      fRpm *= 60;                                 // Periodo en minutos

      dato = fRpm;

  return dato;
    }

}


//MAIN//

void main (void){

  setup_timer_1 (T1_INTERNAL | T1_DIV_BY_8 );
  setup_ccp1 (CCP_CAPTURE_FE);                    // Captura cada pulso = 0 (0v)

  delay_ms (200);
  lcd_init();                                     //inicializa lcd
  enable_interrupts (INT_CCP1);
  enable_interrupts (GLOBAL);

 while(1){

     velocidad();

dato = (long int)fRpm;


     
               //inicializa lcd
   delay_ms(2);
   lcd_gotoxy(1,2);                     //retardo para apreciarse todos los caracteres


   printf(lcd_putc,"Speed: %lu RPM",dato);     //muestra por pantalla el mensaje

 }                                                //Fin While



}


SALUDOS Y GRACIAS