PDA

View Full Version : Calculation Problem - value goes to zero after 65



Tom Gonser
- 28th June 2005, 01:22
I have a very simple equation which works fine from 0 to 65 (MPH in this case), but when it goes above this speed, it shows 1,2,3 MPH... Somehow my variable is overloading and looping back to 0 again.. has anyone seen this before?

I pick up data from an array - equating to speed in Knots:

SSD4= (ssmax[18]>>4)
SSD3= (ssmax[18] & $f)
SSD2= (ssmax[17]>>4)
SSD1= (ssmax[17] & $f)

Then convert to Decimal:
Dec_speed=(ssd4*4096)+(ssd3*256)+(ssd2*16)+ssd1 ' convert to dec

Then convert to MPH:
Dec_speed = (Dec_speed*115)/100

Then display it:

LCDout $fe, L4, " Speed:",#Dec_speed dig 3, #Dec_speed dig 2,#Dec_speed dig 1, ".",dec1 Dec_speed

What I see works great until 65mph, and then it starts over at zero again.. at 10mph I am actually going 75mph...

The Dec_Speed variable is a word..

Looking at the values for KNOTS that I get in the data, it is an 'implied' decimal, so the speed calculation looks like the following going from (520) 52.0 knots to (572) 57.2 knots... As you can see at 57.0 knots the equation is generating a value greater than 65,536.. thus it is wrapping...

Question is WHAT does one do about this?

Knots MPH
520 59800 59.8
521 59915 59.915
522 60030 60.03
523 60145 60.145
524 60260 60.26
525 60375 60.375
526 60490 60.49
527 60605 60.605
528 60720 60.72
529 60835 60.835
530 60950 60.95
531 61065 61.065
532 61180 61.18
533 61295 61.295
534 61410 61.41
535 61525 61.525
536 61640 61.64
537 61755 61.755
538 61870 61.87
539 61985 61.985
540 62100 62.1
541 62215 62.215
542 62330 62.33
543 62445 62.445
544 62560 62.56
545 62675 62.675
546 62790 62.79
547 62905 62.905
548 63020 63.02
549 63135 63.135
550 63250 63.25
551 63365 63.365
552 63480 63.48
553 63595 63.595
554 63710 63.71
555 63825 63.825
556 63940 63.94
557 64055 64.055
558 64170 64.17
559 64285 64.285
560 64400 64.4
561 64515 64.515
562 64630 64.63
563 64745 64.745
564 64860 64.86
565 64975 64.975
566 65090 65.09
567 65205 65.205
568 65320 65.32
569 65435 65.435
570 65550 65.55
571 65665 65.665
572 65780 65.78


TG

Darrel Taylor
- 28th June 2005, 01:51
Hi TOM,

I think it's overflowing in this statement

Dec_speed = (Dec_speed*115)/100

This shoud work better

Dec_speed = Dec_speed*115
Dec_speed = DIV32 100

HTH,
  Darrel

Ingvar
- 28th June 2005, 10:31
If you want to speed it up and add some accuracy you could use....

Dec_speed = Dec_speed + (Dec_speed ** 9882)

..... this will give you 1kn = 1.1507873mph which is darn close to the 1.15078030303 it should be.

/Ingvar

Darrel Taylor
- 28th June 2005, 18:16
That's good Ingvar, got me thinking.

But, since we're going for accuracy too.

1 Nautical Mile = 6076.11549 Feet
1 Mile = 5280 Feet

So the conversion is 1.150779449 (6076.11549/5280), and the number we need is [0.150779449 * 65536] or 9881.482. It's closer to 9881 than 9882

But the biggest problem is with the integer nature of the calculation. Most of the added accuracy is lost in the Low Word of the ** multiplication..

For instance, at 45.0 knots, the MPH is 51.78 MPH (45 * 1.150779449) which is closest to 51.8 MPH.
However, either of our previous formula's will only show 51.7 MPH.

