Help piece together working code from old thread?

Hello all, I was wondering if someone could help me piece together a cut-and-paste sketch using code from an old post (my programming skills are lacking)
This thread: http://forum.arduino.cc/index.php/topic,26678.0.html was about building a tachometer for a small engine, using an inductive sensor wrapped around the spark plug wire. I'd like to build the same thing for my scooter. If you notice later in the post, user bill2009 posted a routine that turned out to be very accurate, but I am unsure how to implement it. If someone could help out this old hillbilly, I'd be so very thankful :slight_smile:

Here's a starting point that might help:

#include <Wire.h>
#include <LiquidCrystal.h>
unsigned int rpm;
unsigned long tachTime;
LiquidCrystal lcd(12, 13, 11, 10,9,8,7);

void rpmISR() {
  static int tachcount = 0; 
  static unsigned long previousmillis;
  if (tachcount < 9) { //bulking up tach interrupts by a factor of 10
    tachcount++;
  }
  else {  //every 10th tach pulse we calculate elapsed time
    tachTime = millis() - previousmillis;
    previousmillis = millis();
    tachcount = 0;
  }
}

void setup()
{
  attachInterrupt(0, rpmISR, RISING);
  rpm = 0;
}

void loop()
{
  delay(200);   // Sample Time
  detachInterrupt(0);

  rpm = 10000UL / tachTime; // tens of pulses per tens of seconds = pulses per second
  rpm = rpm * 20;  // RPM, assuming 3 pulses per revolution: 60/3 = 20

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(int(rpm));  // print rpm

    //Restart the interrupt processing
  attachInterrupt(0, rpmISR, RISING);
}

Hey thank you very very much! I'll give this a shot and report back :slight_smile:

OK it finally quit raining long enough for me to test out the code. It works beautifully, thank you John!

Only thing is, I combined two lines to this:

  rpm = ((10000UL / tachTime)*60)*2; // tens of pulses per tens of seconds = pulses per second
  //rpm = rpm * 60;  // RPM, assuming 1 pulse per revolution: 60/1 = 60    THIS LINE COMMENTED OUT
  //NOTE - I changed the above, placing the 60 in with the math, had to multiply by 2 since
  //it was giving me half the proper RPM reading

I suck at math, but it's giving readings in multiples of 120. For instance, it will go from 1560 RPM to 1680 etc., etc. Any ideas?

On another note, I first thought this circuit used an inductive sensor by wrapping a few turns of wire around the spark plug cable. I've seen several tachs like that, but this uses a small circuit to connect the arduino's INT0 pin to the tach signal coming from the scooter. I'll draw up the schematics when I get a chance and post them, so maybe someone else will get some use out of it.

BackWoodsBrewer:
I suck at math, but it's giving readings in multiples of 120. For instance, it will go from 1560 RPM to 1680 etc., etc. Any ideas?

Try collapsing some of the constants: 10000 * 60 * 2 = 10000 * 120 = 1200000:

rpm = 1200000UL / tachTime; // tens of pulses per tens of minutes = pulses per minute

BackWoodsBrewer:
I suck at math, but it's giving readings in multiples of 120. For instance, it will go from 1560 RPM to 1680 etc., etc. Any ideas?

That's because you're deriving an integer value and then multiplying it by 120.

You could avoid that rounding by doing the multiplication first, but you will need to look at the maximum range of the intermediate value and make sure it doesn't exceed the maximum value of the data type you're using to hold it.

rpm = (60 * 2 * 10000UL) / tachTime;

Hey thanks a lot guys, I've done quite a bit of reading about Ints, long, unsigned long, etc. This project has really enlightened me to the power these little micros have. If I figure right, at 2,000 RPM my spark plug is firing around 33 times per second. And since the atmega can make counting from 0 to 10ms look like a lazy cakewalk, it's really mind blowing the power and precision these things have! Now if we could only figure out how to fit 72 hours in a day, I might find time to actually make some cool new stuff with 'em :slight_smile:

Thank you all so much for help on this project, it is working perfect now :smiley:

Here is the final code for anyone else who may find this useful:

//Graciously pieced together in this thread:
//http://forum.arduino.cc/index.php?topic=167040.0

#include <Wire.h>
#include <LiquidCrystal.h>
unsigned int rpm;
unsigned long tachTime;
LiquidCrystal lcd(12, 11, 5, 4, 3, 7);

void rpmISR() {
  static int tachcount = 0; 
  static unsigned long previousmillis;
  if (tachcount < 9) { //bulking up tach interrupts by a factor of 10
    tachcount++;
  }
  else {  //every 10th tach pulse we calculate elapsed time
    tachTime = millis() - previousmillis;
    previousmillis = millis();
    tachcount = 0;
  }
}

void setup()
{
  attachInterrupt(0, rpmISR, RISING);
  rpm = 0;
  lcd.begin(16, 2);
  lcd.setCursor(0, 0);
  lcd.print("Starting Metro");
    lcd.setCursor(0, 1);
  lcd.print("Tach....");
  delay(1000);  //Delay 1 sec for startup stabilization
}

void loop()
{ 
  delay(200);   // Sample Time, original value 200
  detachInterrupt(0);

  rpm = 1200000UL / tachTime; // tens of pulses per tens of minutes = pulses per minute
  

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(int(rpm));  // print rpm
  lcd.setCursor(13, 0);
  lcd.print("RPM");

    //Restart the interrupt processing
  attachInterrupt(0, rpmISR, RISING);
}

And the circuit for the tach signal is this (bottom one, top is a power supply, although I used an LM317 outputting 7.5v to a barrel jack to power the arduino):

The tach-in connects to the service connector on the Honda Metropolitan/Ruckus (the connector near the positive battery terminal that isn't connected to anything)
I used a pot for R2 (as suggested in original thread)

Once again, THANK YOU! - This Arduino community simply ROCKS!!!!!!

thank you very much! i came across the same thread you did earlier and thought the same thing you did. i figured id give it a go tomorrow if i couldn't find anything else tonight, then i stumbled on your thread, thank you! heads up, ill be making a tutorial on how to make this and post it on a pocket bike forum with credit and links where its due, i would ask but i dont know if you will read this. also what pin is the tach out attached too?

also what pin is the tach out attached too?

attachInterrupt(0, rpmISR, RISING);
Check here

AWOL posted a pretty nifty chart, but if you are a complete Arduino noob like me, that's digital pin 2. I actually didn't realize that until I googled "arduino pinout" or something and it clicked when I saw "INT0" :smiley:

Best of luck! Also note that you will get funky readings until the scoot is actually running (if I remember right)