Go Down

Topic: Contador de velocidad en funcion del tiempo (la distancia no varia) (Read 160 times) previous topic - next topic

x3f3x

Feb 14, 2018, 02:02 pm Last Edit: Feb 14, 2018, 02:04 pm by surbyte Reason: Titulo inutil "Ayuda .."
Buenas tardes, llevo dias programando un arduino para poder calcular la velocidad en funcion del tiempo, porque la distancia no varias, este resultado lo quiero mostrar en 3 displays de 7 segmentos, no soy en experto en programacion he ido leyendo foros y cogiendo el codigo que me interesaba para primero poder mostrar numeros en los displays ya que son 3 displays de 7 segmentos individuales, y estan conectados con los pines individualmente, no estan multiplexados, el caso es que esta parte creo que ya la tengo por la mano o al menos a mi el programa ya me muestra digitos.

La idea de lo que quiero hacer es que el arduino calcule el tiempo que hay entre 2 pulsos (triggers) y a partir de ahi que en los dosplays me muestre la velocidad, lo unico que varia es el tiempo, el problema que tengo es que el arduino no me calcula la velocidad, si que puedo ver el tiempo y lo cuenta bien, pero la velocidad no. Los 2 pulsos que he comentado arriba son muy seguidos y me han comentado que seria interesante tener interrupciones para que el arduino cogiera los 2 pulsos, pero no tengo mucha idea de como hacerlo, este es el codigo:

Code: [Select]
int analogPin=3;
float num=0;

int centisegundo=0;
float decisegundo=0;
float segundo=0;  
int minuto=0;  
int hora=0;
int pausa=0;
float multi=0;

const int pulsador1=53;
const int pulsador2=32;

float t=0, d=0, v=0;
int num_array[10][7] = {  { 1,1,1,1,1,1,0 },    // 0
                          { 0,1,1,0,0,0,0 },    // 1
                          { 1,1,0,1,1,0,1 },    // 2
                          { 1,1,1,1,0,0,1 },    // 3
                          { 0,1,1,0,0,1,1 },    // 4
                          { 1,0,1,1,0,1,1 },    // 5
                          { 1,0,1,1,1,1,1 },    // 6
                          { 1,1,1,0,0,0,0 },    // 7
                          { 1,1,1,1,1,1,1 },    // 8
                          { 1,1,1,0,0,1,1 }};   // 9
                                      
void setup()
{
  pinMode(0, OUTPUT);  // Asignación de las salidas display 1
  pinMode(1, OUTPUT);
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(85, OUTPUT);  // Asignación de las salidas display 2
  pinMode(84, OUTPUT);
  pinMode(83, OUTPUT);
  pinMode(82, OUTPUT);
  pinMode(81, OUTPUT);
  pinMode(80, OUTPUT);
  pinMode(79, OUTPUT);
  pinMode(78, OUTPUT);
  pinMode(77, OUTPUT);  // Asignación de las salidas display 3
  pinMode(76, OUTPUT);
  pinMode(75, OUTPUT);
  pinMode(74, OUTPUT);
  pinMode(73, OUTPUT);
  pinMode(72, OUTPUT);
  pinMode(71, OUTPUT);
  pinMode(pulsador1,INPUT);
  pinMode(pulsador2,INPUT);
}



void loop()
{
  {
  if(digitalRead(pulsador1)==HIGH)  //con este pulsador incrementamos
  {
    pausa=0;
  }
  
  if(digitalRead(pulsador2)==HIGH)  //con este pulsador decrementamos
  {
    pausa=1;
  }
  
   if(pausa==0)  //el reloj tiene que contar
  {
     decisegundo++;
     delay(100);
     if(decisegundo>10)
  {
    decisegundo=0;
    segundo++;    
    if(segundo>59)
    {
      segundo=0;
      minuto++;
      if(minuto>59)
      minuto=0;
    }
  }
  }
  }
multi=decisegundo/100;
t=segundo+multi;
d=2.5;
v=(d/t);
num = t*10;
    {
     Num_Write(num);
    }
}

// Esta funcion escribe el valor en los displays.
void Num_Write(int num)
{
  int x, y, z;  
y = num/100;
z = (num - y*100)/10;
x = (num - y*100 - z*10);
  
  int pin1= 0;
  for (int j=0; j < 7; j++) {
   digitalWrite(pin1, num_array[y][j]);
   pin1++;
  }

  int pin2= 85;
  for (int j=0; j < 7; j++) {
   digitalWrite(pin2, num_array[z][j]);
   pin2--;
  }

  int pin3= 77;
  for (int j=0; j < 7; j++) {
   digitalWrite(pin3, num_array[x][j]);
   pin3--;
  }
}



Ahora mismo el trigger es un boton, mientras lo mantengo pulsado el tiempo aumenta, pero el display no me muestra el resultado de v= que es d/t, alguien me podria echar un cable? Llevo 3 dias sin parar y no consigo hacer que funcione, de paso si alguien ve que hay cosas mal agradeceria que me lo comentara para poder mejorarlo ya que seguro que hay muchas cosas de novato.

Gracias por vuestro tiempo.

Saludos!!

surbyte

Mi pregunta es: probaste la parte de 7 segmentos enviando un número fijo digamos así


Code: [Select]
void loop() {
  Num_Write(123);   
}


Muestra 123 el display?

Empieza por lo básico.

Cuando presentes un problema intenta darnos toda la información.
Usas pines que yo jamás he usado, ejemplo

Code: [Select]
pinMode(85, OUTPUT);  // Asignación de las salidas display 2
  pinMode(84, OUTPUT);
  pinMode(83, OUTPUT);
  pinMode(82, OUTPUT);
  pinMode(81, OUTPUT);
  pinMode(80, OUTPUT);
  pinMode(79, OUTPUT);
  pinMode(78, OUTPUT);
  pinMode(77, OUTPUT);  // Asignación de las salidas display 3
  pinMode(76, OUTPUT);
  pinMode(75, OUTPUT);
  pinMode(74, OUTPUT);
  pinMode(73, OUTPUT);
  pinMode(72, OUTPUT);
  pinMode(71, OUTPUT);

x3f3x

#2
Feb 14, 2018, 02:54 pm Last Edit: Feb 14, 2018, 03:00 pm by surbyte Reason: No repitas lo que ya se lee arriba.
Si si esa parte esta probada y los displays me muestran numeros correctamente, y si quiero ver el tiempo en los display lo veo correctamente.

Lo de los pines es porque estoy usando un chipkit MAX32, y la placa para montar los displays la diseñe asi.

Saludos.

surbyte

Bueno entonces usa el monitor Serie y visualiza si los valores son enteros como lo que esperas,

Agrega un par de Serial.print(distancia) y sus datos parciales y verás que esta ocurriendo.

NOTA:

Para mi tu problema esta en las unidades que usas.
Yo no usaría float para decisegundo, segundo, etc sino unsigned int.

noter

Lo que yo echo de menos si de medir el tiempo se trata es, precisamente, los temporizadores. ¿Por qué no usas millis o, mejor aún, micros?

En cuanto a los cálculos, yo siempre prefiero huir de los float, para hacer un cálculo más "humanizado". A salto de mata lo haría tal que así:

Code: [Select]

unsigned long tiemposalida;
unsigned long tiempotranscurrido;
unsigned long velocidad;
while (digitalRead(pulsador1)==LOW) ; // bucle vacío hasta leer pulsador 1
tiemposalida=millis(); // ¿Qué milisegundo es?
while (digitalRead(pulsador2)==LOW) ; // bucle vacío hasta leer pulsador 2
tiempotranscurrido=millis()-tiemposalida;
unsigned long distancia = 2500000; // micras si es que el 2.5 de distancia eran metros.
velocidad = tiemposalida; // velocidad en micras/ms, lo que da para 3 decimales en mm/ms, que es lo mismo que m/s
Serial.print("velocidad: ");
Serial.print(velocidad/1000);
Serial.print(","); // coma o punto decimal
Serial.print(velocidad%1000);
Serial.println(" metros por segundo");

Zerabla

Hola, buenos días,

antes de nada decir que este es mi primer post en el foro. Pido disculpas por adelantado, en caso de no cumplir con alguna norma del foro.

