TODOPIC

Microcontroladores PIC => * PROYECTOS * => Mensaje iniciado por: Matiasitu en 09 de Julio de 2021, 17:19:41

Título: Contador de Vueltas Programable
Publicado por: Matiasitu en 09 de Julio de 2021, 17:19:41
Hola, tengo este proyecto (PARTE DEL CODIGO LO ENCONTRE POR AHI) que es un contador de vueltas programable, anda bien!solo necesitaría una mano de como explicarlo, ya que no hace mucho eh iniciado en esto.

#include <16f88.h> //PIC
#fuses   nofcmen,noieso,nobrownout //FUSIBLES
#use     delay (internal = 8MHz)//USAMOS CLOCK INTERNO 8MHZ
#include <lcd.c>//INCLUIMOS LIBRERIA LCD Por defecto el LCD se conecta al puerto D, si se desea conectar el LCD en el puerto B se incluye esta línea en el encabezado
#define  use_portb_kbd true // USAMOS EL PUERTO B PARA EL TECLADO
#include <kbd.c>// INCLUIOS LIBRERIA KBD PARA EL MANEJO DE TECLADO 4X4
//#include <stdlib.h>//Funciones de C estandar
                    //-Funciones Artitmeticas
                    //-Numeros Aleatorios
                    //-Conversion de Cadena "
// Nombres para los pines.
#define  pin_relay   pin_a1
#define  sensor_incr pin_a2
#define  pin_buzzer  pin_a4
/*****************************************************************************/
// Declaración de variables.
unsigned int8  i;                                  // Propósito general, Entero de 8bits
unsigned int8  valor_adc=0;                        // Para lectura del ADC, Entero de 8bits
/*****************************************************************************/
// Variables de conteo.
unsigned char  digitos[7]; //Tipo de dato para caracteres, símbolos tipográficos como A, d y $
unsigned int32 temp_vueltas,vueltas; //Numeros Enteros sin Signos de 32Bits
unsigned char  digito[7];//Tipo de dato para caracteres, símbolos tipográficos como A, d y $
unsigned int8  str_vueltas[7];//Define un número de 8 bits sin signo
/*****************************************************************************/
// Declaración de las funciones utilizadas en el programa.
void leer_cantidad_teclado(void);
void iniciar_conteo(void);
void guardar_vueltas(void);
void conteo (unsigned int32 vueltas);
void buzzer_bips(int8 veces,int16 tiempo);
/*****************************************************************************/

void main(void){
   setup_adc_ports(sAN0);        // Seleccionar el canal 0
   setup_adc(ADC_CLOCK_INTERNAL);// Utilizar el reloj interno para el conversor.
   set_adc_channel(0);           // Activar el al 0
/*****************************************************************************/   
   output_low(pin_buzzer);       // Poner a 0 el pin RA4 (Buzzer apagado)
   output_low(pin_relay);        // Poner a 0 el pin RA1 (Relay apagado)
   kbd_init();                   // Inicializar el teclado.
   lcd_init();                   // Inicializar la pantalla.
   port_b_pullups(true);         // Activar las resistencias pull-up del puerto B
 /****************************************************************************/ 
   lcd_putc("\fPROYECTO \n 2020");// Escribimos en el LCD.
   delay_ms(2000); // Esperamos 2000 ms
   
   if (vueltas == 0){vueltas = 300;}   // Esto se puede omitir e iniciar en 0, por defecto iniciamos en 300
                                       // Pusimo 300, ya que son 300 las vuelta que tenemos que contabilizar.
   temp_vueltas = vueltas;
// Subrutina para seleccionar ingreso de vueltas o inicio de conteo.
      while(true) //Bucle Infinito.
      {
         lcd_putc("\f* INGRESA CONTEO\n# INICIAR CONTEO");
   
         while(true)
         {
            digito[0]=kbd_getc();   // Se guarda el valor de la tecla seleccionada.
            if(digito[0]!=0)
            {
               buzzer_bips(1,100);  // Activar el buzzer X veces, X tiempo en Ms.     
               switch (digito[0])
               {
                  case 35:          // Tecla #
                     iniciar_conteo(); // Ir a subrutina para contar las vueltas.
                     break;
                  case 42:          // Tecla *
                     leer_cantidad_teclado();   // Ir a subrutina para leer el teclado.
               }
            }
         }
      }
}

