RPM based switch

Hi everyone,

I am attempting my first Arduino project and would like some advice/help. I'm new to Arduino and have bought myself a Uno R3 to start. I have two years worth of an Electrical and Electronics Engineering degree under my belt so I have experience with C programming, ATMega MCUs and fundamental electronics.

My project is to build an RPM based camshaft profile switch for the SR20VE engine in my car which utilises the Nissan NEOVVL system which is similar to Honda's VTEC system. From factory the intake and exhaust camshaft profiles are switched independently at certain RPM values by a pair of 12V solenoids. What I want to be able to do is make these switching points adjustable so I could have the cams switching simultaneously or at my own chosen RPM values.

My main concern at this point is figuring out how to read the 5V variable frequency square wave signal that is used by the ECU into the Arduino and convert this into a regular RPM value (this would make it a lot easier to change the switching points in the code) with the possibility of adding an LCD display later on.

I then need to figure out how to use these RPM values to control the activation of the solenoids (conditionals?).

Any help or advice would be greatly appreciated.

jevans:
My main concern at this point is figuring out how to read the 5V variable frequency square wave signal that is used by the ECU into the Arduino and convert this into a regular RPM value

Do you know the range of frequencies?

You can use a RISING interrupt to capture the value of micros() or millis()

Assuming you have attachInterrupt(0, myISR, RISING); in setup() the ISR code would be as simple as

void myISR() {
   newMicros = micros();
}

and then the body of your code can subtract the previous reading from the new one in order to know the time between rising pulses

After that it is simple maths.

...R

Robin2:
the ISR code would be as simple as

void myISR() {

newMicros = micros();
}

You could even do the simple maths in your ISR along the lines of

volatile unsigned long oldMicros;
volatile unsigned int RPM;

void myISR() {
unsigned long newMicros = micros();

RPM = 60000000ul/(newMicros - oldMicros);
oldMicros=newMicros;
}

The slight problem this creates is that it only updates RPM when it actually gets called. As a result, when the engine is actually static, it may still have a residual figure in RPM that will never get changed to zero.

To overcome this, you could have a check in the loop along the lines of

if ( (micros() - oldMicros) > 500000 )
  RPM=0;

If you're not actually displaying the RPM though, even this check could be unnecessary.

KenF:
You could even do the simple maths in your ISR along the lines of

Why ? ?

Doesn't improve the result.

...R

Robin2:
Why ? ?

Doesn’t improve the result.

It’s just an option. It keeps all of the functionality responsible for the calculation in one place. (which is kind of neat). It’s not necessarily an improvement, just an alternative.

Robin2:
Do you know the range of frequencies?

You can use a RISING interrupt to capture the value of micros() or millis()

Assuming you have attachInterrupt(0, myISR, RISING); in setup() the ISR code would be as simple as

void myISR() {

newMicros = micros();
}



and then the body of your code can subtract the previous reading from the new one in order to know the time between rising pulses

After that it is simple maths.

...R

The frequency range would be 0 (0 rpm) to ~570Hz (~8500 rpm) although it wouldn't be below 50Hz (750 rpm) much as this is the idle rpm so realistically the range is 50-570Hz.

I was thinking an ISR was the way to approach this, I'll start getting my code together and see what I can do, I need to look at the signal more closely to see how clean it will be, I might need to design a LP filter and also some protection circuitry as I'm not sure how the signal behaves when the car starts.

Greensprings:
Freematics OBD-II Adapter for Arduino | ArduinoDev.com

can you interface with onboard diagnostic computer?

Not an option, the car/engine uses Nissan's Consult system which is Nissan's proprietary diagnostics system.

KenF:
You could even do the simple maths in your ISR along the lines of

volatile unsigned long oldMicros;

volatile unsigned int RPM;

void myISR() {
unsigned long newMicros = micros();

RPM = 60000000ul/(newMicros - oldMicros);
oldMicros=newMicros;
}



The slight problem this creates is that it only updates RPM when it actually gets called. As a result, when the engine is actually static, it may still have a residual figure in RPM that will never get changed to zero.

To overcome this, you could have a check in the loop along the lines of



if ( (micros() - oldMicros) > 500000 )
  RPM=0;





If you're not actually displaying the RPM though, even this check could be unnecessary.

This definitely tidies it up, as I said above I need to investigate the nature of the signal in these sort of conditions to see what would be the best approach.

From what i have read about NEO VVL and VTEC, it appears that the engine speed at which the camshaft is shifted depends upon factors such as engine oil pressure, engine temperature, vehicle speed, and throttle position, as well as engine speed.

How are you going to take all these other parameters into account?

Do you really think you can make a better decision when to make the change, than the manufacturer who has spent millions of $/€/£/¥ in research and development?