Here's another way that does the same thing as the **, but also allows you to round the result according to the low Word of the multiplication.
Dummy = Dec_speed * 9881
Dummy = R0 ; Get High Word of Multiply result
IF R2 > 32768 then Dummy = Dummy + 1 ; Round to nearest .1 MPH
Dec_speed = Dec_speed + DummyThis will hold the result to +/- 1/2 Least Significant Digit.

Best regards,
   Darrel

Ingvar
- 29th June 2005, 13:43
Hi Darrel,

Isn't it wonderful when we try to improve the accuracy with about half a ppm .... and the world has hardly descided how long a nautical mile really is. I got "1 knot = 1.15078030303 mph" from http://www.geocities.com/TheTropics/Shores/7311/ktmph.html , but after doing a little more digging around, i now agree with you. It shows that you can't really trust anything you find on the net.

BTW, i really like the way you do the rounding, i can imagine that beeing speedy in assembler ....... i just might steal it sometime ;-)

Just to be a pain, i'll show how i'd do this calculation with rounding(and adding that extra little accuracy). Perhaps someone will find it useful.

Dec_speed = ((Dec_speed */ 2946) + 5) / 10

It's probably a little slower than your method since it involves a division.

/Ingvar

Darrel Taylor
- 30th June 2005, 05:20
Ingvar,

OK, now we're getting silly, but I just can't resist.

Same thing as before, With Rounding, less code.
Dummy = Dec_speed * 9881
Dec_speed = R0 + R2.15 + Dec_speedSaved 30 Words in the process.

OK, I'll quit now,
   Darrel

Ingvar
- 30th June 2005, 10:13
While were on the task of reducing and optimizing Toms code, i feel a strong urge to reduce .......

SSD4= (ssmax[18]>>4)
SSD3= (ssmax[18] & $f)
SSD2= (ssmax[17]>>4)
SSD1= (ssmax[17] & $f)

Then convert to Decimal:
Dec_speed=(ssd4*4096)+(ssd3*256)+(ssd2*16)+ssd1 ' convert to dec ..... into .....


Dec_speed.HighByte = ssmax[18]
Dec_speed.LowByte = ssmax[17]
...... thus saving time, codespace and ram ... you name it.

How about it Darrel, want a shot at it ;-)

Darrel Taylor
- 30th June 2005, 20:01
Good eye Ingvar,

I didn't even notice that he was Ripping them apart, just to re-assemble them back exactly like they were. That's a pretty big code savings.

And, here's my "Shot at it"

@Dec_Speed = _ssmax + 17
Dec_Speed VAR WORD EXTZero Code.

Think we can reduce it even farther?? :)

Darrel

Dwayne
- 30th June 2005, 20:40
Hello Darrell,,


Darrell>>Zero Code.

Think we can reduce it even farther?? <<


There goes the bankruptsy of Pkzip....

Dwayne

Ingvar
- 1st July 2005, 10:03
Ouch, i believe your "Shot at it" found it's target ..... sinking .... mayday. It's difficult to beat zero code, really difficult ...... sort of impossible.

However, i want to point out that if you change the value of "Dec_Speed" you infact change the values in the array(ssmax17&18). This makes it impossible to use for other tasks, not a problem in this application(i hope). I bet you know that but some people find it difficult to get their head around this.

Good job!

/Ingvar

Darrel Taylor
- 2nd July 2005, 05:38
All true, I guess it's Bad Form to re-use variables like that.

So here it is. The End all, Be all solution to Tom's Knot to MPH conversion.
@Knots = _ssmax + 17
Knots VAR WORD ext

Dec_speed = Knots * 9881
Dec_speed = R0 + R2.15 + Knots
That way it preserves the original Knots value and calculates Dec_speed from it.

Ok, now I really quit. :)

Darrel

Heckler
- 5th March 2010, 05:27
Darrel, Ingvar,

I hope you do not mind dusting off this OLD thread. :)

Quote by Ingvar... "I bet you know that but some people find it difficult to get their head around this."

Boy was he right...:D Very interesting but difficult to follow for a newbie.


I am also trying to convert knots and fractional knots to mph.h

Darrel could you please explain/elaborate on the code from your last post...

@Knots = _ssmax + 17
Knots VAR WORD ext

Dec_speed = Knots * 9881
Dec_speed = R0 + R2.15 + Knots

I thought that "@" usually proceeds "one line of assembly code"

As I read through this thread, I was not able to follow with much clarity.

In my gps program I end up with two variables containing integer knots and decimal knots.

If we assume the variables used are knots (whole knots) and knotsten (fractional knots) how would I apply your final code to provide mph.h?

Thanks much
Dwight

Heckler
- 5th March 2010, 16:48
I wish one could edit their own posts for a longer time than just 1 hour after posting.
I would like to clarify my question posted above...
Darrel, Ingvar,

I hope you do not mind dusting off this OLD thread.

Quote by Ingvar... "I bet you know that but some people find it difficult to get their head around this."

Boy was he right... Very interesting but difficult to follow for a newbie.


I am also trying to convert knots and fractional knots to mph.h

Darrel could you please explain/elaborate on the code from your last post...

@Knots = _ssmax + 17
Knots VAR WORD ext

Dec_speed = Knots * 9881
Dec_speed = R0 + R2.15 + Knots

1. I thought that "@" usually proceeds "one line of assembly code"?
2. The last two lines of your code equates "Dec_speed" to one thing and then another thing. Doesn't the second line negate the first? Or, is the code shown out of context?
3. What are the items "R0" and "R2.15"? variables? or math function?
As I read through this thread, I was not able to follow with much clarity, sorry, newbie alert!! :D.

In my gps program I end up with two variables containing integer knots and decimal knots.

If we assume the variables used are knots (whole knots) and knotsten (fractional knots) how would I apply your final code to provide mph.h? (miles per hour & fractional miles per hour)

Thanks much
Dwight

Darrel Taylor
- 9th March 2010, 01:32
1. I thought that "@" usually proceeds "one line of assembly code"?
It does, and that's what it is.
But he had the value stored in a specific location in an array, so you should just forget that part and make it ...

Knots VAR WORD

R0 and R2 are two of PBP's system variables.
When you do a multiplication (Knots * 9881), R2 has the low word of the result which also gets copied to Dec_speed.
And R0 has the High Word of the result, the same as if you did a Knots ** 9881, without having to do the multiplication a second time.

So yes, the second Dec_speed does "negate" the first one, but the result is still in R0 and R2 so it doesn't matter.


MPH = Knots * 1.150779
And 9881 / 65536 = 0.150772, which is as close as we can get with integer math. That's the decimal part.
The integer part is 1, so just adding Knots to the final result is the same thing.

R2.15 is the highest bit in the low word, so it indicates if the high word should be rounded up or down.

So all together, the multiplication does (Knots * 0.150772), the result is in R0, Round up if R2.15=1, then add Knots (knots * 1).

Clear as mud.
<br>

Heckler
- 12th March 2010, 05:10
Thanks Darrel,

sorry it took so long for me to get back to this thread...

here is my code as I have it now (seems to work ok)

I enter the subroutine having parsed the NMEA $GPRMC recieved from the GPS.

VAR "Knots" contains the integar value, VAR "Knotss" contains the decimal or fractional value of speed data recieved from the GPS.

CalcMPH:
arraywrite speed,[dec2 knots,dec2 knotss] 'combine knots and knotss into 4 byte array
arrayread speed,[dec4 kk] 'now get the 4 digit dec value of the array

mph = kk * 9881
mph = R0 + R2.15 + kk 'mph now contains 4 digit value of mph/tenths/hundredths

mphh = mph//100 'isolate tenths and hundredths
mphh = mphh/10 'eliminate the hundreths and keep tenths
mph = mph/100 'now keep integer mph, first two digits of 4 digit value
return



I would like to learn more about the use of system variables (R0, R2...) can you point me to where these are documented? I searched the 12f683 document and did not find them.


Thanks for your help.
Dwight