Go Down

Topic: PROYECTO CONTROL DE TIEMPOS (Read 2611 times) previous topic - next topic

COCO_ONE

Mar 14, 2017, 08:55 pm Last Edit: Mar 17, 2017, 11:38 pm by Hector_A Reason: No respetó las normas del foro
Hola soy nuevo en esto de arduino, y comenzado con un control de tiempos para slot (scalextric), el sketch lo he sacado de un hilo del foro bastante antiguo, y el circuito lo he montado desde el sketch y fijándome en tutoriales y demás.-
El problema lo tengo en como me muestran los tiempos la lcd 16,2, me gustaría que mostraras minutos:segundos´decimas y centésimas (m:s,000) os ajunto el sketch, y el esquema del protoboard, gracias por adelantado.-

Code: [Select]
/*
Cuentavueltas y crono

*/

#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int Nvueltas = 1; //Numero de vueltas
int control = 10; //Pin de control (Boton A)
int control2 = 5; //Pin ANALOGICO de control 2 (Boton B)
int rojo1 =  6; //Pin led rojo 1
int rojo2 =  7; //Pin led rojo 2
int rojo3 =  8; //Pin led rojo 3
int verde =  9; //Pin led verde
int intervalo =  1000; //Intervalo de la secuencia
int paso = 13; //Pin de paso de vuelta
int vuelta = 0; //Contador de vueltas
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 = 99999; //Vuelta rapida



void setup()    {
pinMode(rojo1, OUTPUT);
pinMode(rojo2, OUTPUT);
pinMode(rojo3, OUTPUT);
pinMode(verde, OUTPUT);
pinMode (paso, INPUT);
pinMode (control, INPUT);
// set up the LCD's number of rows and columns:
lcd.begin(16, 2);
lcd.print("Vuelta:");
lcd.setCursor(0, 1);
lcd.print("Tiempo:");
}

void semaforo()
{
digitalWrite(rojo1, HIGH); //Encendido secuencial de los rojos
delay(intervalo);
digitalWrite(rojo2, HIGH);
delay(intervalo);
digitalWrite(rojo3, HIGH);
delay(intervalo);

digitalWrite(rojo1, LOW); //Apaga los leds rojos
digitalWrite(rojo2, LOW);
digitalWrite(rojo3, LOW);
digitalWrite(verde, HIGH); // Enciende el verde
delay(intervalo*2);
digitalWrite(verde, LOW);  //Apaga verde
tiempoS = millis();
}

void pasoDEvuelta(){
vuelta = vuelta + 1; //Conteo de vuelta
tiempoF = millis(); //Calculo de tiempo de vuelta
tiempoV = tiempoF - tiempoS;
tiempoS = tiempoF; //Pone el tiempo de salida nuevo
if (tiempoR > tiempoV) {
 tiempoR = tiempoV;
}
delay(250); //Espera para para no contar varias veces por paso
}

void pantalla(){
//Mostrar el numero de vuelta y tiempo
lcd.clear();
lcd.print("Vuelta:");
lcd.setCursor(0, 1);
lcd.print("Tiempo:");
lcd.setCursor(10, 0); //Situar el cursor
lcd.print(vuelta);
lcd.setCursor(10, 1); //Situar el cursor
lcd.print("   ");
lcd.setCursor(10, 1); //Situar el cursor
lcd.print(tiempoV/1000);
}

void fin() {
//Muestra vuelta rapida
lcd.clear();
lcd.print("Vuelta rapida:");
lcd.setCursor(0, 1);
lcd.print(tiempoR / 1000);
delay(5000);
Nvueltas = 1;

}

void numeroDEvueltas() {
lcd.clear();
lcd.print("Cuantas vueltas?");
lcd.setCursor(0, 1);
lcd.print(Nvueltas);

//Definir el numero de vueltas de carrera

while(analogRead(control2) < 256) {


if (digitalRead(control) == HIGH ) {
++Nvueltas;
lcd.setCursor(0, 1);
lcd.print("   ");
lcd.setCursor(0, 1);
lcd.print(Nvueltas);
delay(250);
}
}

lcd.clear();
lcd.print("Preparados?");
lcd.setCursor(0,1);
lcd.print("A");
while(digitalRead(control) == 0) {
delay(5);
}
delay(5);
}

void loop()  {
lcd.clear();
lcd.print("     BUENA");
lcd.setCursor(0, 1);
lcd.print("    CARRERA!");
delay(3000);
numeroDEvueltas();
semaforo();
vuelta = 0;
//Cuenteo de vueltas y tiempos

while(vuelta < Nvueltas){
if (digitalRead(paso) == HIGH ) {
pasoDEvuelta();
pantalla();
}
}
}

https://forum.arduino.cc/index.php?action=dlattach;topic=462668.0;attach=203782