// Subrutina para activar el buzzer durante X tiempo X veces.
void buzzer_bips(int8 veces,int16 tiempo)
{
   int8 x;
   
   for (x=1;x<=veces;x++)//Varie la variable de control de 1 a VECES en incrementos de a 1:
   {
      output_high(pin_buzzer);
      delay_ms(tiempo);
      output_low(pin_buzzer);
      delay_ms(tiempo);
   }
}

// Subrutina de conteo para sensor magenetico.
void conteo (unsigned int32 vueltas)
{
   unsigned int32 contador=0,restantes=0;

   output_high(pin_relay);    // Encender el relevador.
   
   while(true)
   {
//*****************************************************************************
// Se utiliza la técnica de Polling. (Leer constantemente las entradas)
      while(input(sensor_incr))
      {
         contador++; // Incrementar el contador cuando Sensor Magnetico pase de 1 a 0
         while(input(sensor_incr));
      }
   
      if(contador >= vueltas)   // Cuando contador >= vueltas...
      {
         output_low(pin_relay);  // Apagar relevador.
         lcd_putc("\fCONTEO TERMINADO\n");   // Mostrar conteo finalizado.
         printf(lcd_putc,"%07lu VUELTAS",contador);
         contador = 0;     // Resetear el contador a 0
         buzzer_bips(10,100);    // Avisar con X bips del buzzer.
         break;
      }
      lcd_gotoxy(1,2);
      // Mostrar la cuenta de las vueltas.
         printf(lcd_putc,"%07lu VUELTAS",contador);
   }
}

// Subrutina previa para iniciar el conteo.
void iniciar_conteo(void)
{
   if( vueltas == 0)   // Notificar que no se ha ingresado la cantidad de vueltas.
   {
      lcd_putc("\f ERROR EN CONTEO\n   PRESIONE *");
   }
   else
   {
      printf(lcd_putc,"\fCONTAR: %07lu\n     VUELTAS",vueltas);
      delay_ms(2000);
      conteo(vueltas);     // Ir a la subrutina de conteo.
   }
}

// Subrutina para guardar el conteo principal en la memoria EEPROM interna.
void guardar_vueltas(void)
{
   write_eeprom(10,0);      // Guardar un 0 para indicar cambio de vueltas
   sprintf (str_vueltas,"%lu",vueltas);
   for (i=0;i<=6;++i)
   {
      write_eeprom (i,str_vueltas);
      delay_ms(10);
   }

   lcd_putc("\fCONTEO GUARDADO\nEN LA MEMORIA");
   
   buzzer_bips(6,100);          // Avisar con X bips del buzzer.
   
   delay_ms(3000);
   lcd_putc("\f PRESIONE EL #\n PARA INICIAR");
 
   while(true)
   {
      digito[0]=kbd_getc();
      if(digito[0]!=0)
      {
         switch (digito[0]){
            case 35:       // Tecla #
               buzzer_bips(1,100);          // Avisar con X bips del buzzer.
               iniciar_conteo();
         }
      }
   }
}

// Subrutina para leer la cantidad ingresada por el teclado.
void leer_cantidad_teclado(void)
{
releer:
   printf(lcd_putc,"\fACTUAL: %07lu\nNUEVO: ",vueltas);
// Iniciar el bucle de lectura de la frecuencia por teclado.
   lcd_gotoxy(9,2);      //Posicion
   lcd_cursor_on(1);    // Enciendo el cursor con parpadeo.
   
   while(true)
   {
 // Leer los valores de las teclas pulsadas.
      for (i=0;i<=6;i++)
      {
         while(true)
         {
            digitos=kbd_getc();  // Guardar en dígito[i+1] el valor de la tecla pulsada.
            if(digitos!='\0')      // Si se pulsó una tecla, continuar.
            {
               if(digitos=='*'){digitos='0';} // Convertir el * (42) en 0 al restar 48.
               if(digitos=='#'){digitos='0';} // Convertir el # (35) en 0 al restar 48.
         
               lcd_gotoxy(9+i,2);
               printf(lcd_putc,"%c",digitos);
               buzzer_bips(1,100);   // Activar el buzzer X veces, X tiempo en Ms.
               break;
            }
         }
      }
           
      lcd_cursor_on(0);         // Apago el parpadeo del cursor.
      // Convertir la cantidad de vueltas ingresada por teclado a entero.
      vueltas = atoi32(digitos);
   
      buzzer_bips(2,100);          // Avisar con X bips del buzzer el fin cantidad.
      delay_ms(3000);
   
      if(vueltas>9999999 || vueltas == 0)  // Por si no se ingresa conteo o es mayor a 9999999
      {
         lcd_putc("\f ERROR EN CONTEO\n INGRESE NUEVO");
         delay_ms(3000);
         vueltas = temp_vueltas;
         goto releer;
      }
     

      sprintf (str_vueltas,"%lu",vueltas);
      vueltas = atoi32(str_vueltas);
   
   
      lcd_putc("\f* GUARDAR CONTEO\n# INICIAR CONTEO");
   
      while(true)
      {
         digito[0]=kbd_getc();
         if(digito[0]!=0)
         {
            switch (digito[0]){
               case 35:       // Tecla #
                  buzzer_bips(1,100);          // Avisar con X bips del buzzer.
                  iniciar_conteo();
                  break;
               case 42:       // Tecla *
                  guardar_vueltas();
            }
         }
      }
   }
}
Título: Re:Contador de Vueltas Programable
Publicado por: Jorge Bern en 16 de Julio de 2021, 16:35:07
Hola, te comento que hace mucho tiempo armé un cuentavueltas de laboratorio con lógica discreta, o sea contadores, monoestables, memorias EEPROM y display de 7 segmentos. Era con base de tiempo a cristal, cuatro digitos y una presición de una RPM en todo el rango de 800 a 9999 RPMs, o sea de presición y calidad de laboratorio.
No me queda claro como hace la medición este código que publicaste, pero según mi experiencia  para lograr una presición de una vuelta en todo el rango,  es necesario medir periodo en lugar de frecuencia y luego hacer la conversión de período a frecuencia (RPMs)
Esto yo lo hacia directamente con una tabla con la cuenta RPM = 60/ Periodo [seg.] pregrabada en EEPROM, entonces la conversión entre el período de vuelta medido con la cuenta de N pulsos del cristal dentro de una vuelta, entraba directamente a la EEPROM y esta mostraba en el display las RPMs con cero retardo.
Te explico porque esto me pareció mejor, pues el problema es en baja vueltas en donde se pierde resolución midiendo directamente RPMs. Por ejemplo suponiendo una medición directa, si estas midiendo 960 RPM, durante un segundo contas 16 vueltas, pero cuando pasas a medir una vuelta mas, 17 vueltas por segundo, ya estas en 1020 RPM o sea una resolución de 60 vueltas que puede estar bien para una aplicación casera pero no de presición.
En cambio midiendo periodo con un buen diseño de conversión matemática, podés lograr 1 RPM de resolución en todo el rango y el tamaño de la memoria dependerá del rango requerido.
Por ahí debo tener el proyecto con los detalles, y pienso que actualizarlo al uso de un PIC no debe ser dificil siguiendo la misma técnica y usando una memoria serial de capacidad adecuada para obtener la cuenta.
Lo buscaré si te interesa.
Saludos

Título: Re:Contador de Vueltas Programable
Publicado por: KILLERJC en 16 de Julio de 2021, 18:59:43
El problema de esta persona, es que literalmente "copio" el código. Y no se detuvo a ver como funciona, porque no tiene conocimientos de programación.

El programa al presionar "*"  pide el ingreso de una cantidad de vueltas, Y luego al presionar el "#", activa la salida (supongo motor) y comienza a contar las vueltas... Y luego de cierta cantidad de vueltas se detiene. Seguramente cuente algo bastante "lento". Ya que entre cuenta de revoluciones, puede escribir los 16 caracteres en el LCD sin problemas.

Aunque no quedo claro la diferencia que planteas Jorge, la idea es contar la cantidad de vueltas que dio algo lento y parar, y no la cantidad de vueltas que posee de forma continua algo que este girando.

Es simple si uno mira el main solo. Solo debe seguir la línea. Pero si copio y no sabe por donde comienza el programa es complicado.
Título: Re:Contador de Vueltas Programable
Publicado por: Jorge Bern en 17 de Julio de 2021, 01:14:14
Ah Ok, no había interpretado que se trataba de esa función en mi rápida mirada al código, aparte es super largo.
Tienes razón, poco que ver con lo mio que realizaba mediciones continuas tipo frecuencimetro, asi que quedamos a la espera de algún aporte más del creador del tema.
Un saludo