PDA

View Full Version : Has anyone written code to read an automotive tach signal?



turbosupra
12-23-2009, 12:37 PM
I believe my tach signal is low side pulses per minute. I'd like to see someones prop code if they don't mind sharing.

Did you have to do anything on the hardware side? I'd theorize that the prop could handle the pulses per minute without additional hardware, maybe sans a pull up resistor?

BradC
12-23-2009, 01:56 PM
I'm doing similar but different at the moment. I'm trying a minimal approach to reading the RPM on some marine diesels. The diesels use inductive sensors. The Cummins use a sensor on the injector pump shaft at 2 pulses per rev, and the Volvos use one on the flywheel at 20 pulses per rev.

Initially I tried a simple high value series resistor (100K) directly into a port pin. This works ok at idle, but as soon as the revs come up and the voltage starts to creep up (I get 2V p-p at idle and 40v p-p at redline) things go haywire. I've borrowed a portable cro now and I'm going to have a crack at it again on Boxing day to see if I can add some "simple" passive external conditioning to calm it down. If that fails I'll have to built a zero crossing detector and some hysteresis to really clean it up.

Anyway, the code is probably no good to you, but all I'm doing is timing 8 input cycles by using a waitpeq/waitpne loop in a separate cog. That cog writes the timed period to the hub and some spin code converts it to RPM. It's pretty ugly and untidy.

I guess my point was you might want to look at some external signal conditioning. I'm thinking a simple low pass filter at the moment using an RC network, but I'll see how the next test pans out. It'd be easier if I could just walk to the car in the driveway and do the tests ;)

<edit> forgot the code

the extra delays in there help it settle, but it still bounces and false triggers at high rpm so I need to try something else. This is the code for the Cummins, so it gives me RPM for 2 pulses per cycle.




PUB GetRPM(pin,Rvar) | X, Y
Pin := 1<<Pin
repeat
waitpeq(0,Pin,0)
waitcnt(cnt+clkfreq/1000)
waitpeq(Pin,Pin,0)
X := Cnt
' Positive Edge
repeat 4
waitpeq(0,Pin,0)
waitcnt(cnt+clkfreq/1000)
waitpeq(Pin,Pin,0)
Y := Cnt
X := (Y-X)/10
long[ Rvar ] := ((800000000/X)/5)*3 <# 9999


▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Life may be "too short", but it's the longest thing we ever do.

pmrobert
12-23-2009, 09:19 PM
You can't beat a low cost LM1815 for reading VR sensors even in a noisy environment.

Aquaaddict
12-23-2009, 09:58 PM
Engines tach signals vary between engines, alot of diesels (esp marine), use a signal from the alternator, others use inductive pickups, others come from the ECU based on data from other engine sensors.

Ants

turbosupra
12-23-2009, 11:25 PM
How about using the cam or crank signal?


http://img9.imageshack.us/img9/5773/2zzcranksignal1.jpg





Aquaaddict said...
Engines tach signals vary between engines, alot of diesels (esp marine), use a signal from the alternator, others use inductive pickups, others come from the ECU based on data from other engine sensors.

Ants

pmrobert
12-23-2009, 11:40 PM
Use the crank signal, if it's of appropriate level - VRs can easily turn out tens of volts at faster than idle speeds. As previously noted, you'll probably have to condition it in some way. Measure ticks between pulses, calculate next predicted pulse time. Use these numbers to calc rpm. That crank sensor trace looks like a 36-1 pattern. This makes calcs nice and easy, each tooth is 10 degrees apart. To get around the missing tooth problem, if actual pulse comes in more than 10% later than predicted time of next pulse, ignore it and do not update the calculated rpm until the next pulse appears. Rinse, repeat.

turbosupra
12-24-2009, 12:33 AM
That's exactly what it is, 36-1.

Do you think a transistor could switch fast enough to keep up with the vr sensor pulses, to deal with my voltage issue? Maybe an optocoupler on a circuit with a 3v source and pull down resistor?

I'll really have to think about how to code for what you suggested with predicted pulse time, I thought it would be as easy as measuring tickets per second :(





pmrobert said...
Use the crank signal, if it's of appropriate level - VRs can easily turn out tens of volts at faster than idle speeds. As previously noted, you'll probably have to condition it in some way. Measure ticks between pulses, calculate next predicted pulse time. Use these numbers to calc rpm. That crank sensor trace looks like a 36-1 pattern. This makes calcs nice and easy, each tooth is 10 degrees apart. To get around the missing tooth problem, if actual pulse comes in more than 10% later than predicted time of next pulse, ignore it and do not update the calculated rpm until the next pulse appears. Rinse, repeat.

