Velocimetro só chega a 96Km/h ... ajuda

montei um velocimetro simples com um arduino uno + lcd 16x2 + led + sesor hall

ja usei sensor optico mas acontece o mesmo, so faz leitura ate 96 Km/h depois disso não vai

é 1 sinal por volta da roda de circunferencia de 16cm

alguem tem alguma ideia do que esta acontecendo ???

segue sketch

#include <LiquidCrystal.h>
#define PMS_PIN 2
#define LED_PIN 13
LiquidCrystal lcd(8,9,4,5,6,7);
float start, finished;
float elapsed, time;
float circMetric=0.16;
float speedk;
void setup()
{
  pinMode(PMS_PIN, INPUT);
  pinMode(LED_PIN, OUTPUT);  
attachInterrupt(0, speedCalc, RISING);
  start=millis();
  lcd.begin(16,2);   
  lcd.clear();
 }
void speedCalc()
{
  elapsed=millis()-start;
  start=millis();
  speedk=(3600*circMetric)/elapsed;
}
void loop()
{
  lcd.setCursor(5,0);
  lcd.print(int(speedk));
  lcd.print("  km/h              ");
  lcd.setCursor(0,1);
  lcd.print("   Medindo...   ");
digitalWrite(LED_PIN, digitalRead(PMS_PIN));
}

Faz um teste ai.
Retire todas as instruções println para o lcd, menos a que mostra a velocidade, tenta trabalhar com menos variaveis float, minhas suspeitas está em cima do ciclo do arduino do loop().
Ou coloque para as informções sairem na Serial.
Me de um feedback.

preciso disso no LCD

ja enxuguei o maximo de linhas que podia, desconheço outro metodo para oque preciso

mesmo assim :

#include <LiquidCrystal.h>
LiquidCrystal lcd(8,9,4,5,6,7);
float start, finished;
float elapsed, time;
float circMetric=0.16;
float speedk;
void setup()
{
attachInterrupt(0, speedCalc, RISING);

  lcd.begin(16,2);   
  lcd.clear();
}
void speedCalc()
{
  elapsed=millis()-start;
  start=millis();
  speedk=(3600*circMetric)/elapsed;
}
void loop()
{
  lcd.setCursor(5,0);
  lcd.print(int(speedk));
  lcd.print("  km/h ");
}

não passa de 96km/h ... :roll_eyes:

Só vai passar de 96 km quando você passar de 115 km/h. Faça as contas e você vai entender.

Dica: millis() retorna um long, que não passa de um inteiro.

LegendBR:
Só vai passar de 96 km quando você passar de 115 km/h. Faça as contas e você vai entender.

Dica: millis() retorna um long, que não passa de um inteiro.

sera que se usar micros() resolve ??? nâo entendi direito

Risso:

LegendBR:
Só vai passar de 96 km quando você passar de 115 km/h. Faça as contas e você vai entender.

Dica: millis() retorna um long, que não passa de um inteiro.

sera que se usar micros() resolve ??? nâo entendi direito

Vamos lá, seu problema está na matemática da coisa. A função millis() retorna um long, que é um valor inteiro. Fazendo as contas, você vai ver que, quando a velocidade é 96 km/h, é porque se passaram 6 milissegundos entre as duas leituras (3600 * 0.16 / 6 = 96). A próxima velocidade seria quando a diferença entre as duas leituras fosse de 5 milissegundos, que daria 3600 * 0.16 / 5 = 115.2. Como a diferença nunca vai dar 5.5, por exemplo, você não vai conseguir ler as velocidades intermediárias.

A função micros() pode resolver, mas você teria 2 questões:

  • a cada 70 minutos o micros() é zerado. Isso não traria muito impacto, somente a cada 70 minutos um valor estranho iria aparecer, mas logo seria substituído;
  • o display iria mostrar valores mudando muito rapidamente, e pode ficar pouco legível, pois a cada pequena variação de velocidade, a velocidade mostrada seria diferente.

Pense no velocímetro digital de um carro. Ele se atualiza em uma frequência constante (1 vez por segundo, por exemplo), ao invés de ficar se atualizando a cada pequena variação de velocidade. O que ele faz é pegar uma velocidade média naquele intervalo de 1 segundo, e acho que assim o velocímetro fica mais legível. Vou modificar o seu código para você ver como seria esse velocímetro com valor "médio":

