Me encanta enseñar el código que escribo. ¿Por que?. En parte por un poco de orgullo. Pero también para que los demás puedan mostrarme mis errores o como puedo optimizar el rendimiento de lo que he escrito y para que los pocos que saben menos que yo tengan un algo que copiar, tal y como hago muchas veces. Creo que esa es una parte esencial del software libre, la reutilización de porciones de código así, por ejemplo, cuando he necesitado escribir en la LCD no he creado la librería, he utilizado una de código libre.

Y seas el tipo de lector que seas, ya quieras aprender, sea por curiosidad, por que quieras un fragmento de código o por que quieras modificar Arduslot (cosa que me haría mucha ilusión), aquí tienes el código comentado de la primera versión comentada de Arduslot:

[spoiler show=»Configuración y loop» hide=»Configuración y loop»]En esta primera sección del programa se configura la disposición y función de cada uno de los pines y se declaran las variables que se van a usar. También incluyo aquí el «loop», que sigo usando para el mensaje de bienvenida y para lanzar cada uno de los tipos de carreras.

/*

Cuentavueltas y crono 0.3

Interrupciones:

La 0 (en el pin digital 2) CORREDOR 1

la 1 (en el pin digital 3) CORREDOR 2

*/

 

#include <LiquidCrystal.h> //Para controlar LCD

LiquidCrystal lcd(12, 11, 5, 4, 10, 6); //Pines del LCD

int sonido = 13; //Pin de sonido

int intervalo = 1000; //Intervalo de la secuencia del semáforo

int pausaPantalla = 1500;

 

int control = 4; //Pin ANALOGICO del Boton +

int control2 = 3; //Pin ANALOGICO del Boton –

int intro = 5; //Pin ANALOGICO del boton de INTRO

 

// En el 595: Rojos en Q0, Q1 y Q2 y verde en Q3

//Pin conectado al ST_CP del 74HC595

int latchPin = 8;

//Pin conectado al SH_CP del 74HC595

int clockPin = 9;

//Pin conectado al DS del 74HC595

int dataPin = 7;

 

//Pines de paso de vuelta

int paso1 = 2; //corredor 1

int paso2 = 3; //corredor 2

 

//Corredor 1

int vuelta = 1; //Contadores de vueltas

//int vueltaB = 1;

unsigned long tiempoF = 0; // Tiempo de fin de vuelta

unsigned long tiempoS = 0; //Tiempo de salida de vuelta

unsigned long tiempoV = 0; //Tiempo de vuelta

unsigned long tiempoR = 4294967295; //Tiempo de vuelta rapida

int vueltaR = 0; //Vuelta rápida

 

//Corredor 2

int vuelta2 = 1; //Contadores de vueltas

//int vueltaB2 = 1;

unsigned long tiempoF2 = 0; // Tiempo de fin de vuelta

unsigned long tiempoS2 = 0; //Tiempo de salida de vuelta

unsigned long tiempoV2 = 0; //Tiempo de vuelta

unsigned long tiempoR2 = 4294967295; //Tiempo de vuelta rapida

int vueltaR2 = 0; //Vuelta rápida

 

//Comunes

int vueltaT = 0;

unsigned long tiempoRT = 4294967295; //Tiempo de vuelta rapida

int vueltaRT = 0; //Vuelta rápida

int corredor = 0;

 

//Variables para el tipo de carrera

int t = 0;

 

//Opciones del menu de t de carrera

char* menu[]={

«N de vueltas», «Resistencia», «Entrenamiento»};

 

//Carrera a vueltas

int Nvueltas = 1; //Numero de vueltas

 

 

//////////////////////////

//Carrera de resistencia//

//////////////////////////

 

//Duracion

int Reshoras = 0;

int Resmin = 15;

unsigned long ResmilisFin = 0; //para controlar la finalizacion de la carrera. Tambien final en vuelta y entrenamiento.

unsigned long ResmilisDuracion = 0; //para controlar la finalizacion de la carrera. Tambien inicio en vuelta y entrenamiento.

 

 

//Variables cronometro

int seg = 0;

int minut = 0;

int mil = 0;

int seg2 = 0;

int minut2 = 0;

int mil2 = 0;

int hora =0;

 

 

unsigned long tiempocrono = 0;

unsigned long tiempocrono2 = 0;

int tipocrono = 0;

/*

Con esta ultima variable puedo usar la misma subrrutina

«crono()» para representar los distintos tipos de tiempos,

condicionando tiempocrono a tipocrono.

*/

 

 

 

void setup() {

//Configura los pines digitales

 

pinMode(sonido, OUTPUT);

 

//Configura pines 595

pinMode(latchPin, OUTPUT);

pinMode(clockPin, OUTPUT);

pinMode(dataPin, OUTPUT);

 

// Configurar el numero de Columnas y filas del LCD

lcd.begin(16, 2);

lcd.clear();

 

//Configurar pines de control del 595

pinMode(latchPin, OUTPUT);

pinMode(clockPin, OUTPUT);

pinMode(dataPin, OUTPUT);

 

//Configura los pines de paso de vuelta y las interrepciones

pinMode(paso1, INPUT);

pinMode(paso2, INPUT);

attachInterrupt(0, pasoVuelta1, RISING);

attachInterrupt(1, pasoVuelta2, RISING);

 

//Apaga semaforo

digitalWrite(latchPin, LOW);

shiftOut(dataPin, clockPin, LSBFIRST, 0);

digitalWrite(latchPin, HIGH);

}

 

 

 

void loop() {

 

lcd.clear();

lcd.print(» BUENA»);

lcd.setCursor(0, 1);

lcd.print(» CARRERA!»);

delay(pausaPantalla);

seleccion();

switch (t) {

case 0: //Carrera a numero de vueltas

carreraVueltas();

break;

 

case 1: //Carrera de resistencia

resistencia();

break;

 

case 2: //Entrenamientos

entrenamiento();

break;

}

}

[/spoiler]

[spoiler show=»Selección, semáforo, reset, paso de vuelta, pausa y rutinas interrupciones» hide=»Selección, semáforo, reset, paso de vuelta, pausa y rutinas interrupciones»]Esta sección contiene las subrutinas comunes a todos los tipos de carreras:

  • Semáforo: Simula el que se usa en la fórmula uno, con tres luces rojas y una verde. No sería difícil cambiarlo por cualquier otro tipo de semáforo. Un poco más complicado (no mucho) sería poner una cuenta atrás como en los rallys, pero eso lo dejaré para una segunda versión del gestor que incluirá una carrera tipo Rally.
  • Selección: El menú de Arduslot. Sumamente básico, simplemente una variable se va incrementando / decrementando mientras recorre un array. Mas sencillo imposible.
  • Reset: Restaura el valor original de las variables.
  • Paso de vuelta: Calcula los tiempos de cada vuelta y los guarda si son los de la vuelta rápida de cada corredor junto con el número de dicha vuelta.
  • Pausa: Me di cuenta que pausaba el programa varias veces hasta que se pulsara un botón, así que puesto en una rutina me ahorraba memoria para futuras ampliaciones.
  • Rutinas de interrupciones: Son las rutinas que se ejecutan cuando pasa un coche por meta.  Deben ser lo mas cortas posibles para evitar funcionamientos anómalos (perdidas de vueltas y falta de precisión en el crono)

void seleccion() {

/*

Seleccionar entre tipos de carreras:

0: Número de vueltas.

1: Resistencia o a tiempo fijo.

2: Entrenamiento o vueltas libres

*/

t = 0;

lcd.clear();

lcd.print(» Elige el tipo»);

lcd.setCursor(0,1);

lcd.print(» de carrera»);

delay(pausaPantalla);

 

lcd.clear();

lcd.print(«Tipo de carrera»);

lcd.setCursor(0,1);

lcd.print(menu[t]);

 

while(analogRead(intro) < 525) {

if (analogRead(control) > 525) {

++t;

if (t > 2) t = 0;

lcd.clear();

lcd.print(«Tipo de carrera»);

lcd.setCursor(0,1);

lcd.print(menu[t]);

tone(sonido, 440, 100);

delay(250);

}

if (analogRead(control2) > 525) {

–t;

if (t < 0) t = 2;

lcd.clear();

lcd.print(«Tipo de carrera»);

lcd.setCursor(0,1);

lcd.print(menu[t]);

tone(sonido, 440, 100);

delay(250);

}

}

}

 

 

 

