Engine tachometer & AF Help

Hi all, I'm new here iv had the Arduino kit for about 6 months but its been sitting waiting for some time to have a play, i now have a project for it, I'm an electrical engineer and Hardware wise I'm spot on but software I'm not so hot, I'm after some advice, the eventual goal it data log rpm and a 0 to5v analogue output from a Air fuel sensor, the idea is to log to sd card rpm and Air fuel mixture say once a second or more so i can tune the engine at different rpm.

its a Harley Davidson Sportster, it has a tach output on the CDI,not sure if its 12v or 5v yet will find that out. i will then be hooking up a wideband AF controller to take those readings from the exhaust. this AV controller analogue output is ov to 5v and to calculate air fuel its voltage x 2 +10. so at 2.5v it would be a fuel/Air Ratio of 15/1

I'm looking to do this is stages so my initial goal is to build the kit up with the LCD and read RPM and get that working, once i understand how to achieve that i want to add the air fuel input and display that as well, then once iv got my head around that i will buy a sd card shield and go for data logging.

any advice where to start with this, any code would be grate.

thanks in advance

Ian

Before you get too far down this road, bear in mind that many wideband controllers can log directly to PC and that there are also many existing loggers that can capture an analog voltage to an SD card at regular intervals with other added functions such as calculating engine speed from a tach signal. If your bike provides a CANBUS then you also have a whole load of options for loggers that could take data from that. If you just want the end result, there are many options that would be easier than implementing your own logger.

With that out of the way, all the elements of your project seem entirely feasible. You would need to provide a simple electronic circuit to condition your tacho signal down to the 0 .. 5V that the Arduino can tolerate. The code to calculate the engine speed from a sequence of tacho pulses is simple and I suspect you would find several worked examples in the playground because the topic comes up quite often. I suspect you would also want to log engine load (MAP, throttle angle, Mass Air Flow or whatever is most convenient) to know which part of the map each sample relates to.

I don't know how frequently you were thinking about doing the logging, but if you're aiming for something in the 10..20Hz sort of range then I don't think performance will be a problem.

You will need to decide what format to save your results in the SD card. I'd suggest saving them in a text file in CSV format - that format can be read directly by most spreadsheet programs.

appreciate the reply, i bike open the box tonight and set it up, I'm using the 4n35 opto isolator, iv fount that their is no tach wire on the bike the the cdi fires each coil by sending it a ground pulse, so iv changed my circuit and the optoisolator is permanently live with the ground coming from the CDI for one of the 2 coils, iv got it reading rpm and at low level sub 1500 it seems about rite but when i increase it it seems to under read a lot.

below is the code iv used, any advice would be grate, was taken from the optical tach i found and changed slightly

/*

  • Optical Tachometer

*/

volatile byte rpmcount;
unsigned int rpm;
unsigned long timeold;

// include the library code:
#include <LiquidCrystal.h>
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

void rpm_fun()
{
//Each rotation, this interrupt function is run twice, so take that into consideration for
//calculating RPM
//Update count
rpmcount++;
}

void setup()
{
lcd.begin(16, 2); // intialise the LCD

//Interrupt 0 is digital pin 2, so that is where the IR detector is connected
//Triggers on FALLING (change from HIGH to LOW)
attachInterrupt(0, rpm_fun, FALLING);

rpmcount = 0;
rpm = 0;
timeold = 0;
}

void loop()
{
//Update RPM every second
delay(1000);
//Don't process interrupts during calculations
detachInterrupt(0);
//Note that this would be 60*1000/(millis() - timeold)rpmcount if the interrupt
//happened once per revolution instead of twice. Other multiples could be used
//for multi-bladed propellers or fans
rpm = 30
1000/(millis() - timeold)*rpmcount;
timeold = millis();
rpmcount = 0;

//Print out result to lcd
lcd.clear();
lcd.print("RPM=");
lcd.print(rpm);

//Restart the interrupt processing
attachInterrupt(0, rpm_fun, FALLING);
}

here is the basics of what iv done with the optocoupler, any issues ?