Speedometer , fuel gauge

Hey, Im in the middle of creating a digital speedometer and a fuel guage for my ride using two 20*4 lcd displays, ive already incorporated a stopwatch , a tempaerature reader with it........However im not able to pick up a good speed sensor, ive tried using a reed switch and a magnet but its not sensitive at all, latrer i used the hall effect sensor AH44E which also gave me commentable values when the magnet on the wheel came very very damn close to it , but it cannot read speeds more than 10km/h....im desperately needed of some help as i have invested into this a LOT........!!

but it cannot read speeds more than 10km/h.

Seems you need a gearbox 20:1 and have two hall sensors, one on the original (for low speed) and on the "new" wheel (high speed). If the car allready contains a gearbox you might find there better places for your sensor(s) there.

i used the hall effect sensor AH44E which also gave me commentable values when the magnet on the wheel came very very darn close to it , but it cannot read speeds more than 10km/h

Actually, it can't read speeds at all. All that it does is generate a pulse when the magnet moves by. It is up to the Arduino to count the pulses and convert the number of pulses in some period of time to a speed.

If you can't do this to measure speeds greater than 10km/h, the problem is not with the sensor. It is with the code that reads the pulses and/or the code that converts the pulse counts to speeds.

Of course, we can't see that code...

I use a hall effect sensor on the tailshaft that is running 7.22 times faster than the wheels, and it work just fine. So the problem is almost certainly with your code.


Rob

Why not use a GPS receiver. You can buy a GPS-360 off eBay for about $15. You dont need the wire, just the small clear box. The GPS-360 only updates once a second so your speedometer will update once per second as well (I have read that the 2008 Honda Civic speedometer only updates twice per second) but there are receivers that update as many as ten times per second for around $60 new. The GPS-360 needs only three wires connected; one wire that connects to your 3.3v or 5v pin, one wire to ground, and one wire to a digital pin.

//My program please, ignore the big characters code.

const int inputPin = 2;
unsigned long time[4] = {
0, 0, 0, 0};
int lastButtonState = 1;
int curSpeed = 0;

#include <LiquidCrystal.h>
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
int a,b,c;
byte custchar[8][8] = {
{
B11111,
B11111,
B11111,
B00000,
B00000,
B00000,
B00000,
B00000
}, {
B00000,
B00000,
B00000,
B00000,
B00000,
B11111,
B11111,
B11111
}, {
B11111,
B11111,
B11111,
B00000,
B00000,
B11111,
B11111,
B11111
}, {
B00000,
B00000,
B00000,
B00000,
B00000,
B01110,
B01110,
B01110
}, {
B00000,
B00000,
B00000,
B01110,
B01110,
B01110,
B00000,
B00000
}, {
B00000,
B00000,
B00000,
B00000,
B00000,
B00000,
B00000,
B00000
}, {
B00000,
B00000,
B00000,
B00000,
B00000,
B00000,
B00000,
B00000
}, {
B00000,
B00000,
B00000,
B00000,
B00000,
B00000,
B00000,
B00000
}
};

byte bignums[10][2][3] = {
{
{255, 0, 255},
{255, 1, 255}
},{
{0, 255, 254},
{1, 255, 1}
},{
{2, 2, 255},
{255, 1, 1}
},{
{0, 2, 255},
{1, 1, 255}
},{
{255, 1, 255},
{254, 254, 255}
},{
{255, 2, 2},
{1, 1, 255}
},{
{255, 2, 2},
{255, 1, 255}
},{
{0, 0, 255},
{254, 255, 254}
},{
{255, 2, 255},
{255, 1, 255}
},{
{255, 2, 255},
{254, 254, 255}
}
};