pmrobert
12-24-2009, 01:17 AM
The LM1815 www.national.com/ds/LM/LM1815.pdf (http://www.national.com/ds/LM/LM1815.pdf) I spoke of earlier is specifically designed to detect VR zero crossings and output a variety of square wave signals/pulses/etc. The only reason I mention using a predicted pulse time window is so you can exclude the 200% longer gap at the missing tooth. Basically, detect the long gap as a statistical outlier and use the rest of the interteeth gaps to calc rpm. It IS as easy as measuring ticks per time period but you gotta detect and throw out the artifactual "bad data" caused by the missing tooth in your calcs. I usually calculate microseconds between teeth and go from there. I'm not being deliberately obtuse, I'm not home at the moment and posting this off a phone. If you need sample working code, let me know.

ry.david
12-24-2009, 01:21 AM
I am actually working on this exact same problem... 36 teeth/rev for the crank position sensor, but on a little 2.4L, haha

I was planning on using a cog counter in the Positive (or Negative) Edge mode, so I can do other tasks with the cog at the same time. I am not sure of the hardware to safely interface a either 5v or 12v signal to the prop. I was looking at what they use for Megasquirt, and it was an optoisolator, but I am not sure of the reasoning behind a optoisolator versus a transistor between the signal and prop

Cluso99
12-24-2009, 01:23 AM
Wouldn't a 100K series resistor and 3V3 zener to gnd at the prop pins work?

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Links to other interesting threads:

· Home of the MultiBladeProps: TriBlade (http://forums.parallax.com/showthread.php?p=786418),·RamBlade (http://forums.parallax.com/showthread.php?p=849265),·SixBlade (http://forums.parallax.com/showthread.php?p=780033), website (http://bluemagic.biz/cluso.htm)
· Single Board Computer:·3 Propeller ICs·and a·TriBladeProp board (ZiCog Z80 Emulator) (http://forums.parallax.com/showthread.php?p=790917)
· Prop Tools under Development or Completed (Index) (http://forums.parallax.com/showthread.php?p=753439)
· Emulators: CPUs Z80 etc; Micros Altair etc;· Terminals·VT100 etc; (Index) (http://forums.parallax.com/showthread.php?p=778427) ZiCog (Z80) (http://forums.parallax.com/showthread.php?p=788511) , MoCog (6809) (http://forums.parallax.com/showthread.php?p=811043)
· Search the Propeller forums (http://search.parallax.com/search?site=parallax&client=parallax&output=xml_no_dtd&proxystylesheet=parallax&proxycustom=<HOME/>&ie=&oe=&lr=)·(uses advanced Google search)
My cruising website is: ·www.bluemagic.biz (http://www.bluemagic.biz)·· MultiBladeProp is: www.bluemagic.biz/cluso.htm (http://www.bluemagic.biz/cluso.htm)

pmrobert
12-24-2009, 01:51 AM
@Cluso, good idea! He doesn't require the precise timing zero crossing provides, just a pulse. Much easier to implement than another IC as well.
@ry.david, there's a sticky thread or an app note that details interfacing 5/12 to the prop with several methods. I'm pretty sure the MS' opto helps keep the coil flyback voltage/ringing from getting to the processor. Most Kettering coils produce a flyback of 1-300+ volts on the coil -, you really don't want that too near logic level components.

turbosupra
12-24-2009, 02:34 AM
Hey Robert,

I'd love to see the sample code, when you have a chance, especially the logic behind it. Did you use an oscope to calculate the microseconds at idle and then go from there to build a reference table?



pmrobert said...
The LM1815 www.national.com/ds/LM/LM1815.pdf (http://www.national.com/ds/LM/LM1815.pdf) I spoke of earlier is specifically designed to detect VR zero crossings and output a variety of square wave signals/pulses/etc. The only reason I mention using a predicted pulse time window is so you can exclude the 200% longer gap at the missing tooth. Basically, detect the long gap as a statistical outlier and use the rest of the interteeth gaps to calc rpm. It IS as easy as measuring ticks per time period but you gotta detect and throw out the artifactual "bad data" caused by the missing tooth in your calcs. I usually calculate microseconds between teeth and go from there. I'm not being deliberately obtuse, I'm not home at the moment and posting this off a phone. If you need sample working code, let me know.



http://img24.imageshack.us/img24/6876/lm1815.jpg

turbosupra
12-24-2009, 04:14 AM
Meaning like this?


Revision 2
http://img51.imageshack.us/img51/6830/propellerchip2.jpg

Would an optocoupler be a better choice, or is EMI not going to be a concern?



Cluso99 said...
Wouldn't a 100K series resistor and 3V3 zener to gnd at the prop pins work?

Post Edited (turbosupra) : 12/23/2009 8:40:03 PM GMT

pmrobert
12-24-2009, 04:15 AM
No problem, I'll post code in a couple of days. You can calc rpm by simple math. For a 36 tooth wheel:

Step1: usec/tooth*36 = usec/rev
Step 2: ((1000000/(usec/rev))*60) = rpm

Remember that the Prop has no hardware floating point capability for variables, everything has to be integer. Scale accordingly!
You could also use one of the floating point objects as well.

Your diagram needs to have the Zener between signal and ground, the resistor would be between the Zener and prop.

EMI's always a concern around internal combustion engines. Route wires intelligently, ground appropriately with shielded wire and see how it works.

Post Edited (pmrobert) : 12/23/2009 8:20:55 PM GMT

turbosupra
12-24-2009, 04:39 AM
Ok, I updated the partial schematic

Thanks for the hint about floats, I did not know that




pmrobert said...
No problem, I'll post code in a couple of days. You can calc rpm by simple math. For a 36 tooth wheel:

Step1: usec/tooth*36 = usec/rev
Step 2: ((1000000/(usec/rev))*60) = rpm

Remember that the Prop has no hardware floating point capability for variables, everything has to be integer. Scale accordingly!
You could also use one of the floating point objects as well.

Your diagram needs to have the Zener between signal and ground, the resistor would be between the Zener and prop.

EMI's always a concern around internal combustion engines. Route wires intelligently, ground appropriately with shielded wire and see how it works.

AJM
12-24-2009, 05:19 AM
I have been using a LM358, as a unity gain buffer, wired directly to the output pin from the ECU.

I haven't had any issue thus far.

pmrobert
12-24-2009, 05:29 AM
AJM, he's tapping the VR crank sensor, not a logic level signal. Apples/oranges.

AJM
12-24-2009, 05:40 AM
I suppose I should read the whole thread before posting.

In any case, if you have access to the ECU logic levels, the op amp will work.

Sorry for the confusion http://forums.parallax.com/images/smilies/blush.gif

pmrobert
12-24-2009, 05:55 AM
No problem, I apologize if I came off less than genteel. I do like the idea of the opamp's extra isolation when connecting to the very expensive OEM ECUs!

turbosupra
12-24-2009, 06:07 AM
What type of engine/ecu are you doing this on?



AJM said...
I have been using a LM358, as a unity gain buffer, wired directly to the output pin from the ECU.

I haven't had any issue thus far.

Miner_with_a_PIC
12-24-2009, 07:31 AM
In the above circuit, where a zener and resistor were employed the resistor might be best placed before rather than after the zener, this way the current taken from the crank sensor is limited. See the attached image, the optional capacitor can be used to suppress short duration spikes and should be selected so that RC (R= 100,000 in this example) is much less that the duration of the pulses.

Post Edited (Miner_with_a_PIC) : 12/24/2009 4:54:23 AM GMT

AJM
12-24-2009, 07:40 AM
turbosupra,

I tried this on the ECU for a Toyota 2AZ-FE from my daily driver.

turbosupra
12-24-2009, 08:48 AM
Haha, sweet, scion or xrs?

Mine is for a 2zz, so I'd imagine whatever you did would work perfect for me, and if you don't mind sharing, I'd rather take the easier road, then the harder

Can we talk via email?





AJM said...
turbosupra,

I tried this on the ECU for a Toyota 2AZ-FE from my daily driver.

matb
12-24-2009, 09:12 AM
Just building the same thing myself. I was planning on taking the 12V signal from the low side of the coil, or possibly earlier on from one of the ECU outputs, ideally the tacho output.

Since I expect to pick up on a generic NO ecu output, I had a similar circuit, but with a pull down resistor added. I didn't allow for a cap, but darn good point on that!

As for software, one way is a with a (semi) dedicated cog to time-stamp the edge. The loop looks like:
- set the counter in level detect mode to match HIGH level. Set the step to 1, and the phase to CNT.
- spare time, do speed calcs from last transition
- wait for pin LOW
- store the counter value

- set the counter in level detect mode to match LOW level. Set the step to 1, and the phase to CNT.
- spare time, do speed calcs from last transition
- wait for pin HIGH
- store the counter value

The trick is pre-loading the counter with CNT, and therafter it keeps counting up in lock step with CNT until the input changes.

I have code that does that, but has a mess of other stuff in there, such as calibratable odometer and start detection. Can post if wanted.


BTW if the tacho is not critical, you can monitor it on a round robin basis. I will probably do that as I just want a informational display of tacho and also injector duty cycle. The odo is critical, hence got a dedicated cog.

Post Edited (matb) : 12/24/2009 1:20:19 AM GMT

turbosupra
12-24-2009, 09:31 AM
Hey Mat,

I would like to see your code if possible, just to see some example code of what you did, especially the syntax.




matb said...
Just building the same thing myself. I was planning on taking the 12V signal from the low side of the coil, or possibly earlier on from one of the ECU outputs, ideally the tacho output.

Since I expect to pick up on a generic NO ecu output, I had a similar circuit, but with a pull down resistor added. I didn't allow for a cap, but darn good point on that!

As for software, one way is a with a (semi) dedicated cog to time-stamp the edge. The loop looks like:
- set the counter in level detect mode to match HIGH level. Set the step to 1, and the phase to CNT.
- spare time, do speed calcs from last transition
- wait for pin LOW
- store the counter value

- set the counter in level detect mode to match LOW level. Set the step to 1, and the phase to CNT.
- spare time, do speed calcs from last transition
- wait for pin HIGH
- store the counter value

The trick is pre-loading the counter with CNT, and therafter it keeps counting up in lock step with CNT until the input changes.

I have code that does that, but has a mess of other stuff in there, such as calibratable odometer and start detection. Can post if wanted.


BTW if the tacho is not critical, you can monitor it on a round robin basis. I will probably do that as I just want a informational display of tacho and also injector duty cycle. The odo is critical, hence got a dedicated cog.

Cluso99
12-24-2009, 11:30 AM
turbosupra: The zener is reverse polarity (swap polarity) and move it to the prop side.

What it will do is clamp the max voltage to 3v3 and the voltage drop will be throught the 100K resistor which should not interfere with the existing circuit. A capacitor should not be required.

Why is the polarity of the zener reversed? The way you have it, the zener will always conduct when the input voltage is about 0.6V so you will never see a high. When a zerer is reverse biased, the zener will conduct whenever the voltage is above its voltage reference (3v3 in this case - a 2v7 would also be fine). When it conducts, the current it passes causes a voltage drop on the resistor.

Why is it on the prop side? In the above I showed the 100K resistor (could probably use a 1M also) is used to drop the voltage. This protects the prop and does not (should not because of the high resistance) interfere with the existing circuit.

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Links to other interesting threads:

· Home of the MultiBladeProps: TriBlade (http://forums.parallax.com/showthread.php?p=786418),·RamBlade (http://forums.parallax.com/showthread.php?p=849265),·SixBlade (http://forums.parallax.com/showthread.php?p=780033), website (http://bluemagic.biz/cluso.htm)
· Single Board Computer:·3 Propeller ICs·and a·TriBladeProp board (ZiCog Z80 Emulator) (http://forums.parallax.com/showthread.php?p=790917)
· Prop Tools under Development or Completed (Index) (http://forums.parallax.com/showthread.php?p=753439)
· Emulators: CPUs Z80 etc; Micros Altair etc;· Terminals·VT100 etc; (Index) (http://forums.parallax.com/showthread.php?p=778427) ZiCog (Z80) (http://forums.parallax.com/showthread.php?p=788511) , MoCog (6809) (http://forums.parallax.com/showthread.php?p=811043)
· Search the Propeller forums (http://search.parallax.com/search?site=parallax&client=parallax&output=xml_no_dtd&proxystylesheet=parallax&proxycustom=<HOME/>&ie=&oe=&lr=)·(uses advanced Google search)
My cruising website is: ·www.bluemagic.biz (http://www.bluemagic.biz)·· MultiBladeProp is: www.bluemagic.biz/cluso.htm (http://www.bluemagic.biz/cluso.htm)

yarisboy
12-29-2009, 02:37 AM
I've gotten help from forum members on this issue. On Toyotas (OBD2 wire) I can use a resistor and a zener to feed the pin on either a BS2 (5 volts) or a Propeller (3.3 volt zener). Just in case some one uses my tachometers on a points distributor antique I have an opto-isolator in the layout now. The one specified by another forum member has hysteresis or schmitt trigger characteristics to clean up the signal going to the pin.

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
MOORE'S LAW: The capabilities of electronics shall double every 18 months.
cloyd's corollary: Hardware is easy, software is hard.

matb
12-29-2009, 05:32 PM
My odo counter object is attached as example of the counting technique.

As usual, code needs more cleanup.

turbosupra
12-31-2009, 01:06 PM
@Clusco and yarisboy, I will try that circuit out, thank you!

@Matb, thanks so much for the code, now to try and institute it, since my car is a 4 stroke coil on plug (no waste spark) I may have to have it read something every 2 revolutions, correct?

turbosupra
12-31-2009, 02:33 PM
So the consensus is that this is the best setup for my tach input circuit?


http://img269.imageshack.us/img269/8422/tachsignalprop1.jpg





And the consensus is that this is the best setup for my voltage follower?


http://img63.imageshack.us/img63/1295/voltagefollowerprop1.jpg

Miner_with_a_PIC
01-01-2010, 01:19 AM
Turbosupra, there are a couple of issues with the first circuit that would need to be addressed before it would work successfully...

1) The tach signal is insufficient to drive the LED in the optocoupler
2) No current limiter for the LED in the optocoupler
3) Optocoupler output transistor is inserted in the opposite polarity


See attached image for suggested fixes...the 100k value probably needs some experimentation. Please note that the signal at the pin is expected to be inverted in the attached schematic (i.e. pin high with no signal and low when signal pulse is applied to tach input). Simple changes to software could correct for this.

Incidentally does anyone know what to do with the dangling base on the optocoupler output?

I didn't look too closely at the second circuit as I was unsure what its purpose was.

Miner_with_a_PIC
01-01-2010, 07:23 AM
An afterthought>> replace the transistor with a n-channel MOSFET like a 2N7000 and remove the 4.7K, doing this should allow you to keep the 100K resistor as MOSFETs are voltage controlled devices rather than current.

Just connect the source where the emitter is in the above schematic along with drain for the collector & gate for the base.

matb
01-02-2010, 02:03 PM
Turbo, the zener as shown does not really achieve anything. (In fact I expect it will not work at all)

The Zener design is an alternative to using an opto. I gave up using an opto for protection as they needed more protection than the prop itself. The ones I found You need at least reverse polarity protection across the opto.

ie the idea was:



input ----R----------- prop Pin
|
Z
|
gnd



However that turns out to be rubish if you are trying to keep it low power as the zener needs lots of current, so needs a low R. I tried a 1N4728 3.3v zener as input protection, but it needs about 70mA of current.

For the moment I will just increase my series resistance and discard the diodes altogether, and rely on the props built in protection.

If I rebuild I will consider using more traditional protection of 2 (low leakage) diodes, one to gnd and one to the 3.3 rail.




3.3V
|
D
|
input ----R----------- prop Pin
|
D
|
gnd





Ascii schematics... where is the prop font when you need it!

Post Edited (matb) : 1/2/2010 6:08:49 AM GMT

turbosupra
01-02-2010, 02:46 PM
So scrap the opto and go with this?

Is that (2) 3.3v standard diodes? What value resistor did you use, or are you not sure, so the blank value implies a little experimentation?


[quote]

3.3V
|
D
|
input ----R----------- prop Pin
|
D
|
gnd

rjo_
01-03-2010, 03:04 PM
I didn't know what a crankshaft position sensor was until I had to replace mine:)
The wavelength will vary with your rpms... so your basic code would be something like





PRI readCrankshaftPS(pin) | period
dira[pin]~
waitpne(|<pin, |< pin, 0) 'pin high...but may be in middle of pulse
waitpeq(|<pin, |< pin, 0) 'pin low... beginning of low period but not beginning of the signal
Repeat
waitpne(|<pin, |< pin, 0) 'pin high, beginning of high period and beginning of pulse signal
tix:=cnt 'get clock
waitpeq(|<pin, |< pin, 0) 'pin low...end of high pulse
tix2:=cnt
waitpne(|<pin, |< pin, 0) 'pin high end of low period, end of signal wave
fcnt:=cnt
period:=(fcnt-tix)