void semaforo()

{

digitalWrite(latchPin, LOW);

shiftOut(dataPin, clockPin, LSBFIRST, 0);

digitalWrite(latchPin, HIGH);

delay (50);

 

digitalWrite(latchPin, LOW);

shiftOut(dataPin, clockPin, LSBFIRST, B10000000);

digitalWrite(latchPin, HIGH);

tone(sonido, 440, intervalo);

delay(intervalo);

 

digitalWrite(latchPin, LOW);

shiftOut(dataPin, clockPin, LSBFIRST, B11000000);

digitalWrite(latchPin, HIGH);

tone(sonido, 540, intervalo);

delay (intervalo);

 

digitalWrite(latchPin, LOW);

shiftOut(dataPin, clockPin, LSBFIRST, B11100000);

digitalWrite(latchPin, HIGH);

tone(sonido, 640, intervalo);

delay (intervalo);

 

digitalWrite(latchPin, LOW);

shiftOut(dataPin, clockPin, LSBFIRST, B00010000);

digitalWrite(latchPin, HIGH);

tone(sonido, 740, intervalo*2);

delay (intervalo*2);

 

tiempoS = millis(); //Paso de salida (pone milis como 0)

tiempoS2 = tiempoS;

tiempoF = tiempoS;

tiempoF2 = tiempoS;

 

 

digitalWrite(latchPin, LOW);

shiftOut(dataPin, clockPin, LSBFIRST, 0);

digitalWrite(latchPin, HIGH);

}

 

 

 

void reset(){

//Reestablece las variables de los corredores

vuelta = 1; //Contadores de vueltas

//vueltaB = 1;

tiempoF = 0; // Tiempo de fin de vuelta

tiempoS = 0; //Tiempo de salida de vuelta

tiempoV = 0; //Tiempo de vuelta

tiempoR = 4294967295; //Tiempo de vuelta rapida. Es el valor maximo.

vueltaR = 1; //Vuelta rápida

vuelta2 = 1; //Contadores de vueltas

tiempoF2 = 0; // Tiempo de fin de vuelta

//tiempoFb2 = 0;

tiempoS2 = 0; //Tiempo de salida de vuelta

tiempoV2 = 0; //Tiempo de vuelta

tiempoR2 = 4294967295; //Tiempo de vuelta rapida

vueltaR2 = 0; //Vuelta rápida

vueltaT = 1;

tiempoRT = 4294967295; //Tiempo de vuelta rapida

vueltaRT = 0; //Vuelta rápida

corredor = 0;

Nvueltas = 1;

 

//Reasistencia

Reshoras = 0;

Resmin = 15;

ResmilisFin = 0; //para controlar la finalizacion de la carrera

 

}

 

 

 

void pasoDEvuelta(){

 

/*Calcula los tiempos de cada vuelta y los guarda si

son los de la vuelta rápida

*/

 

switch (corredor) {

case 1:

tiempoV = tiempoF – tiempoS;

tiempoS = tiempoF; //Pone el tiempo de salida nuevo

if (tiempoR > tiempoV) {

tiempoR = tiempoV;

vueltaR = (vuelta-1);

tone(sonido, 740, 250);

}

else {

tone(sonido, 250, 250);

}

break;

case 2:

tiempoV2 = tiempoF2 – tiempoS2;

tiempoS2 = tiempoF2; //Pone el tiempo de salida nuevo

if (tiempoR2 > tiempoV2) {

tiempoR2 = tiempoV2;

vueltaR2 = (vuelta2-1);

tone(sonido, 740, 250);

}

else {

tone(sonido, 250, 250);

}

break;

}

}

 

 

void pausa(){

delay(500);

while(analogRead(intro) < 525 ) {

delay(1);

}

tone(sonido, 500, 250);

}

 

 

//RUTINAS DE INTERRUPCIONES

 

void pasoVuelta1(){

if (millis() > (tiempoS+1000)){

tiempoF = millis ();

//++vuelta;

}

}

 