Arduinito

#1
Mar 14, 2017, 09:20 pm Last Edit: Mar 14, 2017, 09:27 pm by Arduinito
Otra vez el proyecto del slot y la pantalla lcd...

Puedes cambiar milis() por micros() (Si quieres, claro) para ajustar la precisión.
Una vez tienes los segundos que sabes que usando milis() por ejemplo es dividiendo entre 1000, haces las correspondientes divisiones para obtener el resto.

décimas: segundos / 10.
centésimas: segundos / 100
milésimas: segundos/ 1000. (aunque este ya de por sílo tienes en tiempoV)

Obvio, si se usa micros() cambiamos la escala:

enlace de micros()

Quote
there are 1,000 microseconds in a millisecond and 1,000,000 microseconds in a second.
Matemáticas simples.

P.D: repito lo del delay() como en el anterior post que era inciado por otro usuario y preguntaste en él. Si usas un delay(250) en pasoDEvuelta() significa que cada paso de vuelta tú código va a tener un retraso de 250 milisegundos cuando pasé tu vehículo de slot... Así que usa milis() o micros(), usa timers, no delays. Para nada ajustas los milisegundos si vas a tener semejante retraso por vuelta.

COCO_ONE

Muchas gracias mañana lo probare, lo siento si es repetido no lo he encontrado

Metaconta

#3
Mar 15, 2017, 02:04 am Last Edit: Mar 15, 2017, 02:05 am by Metaconta
Hola:

Para ahorrar memoria, ¿por qué no lo pasas de int a bytes?

Son de 0 al 255 en byte.

Lo tienes así:
Code: [Select]
int Nvueltas = 1; //Numero de vueltas
int control = 10; //Pin de control (Boton A)
int control2 = 5; //Pin ANALOGICO de control 2 (Boton B)
int rojo1 =  6; //Pin led rojo 1
int rojo2 =  7; //Pin led rojo 2
int rojo3 =  8; //Pin led rojo 3
int verde =  9; //Pin led verde
int intervalo =  1000; //Intervalo de la secuencia
int paso = 13; //Pin de paso de vuelta
int vuelta = 0; //Contador de vueltas


Solo lo cambiar de int a byte así y de forma constante:
Code: [Select]
int Nvueltas = 1; //Numero de vueltas
const byte control = 10; //Pin de control (Boton A)
const byte  control2 = 5; //Pin ANALOGICO de control 2 (Boton B)
const byte  rojo1 =  6; //Pin led rojo 1
const byte  rojo2 =  7; //Pin led rojo 2
const byte  rojo3 =  8; //Pin led rojo 3
const byte  verde =  9; //Pin led verde
int  intervalo =  1000; //Intervalo de la secuencia
const byte  paso = 13; //Pin de paso de vuelta
const byte  vuelta = 0; //Contador de vueltas


Hablo de los pines de Arduino.

Alfaville

#4
Mar 15, 2017, 02:42 am Last Edit: Mar 15, 2017, 03:02 am by Alfaville
Hola.

Suponiendo que usas un Arduino UNO, tal y como aparece en el esquema, hay un pequeño error aqui:

Code: [Select]
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int control = 10;  //Pin de control (Boton A)
//int control2 = 5;  // <<== Error, este pin ya lo usa el display
int control2 = A5; // Pin ANALOGICO de control 2 (Boton B)
int rojo1 =  6;    //Pin led rojo 1

Por otro lado para ver los tiempos en formato "mm:ss,000" incluye esta modificacion en tu código:

Code: [Select]
void pantalla()
{
 //Mostrar el numero de vuelta y tiempo
 lcd.clear();
 lcd.print("Vuelta:");
 lcd.setCursor(0, 1);
 lcd.print("Tiempo:");
 lcd.setCursor(10, 0); //Situar el cursor
 lcd.print(vuelta);
 lcd.setCursor(10, 1); //Situar el cursor
 lcd.print("   ");
 lcd.setCursor(10, 1); //Situar el cursor
 //*******************
 lcd.print(tiempoV/60000);   // <<== minutos
 lcd.print(":");
 lcd.print((tiempoV%60000)/1000);  // <<== segundos
 lcd.print(",");
 lcd.print((tiempoV%1000)/10);  // <<== decimas + centesimas
 //*******************
// lcd.print(tiempoV/1000);  // <<== linea no válida
}


Por supuesto hay varios aspectos a mejorar para que el programa pueda optimizarse (declaracion de los pines, obtencion de los tiempos, lectura del boton "B" como analógico, etc,..), pero como el código no lo has desarrollado tú sino que es un copy-paste según comentas pues quizás no te serviría como aprendizaje, por lo que ahí queda.

Prueba y comenta si funciona como quieres.
Saludos.

Arduinito