Sobre lo que comentas sobre como medir el tiempo y las interrupciones, en mi opinion todo depende de la precisión que necesites/quieras. Por supuesto es mejor utilizar interrupciones, puesto te aseguras que las rutinas

Zerabla

Hola, buenos días,

antes de nada decir que este es mi primer post en el foro. Pido disculpas por adelantado, en caso de no cumplir con alguna norma del foro.

Sobre lo que comentas sobre como medir el tiempo y las interrupciones, en mi opinion todo depende de la precisión que necesites/quieras. Por supuesto es mejor utilizar interrupciones, puesto te aseguras que las rutinas que programes se realicen cuando quieras, disminuyendo algunos retardos. Pero eso significa estudiar el integrado y el funcionamiento de sus interrupciones. Si te lo puedes permitir puedes utilizar el codigo que has utilizado.

También comentas que has utilizado un chipkit MAX32, que aunque por lo que he visto es compatible con el hardware y software ARDUINO, no es un arduino. Lo digo ya que he podido ver que lleva un chip PIC y no ATMEGA, por lo tanto las gestiones de interrupciones serán diferentes a las placas ARDUINO que llevan el chip de ATMEL.

Por lo tanto mejor olvidarse del tema de las interrupciones.

Por cierto cuando cuelges codigo, se agradeciría que tengas en cuenta la identación del progama, para facilitar su comprensión.

Como dice noter, veo mucho mejor utilizar la función milis o micros para contar el tiempo.

Sobre lo del tipo de variables no te diré nada sobre si es mejor un float , un double o un unsigned int, que creo que cada uno debe tener en cuenta según sus necesidades, pero si en que todo sea correcto.
Observa tu codigo

Code: [Select]

...
float t=0, d=0, v=0;
...
void Num_Write(int num)
{
...
}


void loop()
{
...
Num_Write(v)
...
}


Ten en cuenta que al construir la función Num_Write necesitas pasarle un integer, pero si le pasas la velocidad le estás pasando un float y puedes tener algun error.


Por tu codigo, cuando pausa es activado = 1 (con el pulsador 2) no tiene que hacer nada.

cuando pausa es desactivado = 0 (con el pulsador 1) tiene que contar el tiempo.

Es decir con cuando activas una vez el pulsador 1 comienza el crono y se pausa con el pulsador 2. Si vuelves a pulsar el pulsador 1 continuas con el crono. Jamás lo reseteas.

Por lo que el tiempo aumenta hasta el infinito ( en tu caso lo has limitado a 59 segundos y pico)

v = d / t   ----> cuando el tiempo sea mayor a la distancia la velocidad es menor a 1 y como tu función admite enteros

Code: [Select]
void Num_Write(int num)
{
...
}

El resultado es cero.

Además estás actualizando constantemente la cifra en los displays.

Como dice noter lo puedes comprobar facilmente incluyendo Serial.print a modo de debugger.

Supongo que tu proposito es controlar el tiempo que transcurre desde que se produce un flanco de subida en el pulsador 1 hasta que se produzca otro flanco de subida en el pulsador 2.

Quieres tener en cuenta posibles errores, como por ejemplo que tengas se active el pulsador 1 , pero a veces no funciones el pulsador 2, o tener una velocidad mínima, por ejemplo de 1 unidad/tiempo.



Se podria hacer parecido a como dice noter

Code: [Select]

[code]void loop()
{

  int reloj_on = 0;
  int max_time=2.5;  //poner el tiempo para acotar la velocidad mínima
  unsigned long time_star , time_elapsed ;

  if (pulsador1== HIGH )                  //activacion del cronometro
    {
      time_star = milis();
      reloj_on = 1;
    }
  if ( (milis()-time_star) > max_time)  //comprobación del tiempo para la velocidad mínima.
    {
      reloj_on = 0;                         //reseteo del cronometro en caso de superar la velocidad mínima
    }
  if ( reloj_on && (pulsador2 == HIGH))  // cronometro en marcha y pulsador 2 activado
    {
      time_elapsed = milis() - time_star;     //tiempro transcurrido
      v = d / time_elapsed;                   //calculo de la velocidad.
      Num_Write(v);                           //actualización en los displays
      reloj_on = 0;                           //reseteo del cronometro para la siguiente medición.
    }
}

[/code]

Go Up