Reading waves from ignition wire on ECU

Hey everyone

I have been studying how to bring what I would like to do into reality, and in theory it sounds straightforward, however the Arduino just isn't responding how I think it should.

What I'm Trying To Do:
I have a row of Adafruit Neo Pixel LED's that I am attempting to use as a shift light for my car, with the LED's lighting up different ways as the Arduino interperts vehicle RPM's. I have gotten this to successfuly work using an OBD-II board but I would like to remove the OBD-II part for various reasons.

Instead, I would like to use the car's electrical system and use the Arduino as an interpreter. I have successfuly tracked down a wire (IGT) from the car's ECU that is used to command an ignition coil (engine is coil-on-plug).

Basically, I would just like to have an "RPM" integer that changes number depending on revs, that I can then use to change LED modes.

The Issue(s):
When the engine is turned on, my oscilloscope - connected to ground and the ignition coil wire - appears to show a perfectly clean waveform that increased in frequency with revs, as expected. A video of this is attachedThe problem I'm having, is that the Arduino just doesn't seem to acknowledge this waveform at all. With the Arduino's GRD to the chassis' ground, and IGT is connected to an analogue pin, when outputting the ADC sensor value to serial, it just hovers around 0-3 contiuously (0.005-0.015v) and doesn't seem to respond to changes in RPM. The oscilloscope shows, if i'm interpreting it correctly, that the ignition pulses are of about 0.55v, or 550mv which by my maths should show about 113 on the ADC sensor value?

Similarly, when IGT is attached to a Digital pin, interrupts using either Rising or Falling and pulsein() produce garbage results that do not correspond to RPM at all.

I have considered the possibility that perhaps because the signal is rising and subsequently falling so fast, that perhaps the Arduino can't detect any change, but this seems unlikely to me - would a capacitor help in this regard to maybe lengthen the pulses for a more-squared waveform? To give the arduino a greater "chance" of seeing the pulses?

I'm kind of stumped at this point and don't know how to proceed. I can see the DC voltage increase with revs on my multimeter... I can see the waves clearly increase in frequency with my oscilloscope, with little to no distortion or noise.... but the Arduino just doesn't want to play ball.

Any help on how to proceed would be greatly appreciated, thanks in advance.

Video of oscilloscope: https://photos.app.goo.gl/cvYJKjU7Vx534rqk6

0.5 volt for the IGT signal sounds a bit low. Is the scope probe set to x10 giving a reading 10 times lower than it actually is?

The duty cycle of the square wave is probably in the region of 1% which means 99% of your ADC readings are going to be close to zero. Add some logic that only prints out values when they are above a particular threshold.

Using an A2D input to read a digital signal is the wrong approach, use a digital input. If the waveform is as clean as you say then the Arduino should read it without a problem. Make sure you correctly know the voltage, I agree with mikb55, 0V5 seems very low and unlikely to be correct.

Thanks for the replies guys.

mikb55:
0.5 volt for the IGT signal sounds a bit low. Is the scope probe set to x10 giving a reading 10 times lower than it actually is?

The duty cycle of the square wave is probably in the region of 1% which means 99% of your ADC readings are going to be close to zero. Add some logic that only prints out values when they are above a particular threshold.

I'm not entirely sure about the true voltage, the oscilloscope shoes the wave having just over two divisions between the base and peak, when in 0.2v/div resolution, so I don't have much else to go on, frankly. The multimeter also shows around this voltage.

If the digital input should work correctly, perhaps its my coding that is the issue? Im out at the moment but when I get the chance I'll post the code I used when connecting IGT to a digital pin.

I'm not entirely sure about the true voltage, the oscilloscope shoes the wave having just over two divisions between the base and peak, when in 0.2v/div resolution, so I don't have much else to go on, frankly. The multimeter also shows around this voltage.

A mulitmeter is not the correct tool for measuring the voltage of a pulsed waveform, it will show the average voltage, not the peak.

Connect your oscilloscope probe to a known DC voltage, a battery for example, to understand the scale you are using.

Hi,
What is IGT?
Where in the car are you getting this signal?

Can you tell us your electronics, programming, arduino, hardware experience?

Tom... :slight_smile:

Reads like you want to count pulses being sent out by the car’s ECU and then divide those pulses by the number of cylinders of the engine to get RPM’s.

There will be a sample circuit that should isolate the pulses from the ECU, to the engine, to the micro controller. I’d consider using an opto-isolated circuit using a high speed opto-isolator module. There are many choices for a high speed opto-isolated modules, use the words “high speed opto-isolator” to search the internet for some info/research to find the model that fits your requirements.

Then you’ll want the uController to count pulses. When I used an Arduino Uno, I ran across a library for counting frequency, worked real well and could be modified to operate a string of LED’s or what ever.

Now for the shameless plug. ESP32.

The ESP32 has an on board Pulse Counter

The PCNT (Pulse Counter) module is designed to count the number of rising and/or falling edges of an input signal. Each pulse counter unit has a 16-bit signed counter register and two channels that can be configured to either increment or decrement the counter. Each channel has a signal input that accepts signal edges to be detected, as well as a control input that can be used to enable or disable the signal input. The inputs have optional filters that can be used to discard unwanted glitches in the signal.

The PCNT is accessed though the ESP32 PCNT API.
https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/pcnt.html
The PCNT is a on board module that does not use CPU time to take its measurements.

PerryBebbington:
A mulitmeter is not the correct tool for measuring the voltage of a pulsed waveform, it will show the average voltage, not the peak.

Connect your oscilloscope probe to a known DC voltage, a battery for example, to understand the scale you are using.

Good idea thanks, I'll try that.

TomGeorge:
Hi,
What is IGT?
Where in the car are you getting this signal?
Can you tell us your electronics, programming, arduino, hardware experience?
Tom... :slight_smile:

