Motorbike Speedometer

Hi there,

I am putting a new set of wheels on my motorbike that used to have a cable speedodrive driving a rotary encoder. The rotary encoder had 50% covered and 50% uncovered with four slots in it. This board sent 50% duty cycle square wave to the bikes LCD display e.g. 100km/h was 150Hz. I have tested putting in 50% duty cycle at 5v and varying the frequency and this alters the speed. Now I'd like to create an Arduino solution to read the frequency from either an inductive sensor, hall effect sensor, or a reed switch. I would like to multiply the frequency from any of these sensors by 10 because this is the correct ratio for the wheels I have. In short, I need to read frequency between ranges of approximately 1Hz and 20Hz and output accordingly to 10Hz and 200Hz. Lower ranges would be nice if possible. If someone could give me an example of some code that can (accurately as possible) read frequencies between that range that would be amazing!

Regards,
Will

Hi,

Here is a thread thread that might help you get started.
I ran a search in the forum with the keyword "tachometer" and several posts which might be of interest and useful to you to put together your code did come up...

If you have issues with your code, post it using the instructions provided here and people will be able to review your code and provide suggestions or fixes.

Don't forget to provide indications as to which pin(s) you are using and which hardware you are using as well (UNO ? ATMEGA328P , etc).

Thanks

dan

I made a "simple" interface for an automotive speedometer that uses a variable reluctance sensor(permanent magnet generator). The sensor outputs an analog sine wave so I built a full wave rectifier connected to a 2n2222 transistor then to Mega 2560(with current limiting resistors inline). The code below doesn't use any interrupts which was a requirement for me(don't ask why just accept it).

It works using "pulseIn" counting the low time between pulses, combined with things like feet per mile, pulses per tire revolution, tire rolling circumference, a few other items and a scalar. Now, with some smoothing/averageing, the code is pretty darn accurate according to the speeo in my truck. You're welcome to try it if it will work for you.

//VEHICLE SPEED SENSOR INTERFACE CODE 
//AUTOTCU(c) 2014,2015 BRIGHTSPARK ELECTRONICS
//Bwallace 2015


#include <Wire.h>  // Comes with Arduino IDE
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address

#define DIV 120
#define FPM 5280
#define TIME 1000
const float TIRCIR = 7.56;
const float PPR = 123.2;
unsigned int vsspulse = 0;
const byte vssIn = 4;
double time1 = 0.001;
const int numReadings = 30;
int readings[numReadings];      // the readings from the input
int index = 0;                  // the index of the current reading
int total = 0;                  // the running total
int average = 0;                // the average
float scalar1 = 1.70;        //error correction scalar 
void vss()
{
  // tone(4,2000);
  unsigned int vsspulse = pulseIn(vssIn, LOW);
  float vssval = (vsspulse * time1) ;
  byte MPH = ((1 / vssval) / time1 * 2 / FPM * TIRCIR / PPR * DIV * 4 * scalar1 );
  // subtract the last reading:
  total= total - readings[index];         
  // read from the sensor:  
  readings[index] = MPH; 
  // add the reading to the total:
  total= total + readings[index];       
  // advance to the next position in the array:  
  index = index + 1;                    
  // if we're at the end of the array...
  if (index >= numReadings)              
    // ...wrap around to the beginning: 
    index = 0;                           
  // calculate the average:
  average = total / numReadings;         
  // send it to the computer as ASCII digits
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Veh MPH  = ");
  lcd.setCursor(12,0);
  lcd.print(average);
  lcd.setCursor(0,1);
  lcd.print("Pulse in = ");
  lcd.setCursor(12,1);
  lcd.print(vsspulse);
  lcd.setCursor(0,2);
  lcd.print("vssval   = ");
  lcd.setCursor(12,2);
  lcd.print(vssval);
  lcd.setCursor(0,3);
  lcd.print("Average  = ");
  lcd.setCursor(12,3);
  lcd.print(MPH);
  delay(100);
}

void setup()
{
  // Serial.begin(115200);
  lcd.begin(20,4);   // initialize the lcd for 20 chars 4 lines, turn on backlight
  lcd.backlight(); // finish with backlight on  
  pinMode(vssIn, INPUT_PULLUP);
  lcd.clear();
 
  for (int thisReading = 0; thisReading < numReadings; thisReading++)
    readings[thisReading] = 0;   
}
void loop()
{
  vss();
}

If you can get away with a lower "numberofReadings[]" it will speed up the refresh rate especially on deceleration. With a numbofreading of 30 i get a little wonky 2-3 MPH fluctuation but below that it is pretty stable and can use a lower number of readings if you dont get to 70MPH often.

The PPR, is pulse per tire revolution. My reluctor/tone ring has 40 teeth and truck has a gear ratio pf 3.08:1 so 40 * 3.08 = 123.2. Since your bike is likely 1:1 at the axle, just use the number of readings you will get per tire rev(i.e. if you have a 50/50 wheel shutter, your PPR should be 1).

The TIRCIR is the rolling feet of your tire. How many feet does your tire travel in one revolution? You can convert to your desired unit of measure but you will have to change the FPM as well.

It works, I've used it, here it is.

Bill