Calculation Problem - value goes to zero after 65


Closed Thread
Results 1 to 15 of 15
  1. #1
    Join Date
    Feb 2005
    Location
    Bellevue
    Posts
    125

    Question Calculation Problem - value goes to zero after 65

    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

  2. #2
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    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

  3. #3
    Join Date
    Jul 2003
    Location
    Sweden
    Posts
    237


    Did you find this post helpful? Yes | No

    Post

    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

  4. #4
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    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.
    Code:
    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 + Dummy
    This will hold the result to +/- 1/2 Least Significant Digit.

    Best regards,
       Darrel
    Last edited by Darrel Taylor; - 28th June 2005 at 18:23.

  5. #5
    Join Date
    Jul 2003
    Location
    Sweden
    Posts
    237


    Did you find this post helpful? Yes | No

    Talking

    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/...311/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

  6. #6
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    Ingvar,

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

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

    OK, I'll quit now,
       Darrel

  7. #7
    Join Date
    Jul 2003
    Location
    Sweden
    Posts
    237


    Did you find this post helpful? Yes | No

    Talking Reducing even further .....

    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 .....
    Code:
    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 ;-)

  8. #8
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    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"
    Code:
    @Dec_Speed = _ssmax + 17
    Dec_Speed   VAR  WORD  EXT
    Zero Code.

    Think we can reduce it even farther??

    Darrel

  9. #9
    Join Date
    Dec 2003
    Location
    Wichita KS
    Posts
    511


    Did you find this post helpful? Yes | No

    Default

    Hello Darrell,,


    Darrell>>Zero Code.

    Think we can reduce it even farther?? <<


    There goes the bankruptsy of Pkzip....

    Dwayne
    Ability to Fly:
    Hurling yourself towards the ground, and missing.

    Engineers that Contribute to flying:
    Both optimists and pessimists contribute to the society. The optimist invents the aeroplane, the pessimist the parachute

    Pilots that are Flying:
    Those who know their limitations, and respect the green side of the grass...

  10. #10
    Join Date
    Jul 2003
    Location
    Sweden
    Posts
    237


    Did you find this post helpful? Yes | No

    Thumbs up

    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

  11. #11
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    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.
    Code:
    @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

  12. #12
    Join Date
    Oct 2009
    Location
    Utah, USA
    Posts
    427


    Did you find this post helpful? Yes | No

    Default

    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


    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

  13. #13
    Join Date
    Oct 2009
    Location
    Utah, USA
    Posts
    427


    Did you find this post helpful? Yes | No

    Default

    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!! .

    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

  14. #14
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    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>
    Last edited by Darrel Taylor; - 9th March 2010 at 02:17.
    DT

  15. #15
    Join Date
    Oct 2009
    Location
    Utah, USA
    Posts
    427


    Did you find this post helpful? Yes | No

    Default

    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.
    Code:
    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

Similar Threads

  1. Problem to compile my program
    By wagner in forum Off Topic
    Replies: 5
    Last Post: - 7th July 2008, 20:17
  2. USART Problem , but don't know where, in pc? or in PIC?
    By precision in forum mel PIC BASIC Pro
    Replies: 0
    Last Post: - 15th July 2007, 08:12
  3. Microcode Studio 18f2455 problem?????
    By volkan in forum mel PIC BASIC Pro
    Replies: 11
    Last Post: - 21st May 2007, 21:04
  4. calculation problem
    By nicolelawsc in forum mel PIC BASIC Pro
    Replies: 2
    Last Post: - 31st March 2006, 15:23
  5. 1 slave 1 master 1 MAX232 1 problem ?
    By SuB-ZeRo in forum mel PIC BASIC Pro
    Replies: 19
    Last Post: - 31st July 2005, 22:59

Members who have read this thread : 1

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts