Pages: [1]   Go Down
Author Topic: Problema con velocimetro  (Read 3078 times)
0 Members and 1 Guest are viewing this topic.
A Coru
Offline Offline
Newbie
*
Karma: 0
Posts: 2
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hola
estoy preparando un velocímetro para la moto utilizando un fotointerruptor. El caso es que no consigo que marque la velocidad correctamente en el lcd, empiezan a fluctuar números incorrectos a toda velocidad. Pego el código a continuación, por si alguien sabe que ocurre y puede hecharme una mano. No sé si es problema de variables, de la función o que le pasa.
Gracias y un saludo a todos.

Code:
#include <LiquidCrystal.h>
static float odometro=0.0; // Km totales
static float km_parc=0.0; // Km parciales
int tinicial=0; //instante en el que se recibe un pulso (bajo) de velocidad (inicio vuelta de rueda)
int tfinal=0; // instante en el que se recibe el siguiente pulso (bajo) de velocidad (tfinal-tinicial=1 vuelta completa)
int tparado=0; // variable que si supera cierto valor pone la velocidad del cuadro a 0
int varVel=0; // variable para contar una vuelta de rueda en la funcion velocidad

int vel=0; // variable que almacena la velocidad
int velMax=0; // variable que almacena la velocidad maxima alcanzada
int perimetro=1805; // perimetro de la rueda en mm (para calculos de velocidad y distancias)

void setup(){
  Wire.begin();
  Serial.begin(9600);
  lcd.begin(16, 2);
}

void loop(){

attachInterrupt(0, velocidad, LOW);

// Velocidad en pantalla principal
  lcd.setCursor(0,0);
   if(vel<100)
    {
      lcd.print(" ");
      if(vel<10)
        {
        lcd.print(" ");
        }
    }
  lcd.print(vel,DEC);
  lcd.setCursor(4,0);
  lcd.print("Kmh");

// Km parciales en pantalla principal   
lcd.setCursor(6,1);
        if(km_parc<1000)
        {
          lcd.print(" ");
          if(km_parc<100)
          {
            lcd.print(" ");
            if(km_parc<10)
            {
              lcd.print(" ");
            }
          }
        }
      lcd.print(km_parc,0); // muestra los km parciales
      lcd.print("Km");
}
 
/* CALCULO DE LA VELOCIDAD
a esta fulcion se entra cada vez que el sensor detecte un nivel bajo, es decir al
iniciar la vuelta de la rueda y al finalizarla (dos veces por vuelta) */
void velocidad ()
    {
      if(varVel==0) //entra si es el inicio de la vuelta y toma el tiempo actual
      {
        tinicial=millis();
        varVel=1;
      }
      else if (varVel==1) //si es el final de la vuelta resta el tiempo actual al inicial
      // para calcular el tiempo transcurrido entre los 2 pulsos (1 vuelta completa)
      {
        tfinal=millis()-tinicial;                       
        varVel=0;                                       
        vel=perimetro/tfinal;
        vel=vel*3.6;
       
        km_parc=km_parc+(perimetro/100000.0);   
        if(km_parc>1200)
          km_parc=0;   
        odometro=odometro+(perimetro/100000.0);   
        if(odometro>100000)
          odometro=0;
        revision=revision-(perimetro/100000.0); // a esta interrupcion entra 1 vez por vuelta,
        // por lo que le restamos el perimetro de la rueda
      }
    }

Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

afcabanas:
Estas seguro que el perimetro es 1805mm?, eso da casi 2 metros no?
Logged

0
Offline Offline
Edison Member
*
Karma: 17
Posts: 1413
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

podrias poner que numeros son los que registra, cabe la posibilidad de que el sensor falle en algunas lecturas, por lo que el tiempo seria el doble o el triple y al calcular la velocidad pues parece que fluctue.

puedes usar algun tipo de logica respecto al tiempo leido, algo como que el tiempo leido tiene que estar entre un porcentaje del tiempo anterior o algo asi. o puedes tomar 5 valores y calcular la media.

vamos que creo que lo que falla es que el sensor a veces no registra la lectura.
Logged

* Si preguntas, pon el código de tu programa, hace mucho mas fácil ayudarte. Y me ahorro un mensaje pidiendo que lo hagas.
* Si consigues solucionar tu problema, dedica unos minutos a explicar en tu post como lo conseguiste para beneficio de todos.
* Cambia el 'Subject' de tu hilo y añade 'SOLUCIONADO' cuando hayas llegado a una solución al problema que planteaste.
* Utiliza un 'Subject' para tu hilo que explique de que va el hilo.
Si estas empezando:
* Comienza a usar Arduino
* Guías de iniciación a Arduino
* Ejemplos
* Referencia del Lenguaje
* Conceptos básicos
Guia de usuario de arduino
Tutoriales en Ingles
Si necesitas que alguien te escriba el código: http://www.freelancer.com/  o esta  http://www.guru.com/