void pasoVuelta2(){

if (millis() > (tiempoS2+1000)){

tiempoF2 = millis ();

//++vuelta2;

}

}

 

//FIN RUTINAS INTYERRUPCIONES

 

[/spoiler]

[spoiler show=»Cronometro» hide=»Cronometro»]Conjunto de rutinas que se encargan de calcular y mostrar en la pantalla los tiempos.

void crono(){

 

/*Muestra los tiempos en pantalla.

Se basa en una variable «tipocrono» y segun su valor,

definido antes de cada llamada a «crono()», se calcula

la variable «tiempocrono», que es la que realmente se

muestra pasada de milisegundos a las unidades necesarias.

 

0 = Crono continuo de carreras a vuelta y entrenamientos

1 = Final de cada vuelta

2 = Final de carrera a vueltas

3 = Crono continuo en resistencia

4 = Tiempo total

*/

 

 

switch (tipocrono) {

case 0: //crono continuo en vueltas y entrenamiento

tiempocrono = millis()-tiempoS;

tiempocrono2 = millis()-tiempoS2;

crono_doble();

break;

 

case 1: //fin de cada vuelta

switch (corredor) {

case 1:

tiempocrono = tiempoV;

break;

case 2:

tiempocrono = tiempoV2;

break;

}

crono_sencillo();

break;

 

case 2: //final de carrera a vueltas

switch (corredor) {

case 1:

tiempocrono = tiempoR;

break;

case 2:

tiempocrono = tiempoR2;

break;

}

crono_sencillo();

break;

 

case 3: //crono continuo en vueltas y entrenamiento

tiempocrono = ResmilisFin – millis();

crono_resistencia();

break;

 

case 4: //Tiempo total

tiempocrono = ResmilisFin – ResmilisDuracion;

crono_sencillo();

break;

}

 

 

 

//delay (100); //evita parpadeos

}

 

 

void crono_doble(){

 

//Calculo de los tiempos a mostrar

minut = (tiempocrono/60000);

seg = ((tiempocrono/1000)-(minut*60));

mil = (tiempocrono-(minut*60000)-(seg*1000));

 

minut2 = (tiempocrono2/60000);

seg2 = ((tiempocrono2/1000)-(minut2*60));

mil2 = (tiempocrono2-(minut2*60000)-(seg2*1000));

 

 

//Tiempo corredor 1

lcd.setCursor (8,0);

if (minut < 10) {

lcd.print («0»);

}

lcd.print (minut);

lcd.setCursor (11,0);

if (seg < 10) {

lcd.print («0»);

}

lcd.print (seg);

lcd.setCursor (14,0);

lcd.print (mil);

 

//Tiempo corredor 2

lcd.setCursor (8,1);

if (minut2 < 10) {

lcd.print («0»);

}

lcd.print (minut2);

lcd.setCursor (11,1);

if (seg2 < 10) {

lcd.print («0»);

}

lcd.print (seg2);

lcd.setCursor (14,1);

lcd.print (mil2);

 

}

 

 

void crono_sencillo(){

 

//Calculo de los tiempos a mostrar

minut = (tiempocrono/60000);

seg = ((tiempocrono/1000)-(minut*60));

mil = (tiempocrono-(minut*60000)-(seg*1000));

 

 

 

lcd.setCursor (8,1);

if (minut < 10) {

lcd.print («0»);

}

lcd.print (minut);

lcd.setCursor (11,1);

if (seg < 10) {

lcd.print («0»);

}

lcd.print (seg);

lcd.setCursor (14,1);

lcd.print (mil);

}

 

void crono_resistencia(){

 

//Calculo de los tiempos a mostrar

hora = tiempocrono/3600000;

minut = (tiempocrono/60000) – (hora*60);

seg = (tiempocrono/1000) – (minut*60) – (hora*3600);

 

lcd.setCursor (8,0);

if (hora < 10) {

lcd.print («0»);

}

lcd.print (hora);

lcd.setCursor (11,0);

if (minut < 10) {

lcd.print («0»);

}

lcd.print (minut);

lcd.setCursor (14,0);

if (seg < 10) {

lcd.print («0»);

}

lcd.print (seg);

 

}

 

 

[/spoiler]

[spoiler show=»Carrera a vueltas» hide=»Carrera a vueltas»]Rutinas exclusivas de la carrera a un número determinado de vueltas. Primero se elige el número de vueltas, se da la salida con el semáforo y se realiza la carrera. Durante la carrera se muestran en cada linea los datos de número y tiempo de vuelta de cada corredor. Al acabar se muestra quien ha ganado y las vueltas rápidas de cada uno de los dos corredores.

void carreraVueltas(){

//Rutina principal de la carrera a vueltas.

 

reset();

 

//Definir el numero de vueltas de carrera

lcd.clear();

lcd.print(«Cuantas vueltas?»);

lcd.setCursor(0, 1);

lcd.print(Nvueltas);

delay(250);

 

while(analogRead(intro) < 525) {

if(analogRead(control) > 525) {

delay (100);

++Nvueltas;

lcd.setCursor(0, 1);

lcd.print(» «);

lcd.setCursor(0, 1);

lcd.print(Nvueltas);

tone(sonido, 440, 100);

delay(150);

}

 

if(analogRead(control2) > 525) {

delay (100);

–Nvueltas;

if (Nvueltas < 1) Nvueltas = 1;

lcd.setCursor(0, 1);

lcd.print(» «);

lcd.setCursor(0, 1);

lcd.print(Nvueltas);

tone(sonido, 440, 100);

delay(150);

}

}

 

//Inicio carrera

lcd.clear();

lcd.print(«Preparados?»);

lcd.setCursor(0,1);

lcd.print(«Boton +»);

while(analogRead(control) < 900 ) {

delay(1);

}

 

semaforo();

ResmilisDuracion = tiempoS; //Para calcular el tiempo total de carrera.

 

//Prepara los elementos fijos de la pantalla para evitar parpadeos.

lcd.clear();

lcd.print(«J1 V 1 : :»);

lcd.setCursor(0,1);

lcd.print(«J2 V 1 : :»);

 

//Controla la duracion de la carrera

while (Nvueltas >= vueltaT){

 

tipocrono = 0;

crono();

 

//Comprueban si se ha pasado por meta.

 

if (tiempoF != tiempoS){

corredor = 1;

++vuelta;

pasoDEvuelta();

pantallaVUELTA();

}

if (tiempoF2 != tiempoS2){

corredor = 2;

++vuelta2;

pasoDEvuelta();

pantallaVUELTA();

}

}

ResmilisFin = millis ();

finVueltas();

}

 

 

 

void pantallaVUELTA(){

//Controla la pantalla de cada final de vuelta en carreras a vueltas

 

//Calcula vueltaT

if (vuelta > vuelta2){

vueltaT = vuelta;

}

else if (vuelta < vuelta2) {

vueltaT = vuelta2;

}

else {

vueltaT = vuelta;

}

 

 

if (vueltaT <= (Nvueltas)){

lcd.clear();

lcd.setCursor(0,0);

lcd.print(«Jug: Vuelta:»);

lcd.setCursor(4,0);

lcd.print(corredor);

lcd.setCursor(15,0);

switch (corredor) {

case 1:

lcd.print (vuelta-1);

break;

case 2:

lcd.print (vuelta2-1);

break;

}

lcd.setCursor(0,1);

lcd.print(«Tiempo:»);

lcd.setCursor(10,1);

lcd.print(«:»);

lcd.setCursor(13,1);

lcd.print(«:»);

 

tipocrono = 1;

crono();

delay (pausaPantalla);

 

lcd.clear();

lcd.print(«J1 V : :»);

lcd.setCursor(0,1);

lcd.print(«J2 V : :»);

lcd.setCursor(6,0);

lcd.print(vuelta);

lcd.setCursor(6,1);

lcd.print(vuelta2);

}

 

if (vueltaT > Nvueltas){

lcd.clear();

lcd.setCursor(0,0);

lcd.print(«Jug: Vuelta:»);

lcd.setCursor(4,0);

lcd.print(corredor);

lcd.setCursor(15,0);

switch (corredor) {

case 1:

lcd.print (vuelta-1);

break;

case 2:

lcd.print (vuelta2-1);

break;

}

lcd.setCursor(0,1);

lcd.print(«Tiempo:»);

lcd.setCursor(10,1);

lcd.print(«:»);

lcd.setCursor(13,1);

lcd.print(«:»);

 

tipocrono = 1;

crono();

delay (pausaPantalla);

lcd.clear();

lcd.print(» FIN»);

delay (pausaPantalla);

}

}

 

 

 