#include <LiquidCrystal.h>

// Atualiza a cada 1000 milissegundos. Modificar para o tempo que te agradar melhor
#define REFRESH_TIME 1000

LiquidCrystal lcd(8,9,4,5,6,7);
long lastRefresh;   // Para trabalhar com o millis(), use long, e não float.
float circMetric=0.16;
float speedk;
long loopCount;   // Contador de giros

void setup()
{
  attachInterrupt(0, speedCalc, RISING);

  lcd.begin(16,2);   
  lcd.clear();
  loopCount = 0;
  lastRefresh = millis();
  speedk = 0.0
}
void speedCalc()
{
  loopCount++;
}
void loop()
{
  
  if (millis() - lastRefresh >= REFRESH_TIME)
  {
    speedk = (3600*circMetric*loopCount)/(millis() - lastRefresh);
    loopCount = 0;
    lastRefresh = millis();
  } 

  lcd.setCursor(5,0);
  lcd.print(int(speedk));
  lcd.print("  km/h ");
}

Testa esse código e o seu substituindo o millis() pelo micros(), e fazendo o ajuste no cálculo (speedk=(3600000*circMetric)/elapsed) e vê qual resultado te agrada mais. Depois posta se funcionou ;).

LegendBR:

Risso:

LegendBR:
Só vai passar de 96 km quando você passar de 115 km/h. Faça as contas e você vai entender.

Dica: millis() retorna um long, que não passa de um inteiro.

sera que se usar micros() resolve ??? nâo entendi direito

Vamos lá, seu problema está na matemática da coisa. A função millis() retorna um long, que é um valor inteiro. Fazendo as contas, você vai ver que, quando a velocidade é 96 km/h, é porque se passaram 6 milissegundos entre as duas leituras (3600 * 0.16 / 6 = 96). A próxima velocidade seria quando a diferença entre as duas leituras fosse de 5 milissegundos, que daria 3600 * 0.16 / 5 = 115.2. Como a diferença nunca vai dar 5.5, por exemplo, você não vai conseguir ler as velocidades intermediárias.

A função micros() pode resolver, mas você teria 2 questões:

  • a cada 70 minutos o micros() é zerado. Isso não traria muito impacto, somente a cada 70 minutos um valor estranho iria aparecer, mas logo seria substituído;
  • o display iria mostrar valores mudando muito rapidamente, e pode ficar pouco legível, pois a cada pequena variação de velocidade, a velocidade mostrada seria diferente.

Pense no velocímetro digital de um carro. Ele se atualiza em uma frequência constante (1 vez por segundo, por exemplo), ao invés de ficar se atualizando a cada pequena variação de velocidade. O que ele faz é pegar uma velocidade média naquele intervalo de 1 segundo, e acho que assim o velocímetro fica mais legível. Vou modificar o seu código para você ver como seria esse velocímetro com valor "médio":

#include <LiquidCrystal.h>

// Atualiza a cada 1000 milissegundos. Modificar para o tempo que te agradar melhor
#define REFRESH_TIME 1000

LiquidCrystal lcd(8,9,4,5,6,7);
long lastRefresh;   // Para trabalhar com o millis(), use long, e não float.
float circMetric=0.16;
float speedk;
long loopCount;   // Contador de giros

void setup()
{
  attachInterrupt(0, speedCalc, RISING);

lcd.begin(16,2);   
  lcd.clear();
  loopCount = 0;
  lastRefresh = millis();
  speedk = 0.0
}
void speedCalc()
{
  loopCount++;
}
void loop()
{
 
  if (millis() - lastRefresh >= REFRESH_TIME)
  {
    speedk = (3600circMetricloopCount)/(millis() - lastRefresh);
    loopCount = 0;
    lastRefresh = millis();
  }

lcd.setCursor(5,0);
  lcd.print(int(speedk));
  lcd.print("  km/h ");
}




Testa esse código e o seu substituindo o millis() pelo micros(), e fazendo o ajuste no cálculo (speedk=(3600000*circMetric)/elapsed) e vê qual resultado te agrada mais. Depois posta se funcionou ;).

aparentemente ficou ok ... obrigado :smiley:

boa noite

Acabei de me registrar no forum,e gostaria da sua permissao pra usar o codigo do velocimetro, terminei nessa semana uma gaiola e pretendo fazer um mini computador de bordo, nao sei muito de programaçao e to apanhando qui nem gente grande.

Aguardo

Abraço

Sérgio Sgarbi

ssgarbi:
boa noite

Acabei de me registrar no forum,e gostaria da sua permissao pra usar o codigo do velocimetro, terminei nessa semana uma gaiola e pretendo fazer um mini computador de bordo, nao sei muito de programaçao e to apanhando qui nem gente grande.

Aguardo

Abraço

Sérgio Sgarbi

ok

Amigo, eu preciso de um programa com a mesma função que o seu, no entanto estou utilizando um sensor indutivo e não entendo muito de programação, mudaria muito? Teria como você mandar o esquema do seu circuito para eu dar uma olhada?

Muito obrigado

não muda nada se for 1 pulso por volta ...

so altere

float circMetric=0.16;

pela circunferencia que for usar em centimetros, no caso ai esta 16 cm

fiz o seguinte programa com arduino para fazer um velocimetro.
mais somente consegui fazer com que o arduino detecte os polos do ima. e conte a quantidade de vezes que o polo sul passou pelo ima.

estou usando um sensor que a saida dele fica em nivel alto, somente quando passa o polo sul do imã a saida vai para nivel baixo.
ou seja entao o arduino esta detectando a passagem do polo sul pelo sensor.
gostrai que alguem me ajudasse a fazer essa mediçao de velocidade.

int i=0;
int norte=13;
void setup(){

Serial.begin(9600);

pinMode(norte, INPUT);

}

void loop()
{
if(digitalRead(norte)==HIGH){
Serial.println("polo norte");
}
else if(digitalRead(norte)==LOW)
{
Serial.println("poloSul");
i++;
Serial.println(i);
}
delay(50);

}

vc esta usando um sensor Hall ????

se estiver usando um sensor Hall unipolar acontece isso mesmo

vc teria que usar um sensor Hall omnipolar para ler os 2 polos

estou utiltizando o sensor de efeito hall 277
ele tem quatro terminais dois sao alimentaçao e duas saidas.
uma das saidas a que estou utilizando ela fica em nivel alto somente com a pssagem do polo sul do imã ele vai para nivel baixo. e a outra saida e o inverso porem nao estou utilizando.

a partir desta contagem de quantas vezes a entrada foi para nivel baixo neste casso o (" i ")quero calcular a velocidade.
mais nao estou conseguindo manipular isto no arduino.
sei que vou precisar da formula de area.
e a velocidade= vai ser a quantidade de vezes que passou para o nivel baixo em 1 segundo * a area.
mais como colocar isso no programa?

ola pessoal. sou novo aqui no forum e isto é justamente o que procuro um velocimetro a baixo custo, mas gostaria que tivesse uma saida digital do tipo BCD alem da informacao no LCD. E tambem gostaria que a leitura fosse a velocidade real do veiculo e nao as leituras erroneas do velocimetro original do carro. Acho que meu carro usa sensor hall o carro eh uma ecosport 1.6 zetec rocam. Obrigado.

Que e que ja fizeste?

olá,sou novo aki no Fórum, Gostaria de uma ajuda, achei interessante o codigo do velocimetro, usei ele mas não consegui a leitura do sensor hall, como faço para definir a porta do sinal do sensor, muito obrigado.

O sensor é lido por interrupção, por isso deve ser ligado ao pino 0:

attachInterrupt(0, speedCalc, RISING);

luisilva:
O sensor é lido por interrupção, por isso deve ser ligado ao pino 0:

attachInterrupt(0, speedCalc, RISING);

Boas.
Permita discordar.
O sensor deve ser ligado no pino 2(em Arduino Uno): (#define PMS_PIN 2)

O código que fez quote (attachInterrupt(0, speedCalc, RISING):wink: refere a interrupção 0, a função a chamar, e em que tipo de actividade no pino, que é referente ao pino 2.
Podem ver AQUI o código das interrupções e a forma de as usar..

Permita discordar.
O sensor deve ser ligado no pino 2(em Arduino Uno):

Está correcto