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.
//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.
//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.
//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]
Deja una respuesta