PDA

View Full Version : speedometer without timer1



retepsnikrep
- 6th February 2011, 08:30
I'm using Darrel's sspwm.inc program to generate a 2khz pwm signal which works very well. I now need a speedometer function. I have an incomming square wave pulse train from the vehicle speed sensor which pulses at approx 4000/minute at 60mph.

I have spare adc inouts so i was looking at a simple rc filter and measuring a cap voltage. Or i could use a freq to voltage ic LM2907 etc but i don't really want another ic on the board. So can I use ccp without access to timer1 as that's used by sspwm.inc.

I probably can't use count or pulsin for the same reasons, the software pwm must continue in the background and the hpwm is already in use generating a 20khz signal.

Any Ideas?

mister_e
- 6th February 2011, 11:04
5152

"Crystal ball help me... crystal ball... tell me which PIC the OP's using... maybe he could use Timer 0 for it's counting purpose?

Crystal ball tell me more about the OP's requirement...."

retepsnikrep
- 6th February 2011, 14:51
5152

"Crystal ball help me... crystal ball... tell me which PIC the OP's using... maybe he could use Timer 0 for it's counting purpose?

Crystal ball tell me more about the OP's requirement...."




LOL Mister E

Pic is 16F88

I think timer 0 is only 8 bit so can't count high enough?

mister_e
- 6th February 2011, 15:02
It really depend what you need to do with the incoming pulse. Timer0 also have Prescaller/divider, you can play with the acquisition time, and maybe use the overflow interrupt (if any for TMR0).

We don't know the purpose of your 2 PWMs... hard to suggest things.

retepsnikrep
- 6th February 2011, 15:35
The two pwms have to continue unaffected in the background.

What about the RC idea and using the adc to acquire the voltage?

mister_e
- 6th February 2011, 15:38
Sure less flexible & accurate than the Timer idea.

Look @ the classic LM2917... Frequency to Voltage converter. That must mean something ;)

Charles Linquis
- 6th February 2011, 16:46
You can use a timer interrupt. You can use TMR0 or just "piggyback" on Darrel's TMR1 interrupt in the SSPWM routine.

The only caveat is that the period of that interrupt must be shorter than the narrowest pulse (either high or low) that your speedometer sensor puts out.

I have written (and posted) a routine that would do what you want. Mine is written in asm, but could be written in PBP as well.

Below is a section. It measures the speed of 9 fans by watching the tachometers.

A couple of things to note -

It must be written as an ISR.
The interrupt time is determined by PRELOADH and PRELOADL.
The routine runs for an exact number of interrupts before stopping (FanClock is the counter) 1000 is the number here.
So if you interrupt at 1mSec intervals, this routine will run for 1 second before being restarted in the main loop.

To use:

Set your interrupt rate.
Determine how many counts you need to get the accuracy you want (which determines
how long you need to count and therefore, the maximum update rate of your speedometer).

If you get 1 cycle (1 high period and one low period) per foot, and you have a 50% duty cycle, then you will get 88 cycles per second with a high period of 5.6 mSec and a low period of 5.6 mSec. To account for jitter, your interrupt period would have to be 5 mSec or less. You would have 166 transitions (low->high + high -> low) in one second. If you set FanCounter to time out in .3614 seconds (say 100 counts with a 3.614 mSec update rate), the count would be in exact mph with a .3614 second update rate. Longer counting intervals and faster interrupts gives more accuracy and less jitter.


You need clear TPE before you start.
Check TPE in your main loop. If it is set, the routine has completed. Transfer the contents of the FanxCounters to another set of variables (call them FanYcounters, clear all the FanXcounters, Clear FanClock and Clear TPE. Now your main loop can read FanYcounters and display the mph, or RPM, or whatever.

You don't have to stop TMR0 on most chips to reload it. You do have to stop most of the other timers before reloading. Check your datasheet.
The routine runs for an exact number of interrupts before stopping. You need clear TPE before you start.



Asm
ReadTachs
movff PreloadH,TMR0H ; Preload depends on clk speed
movff PreloadL,TMR0L
infsnz MasterClock
incf MasterClock + 1

btfsc TPE,0
bra DoneForNow

;CheckFans
infsnz FanClock
incf FanClock + 1

movlw 0x03 - 1 ; Real value is 1000 = 0x3E8, but must have one less
cpfsgt FanClock + 1 ; to compare with greater than
bra FanRoutine
movlw 0xE8 - 1 ; Likewise, subtract one here, too.
cpfsgt FanClock
bra FanRoutine
bsf TPE,0

clrf FanClock
clrf FanClock + 1
bra DoneForNow

FanRoutine

movf PORTB,0,0
movwf Temp,0 ; Save VAR so can't change between compare and save
xorwf OldPortB,0,0
movwf changedB,0
movff Temp,OldPortB

movf PORTC,0,0
movwf Temp,0
xorwf OldPortC,0,0
movwf changedC,0
movff Temp,OldPortC

movf PORTD,0,0
movwf Temp,0
xorwf OldPortD,0,0
movwf changedD,0
movff Temp,OldPortD


Fan1
btfss changedB,0
bra Fan2
infsnz Fan1Counter
incf Fan1Counter+1

Fan2
btfss changedB,1
bra Fan3
infsnz Fan2Counter
incf Fan2Counter+1

Fan3
btfss changedB,2
bra Fan4
infsnz Fan3Counter
incf Fan3Counter+1
Fan4
btfss changedB,3
bra Fan5
infsnz Fan4Counter
incf Fan4Counter+1

Fan5
btfss changedB,4
bra Fan6
infsnz Fan5Counter
incf Fan5Counter+1

Fan6
btfss changedB,5
bra Fan7
infsnz Fan6Counter
incf Fan6Counter+1

Fan7
btfss changedC,0
bra Fan8
infsnz Fan7Counter
incf Fan7Counter+1

Fan8
btfss changedD,5
bra Fan9
infsnz Fan8Counter
incf Fan8Counter+1

Fan9
btfss changedD,4
bra DoneForNow
infsnz Fan9Counter
incf Fan9Counter+1

DoneForNow

bcf INTCON,2 ; Clear the TIMER0 interrupt flag

INT_RETURN ; WAS RETFIE FAST Return from the interrupt
ENDASM

amgen
- 6th February 2011, 18:32
could you do a "pulse-in" once or twice a second with a limit of 1/4 or 1/3 second so program continues, that uses a 10 micro-sec resolution and 16 bit count, all in basic ?

don
Amgen Marine

Charles Linquis
- 6th February 2011, 19:38
Pulsin has an inherent problem that the duty cycle has to be constant, and often it is not. A cycle is both a "low" time plus a "high" time. It is also a blocking command. While you can do a

PULSIN pin,0,lowtime
PULSIN pin,1,hightime

Period = lowtime + hightime

Speed (or RPM, etc) = constant/Period

To get the correct period even if the duty cycle varies somewhat, you should know that PULSIN can't read the hightime immediately following the lowtime.
It reads the lowtime, misses the next hightime, skips the following lowtime, and then reads the hightime.

If your sensor puts out a good clean signal, then the PULSIN method is the easiest. But also remember, that at very slow speeds, your code will be sitting around for a long time waiting for the next transition.


The good thing about my routine is that it runs in the background and averages over the sample period (I usually use about 0.5 sec), so the results are very stable, even with noisy inputs.

And... There is nothing that keeps you from writing your ISR in PBP. Use Darrel Taylor's Instant Interrupts.

Just -

read the port bit on a timer interrupt
compare it with the last read of that bit
if it has changed, increment a counter
do the above for a fixed amount of time
read the counter.