A Coru
Offline Offline
Newbie
*
Karma: 0
Posts: 2
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

mvaldebenitorojas
Si, date cuenta que hablamos del perímetro, no del diámetro

Sergegsx
parece buena cosa la de tomar varias lecturas por vuelta y calcular la media. De todas forma, ahora me conformo con que registre la velocidad, aunque esta no sea exacta. El sensor si da todas las lecturas, lo he comprobado mediante un led que se enciende al cortar la señal. Por ejemplo, si no se produce ninguna interrupción, el display debería indicar 0, sin embargo indica el último valor mostrado.

Voy a ver el tema de los tipos de variables, tal vez attachInterrup no admita ciertos tipos o no conserve los valores al salir de la funcion.
Gracias por las sugerencias, seguiremos probando
Logged

0
Offline Offline
God Member
*****
Karma: 1
Posts: 524
Arduino inside
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

lo tienes conectadoal pin 2?
Logged

0
Offline Offline
Edison Member
*
Karma: 16
Posts: 1579
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

afcabanas, por qué tienes la interrupción activada por nivel en vez por flanco?

Por otro lado. las variables que son modificadas por la interrupción y que usas fuera de la misma las tienes que declarar como volatile (http://arduino.cc/es/Reference/Volatile).
El perímetro, podrías usar un #define, en vez variable que consume RAM (ésto es por ser quiscolloso).
Yo haría las menos operaciones posibles dentro de la interrupción, como vas a mostrarlo por lcd, que lo actualizarás cada ¿200 ms?, tienes tiempo de sobra para hacerlo fuera.... ¿no? Podrías ir ampliando una variable en la interrupción, y cada los ¿200ms? (por poner un tiempo), calculas la velocidad, ya que sabes el número de pulsos que tienes en esa cierta cantidad de tiempo.

¿Has copiado y pegado de parte de código? Hay una variable revision y un Wire.begin que despistan un poco.... smiley-wink


« Last Edit: August 06, 2011, 01:09:18 pm by Igor R » Logged


0
Offline Offline
Newbie
*
Karma: 0
Posts: 36
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

afcabanas, por qué tienes la interrupción activada por nivel en vez por flanco?


¿Por que sería mejor activarla por flanco?


¿Has copiado y pegado de parte de código? Hay una variable revision y un Wire.begin que despistan un poco.... smiley-wink

Viva el codigo libre.
Logged

La electrónica y el slot (o esos cochecitos)
http://www.juanjofrancia.es/arduslot

0
Offline Offline
Edison Member
*
Karma: 16
Posts: 1579
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hola,

Hoy he estado montando un inventillo con un trafo, y necesitaba medir la frecuencia de la red eléctrica.Me he creado este pequeño programa y me he acordado de este post.Uso interrupciones, y es similar a lo que necesitas. Por cierto,si alguien necesita tener controlado el paso por cero de la senoidal de la red eléctrica (por ejemplo para el control de triacs), también le sirve este código.

Pongo por aquí el código por si te ayuda en algo:

Code:
volatile unsigned long tanterior;
volatile unsigned long tnuevo;
volatile float frec;

void setup()
{
  Serial.begin(19200);
  pinMode(2,INPUT);
  pinMode(13,OUTPUT);  //Led
  attachInterrupt(0,myfunc,CHANGE);
}

void loop()
{
  Serial.println(frec);
}

void myfunc()
{
  if (digitalRead(2))
  {
    tanterior=tnuevo;
    tnuevo=micros();
    frec=1000000.0/(tnuevo-tanterior);
  }
  digitalWrite(13,!digitalRead(13));  //Led
}

La salida digital (dónde esta conectado el led de Arduino) la cambio de estado cada vez que entro a la rutina de interrupción sólo con fines de debug, ya que conecto el analizador lógico para ver que todo esta funcionando como debería.

Acerca de la pregunta de uno de los post por qué no puede ser LOW... entraría a la interrupción todo el rato que dure el pulso bajo (ya que es activación por nivel). Lo que te interesa es entrar una sólo una vez, para capturar el tiempo.

Hace tiempo escribí este post para cálculo de rpm de un coche => http://real2electronics.blogspot.com/2009/09/shift-lights-con-arduino.html

Saludos  smiley-wink


Igor R.
« Last Edit: August 10, 2011, 06:39:38 am by Igor R » Logged


Pages: [1]   Go Up
Jump to: