Autor Tema: Gestor de carreras  (Leído 2638 veces)

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

Desconectado Cortijero

  • PIC12
  • **
  • Mensajes: 57
Gestor de carreras
« en: 10 de Abril de 2011, 12:52:53 »
Bueno, hace ya algo mas de un año que me registré en este foro, sin tener ni la mas minima idea de electronica. Despues de todo este tiempo aprendiendo gracias a todos vosotros, y dando el coñazo en mas de una ocasión, creo que puedo hacer mi primera (y modesta) aportación, e intentar ayudar a quien quiera hacer algo semejante a lo que yo he hecho.

En mis inicios, cuando practicamente solo sabia hacer parpadear un triste led, y poco, muy poco mas, me propuse hacer lo que en un hilo llamé "cronómetro para slot", pero por falta de conocimientos, calló en saco olvidado. (http://www.todopic.com.ar/foros/index.php?topic=32605.0)

Hace unos meses, consideré que ya tenia casi todos los conocimientos necesarios para meterle mano al proyecto, y tras una etapa de examenes, decidí "relajarme" metiendole mano. Y bueno, poco a poco fué tomando forma, aunque tube algun atranque, como el quemar un pic, y descubrir que ya habia dejado de fabricarse. Pregunte por estos lares, pues el "sucesor", pic16f887 no era exactamente igual, y me sacasteis de dudas.

Bueno, pues hoy, podria decir que ya esta casi casi acabado, a falta de algun detallito, que es solo cosa de hecharle unas horitas.

El proyecto en sí consiste en un "gestor de carreras" para slot (SCALEXTRIC para los amigos).

Explicaré un poco como funciona el programa. Tiene dos opicones de funcionamiento. Modo carrera y modo entrenamiento.

En el modo entrenamiento, con el paso del coche por meta, se suma una vuelta y se muestra el tiempo, avisando por medio de un buzzer si ha sido vuelta rapida con un beep para el jugador 1 y dos beem para el jugador 2.

En el modo carrera, se seleccionan el numero de vueltas que durará la carrera, y al paso por meta, se resta una vuelta, y se muestra el tiempo, avisando acusticamente si es vuelta rapida, así como del ganador final de la carrera.

Para detectar el paso por meta, he usado unos fototransistores BPW77 y unos leds IR.

Asismismo, para dar la señal de salida, se utilizan unos led a modo de "semáforo de F1", y el buzzer.

Ahora, quiero añadir la opción de "gestion de combustible" que me gustaria hacer con otros fototransistores y unas barritas de leds, de forma que cuando el coche se pare cortando el az del led IR durante un tiempo determinado, la barrita de leds "empiece a rellenarse".

El circuito ya está montado en una protoboard, donde funciona correctamente, pero esta semana santa, que regreso a mi casa, lo probaré en el circuito a ver que tal se comporta en condiciones "reales".

El codigo fuente es... como lo describiria... UN MALDITO INFIERNO!

Necesita un par de revisiones, pues esta bastante desordenado, pero de todas formas, lo cuelgo, asi como un video donde muestro el funcionamiento, a ver que os parece!
Código: [Seleccionar]
///////////////////////////////////////////////////////////////////////////////////////////
//                                                                                       //
//       GESTOR DE CARRERAS PARA SLOT                                                    //
//                                                                                       //
///////////////////////////////////////////////////////////////////////////////////////////
//                                                                                       //
//        Cuentavueltas                                                                  //
//        Control de tiempos                                                             //
//        Semáforo                                                                       //
//        Gestión de combustible                                                         //
//        Aviso de vuelta rapida                                                         //
//                                                                                       //
//                                                                                       //
///////////////////////////////////////////////////////////////////////////////////////////



#include <16f887.h>

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
#FUSES NOPUT                    //No Power Up Timer
#FUSES MCLR                     //Master Clear pin enabled
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOCPD                    //No EE protection
#FUSES NOBROWNOUT               //No brownout reset
#FUSES IESO                     //Internal External Switch Over mode enabled
#FUSES FCMEN                    //Fail-safe clock monitor enabled
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOWRT                    //Program memory not write protected
#FUSES NOBROWNOUT               //Brownout reset at 4.0V
#FUSES RESERVED                 //Used to set the reserved FUSE bits

#use delay(clock=4M)
#byte PortA=0x05
#bit verde=PortA.0
#byte PortB=0x06
#byte PortD=0x08
#byte PortE=0x09
#bit start=PortD.0
#bit zumbador=PortE.2

#define LCD_ENABLE_PIN  PIN_D1                                   
#define LCD_RS_PIN      PIN_D2                                   
#define LCD_RW_PIN      PIN_D3
#define LCD_DATA4       PIN_D4
#define LCD_DATA5       PIN_D5                                   
#define LCD_DATA6       PIN_D6                                   
#define LCD_DATA7       PIN_D7
#include <lcd.c>

///////////////////////////////////////////////////////////////////////////////////////////
//                                                                                       //
//       DECLARACIÓN DE VARIABLES GLOBALES                                               //
//                                                                                       //
///////////////////////////////////////////////////////////////////////////////////////////

int cont1=0,cont2=0, seg1=0, seg2=0;
signed int vuelta1=0,vuelta2=0;
int bandera=0, bandera1=1,bandera2=0,conf=1;
int contI=99,contII=99,segI=99,segII=99;
int primvuelt1,primvuelt2;
int contr1=99,contr2=99,segr1=99,segr2=99;
int ganador=0;
int act=1;

///////////////////////////////////////////////////////////////////////////////////////////
//                                                                                       //
//       DECLARACIÓN DE FUNCIONES                                                        //
//                                                                                       //
///////////////////////////////////////////////////////////////////////////////////////////

void salida();
void beep();
void mostrar_tiempo();
void paso_por_meta();
void vuelta_rapida();
void winner();

///////////////////////////////////////////////////////////////////////////////////////////
//                                                                                       //
//       INTERRUPCIÓN TIMER0                                                             //
//                                                                                       //
///////////////////////////////////////////////////////////////////////////////////////////

#int_timer0
void interrupcion(){
      set_timer0(217);
      if(seg1!=99)
         cont1++;
      if(seg2!=99)
         cont2++;
   }
   
///////////////////////////////////////////////////////////////////////////////////////////
//                                                                                       //
//       INTERRUPCIÓN CAMBIO ESTADO RB4:RB7                                              //
//                                                                                       //
///////////////////////////////////////////////////////////////////////////////////////////

#int_rb // Interrupcion cambio de estado RB[4-7]
void control_rb() {

   delay_ms(15);
   disable_interrupts(INT_RB);
   
   if((bandera==0)&&(bandera2==0)) //Fuera de todo
   {
      if (input(pin_B4)&&!input(pin_B5)&&input(pin_B6)&&input(pin_B7)) //Pin B5? (MAS)
         bandera1=1;
      if (input(pin_B4)&&input(pin_B5)&&!input(pin_B6)&&input(pin_B7)) //Pin B6? (MENOS)
         bandera1=2;
      if (!input(pin_B4)&&input(pin_B5)&&input(pin_B6)&&input(pin_B7)) //Pin B4? (OK)
         {
            if(bandera1==1)
               bandera=1;
            else if(bandera1==2)
               bandera=2;
         }
   }
   else if ((bandera==1)&&(bandera2==0)) //Modo entrenamiento?
   {
      if (!input(pin_B4)&&input(pin_B5)&&input(pin_B6)&&input(pin_B7)) //Pin B4? (START)
      {
         conf=0;
      }
      if (input(pin_B4)&&input(pin_B5)&&input(pin_B6)&&!input(pin_B7)) //Pin B7? (CANCEL)
      {
         bandera=0;
      }
   }
   else if ((bandera==2)&&(bandera2==0)) //Modo carrera
   {
      if (input(pin_B4)&&!input(pin_B5)&&input(pin_B6)&&input(pin_B7)) //Pin B5? (MAS)
         vuelta1=vuelta1+1;
         
      if (input(pin_B4)&&input(pin_B5)&&!input(pin_B6)&&input(pin_B7)) //Pin B6? (MENOS)
         vuelta1=vuelta1-1;
      if (!input(pin_B4)&&input(pin_B5)&&input(pin_B6)&&input(pin_B7)) //Pin B4? (OK)
         {
               conf=0;
         }
      if (input(pin_B4)&&input(pin_B5)&&input(pin_B6)&&!input(pin_B7)) //Pin B7? (CANCEL)
      {
         bandera=0;
      }
   }
   if (((bandera==1)||(bandera==2))&&(bandera2==1))   //Ya esta funcionando, control de paso por meta o repostaje
   {
      if (!input(pin_B0)&&input(pin_B1)&&input(pin_B2)&&input(pin_B3)) //Pin B0? (COCHE 1)
      {
         bandera1=1;
         primvuelt1=0;
      }
         
      if (input(pin_B0)&&!input(pin_B1)&&input(pin_B2)&&input(pin_B3)) //Pin RB1? (COCHE 2)
      {
         bandera1=2;
         primvuelt2=0;
      }
      if (input(pin_B0)&&input(pin_B1)&&!input(pin_B2)&&input(pin_B3));
     
      if (input(pin_B0)&&input(pin_B1)&&input(pin_B2)&&!input(pin_B3));
     
   }
   act=1;
   enable_interrupts(INT_RB);
   #asm movf PORTB,0 #endasm
   clear_interrupt(INT_RB);
}


///////////////////////////////////////////////////////////////////////////////////////////
//                                                                                       //
//       FUNCIÓN PRINCIPAL                                                               //
//                                                                                       //
///////////////////////////////////////////////////////////////////////////////////////////

void main (){

   set_tris_a(0);
   set_tris_b(0b11111111);
   port_b_pullups(true);
   set_tris_e(0);
   
   output_a(0b000000);
   
   zumbador=0;
     
   lcd_init(); //Inicializar lcd
   delay_ms(100);
   printf(lcd_putc,"Iniciando...");
   delay_ms(1500);
   printf(lcd_putc,"\f   GESTOR  DE\n    CARRERAS");
   delay_ms(2500);
   printf(lcd_putc,"\f\n    by SALVA");
   delay_ms(1500);
   
   setup_adc_ports(NO_ANALOGS|VSS_VDD);
   setup_adc(ADC_CLOCK_DIV_2);
   
   enable_interrupts(global);
   
   disable_interrupts(int_ext);
   
   enable_interrupts(int_rb);
   enable_interrupts(INT_RB0);
   enable_interrupts(INT_RB1);
   enable_interrupts(INT_RB2);
   enable_interrupts(INT_RB3);
   enable_interrupts(INT_RB4);
   enable_interrupts(INT_RB5);
   enable_interrupts(INT_RB6);
   enable_interrupts(INT_RB7);
   #asm movf PORTB,0 #endasm  // con estas 2 lineas, se borra
   clear_interrupt(INT_RB);   // RBIF al inicio del programa
   
   
   
   primvuelt1=primvuelt2=1;
   
   while(conf==1)
      {
         if (act==1)
         {
            if(bandera==0&&bandera1==1)
               {
                  printf(lcd_putc,"\f1.Entrenamiento-\n2.Carrera");
               }
            else if (bandera==0&&bandera1==2)
               {
                  printf(lcd_putc,"\f1.Entrenamiento\n2.Carrera      -");
               }
            if (bandera==1) //Modo entrenamiento
               {
                  printf(lcd_putc,"\f      Modo\n  Entrenamiento");
                  vuelta1=vuelta2=0;
               }
            if (bandera==2) //Modo carrera
               {
                  printf(lcd_putc,"\f Numero vueltas\n       %d",vuelta1);
               }
            act=0;
         }

      }
   vuelta2=vuelta1;
         
   bandera2=1;
   bandera1=0;
   

   enable_interrupts(int_timer0);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);  //configuracion interrupcion TMR0
   set_timer0(217); 
   
   
   
   salida();

   cont1=0;
   cont2=0;
   seg1=0;
   seg2=0;
   mostrar_tiempo();
   while (1)
   {
      if((cont1==99)&&(seg1!=99))
      {
         seg1++;
         cont1=0;
      }
      if((cont2==99)&&(seg2!=99))
      {
         seg2++;
         cont2=0;
       }
     
      if((bandera1==1)||(bandera1==2))
      {
         paso_por_meta();
      }
   } 
}

