PDA

View Full Version : PBPro Maths Help



retepsnikrep
- 30th April 2011, 01:24
Dear All

I have some old code i use to calaculate vehicle speed in mph from a pulsing speed sensor.




CheckSpeed: 'Pulsin measures VSS pulse. In no pulse in the timeout, result will be 0
pulsin VSS,1,Local 'Measure length of a VSS pulse in 5us (8mhz) units (Timeout 0.32768s)
if Local = 0 then JumpSpeed 'If Local = 0 pulsin has timed out and vehicle is moving at < 1.5mph
Local = Local / 11 'Divide Local by 11 to enable results to fit into 16 bit Integer Maths
ActualSpeed = (7908 / Local) + 1 'Returns Speed in mph accurate to 1 mph Approx!



I am constrained by the 16 bit maths but am sure there will be a better way with the pbpro maths experts to code my formula. The code above works but is a bit inacurate and I end up adding 1mph on at the end to get it something like right. Any ideas please.

ASFAIK the VSS speed sensor outputs around 4000 pulses per mile

Charles Linquis
- 30th April 2011, 04:49
Have you thought of doing it a slightly different way? Most sensors have some jitter, so averaging out several samples gives a better result. Also, the duty cycle often isn't constant. To be really accurate, you have to take width of a positive half-cycle and add it to the width of a negative-half cyle.

I had enormous problems measuring the speeds of small fans using PULSIN. In order to get a stable, accurate result I had to average so many samples together the routine was taking too long.

Below is an ISR written in assembly that does the job perfectly.
It is run on a timer interrupt, so you can use any pin. The interrupt period is adjusted to be less than the period of the smallest half-cycle you need to measure.
In the example below, it is 1mSec. TPE is a flag that gets set after a certain number of interrrupts (1000 in this case), so it will measure over 1 second.

To use it, you clear Fanclock and Fan1Counter and TPE

Your main loop checks for TPE being set. If it is, it transfers the contents of Fan1Counter to another variable (call it SPEED), clears FanClock, Fan1Counter and TPE.

Now the variable SPEED always has the number of transitions (twice the pulse rate). It runs totally in the background. The rest of your program really doesn't need to know your timer exists. All it has to do is read SPEED and clear the variables.

Since you are getting ~4K pulses / mile, you will get a little less than 1 pulse per foot of travel. 60MPH = 88 ft/sec. So you could count for a little less than 1/2 second (change 3E8 to something a little smaller than 1F4) and you will get an answer in MPH. No fancy math required.




ReadTach

movlw 0xEC ; Reload TMR0 with 65535 - 10000
movwf TMR0H
movlw 0x7E
movwf TMR0L

bcf INTCON,2 ; Clear the TIMER0 interrupt flag




btfss TPE,0
bra CheckFans
bra DoneForNow

CheckFans
infsnz FanClock
incf FanClock + 1

movlw 0x03 - 1 ; 1000 = 0x3E8, but must have one less
cpfsgt FanClock + 1 ; to compare with greater than
bra FanRoutine
movlw 0xE8 - 1 ; Again, subtract one
cpfsgt FanClock
bra FanRoutine
bsf TPE,0
clrf FanClock
clrf FanClock + 1
bra DoneForNow

FanRoutine

movf PORTB,0,0
movwf Temp,0
xorwf OldPortB,0,0 ' XOR current with old to detect change
movwf changedB,0
movff Temp,OldPortB

Fan1
btfss changedB,0 ' Fan is connected to PortB.0
bra DoneForNow
infsnz Fan1Counter
incf Fan1Counter+1 ; increment the counter

DoneForNow

INT_RETURN

retepsnikrep
- 30th April 2011, 06:13
Thanks for that Charles i probably should have added i am using a 16F88 pic running at 8mhz, TMR1 (16bit) is already in use for another interrupt driven routine. Darrell's SSPWM routine.

Charles Linquis
- 30th April 2011, 06:44
It would still work with that part (I think). I normally run this on a TMR0 interrupt (in an 18F part). You could make the speed interrupt a low priority interrupt, and let the SSPWM be high priority. That way, the speed interrupt wouldn't screw up your PWM.

You could get by with 8 bit counters (ex fan1counter in my example) in your application. I used a 16 bit counter because I often need to measure the speed of
15,000 RPM fans.

retepsnikrep
- 2nd May 2011, 05:06
I will try that later Charles.
I was hoping for some help using DIV32 and that sort of thing to reduce errors in my 16 bit maths :confused:

retepsnikrep
- 5th May 2011, 05:26
Still hoping for some guidance on the div32 type maths to improve the accuracy of my current 16 bit maths;)

Acetronics2
- 5th May 2011, 15:51
Hi, Retep ...

first you have to declare a dummy var ... and a Div flag

then ...




IF Local > 32767 then ' see PBP manual ... for the Why ???
Local = Local/2
Div = 1
Else
Div = 0
ENDIF

Dummy = 11
Dummy = Dummy*7908 ; operation needed by PBP ...
ActualSpeed = DIV32 Local

IF Div THEN ActualSpeed = Actualspeed / 2 ' Ooops ! not *2 ...

ActualSpeed = ActualSpeed + 1

retepsnikrep
- 17th May 2011, 04:42
Thanks for the help so far, here is a different formula though.
How to convert that to use max resolution and div 32 command etc.

3600sph / (count * 0.000005 * 4550)

Count will be a maximum of 10,000

retepsnikrep
- 16th June 2011, 05:38
Does this code look correct to implement the formula?




'Formula Speed = 3600 / (Local * 0.000005 * 4550)

Dummy = Local * 5
Local = 10000
Dummy = Dummy * 4550
Dummy = DIV32 Local
Count1 = 36000
Local = Count1 * 10000
Speed = div32 Dummy
Speed = Speed / 1000