Pages: [1]   Go Down
Author Topic: Bike Speedometer  (Read 1964 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 14
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I am testing code for a bike speedometer (using a reed switch and magnet on the wheel).  The problem is, the code returns a speed that is always higher than the actual speed.  Right now I have it set up with a button acting as the reed switch, and with an estimate of an 80in wheel circumference.  I calculated that the speed at one revolution per second should be 4.56 mph:
80 inches / 63360 inches = .0012626 miles, the circumference in miles
1 second / 3600 seconds = .000277 hours, the time for one revolution
.0012626 miles / .000277 hours = 4.558 mph, the speed at 1 rps
I have modified the code to automatically act as if the wheel is turning at one revolution per second, and it returns 5.6mph, the same result as when I simply press the button once per second.  I have noticed that when the revolutions per second are doubled, so is the difference between the theoretical speed and the speed returned by the code.
Here's the code, both the original and the code modified for 1 rps:
Code:
const int inputPin = 8;
unsigned long time[5] = {
  0, 0, 0, 0, 0};
int lastButtonState = LOW;
float curSpeed = 0;

void setup() {
  pinMode(inputPin, INPUT);
  Serial.begin(19200);
}

void loop(){
    int reading = digitalRead(inputPin);
    if (reading != lastButtonState) {
      if (reading == HIGH) {
        unsigned long curTime = millis();
        for(int i=4; i>0; i--) {
          time[i] = time[(i-1)];
        }
        time[0] = curTime;
        curSpeed = getSpeed();
        Serial.println(curSpeed);
      }
      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 (80 inches per rev. times 5 revs, then converted to miles)
  avgSpeed = (.006313131313131313131313 / avgSpeed);
  //This line was for debugging, it takes away the need to convert to hours
  //avgSpeed = (22727.27273 / avgSpeed);
  return avgSpeed;
}
Modified:
Code:
const int inputPin = 8;
unsigned long time[5] = {
  0, 0, 0, 0, 0};
int lastButtonState = LOW;
float curSpeed = 0;

void setup() {
  pinMode(inputPin, INPUT);
  Serial.begin(19200);
}

void loop(){
  while(true) {
    delay(1000);
    int reading = HIGH;
    //int reading = digitalRead(inputPin);
    //unsigned long curTime = millis();
    if (reading != lastButtonState) {
      if (reading == HIGH) {
        unsigned long curTime = millis();
        for(int i=4; i>0; i--) {
          time[i] = time[(i-1)];
        }
        time[0] = curTime;
        curSpeed = getSpeed();
        Serial.println(curSpeed);
      }
      //lastButtonState = reading;
      reading = LOW;
    }
  }
}

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 (80 inches per rev. times 5 revs, then converted to miles)
  avgSpeed = (.006313131313131313131313 / avgSpeed);
  //This line was for debugging, it takes away the need to convert to hours
  //avgSpeed = (22727.27273 / avgSpeed);
  return avgSpeed;
}
What is the cause of this difference between theoretical speed and the speed returned by the code?
« Last Edit: November 09, 2009, 11:54:15 am by Ayelix » Logged

Left Coast, CA (USA)
Offline Offline
Brattain Member
*****
Karma: 361
Posts: 17294
Measurement changes behavior
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Could be the result of contact bounce from the magnetic reed switch. Why don't you try some debouncing either in software of with external filtering and see if that helps. There is stuff about debouncing switches in the Arduion playground site.

Lefty
Logged

Gothenburg, Sweden
Offline Offline
Jr. Member
**
Karma: 0
Posts: 87
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

From time[0] to time[4] there is 4 revolutions not 5.

Also I would suggest a Hall effect switch as a sensor, they should last longer than the reed contact element.
Logged

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

Quote
From time[0] to time[4] there is 4 revolutions not 5.

Thanks, this fixed it!  At least within reasonable bounds (.05 mph)
Logged

Pages: [1]   Go Up
Jump to: