Log in

View Full Version : Nasty PBP math help ?



Martin
- 22nd March 2005, 04:03
Hi all.

I am doing a rather simple (on the surface of it) one off project to make a remote serial display for a ballistic chronograph unit I have.
The serial comms is easy, did that and happy with that and can get the raw timer data and a feet per sec value.

However I found out from a datasheet that if I use raw timer data from the chronograph and ignor it's internal calculated values I can get about 4% better accuracy. Great, except for one catch. This is the equation that PBP needs to run on the incoming value.

VELOCITY = (12 / ( RAW * ( 1 / 12000000 ) ) / 12


Velocity is the data I need to calculate in FPS (feet per second)
RAW is the incoming chronograph data value and can be as high as a 24bit number but I can get away with bounding it to a 16bit number I think.
12 is the distance between the chronograph sensors in inches (perhaps I should use metric units then convert ?)


I'm no math head sadly and get a headache just writing the equation (runs in the family). Can anyone help with using PBP math to crunch this, I'm lost because of the small fraction involve (1/12000000 divide) which if I do the usual decimal point shifting will blow the other values over 32 bit.

Any tips (other than go back to school) welcome.

Martin

Luciano
- 22nd March 2005, 08:52
Hi!

The PAK-I and PAK-II Math Coprocessors.

PAK-I:
http://www.awce.com/pak1.htm
http://www.awce.com/pak1.pdf

PAK-II:
http://www.awce.com/pak2.pdf

PAKs and PICBasic Pro:
http://www.awce.com/picbasic.htm


I don't know if these Coprocessors can solve your problem.
Read the PDF files.

Best regards,

Luciano

Ingvar
- 22nd March 2005, 17:23
This formula is missing a parethesis.

VELOCITY = (12 / ( RAW * ( 1 / 12000000 ) ) / 12

However, it will probably boil down to ....

VELOCITY = ( 12 * 12000000 ) / ( 12 * RAW )

.... which equals ......

VELOCITY = 12000000 / RAW

This is easy to calculate with DIV32 as long as the divisor is 15 bits or less. 12000000 is way less than 31 bits so that will not be a problem. If you can keep the divisor lower or equal to 15 bits you can use ......



R0.HIGHBYTE = $00 'stuff internal registers with 00B71B00hex=12000000dec
R0.LOWBYTE = $B7
R2.HIGHBYTE = $1B
R2.LOWBYTE = $00
Velocity = DIV32 Raw 'do the division, make sure Raw is <= 15 bits (32767)

This code can't go below 366 ft/s since Raw must not be larger than 32767(12000000/32768=366.21). However, there is a way to get around that. This code will scale the dividend and divisor as long as the divisor is larger than 15 bits.



Div32Value VAR BYTE[4]
Raw VAR BYTE[3]
DataIn VAR WORD
Velocity VAR WORD
TestBit VAR bit

'Blah blah blah

Div32Value[3]=$00 : Div32Value[2]=$B7 : Div32Value[1]=$1B : Div32Value[0]=$00
WHILE Raw[2] > 0
ASM
bcf STATUS,C ;Shift right(/2) until highbyte = 0
rrf _Div32Value+3,f
rrf _Div32Value+2,f
rrf _Div32Value+1,f
rrf _Div32Value+0,f
ENDASM
ASM
bcf STATUS,C ;Divide divisor by 2
rrf _Raw+2,f
rrf _Raw+1,f
rrf _Raw+0,f
ENDASM
WEND
IF Raw.0(15) THEN 'Do it again if necessary to get 15 bits
ASM
bcf STATUS,C
rrf _Div32Value+3,f
rrf _Div32Value+2,f
rrf _Div32Value+1,f
rrf _Div32Value+0,f
ENDASM
ASM
bcf STATUS,C
rrf _Raw+2,f
rrf _Raw+1,f
rrf _Raw+0,f
ENDASM
ENDIF
Datain.HIGHBYTE = Raw[1]
DataIn.LOWBYTE = Raw[0]
R0.HIGHBYTE = Div32Value[3] 'Put dividend into it's internal registers
R0.LOWBYTE = Div32Value[2]
R2.HIGHBYTE = Div32Value[1]
R2.LOWBYTE = Div32Value[0]
Velocity = DIV32 Datain ' Do the divison

Could be useful for those extremley slow bullets, or passing insects :-)

/Ingvar

Martin
- 22nd March 2005, 22:16
This formula is missing a parethesis.

VELOCITY = (12 / ( RAW * ( 1 / 12000000 ) ) / 12

However, it will probably boil down to ....

VELOCITY = ( 12 * 12000000 ) / ( 12 * RAW )

.... which equals ......

VELOCITY = 12000000 / RAW

This is easy to calculate with DIV32 as long as the divisor is 15 bits or less.
/Ingvar

Hi Ingvar, long time since we last conversed....
Your genius has not deminished and I'm humbled by your math skills.

I ran a couple of RAW values on my calculator, YES you are spot on V = 12e6/RAW comes out right. If you knew how much time I spent trying to work that out myself you'd laugh your head off at me :-)

The 12000000 figure is the system clock frequency BTW, but I suspect you guessed that one.

I'd better go digest your code for larger than 15 bits.

Thanks again. Look me up if you ever come visiting Australia

Ingvar
- 23rd March 2005, 07:51
Hi Ingvar, long time since we last conversed....

Time flies when you're having fun


Your genius has not deminished and I'm humbled by your math skills.

*LOL* You just made my day. Now i don't need to feel bad when i take a few extra beers tonight. It seems obvious that I kill off the weaker braincells first ....


I ran a couple of RAW values on my calculator, YES you are spot on V = 12e6/RAW comes out right. If you knew how much time I spent trying to work that out myself you'd laugh your head off at me :-)

Nop, i wouldn't laugh at people who're struggling. People tend to get pissed off by that .... atleast i do.


The 12000000 figure is the system clock frequency BTW, but I suspect you guessed that one.

The thought crossed my mind ...... and again ....... and stuck.


I'd better go digest your code for larger than 15 bits.

Don't forget to chew, it's difficult to perform a Heimlich maneuver from half across the globe.


Thanks again. Look me up if you ever come visiting Australia

No worries, mate.

Martin
- 30th March 2005, 06:43
Hi Ingvar, hope you enjoyed the beers.

The project is running fine on the bench now, got most of the full unit is assembled too, should be finished tonight. Then wait for a fine day to go to field testing.

I do have a quick question, as I'm running the 15bit or less code currently so my accuracy is to +- 1 FPS (last digit).

Can DIV32 give a remainder so rounding can be used ? Like //.

Martin

Ingvar
- 30th March 2005, 09:46
Hi Ingvar, hope you enjoyed the beers.

I sure did, again and again and again and ..... i just hated myself the day after.


I do have a quick question, as I'm running the 15bit or less code currently so my accuracy is to +- 1 FPS (last digit).

Can DIV32 give a remainder so rounding can be used ? Like //.

You can increase the resolution by 10 quite easy. Just preload the registers with 120000000dec(=07270E00hex) instead. You could then do rounding on that.


R0.HIGHBYTE = $07
R0.LOWBYTE = $27
R2.HIGHBYTE = $0E
R2.LOWBYTE = $00
Velocity = DIV32 Raw
Velocity = (velocity + 5 )/10

Just remember that the accuracy decreases with higher speeds. Not much use for tenths of ft/s when the raw data can't be more accurate than 3 ft/s.
Raw = 2000 gives 6000 ft/s
Raw = 2001 gives 5997 ft/s

/Ingvar