///////////////////////////////////////////////////////////////////////////////////////////
//                                                                                       //
//       CUERPO DE FUNCIONES                                                             //
//                                                                                       //
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
//                                                                                       //
//       FUNCION PARA ACTIVAR ZUMBADOR                                                   //
//                                                                                       //
///////////////////////////////////////////////////////////////////////////////////////////
void beep()
{
   zumbador=1;
   delay_ms(50);
   zumbador=0;
}

///////////////////////////////////////////////////////////////////////////////////////////
//                                                                                       //
//       FUNCION PARA SEÑAL DE SALIDA (SEMAFORO)                                         //
//                                                                                       //
///////////////////////////////////////////////////////////////////////////////////////////
void salida()
{
   printf(lcd_putc,"\f  PREPARADOS?!");
   beep();
   delay_ms(50);
   beep();
   delay_ms(2000);
   output_a(0b000010);
   beep();
   delay_ms(1000);
   output_a(0b000110);
   beep();
   delay_ms(1000);
   output_a(0b001110);
   beep();
   delay_ms(1000);
   output_a(0b011110);
   beep();
   delay_ms(1000);
   output_a(0b111110);
   beep();
   delay_ms(1000);
   output_a(0b000001);
   printf(lcd_putc,"\f      YA!!");
   beep();
   beep();
   beep();
   beep();
   beep();
}


