Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Automotive Tach Tip

Status
Not open for further replies.

Mosaic

Well-Known Member
I just wanted to share my approach to an auto tach using a 16f pic.

As it happens the method allows for 8bit integer math and display updates every .3 second.

Also it's inherently accurate to 100 rpm but this can be easily improved to 50 rpm with a bit of 2x oversampling and an integer /2 & using the carry to track the 50rpm state.

The approach directly translates the RPM into binary for a simple bin2dec display to handle.

It works as follows:

1) A 10 ms interupt timer determines the accuracy of the time segment to be sampled for RPM pulses via the T0CK input. Here is the code fragment from my 10 ms ISR routine

Code:
        incf Tachperiod,f ;this routine counts pulses on ra4,t0ck, to calc rpm.
	movf Tachperiod,w
; handle 6cylnders setting
	btfsc RPM6cyl,0; skip if 6cylinders not selected, else
	addlw .10; makes next sublw .30 seem like a sublw .20 for a net 200 msec period.
	sublw .30 ; standard sample period in tens of msec => 300 msec.
	skpz
	goto ISR1 ; ISR1 is a routine to restore w-reg,STATUS & PCLATH before RETFIE
;this defaults to a 4CYL RPM reading, .30 sec updates.
	
	clrf Tachperiod;
	bcf TachLSB,6; default clr LSB of rpm
	movf TMR0,w ; load undivided timer0
	movwf Timer0 ; capture timer 0 .
	bcf STATUS,C
;check for 8cyl setting (1:2)
	btfsc RPM8cyl,1 ; if set then
	rrf Timer0,f ;  div by 2 , else
	btfsc STATUS,C; if carry has a 1 then RPM lsb of 50 is active.
	bsf TachLSB,6 ;set this to be handled by tachdisp, only useful with 8 cyl.
	clrf TMR0 ; reset Timer0
	bcf STATUS,C
;check for ecu signal (1:1) setting
	btfsc RPMecu,3
	rlf Timer0,f; X 2 for  ECU signal
;check for Coil on plug (4:1) setting
    btfsc RPMplug,4
    rlf Timer0,f; x 2
    bcf STATUS,C
    btfsc RPMplug,4
    rlf Timer0,f; x4 for RPMplug

    movlw .50
    btfss Featuresel,2; skip if tachometer feature bit enabled, else
    movwf Timer0; force RPM to read 5000 


As u see this bit of code samples the T0CK tmr0 count over a specified interval of either .30 sec or .20 sec (for 6 cylinders).
It also does some simple integer math to handle different tach inputs such as:
ECU signal, Coil on Plug signal, default 4 cylinder coil signal and 8 cylinder coil signal.

The last section forces a 5000RPM  fixed reading if the RPM display is disabled.

The TachLSB bit setting allows the 8 cylinder mode to be accurate to 50RPM .

The result of this code is a value in the Timer0 user GPR variable that is directly equivalent to the RPM.
If Timer0 = 30, then the rpm = 3000.
Timer0 = 99 then RPM = 9900

Thus the display of the RPM is a simple bin2dec display for 2 significant digits and then the last 2 digits are padded with zeroes. For the 50RPM extra accuracy, you'd have to oversample  by doing a .6 sec sample and then dividing by 2 to get a lsb in the carry to drive the 50RPM accuracy.

The  RPMecu,RPM8cyl, RPM6cyl, RPMplug, TachLsb bits are all bits in a single GPR byte used to configure the tachometer to the type of input. You'll notice the tactic used for the 6 cylinder variant is not to engage in a somewhat time consuming  divide-by-3 asm code but to reduce the sample period and thus get an exact value with no math.

The basis for this approach comes from the formula:

Direct RPM => Pulses per minute/60=> pulses per second

So 3000 RPM =>3000/60 = 50 pulses per second

Thus in .6 sec the # of pulses = 50 *3/5 = 30

Thus for an ecu direct RPM signal sampled over .3sec we multiply by 2 to get the correct result.

For a 4 cylinder coil signal which delivers 2 pulses per rpm (4 cycle engine) the .3 sec sample gives the precise result with no math.

An 8 cyl motor gives 4 pulses per rpm so we divide by 2 to get the precise result and  use the carry to derive incidental 50rpm LSB accuracy.

The 6 cylinder motor has a 3/2 coil pulse relationship to the 4 cyl. So we reduce the sample period by 2/3 to have a 1:1 numerical result.

Coil on plug takes a single signal from 1 plug, which means the plug fires once every 2rpm in a 4 cycle motor regardless of cylinders. this is 1/4 the rate of the 4cyl sample => x 4 to get actual  RPM

In wasted spark systems the shared coil on plug will fire once per rpm, therefore you'd use the ECu direct setting for any wasted spark shared coil on plug signal.

I found this to be just what I needed, simple and flexible. I hope it's useful to the community.
 
Last edited:
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top