If you’re expecting a maximum RPM of 8500, that equates to 141 Revs per second (not sure where you got 570Hz from).

Therefore you’d expect your pulses to be over 7000 microseconds apart. Therefore you could use this to your advantage in your ISR to debounce your input. Something like this.

void myISR() {
unsigned long newMicros = micros();

//ignore the bounce
if ((newMicros - oldMicros) < 5000)
  return;

RPM = 60000000ul/(newMicros - oldMicros);
oldMicros=newMicros;
}

JohnLincoln:
Do you really think you can make a better decision when to make the change, than the manufacturer who has spent millions of $/€/£/¥ in research and development?

It’s not about “better” it’s about different. When it comes to engine performance, manufacturers have to settle on compromises. Fuel economy v acceleration? Short term performance v engine life? etc… It’s not uncommon for the driver to have a different idea about which compromises should be implemented.

I'm assuming (Given your max frequency of 570Hz) you're looking at using the 4 gap lo-res signal from the Nissan CAS (Not the 360 gap hi-res one)? From memory those are in the distributor aren't they? If that's the case then it's actually half that frequency as you only get 2 gaps per crank revolution.

The Nissan optical sensor signal is pretty clean, so even at cranking you shouldn't have too many problems as long as your shielding is reasonable. Having a tach rejection period (essentially a low pass filter) set at say 9000rpm isn't a bad idea though.

Even 570Hz (Though 285Hz is probably right) is pretty low resolution, so you should be fine, but I'd recommend pulling as much of the calculation out of the ISR as possible. Have it done in the main loop to keep the ISR time to a minimum.

Feel free to PM me if you want, I've tested quite a few CAS with arduinos and have had them syncing no problems.

JohnLincoln:
From what i have read about NEO VVL and VTEC, it appears that the engine speed at which the camshaft is shifted depends upon factors such as engine oil pressure, engine temperature, vehicle speed, and throttle position, as well as engine speed.

How are you going to take all these other parameters into account?

Do you really think you can make a better decision when to make the change, than the manufacturer who has spent millions of $/€/£/¥ in research and development?

From my hands on experience, it is completely RPM based, when the ECU rpm signal reaches the required switching RPM, a ground is applied to the solenoid. It is not dependent on any of your other listed factors.
The idea in me developing a way to change the switching points comes from a tuning point of view, changing where the cams switch changes the entire torque/power profile of the engine and hence the driveability of the car. The engine was paired with a CVT transmission from factory and was designed to be an economy engine, it just so happens to be an excellent 2L performance engine platform hence my need.

KenF:
If you’re expecting a maximum RPM of 8500, that equates to 141 Revs per second (not sure where you got 570Hz from).

Therefore you’d expect your pulses to be over 7000 microseconds apart. Therefore you could use this to your advantage in your ISR to debounce your input. Something like this.

void myISR() {

unsigned long newMicros = micros();

//ignore the bounce
if ((newMicros - oldMicros) < 5000)
  return;

RPM = 60000000ul/(newMicros - oldMicros);
oldMicros=newMicros;
}



It's not about "better" it's about different. When it comes to engine performance, manufacturers have to settle on compromises. Fuel economy v acceleration? Short term performance v engine life? etc.. It's not uncommon for the driver to have a different idea about which compromises should be implemented.

I did 8500rpm * 4 pulses per revolution / 60 which I now realize should be 2 pulses per revolution and get the frequency as obtained by noisymime.

noisymime:
I’m assuming (Given your max frequency of 570Hz) you’re looking at using the 4 gap lo-res signal from the Nissan CAS (Not the 360 gap hi-res one)? From memory those are in the distributor aren’t they? If that’s the case then it’s actually half that frequency as you only get 2 gaps per crank revolution.

The Nissan optical sensor signal is pretty clean, so even at cranking you shouldn’t have too many problems as long as your shielding is reasonable. Having a tach rejection period (essentially a low pass filter) set at say 9000rpm isn’t a bad idea though.

Even 570Hz (Though 285Hz is probably right) is pretty low resolution, so you should be fine, but I’d recommend pulling as much of the calculation out of the ISR as possible. Have it done in the main loop to keep the ISR time to a minimum.

Feel free to PM me if you want, I’ve tested quite a few CAS with arduinos and have had them syncing no problems.

Yes it is in the distributor and yes you’re right about the frequency. Sounds like you’ve got experience with what I fundamentally want to do so I’ll definitely let you know if I have any issues.

when the ECU rpm signal reaches the required switching RPM, ...... It is not dependent on engine speed

This is a very illogical statement.

...R

Robin2:
This is a very illogical statement.

…R

Oh wow that really is an error on my part, when I read that I was thinking speed of the vehicle…corrected.