///////////////////////////////////////////////////////////////////////////////////////////
//                                                                                       //
//       FUNCION PARA MOSTRAR TIEMPO EN LCD                                              //
//                                                                                       //
///////////////////////////////////////////////////////////////////////////////////////////
void mostrar_tiempo()
{
   if ((primvuelt1==1)&&(primvuelt2==1))
   {
      lcd_gotoxy(1,1);
      printf(lcd_putc,"\f   %d      %d",vuelta1,vuelta2);
      lcd_gotoxy(1,2);
      printf(lcd_putc," __.__   __.__");
      delay_ms(100);
   } 
   else if ((primvuelt1==0)&&(primvuelt2==1))
   {
      lcd_gotoxy(1,1);
      printf(lcd_putc,"\f   %d      %d",vuelta1,vuelta2);
      lcd_gotoxy(1,2);
      printf(lcd_putc," %2d.%2d   __.__",segI,contI);
      delay_ms(100);
   }
   else if ((primvuelt1==1)&&(primvuelt2==0))
   {
      lcd_gotoxy(1,1);
      printf(lcd_putc,"\f   %d      %d",vuelta1,vuelta2);
      lcd_gotoxy(1,2);
      printf(lcd_putc," __.__   %2d.%2d",segII,contII);
      delay_ms(100);
   }
   else
   {
      lcd_gotoxy(1,1);
      printf(lcd_putc,"\f   %d      %d",vuelta1,vuelta2);
      lcd_gotoxy(1,2);
      printf(lcd_putc," %2d.%2d   %2d.%2d",segI,contI,segII,contII);
   }
}