void finVueltas() {

 

//Muestra el final de carrera: ganador y vueltas rapidas

 

lcd.clear();

lcd.print(» GANADOR»);

lcd.setCursor(0,1);

lcd.print(«Corredor: «);

lcd.print(corredor);

pausa();

lcd.clear();

lcd.print(«Tiempo Total:»);

lcd.setCursor(10,1);

lcd.print(«:»);

lcd.setCursor(13,1);

lcd.print(«:»);

tipocrono = 4;

crono();

pausa();

 

for (corredor = 1; corredor < 3; corredor++){

 

lcd.clear();

lcd.print(«Jug: V.Rap.:»);

lcd.setCursor(4,0);

lcd.print(corredor);

lcd.setCursor(15,0);

switch (corredor) {

case 1:

lcd.print(vueltaR);

break;

case 2:

lcd.print(vueltaR2);

break;

}

lcd.setCursor(0,1);

lcd.print(«Tiempo»);

lcd.setCursor(6,1);

lcd.print(«:»);

lcd.setCursor(10,1);

lcd.print(«:»);

lcd.setCursor(13,1);

lcd.print(«:»);

tipocrono = 2;

crono();

pausa();

}

}

 

 

[/spoiler]

[spoiler show=»Carrera de resistencia» hide=»Carrera de resistencia»]Rutinas exclusivas de la carrera de resistencia. Primero se elige la duración de carrera (horas 0-24 y minutos 2-59), se da la salida con el semáforo y se realiza la carrera. Durante la carrera se muestra en la LCD el tiempo que resta de carrera y las vueltas que lleva cada corredor. Al acabar se muestra quien ha ganado y las vueltas rápidas de cada uno de los dos corredores.

void resistencia(){

//Rutina principal de la carrera de resistencia.

 

reset();

 

//Definir el tiempo de la carrera

 

//HORAS MAX 24

lcd.clear();

lcd.print(«Cuantas horas?»);

lcd.setCursor(0, 1);

lcd.print(Reshoras);

delay(250);

 

while(analogRead(intro) < 525) {

if(analogRead(control) > 525) {

delay (100);

++Reshoras;

if (Reshoras > 24) Reshoras = 24;

lcd.setCursor(0, 1);

lcd.print(» «);

lcd.setCursor(0, 1);

lcd.print(Reshoras);

tone(sonido, 440, 100);

delay(150);

}

 

if(analogRead(control2) > 525) {

delay (100);

–Reshoras;

if (Reshoras < 0) Reshoras = 0;

lcd.setCursor(0, 1);

lcd.print(» «);

lcd.setCursor(0, 1);

lcd.print(Reshoras);

tone(sonido, 440, 100);

delay(150);

}

}

 

//MINUTOS (MINIMO 2 MINUTOS)

lcd.clear();

lcd.print(«Cuantos minutos?»);

lcd.setCursor(0, 1);

lcd.print(» Min 2″);

lcd.setCursor(0, 1);

lcd.print(Resmin);

delay(250);

 

while(analogRead(intro) < 525) {

if(analogRead(control) > 525) {

delay (100);

++Resmin;

if (Resmin > 59) Resmin = 59;

lcd.setCursor(0, 1);

lcd.print(» «);

lcd.setCursor(0, 1);

lcd.print(Resmin);

tone(sonido, 440, 100);

delay(150);

}

 

if(analogRead(control2) > 525) {

delay (100);

–Resmin;

if (Resmin < 2) Resmin = 2;

lcd.setCursor(0, 1);

lcd.print(» «);

lcd.setCursor(0, 1);

lcd.print(Resmin);

tone(sonido, 440, 100);

delay(150);

}

}

 

//Calculo duracion de la carrera

ResmilisDuracion = (Reshoras*3600000) + (Resmin*60000);

 

//Inicio carrera

lcd.clear();

lcd.print(«Preparados?»);

lcd.setCursor(0,1);

lcd.print(«Boton +»);

while(analogRead(control) < 900 ) {

delay(1);

}

 

semaforo();

ResmilisFin = tiempoS + ResmilisDuracion;

 

//Prepara los elementos fijos de la pantalla para evitar parpadeos.

lcd.clear();

lcd.print(«Tiempo : :»);

lcd.setCursor(0,1);

lcd.print(«J1:1 J2:1»);

 

//Controla la duracion de la carrera

while (millis() < ResmilisFin){

 

tipocrono = 3;

crono();

 

//Comprueban si se ha pasado por meta.

 

if (tiempoF != tiempoS){

corredor = 1;

++vuelta;

pasoDEvuelta();

pantallaRESISTENCIA();

}

if (tiempoF2 != tiempoS2){

corredor = 2;

++vuelta2;

pasoDEvuelta();

pantallaRESISTENCIA();

}

}

finResistencia();

}

 

 

 