#5
Mar 15, 2017, 11:01 am Last Edit: Mar 15, 2017, 11:07 am by Arduinito
Alfaville,

lcd.print(tiempoV/1000);  // <<== linea no válida

No es que no sea válido. Si tú divides millis() entre 1000 obtienes los segundos, otra cosa es que para mostrarlo en el display necesites obtener cada dígito usando también MOD, que por si COCO_ONE recién empieza a programar es el operador % (común en muchos lenguajes).

Yo aconsjearía usar sprintf, que además de usar menos líneas le damos un formato a la salida que se va a mostrar al lcd, por ejemplo el uso de 0 a la izquierda si por ejemplo los segundos son menos que 10.

Code: [Select]

    long total_milis = tiempo/1000;
    int mili = total_milis % 10;
    int cent = total_milis / 10 % 10;
    int deci = total_milis / 100 % 10;
    int seg  = total_milis / 1000;

    char crono[0];   
    sprintf(crono,"%.2d:%.2d:%.2d:%.2d",seg,deci,cent,mili);
   
    lcd.print(crono);


¡¡¡Teniendo en cuenta que en mi cronómetro yo NO usé millis(), sino micros() !!! tiempo = micros(); Bueno y en mi código real fui más allá de los milisegundos, pero así este que he modificado como ejemplo va bien diviendo entre 1000.

COCO_ONE, en caso de usar millis(), usa los mod que te pone Alfaville y ya después puedes usar igualmente el sprintf.
Las variables las declaré para que se entendiese pero te las puedes "comer" y añadir cada operación dentro del correspondiente parámetro de sprintf.

Obvio que en este caso deci, cent y mili nunca tendrán dos dígitos, ya que una vez llegado a 10 se cambia la; centésima o décima correspondiente. Le añadí a esas variables el %.2d para hacerlo más visual rellenando también con ceros a la izquierda.

Recuerda y repito hasta la saciedad que usar delays() afectará a la precisión de tu cronómetro, Y MUCHO.
Tienes que poner un botón que funcione como un Switch. Lo único que tienes que hacer es poner que si el estado está en HIGHT mostrar el valor en la lcd. Si usas delay, arrastrarás ese retraso cada vuelta que dé el loop, si no usas nada irá tan rápido que no mostrarás bien los datos en la pantalla porque necesitas usar el lcd.clear().

Otra cuestion, si usas micros() y lo muestras con un Serial.println(); verás que acorta los datos y suelen salir como un número y un periodo repetido estilo: 37777, eso es porque es un long, pero si separas como te comentamos y lo muestras, obtendrás los segundos, decimas, centésimas y milésimas bien en la lcd.

Ejemplo:

Sin presionar:


Presionado: (Nótese los segundos transcurridos en el simulador en la parte superior izquierda y bajo esta línea)


21 segundos, 1 décima de segundo, 1 centésima de segundo, 8 milésimas de segundo, o lo que es lo mismo: 21118 milisegundos.

Un saludo.

surbyte

#6
Mar 16, 2017, 04:13 am Last Edit: Mar 16, 2017, 04:14 am by surbyte
3er hilo en un dia con la palabra AYUDA en el titulo.

1. Lee las normas del foro.
2. Edita tu título.
3. Edita el código para que se ve como las normas lo indican o sea usando la etiqueta de códigos.
4. Si pones una imagen, esta debe verse y no solo adjuntarse.

para el punto 2 en adelante necesitas EDITAR asi que ve a More, luego Modify y estas en modo EDICION.
Ahora presta atención.
1. Ve al titulo y quita la palabra Ayuda. usa p.ej: Control de tiempos para SLOT.
2. Selecciona todo el código y click en </> arriba del emoticon.
3. con boton derecho del mouse (antes de editar captura el enlace de la imagen adjunta). Y luego cuando estes en EDICION click en icono pantalla junto al eslabón y pega el enlace capturado antes.


COCO_ONE

hola buenas noches ya he estado probando y con tutoriales y vuestra ayuda ya he conseguido que el tiempo salga en formato min:seg,00, ahora estoy viendo como hacer que el formato de los segundos no pase de 60,
por ejemplo cuando llevo 1:05, un minuto, cinco segundos me marca 1:65, pero me esta apasionando esto de arduino, muchas gracias seguiré compartiendo mis pinitos.-

Alfaville

#8
Mar 17, 2017, 12:43 am Last Edit: Mar 17, 2017, 12:44 am by Alfaville
Asi:

Code: [Select]
//*******************
 lcd.print(tiempoV / 60000);   // <<== minutos
 lcd.print(":");
 lcd.print((tiempoV % 60000) / 1000);  // <<== segundos
 lcd.print(",");
 lcd.print((tiempoV % 1000) / 10);  // <<== decimas + centesimas
 //*******************


Saludos.

Go Up