IGT is my shorthand for a wire that is coming directly of the engine computer, it's actually labled IGT4 in the diagram as it controls the spark for cylinder #4. It leads to a loom in the engine compartment and its following wire leads to the ignition coil on top of the spark plug inside cylinder #4.

I am entirely a hobbyist - no professional experience - I have been primarly tinkering with automotive electrical systems, mainly 12v DC currents. Mostly with lighting, audio systems etc. Only other Arduino projects I have done is the aformentioned shift light, an Arduino Nano connected to an Adafruit NeoPixel LED Strip and talking over its serial bus to a OBD-II UART interpreter board via ELM327 commands. Its a lot simpler than it sounds. It also has a solid-state relay connected to the lights of the car, that triggers a HIGH or LOW state in the arduino, for dimming the LEDS when the headlights are on at night.
The other project is in the same car, I connected a wire from the engine's Oil Temperature sensor to an arduino Uno R3. The arduino reads the voltage from the temperature sensor, which scales logarithmically with temperature, converts it into degrees centigrade and displays the output on a 128x32 OLED display. I eventually plan to connect the OBD-II UART board to the Uno R3 so I can display other data such as coolant temperature, oxygen sensor voltage (lambda), amongst other paramaters on the screen as well. I can only have one OBD-II device plugged in at once, so I am seeking an alternative method for implementing the shift light. The shift light, using OBD-II, also has a built-in delay, to give the board time to communicate with the OBD-II bus and the Arduino and therefore also isn't ideal.

Idahowalker:
Reads like you want to count pulses being sent out by the car's ECU and then divide those pulses by the number of cylinders of the engine to get RPM's.

Pretty much, yeah. I haven't thought about the maths yet as I'm just doing the first step and trying to get the arduino to be able to even see the pulses at this stage. I'll probably end up coming back to this thread or making another one when I get around to that stage lol.

There will be a sample circuit that should isolate the pulses from the ECU, to the engine, to the micro controller. I'd consider using an opto-isolated circuit using a high speed opto-isolator module. There are many choices for a high speed opto-isolated modules, use the words "high speed opto-isolator" to search the internet for some info/research to find the model that fits your requirements.

Thank you, I'll definitely do that.

Then you'll want the uController to count pulses. When I used an Arduino Uno, I ran across a library for counting frequency, worked real well and could be modified to operate a string of LED's or what ever.

Now for the shameless plug. ESP32.

The ESP32 has an on board Pulse Counter
The PCNT is accessed though the ESP32 PCNT API.
Pulse Counter - ESP32 - — ESP-IDF Programming Guide latest documentation
The PCNT is a on board module that does not use CPU time to take its measurements.

That's fascinating, thank you for that. I'm assuming this is a module that can communicate with an Arduino or does it work stand-alone?

Right, so today I attempted to find out the proper voltage of the IGT wire, by putting the oscilloscope onto another voltage source. I tried at the battery terminals, and it showed about 1.2 volts.. I then tried on a 9v battery and it showed less than a volt..After taking the unit apart, calibrating it (which turns out had not been done from factory so not a complete waste of time lol) I then happened to see that the probe has a 1x and 10x setting... guess which one it was on? yep.. .10x.. There is literally no mention of this in the instruction manual.. anyway, I switched the probe to 1x and lo and behold the 9v battery now shows 9v on the oscilloscope. I know this, because in 5v/div mode, the wave is just short of two divisions tall, ergo I now believe it to be accurate.

I measured the IGT wire, and the waves were one division tall, they are exactly 5v. This only serves to confuse me more as from what I understand this is ideal voltage for an Arduino to read on a digital pin..

I researched into optocouplers / optoisolators before I "fixed" the oscilloscope, and at the time It seemed like a viable solution - I could use the Arduino's 5v output on the output side of the optocoupler, and the low-voltage from the IGT wire could power the LED inside the optocoupler and trigger the arduino's 5v circuit, and thus I could read the frequency of the waves.

But now that I know that the IGT wire itself is already 5v, wouldn't this render the optocoupler redundant?

It seems I'm back to square one, however i haven't looked into idahowalker's ESP32 solution just yet.

Have you thought about tapping the Crank position sensor or cam position sensor? The Crank position sensor reads a square saw tooth wheel on the back of the crank pulley, Or sometimes the flywheel. OBDII with coil on plug should be at least a 36-1 wheel. Basically a 35 tooth wheel with one tooth missing to mark Top Dead Center on the number piston 1. That way the ECU can keep track of the crank. Should be a hall effect type sensor. Or you could mount your own sensor and use the same trigger wheel. Considering, CPS failure usually results in a no start, it may be better not to mess with the engine's own wiring. Find 2 or 3 bolts on the engine, bend a piece of metal with pliars drill a few holes and mount the same or a similar type sensor wherever you want, yet close enough to the trigger wheel. You can measure the factory spacing if you want and go by that. Cam sensor if you've got one, should operate in a similar manner but half the speed, 2 revolutions of the crank to one revolution of the cam.

DON'T remove oil pan bolts for a mount, you might ruin a gasket and start a leak where there wasn't one before. Gaskets are one time use and do not decompress. You should be able to find something to mount to on or around the crank.

EDIT: Sometimes there are other things you can tap into, things that happen at certain RPMs I have a 4 stage intake that opens and closes vacuum operated valves at certain RPMs that might be perfect for your side project. A common one is VTEC on Hondas that switches at around 5000 RPM. Probably very specific to whatever you're driving. So it could be higher or lower, dependent on revisions, etc.. There should be some sort of 12v or electrical sensing or control that can be tapped for your project.

Edit no. 2 sounds like a 4 cylinder sport bike.