///////////////////////////////////////////////////////////////////////////////////////////
//                                                                                       //
//       FUNCION PARA GESTIONAR PASO POR META                                            //
//                                                                                       //
///////////////////////////////////////////////////////////////////////////////////////////
void paso_por_meta()
{
   if(bandera1==1) //Coche1 pasa por meta
   {
      if(bandera==1) //Modo entrenamiento?
         vuelta1++;
      else if (bandera==2) //Modo carrera?
      {
         vuelta1--;
         if(vuelta1<0)
         {
            ganador=1;     
            winner();
         }
      }
      contI=cont1;
      segI=seg1;
      cont1=seg1=0;
   }
   else if (bandera1==2) //Coche2 pasa por meta
   {
      if(bandera==1)  //Modo entrenamiento?
         vuelta2++;
      else if (bandera==2)  //Modo carrera?
      {
         vuelta2--;
         if(vuelta2<0)
         {
            ganador=2;     
            winner();
         }
      }
      segII=seg2;
      contII=cont2;
      cont2=seg2=0;
   }
   
   mostrar_tiempo();
   vuelta_rapida();
   
   bandera1=0;
}


///////////////////////////////////////////////////////////////////////////////////////////
//                                                                                       //
//       FUNCION PARA DETECTAR VUELTA RAPIDA                                             //
//                                                                                       //
///////////////////////////////////////////////////////////////////////////////////////////
void vuelta_rapida()

   if ((segI<segr1)||(segI==segr1&&(contI<contr1)))
   {
      beep();
      contr1=contI;
      segr1=segI;
   }
   if ((segII<segr2)||(segII==segr2&&(contII<contr2)))
   {
      beep();
      delay_ms(50);
      beep();
      contr2=contII;
      segr2=segII;
   }
}



///////////////////////////////////////////////////////////////////////////////////////////
//                                                                                       //
//       FUNCION PARA DETECTAR GANADOR EN MODO CARRERA                                   //
//                                                                                       //
///////////////////////////////////////////////////////////////////////////////////////////
void winner()
{
   beep();
   delay_ms(50);
   beep();
   delay_ms(50);
   beep();
   delay_ms(50);
   beep();
   delay_ms(50);
   beep();
   delay_ms(50);
   beep();
   while(1)
   {
      printf(lcd_putc,"\f    GANADOR!\n    PILOTO %d",ganador);
      delay_ms(500);
      printf(lcd_putc,"\f");
      delay_ms(500);
   }
}

PD: En el video se ve algún fallo por ejemplo en el aviso en vueltas rapidas, pero ya está corregido.


Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Re: Gestor de carreras
« Respuesta #1 en: 11 de Abril de 2011, 02:15:21 »
Felicidades Cortijero. A ver si nos muestras el vídeo cuando lo tengas montado en la pista y usando coches en vez de el dedo  :D

Desconectado Miquel_S

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1251
Re: Gestor de carreras
« Respuesta #2 en: 11 de Abril de 2011, 04:28:16 »
Excelente trabajo Cortijero, ahora como dice Manolo a las pruebas reales.

Saludos
Miquel_S
Todos somos muy ignorantes. Lo que ocurre es que no todos ignoramos las mismas cosas.

Desconectado Cortijero

  • PIC12
  • **
  • Mensajes: 57
Re: Gestor de carreras
« Respuesta #3 en: 11 de Abril de 2011, 04:52:03 »
Jeje, muchas gracias. A ver si esta semana santa puedo poner a punto la pista , que esta medio abandonada, y probarlo. Y para la proxima, me hago la manicura antes del video para salir guapo :D