Reading a tach signal

I need to read a tachometer in signal from an ECU, one that outputs 5v pulses with a 30% duty cycle as a square wave, which is apparently the standard from what I've seen. I'm pretty sure it's a straightforward case of using a pulse counter, but I need some help with the implementation.

If the duty cycle is fixed you can just use the pulseIn() function to measure the length of the pulse. From that you can calculate everything else.

http://arduino.cc/en/Reference/PulseIn

#define MICROSECONDS_PER_MINUTE (60UL*1000000UL) 
#define PULSES_PER_REVOLUTION 128 /* You'll have to figure this out */
int rpm(int inputPin) {
    unsigned long pulseLength = pulseIn(inputPin, HIGH);  // Microseconds per pulse
    pulseLength = (pulseLength * 100) / 30;  // Convert from 30% to 100%
    unsigned long pulseRate = MICROSECONDS_PER_MINUTE / pulseLength; // Pulses per minute
    return pulseRate / PULSES_PER_REVOLUTION;
}

An alternative, which I fancy would give more accurate results at higher frequencies, is to count the number of pulses over a short interval such as a second.

What are you going to to with the RPM figure once you have it?

I'm building a semi-automatic shifter for a formula car. I'll post the full design for it once the car is in the competition. I just want to leave it semi-proprietary until it's not relevant for this season. We have an ECU that puts out a square wave signal.

edit, I forgot to actually say what I was using the value for!
I'm making a semi-automatic system, so you can queue shifts and it will wait for the RPM to be at the optimum value to shift, reducing loss of power and making shifts on curves easier.

Sounds interesting. If you can perform a gear change based on simple digital outputs then I don't see any reason why an Arduino couldn't control it. Do you have to do a power cut and synchronise the change with the fall in engine revs (like Zeroshift) or can you just slam it into the next gear?

A few years ago I used a clutch-operated rev limiter to support full throttle gear shifts but I could never convince myself to trust my engine to it so it hardly saw any use in the end. That's the problem with this sort of project - you really have to trust it, because if anything goes wrong then things could get nasty in a hurry.

chuff014:
I need to read a tachometer in signal from an ECU, one that outputs 5v pulses with a 30% duty cycle as a square wave, which is apparently the standard from what I've seen. I'm pretty sure it's a straightforward case of using a pulse counter, but I need some help with the implementation.

I kind of like using, for this kind of thing a user interrupt pin to detect the raising edge of the signal and in the interrupt ISR use either millis() or micros() to 'timestamp' the signal and set a flag with each new update, then in the main loop calculate the time between the newest reading 'timestamp' and the prior and calculate then convert the time period to RPM units and finally reset the flag.

Lefty

PeterH:
Sounds interesting. If you can perform a gear change based on simple digital outputs then I don't see any reason why an Arduino couldn't control it. Do you have to do a power cut and synchronise the change with the fall in engine revs (like Zeroshift) or can you just slam it into the next gear?

A few years ago I used a clutch-operated rev limiter to support full throttle gear shifts but I could never convince myself to trust my engine to it so it hardly saw any use in the end. That's the problem with this sort of project - you really have to trust it, because if anything goes wrong then things could get nasty in a hurry.

The system is a lot simpler, we have a transmission similar to a motorcycle's. It has a pingel speed shifter to handle the actual shift. I just have to set up the arduino to punch a couple of relays at the right moment, as well as drive a couple of dash elements. The semi-auto design I'm working on will let the driver queue shifts and then accelerate or decelerate naturally to shift.

After reading more docs on the ECU, the square wave is pulled to VBatt, which is actually 12v. I know the arduino can't handle a 12v pulse on a digital input pin, so I'll need a transistor. I don't know exactly what one, though.

edit
Actually, after reading more into it, wouldn't a voltage divider be a better solution? That wouldn't muddy my signal, would it?

A voltage divider would be fine.

Will your shift point be specific to the gear you're in i.e. taking the difference between gears into account? If not, you could simply use a shift light as a trigger and solve this problem with electrics rather than electronics.

PeterH:
A voltage divider would be fine.

Will your shift point be specific to the gear you're in i.e. taking the difference between gears into account? If not, you could simply use a shift light as a trigger and solve this problem with electrics rather than electronics.

I was planning to use a lookup table array with the optimal RPMs for each gear.

chuff014:
I was planning to use a lookup table array with the optimal RPMs for each gear.

Wouldn't you then need a way to detect which gear you were in? You could measure both engine RPM and wheel (or driveshaft) RPM to determine the current gear.

johnwasser:

chuff014:
I was planning to use a lookup table array with the optimal RPMs for each gear.

Wouldn't you then need a way to detect which gear you were in? You could measure both engine RPM and wheel (or driveshaft) RPM to determine the current gear.

I was going to go a bit simpler and have the arduino keep count from neutral.

chuff014:
I was going to go a bit simpler and have the arduino keep count from neutral.

What will you do if the Arduino triggers a shift and the revs still remain above the threshold? You will design it to avoid the possibility of missed shifts, and test it thoroughly, and it will still find a way to do something you didn't expect. If it's a sequential box it may have a selector barrel which you can get a position sense from.

PeterH:

chuff014:
I was going to go a bit simpler and have the arduino keep count from neutral.

What will you do if the Arduino triggers a shift and the revs still remain above the threshold? You will design it to avoid the possibility of missed shifts, and test it thoroughly, and it will still find a way to do something you didn't expect. If it's a sequential box it may have a selector barrel which you can get a position sense from.

It only shifts as many gears as it's told to. I'm not sure I follow you.
I can see if there's a barrel.

chuff014:
I'm not sure I follow you.

I mean that your Arduino sketch sends the output that is intended to perform a gear shift, and for whatever reason it doesn't manage to perform the shift, or doesn't shift at all, or there's an electrical glitch and what you thought was one pulse ended being broken into two pulses and you shift two gears. Without any feedback at all, your sketch has no idea whether that pulse actually engaged the next gear; you could be left in the original gear, or neutral, or somewhere else. You can design and test all you want, but Sod's law is inescapable.

PeterH:

chuff014:
I'm not sure I follow you.

I mean that your Arduino sketch sends the output that is intended to perform a gear shift, and for whatever reason it doesn't manage to perform the shift, or doesn't shift at all, or there's an electrical glitch and what you thought was one pulse ended being broken into two pulses and you shift two gears. Without any feedback at all, your sketch has no idea whether that pulse actually engaged the next gear; you could be left in the original gear, or neutral, or somewhere else. You can design and test all you want, but Sod's law is inescapable.

That is true. I don't think the system will be able to fail in that respect though. The Pingel shifter is pretty reliable.