void pantallaRESISTENCIA(){

//Controla la pantalla de cada final de vuelta en carreras a vueltas

 

//Calcula vueltaT

 

 

lcd.clear();

lcd.setCursor(0,0);

lcd.print(«Jug: Vuelta:»);

lcd.setCursor(4,0);

lcd.print(corredor);

lcd.setCursor(15,0);

switch (corredor) {

case 1:

lcd.print (vuelta-1);

break;

case 2:

lcd.print (vuelta2-1);

break;

}

lcd.setCursor(0,1);

lcd.print(«Tiempo:»);

lcd.setCursor(10,1);

lcd.print(«:»);

lcd.setCursor(13,1);

lcd.print(«:»);

 

tipocrono = 1;

crono();

delay (1000);

 

lcd.clear();

lcd.print(«Tiempo : :»);

lcd.setCursor(0,1);

lcd.print(«J1: J2:»);

lcd.setCursor(3,1);

lcd.print(vuelta);

lcd.setCursor(12,1);

lcd.print(vuelta2);

}

 

 

 

void finResistencia() {

 

//Muestra el final de carrera: ganador y vueltas rapidas

 

//Seleccion del ganador: Gana el que de mas vueltas y a iguladad se produce un empate

//Mas adelante se podria valorar la inclusion de comas.

//Quizas con un counter que active distintas resitencias que serian leidas por un solo pin

//analogRead(comas), dando la posicion en el circuito, pero harian falta mas sensores distribuidos por la pista,

//lo que daria problemas de estandarizacion.

if (vuelta > vuelta2){ //Ganador corredor 1

corredor = 1;

pantallaGanador();

}

else if (vuelta < vuelta2) { //Ganador corredor 2

corredor = 2;

pantallaGanador();

}

else {

pantallaEmpate();

}

}

 

void pantallaGanador() {

lcd.clear();

lcd.print(» GANADOR: «);

lcd.print(corredor);

lcd.setCursor(0,1);

lcd.print(» Vueltas: «);

if (vuelta > vuelta2){ //Ganador corredor 1

lcd.print(vuelta);

}

else if (vuelta < vuelta2) { //Ganador corredor 2

lcd.print(vuelta2);

}

 

pausa();

vueltasRapidas();

}

 

 

 

void pantallaEmpate() {

lcd.clear();

lcd.print(» EMPATE»);

lcd.setCursor(0,1);

lcd.print(«Vueltas: «);

lcd.print(vuelta);

pausa();

vueltasRapidas();

}

 

void vueltasRapidas() {

for (corredor = 1; corredor < 3; corredor++){

lcd.clear();

lcd.print(«Jug: V.Rap.:»);

lcd.setCursor(4,0);

lcd.print(corredor);

lcd.setCursor(15,0);

switch (corredor) {

case 1:

lcd.print(vueltaR);

break;

case 2:

lcd.print(vueltaR2);

break;

}

lcd.setCursor(0,1);

lcd.print(«Tiempo»);

lcd.setCursor(7,1);

lcd.print(«:»);

lcd.setCursor(10,1);

lcd.print(«:»);

lcd.setCursor(13,1);

lcd.print(«:»);

tipocrono = 2;

crono();

pausa();

}

}

 

 

[/spoiler]

[spoiler show=»Carrera de entrenamiento» hide=»Carrera de entrenamiento»]Rutinas exclusivas de la carrera de entrenamiento. Se da la salida con el semáforo y se realiza el entrenamiento, que se acaba al apretar un botón. Durante la carrera se muestran en cada linea los datos de número y tiempo de vuelta de cada corredor. Al acabar se muestran las vueltas rápidas de cada uno de los dos corredores.

void entrenamiento(){

//Rutina principal de la carrera a vueltas.

 

reset();

 

//Inicio carrera

lcd.clear();

lcd.print(«Se termina con»);

lcd.setCursor(0,1);

lcd.print(«Boton -«);

delay (pausaPantalla);

lcd.clear();

lcd.print(«Preparados?»);

lcd.setCursor(0,1);

lcd.print(«Boton +»);

while(analogRead(control) < 900 ) {

delay(1);

}

 

semaforo();

ResmilisDuracion = tiempoS; //Para calcular el tiempo total de carrera.

 

//Prepara los elementos fijos de la pantalla para evitar parpadeos.

lcd.clear();

lcd.print(«J1 V 1 : :»);

lcd.setCursor(0,1);

lcd.print(«J2 V 1 : :»);

 

//Controla la duracion del entrenamiento

while (analogRead(control2) < 525){

 

tipocrono = 0;

crono();

 

//Comprueban si se ha pasado por meta.

 

if (tiempoF != tiempoS){

corredor = 1;

++vuelta;

pasoDEvuelta();

pantallaENTRENAMIENTO();

}

if (tiempoF2 != tiempoS2){

corredor = 2;

++vuelta2;

pasoDEvuelta();

pantallaENTRENAMIENTO();

}

}

ResmilisFin = millis ();

finENTRENAMIENTO();

}

 

 

 

void pantallaENTRENAMIENTO(){

 

//Controla la pantalla de cada final de vuelta en entrenamiento

 

lcd.clear();

lcd.setCursor(0,0);

lcd.print(«Jug: Vuelta:»);

lcd.setCursor(4,0);

lcd.print(corredor);

lcd.setCursor(15,0);

switch (corredor) {

case 1:

lcd.print (vuelta-1);

break;

case 2:

lcd.print (vuelta2-1);

break;

}

lcd.setCursor(0,1);

lcd.print(«Tiempo:»);

lcd.setCursor(10,1);

lcd.print(«:»);

lcd.setCursor(13,1);

lcd.print(«:»);

 

tipocrono = 1;

crono();

delay (1000);

 

lcd.clear();

lcd.print(«J1 V : :»);

lcd.setCursor(0,1);

lcd.print(«J2 V : :»);

lcd.setCursor(6,0);

lcd.print(vuelta);

lcd.setCursor(6,1);

lcd.print(vuelta2);

}

 

 

 

void finENTRENAMIENTO() {

 

//Muestra el final del entrenamiento con las vueltas rapidas

 

lcd.clear();

lcd.print(«Tiempo Total:»);

lcd.setCursor(10,1);

lcd.print(«:»);

lcd.setCursor(13,1);

lcd.print(«:»);

tipocrono = 4;

crono();

pausa();

 

for (corredor = 1; corredor < 3; corredor++){

lcd.clear();

lcd.print(«Jug: V.Rap.:»);

lcd.setCursor(4,0);

lcd.print(corredor);

lcd.setCursor(15,0);

switch (corredor) {

case 1:

lcd.print(vueltaR);

break;

case 2:

lcd.print(vueltaR2);

break;

}

lcd.setCursor(0,1);

lcd.print(«Tiempo»);

lcd.setCursor(6,1);

lcd.print(«:»);

lcd.setCursor(10,1);

lcd.print(«:»);

lcd.setCursor(13,1);

lcd.print(«:»);

tipocrono = 2;

crono();

pausa();

}

}

[/spoiler]

DESCARGA del archivo