Help Required - Frequency Calculation

I am new to the Arduino Programming Enviroment and I am trying to impliment a gear shift indicator for a Formula Student Race Car.

My idea is to measure the frequency of the wheel rotating and the frequency of the engine rotating and then using the pre known gear ratios have the arduino calculate which gear the car is in and display it on the dash as a series of LED lights (one for each gear).

I thought of using the internal timer to time a pre defined period and to count how many revolutions of both engine and wheel occour within that alloted time, thus giving the RPM’s of both and then impliment a look up table which will compare the ratio calulated to the pre defined ratios given for each gear.

The problem I have is that I dont know how to program this.

Any assistance would be great.

Thanks

Mark

There are both hardware and software issues here. Do you have the hardware? Is it installed? Does it work? How do you know it works?

With two devices sending signals, and two external interrupts available, you could, in each interrupt, increment a counter. The interrupt would be generated by the wheel and engine sensors detecting rotation.

The Arduino would simply check the values of this variables on a regular basis, using millis() to determine how much time has elapsed. Each time millis() determines that enough time (you define what that means) has elapsed, it would reset the counters, compute the RPM of each (which is just a matter of scaling based on the ratio of "enough time" and one minute), and comparing some ranges of values.

You haven't defined what the Arduino should then do with that information. Kill the engine if the ratio is out-of-whack? Shock the driver? Blare an alarm? Light an LED?

"The rest of you get busy coding while I figure out what the requirements are."

" My idea is to measure the frequency of the wheel rotating and the frequency of the engine rotating and then using the pre known gear ratios have the arduino calculate which gear the car is in and display it on the dash as a series of LED lights (one for each gear). "

The implimentation uses Hall Effect Sensors to sense magnets placed on the engines flywheel and of the brake disk of a front wheel, this sends a pulse everytime the sensor senses the magnet.

The implimentation uses Hall Effect Sensors to sense magnets placed on the engines flywheel and of the brake disk of a front wheel, this sends a pulse everytime the sensor senses the magnet.

And you are able to read this pulse with the Arduino?

yes it can be interfaced to the analog inputs or with a simple op amp operating as a comparator (with no feedback) to a digital input

yes it can be interfaced to the analog inputs

Analog?

If you are able to read the two sensors with the Arduino, what is it you need help with?

The actual code to calulate the frequencies of the pulses and in turn the code to decide which gear the engine is in.

The actual code to calulate the frequencies of the pulses and in turn the code to decide which gear the engine is in.

Let's see the code you have now.

If you are counting pulses, it should be nearly trivial to add code to reset the counters on a regular basis.

The last value of the counter, before reset, in a given period of time can be used, then, to calculate RPM.

Once you know RPM of the wheel and RPM of the engine, computing gear ratio is simple. Divide one number by the other. The value will not be exact, since there is no way for you to account for wheel slippage or clutch slippage.

The actual value will be close enough to one of the n stored values (one for each gear) to determine with some degree of accuracy which gear the car is in.

What do you want to do with that information?

Here is the code i have got so far:

int wheel = 2;
int engine = 3;
int wheel_count = 0;
int engine_count = 0;
int ratio = 0;
extern volatile unsigned long timer0_overflow_count;

void setup()
{
  Serial.begin(9600);
}
void loop()
{
  if (timer0_overflow_count < 1000)
  {
    if (wheel == 1)
    {
      wheel_count ++;
    }
  }
  timer0_overflow_count = 0;
  
  if (timer0_overflow_count < 1000)
  {
    if (engine == 1)
    {
      engine_count ++;
    }
  }
  timer0_overflow_count = 0;
  
  ratio = engine_count/wheel_count
 
}

if (wheel == 1)

"wheel" is assigned the value 2. How can it ever be 1?

Did you miss out a pin assignment?

int wheel = 2;
int engine = 3;

Not sure what these mean, but, OK.

int wheel_count = 0;
int engine_count = 0;

Explicit initialization is good.

if (wheel == 1)
{
wheel_count ++;
}

wheel isn’t 1, so wheel_count is not incremented.

  timer0_overflow_count = 0;
  
  if (timer0_overflow_count < 1000)

This test hardly seems necessary…

    if (engine == 1)
    {
      engine_count ++;
    }

engine isn’t one, so engine_count is not incremented.

  ratio = engine_count/wheel_count

Division by 0 is not usually a good thing.

When does timer0_overflow_count change? Where are the sensors connected?

yes i missed the signal assignments out

Is this any better;

int wheel = 2;
int engine = 3;
int wheel_count = 0;
int engine_count = 0;
int ratio = 0;
extern volatile unsigned long timer0_overflow_count;

void setup()
{
  pinMode(wheel, INPUT);
  pinMode(engine, INPUT);
  Serial.begin(9600);
}
void loop()
{
  if (timer0_overflow_count < 1000)
  {
    if (wheel == 1)
    {
      wheel_count ++;
    }
  }
  timer0_overflow_count = 0;
  
  if (timer0_overflow_count < 1000)
  {
    if (engine == 1)
    {
      engine_count ++;
    }
  }
  timer0_overflow_count = 0;
  
  ratio = engine_count/wheel_count;
  
  Serial.println(ratio);
 
}

timer0_overflow_count is the internal timer/counter that incriments on its own isnt it?

Is this any better;

int wheel = 2;
if (wheel == 1)

No. You missed out the digitalRead.

oh yes, sorry my mistake!

I think this should work?

int wheel = 2;
int engine = 3;
int wheel_count = 0;
int engine_count = 0;
int ratio = 0;
extern volatile unsigned long timer0_overflow_count;

void setup()
{
  pinMode(wheel, INPUT);
  pinMode(engine, INPUT);
  Serial.begin(9600);
}
void loop()
{
  if (timer0_overflow_count < 1000)
  {
    if (digitalRead(wheel) == 1)
    {
      wheel_count ++;
    }
  }
  timer0_overflow_count = 0;
  
  if (timer0_overflow_count < 1000)
  {
    if (digitalRead(engine) == 1)
    {
      engine_count ++;
    }
  }
  timer0_overflow_count = 0;
  
  ratio = engine_count/wheel_count;
  
  Serial.println(ratio);
 
}

It may work, but when you do your "Serial.println", your sensor is going to be "blind" for the time it takes to transmit the string, which may be several milliseconds each time through "loop" (one character takes 1040us @ 9600bps) This may affect your results.

Have look at using interrupts for your sensors if you're going to carry on using Serial. (have a look at interrupts anyway ;)

In Portugal the engines used in those cars are from Gsxr's, R6's, Cbr's 600 and the like and those engines already have a gear indicator sensor, just connect it to the adc and measure, as each gear as a specific resistance.

Interesting, we are using a CBR600 RR-8 engine and if so will save me a lot of work

Just rang a honda dealer up and spoke with a technician there and there is not a sensor like that on our engine so the problem is still unsolved.

I have just implimented the code and it does not seem to be working.

AWOL mentioned interupts, how could i use them to improve the code?