void loadchars() {
lcd.command(64);
for (int i = 0; i < 8; i++)
for (int j = 0; j < 8; j++)
lcd.write(custchar*[j]);*
lcd.home();
}
void printbigchar(byte digit, byte col, byte row, byte symbol = 0) {
if (digit > 9) return;
for (int i = 0; i < 2; i++) {

  • lcd.setCursor(col, row + i);*
  • for (int j = 0; j < 3; j++) {*
    _ lcd.write(bignums[digit][j]);_
    * }*
    * lcd.write(254);*
    }
    if (symbol == 1) {
    * lcd.setCursor(col + 3, row + 1);*
    * lcd.write(3);*
    } else if (symbol == 2) {
    * lcd.setCursor(col + 3, row);*
    * lcd.write(4);*
    * lcd.setCursor(col + 3, row + 1);*
    * lcd.write(4);*
    }

lcd.setCursor(col + 4, row);
}
void setup() {
* pinMode(inputPin, INPUT);*
*digitalWrite(inputPin, HIGH); *
Serial.begin(19200);
lcd.begin(20, 4);
loadchars();
}
void loop(){
* while(true) {*
* delay(200);*

* int reading = digitalRead(inputPin);*
* unsigned long curTime = millis();*
* if (reading != lastButtonState) {*
* if (reading == 0) {*
* unsigned long curTime = millis();*
* for(int i=4; i>0; i–) {*
_ time = time[(i-1)];
* }
time[0] = curTime;
curSpeed = getSpeed();*_

a=curSpeed;
b=curSpeed/10;
c=curSpeed%10;
printbigchar(b, 0, 1);
printbigchar(c, 4, 1);

}
* lastButtonState = reading;*

* }*

* }*
}
float getSpeed() {
* float avgSpeed;*
* avgSpeed = (time[0] - time[4]); //Difference in time b/w first and fifth rev.*
* avgSpeed = (avgSpeed / 3600000); //Convert to hours*
* //Divide circumference in miles by hours, gives mph (53.38 inches per rev. times 5 revs, then converted to km)*
* avgSpeed = (0.007018528 / avgSpeed);*
* return avgSpeed;*
*} *
//radius of tyre=8.5 inches , i want the speed in KM/h…!! HELP

delay(200);

I suspect that's your problem, your code sits and does nothing for 200mS.

Plus all the floating point maths and LCD writing wouldn't help.


Rob

Yea, at 10km/hr it'll be about 488ms per rev, so a delay of 200 with all that printing/lcdwrite stuff might cause you to 'miss' one of the pulses. Once you get to 25km/hr, the time between pulses will be under 200ms, so that delay will cause you to miss pulses. I'd say at 10km/hr a delay of 200ms will cause significant errors in the calculation. I don't see the purpose of having the delay there at all. I also don't see the purpose having the while(true) there either, although I don't see it hurting anything either. void loop() already takes care of the looping, why put the while(true) there too?

Also, when you say it "cannot read speeds higher than 10km/hr", what does it do? Print inaccurate numbers, print completely bogus numbers, print nothing at all?

spark fun has the Venus GPS with SMA connector for ~50 bucks. you can get it to update 10x per second, so you can get pretty fine grained speed and location. I have yet to find anything else that can update that fast, i'm using it for my race dash and data acquisition system so i can get reasonably accurate lap timing and position.

the other thing to do is hook the speed sensor you are using to an interrupt. you can count the pulses (i;m using an interrupt for a tach input), and then simply handle the calculation based on elapsed time (say once every 250ms). that way you don;t loose pulses. There is a decent writup on tach input in this forum, and a speed sensor like you are doing is not much more than what a tach does.

can someonr please tell me more about the GPS way..........it sounds like its easier..!! But what about its code??.........Will the location affect things??

int reading = digitalRead(inputPin); unsigned long curTime = millis(); if (reading != lastButtonState) { if (reading == 0) { unsigned long curTime = millis(); for(int i=4; i>0; i--) { time = time[(i-1)]; * }* * time[0] = curTime;* * curSpeed = getSpeed();*

g=curSpeed; h=curSpeed/10; i=curSpeed%10; printbigchar(h, 0, 0); printbigchar(i, 4, 0); lcd.setCursor(8, 1); lcd.print("Km/H"); x++; * *} * lastButtonState = reading;* * }* if(x==0) {printbigchar( 0, 0, 0); lcd.setCursor(8, 1); lcd.print("Km/H"); printbigchar( 0, 4, 0); printbigchar2( 0, 0, 2); printbigchar2( 0, 4, 2, 1); lcd2.setCursor(8, 3); lcd2.print("1000 Rp/M"); }

  • }* } float getSpeed() {
  • float avgSpeed;*
  • avgSpeed = (time[0] - time[4]); //Difference in time b/w first and fifth rev.*
  • avgSpeed = (avgSpeed / 3600000); //Convert to hours*
  • //Divide circumference in miles by hours, gives mph*
  • avgSpeed = (0.007018528 / avgSpeed);*
  • //This line was for debugging, it takes away the need to convert to hours*
  • //avgSpeed = (22727.27273 / avgSpeed);*
  • return avgSpeed;* } * *This is my modified code.........What it does above 10km/h is nothing.....it just displays 10 like a constant.....!! [code][code][code][code][code][code][/code][/code][/code][/code][/code][/code]

Hi ars,

Can you edit that last post and put the code into code tages, the # button above when you're editng the post. Also check that the indenting is right. It's just too hard to read as is.


Rob

 void loop()
{
int reading = digitalRead(inputPin);
   unsigned long curTime = millis();
   if (reading != lastButtonState) {
     if (reading == 0) {
       unsigned long curTime = millis();
       for(int i=4; i>0; i--) {
         time[i] = time[(i-1)];
       }
       time[0] = curTime;
       curSpeed = getSpeed();
     

g=curSpeed;
h=curSpeed/10;
i=curSpeed%10;
printbigchar(h, 0, 0);
printbigchar(i, 4, 0);
lcd.setCursor(8, 1);
lcd.print("Km/H");
x++;            
}

     lastButtonState = reading;

   }
if(x==0)
{printbigchar( 0, 0, 0);
lcd.setCursor(8, 1);
lcd.print("Km/H");
printbigchar( 0, 4, 0);
printbigchar2( 0, 0, 2);
printbigchar2( 0, 4, 2, 1);
lcd2.setCursor(8, 3);
lcd2.print("1000 Rp/M");
}


 }





float getSpeed() {
 float avgSpeed;
 avgSpeed = (time[0] - time[4]); //Difference in time b/w first and fifth rev.
 avgSpeed = (avgSpeed / 3600000); //Convert to hours
 //Divide circumference in miles by hours, gives mph
 avgSpeed = (0.007018528 / avgSpeed);
 //This line was for debugging, it takes away the need to convert to hours
 //avgSpeed = (22727.27273 / avgSpeed);
 return avgSpeed;
}

Also check that the indenting is right.

Don't make it hard for us, I tried to suck in into a program editor and reformat but then realised I've got things I'd rather be doing :)


Rob

Can someone tell me how to display speeds to an lcd using a GPS........??

Speed = distance / time;

So you must make a location measurement L1 at time T1. Then after1 second you make another location measurement L2 than you have the basic measurements. But note that if you drive in a circle it will calculate as if there was a straight line between the points. Don't know how fast the GPS can produce lat / lon data. but here some code to get the idea.

float lat1, lon1, lat2, lon2, distance, speed;
unsigned long T1, T2;

setup()
{
  lat1 = GPS.geLat(); // don't know how its done but you get the idea
  lon1= GPS.geLon(); 
  T1 = getTime(); // could be millis() or RTC based
}

loop()
{
  T2 = getTime();
  if ((T2 - T1) > 1) 
  {
    lat2 = GPS.geLat(); // still don't know how its done ...
    lon2= GPS.geLon(); 
   
    distance = HaverSine(lat1, lon1, lat2, lon2); // See below
    speed = distance/(T2-T1)/3600; // km/h
    lat1 = lat2;
    lon1 = lon2;
    T1 = T2;
    LCD.print(speed);
  }
}

The haversine is copied from http://www.movable-type.co.uk/scripts/latlong.html which present it in javascript. Here is a transcript to Arduino.

The haversine formula 'remains particularly well-conditioned for numerical computation even at small distances'

float HaverSine(float lat1, float lon1, float lat2, float lon2)
{
  float ToRad = PI / 180.0;
  float R = 6371;   // radius earth in Km, change for other planets :)
  
  float dLat = (lat2-lat1) * ToRad;
  float dLon = (lon2-lon1) * ToRad; 
  
  float a = sin(dLat/2) * sin(dLat/2) +
        cos(lat1 * ToRad) * cos(lat2 * ToRad) * 
        sin(dLon/2) * sin(dLon/2); 
        
  float c = 2 * atan2(sqrt(a), sqrt(1-a)); 
  
  float d = R * c;
  return d;
}

From another thread, you could also use http://arduiniana.org/libraries/tinygps/ if your GPS is compatible with the tinygps library.

Thanks a lot........i got a 10 hz gps, it has 7 pins , can you please tell me the connections......!!

.i got a 10 hz gps, it has 7 pins , can you please tell me the connections......!!

I don't know your GPS type, look for the typenumber and google it together with the string datasheet. It should be all in there.