Shop OBEX P1 Docs P2 Docs Learn Events
Reading from the SIN table in ROM — Parallax Forums

Reading from the SIN table in ROM

HarpritHarprit Posts: 539
edited 2015-03-20 12:18 in Propeller 1
When I use

sineval[Y]:=(word[(($E000+(2047)*Y/90))]*10000/65536)

to read from the sine tables in ROM, I do not get values that are
exact for some values from 0 to 90 in steps of 1.
This is for fast circular move segments for a CNC machine.

I should get numbers between 0 and 10000 so I can use integer math.
What am I doing wrong?

H

.

Comments

  • Tracy AllenTracy Allen Posts: 6,664
    edited 2015-03-19 11:28
    Does the value of Y go from 0 to 90 as integer?

    The precision of the fraction 10000/65536 can be improved by using the ** operator. Note that 655360000 / (2^32) = 100000/65536. The sine table goes all the way 0 to 90 inclusive with a word at location 2048, so use 2048 instead of 2047.

    sineval[Y] := word[ $E000][ 2048*Y/90] ** 655360000

    Also maybe better roundoff in the division by 90.

    sineval[Y] := word[ $E000][ (4096*Y/90 + 1)/2] ** 655360000
  • HarpritHarprit Posts: 539
    edited 2015-03-19 12:04
    Yes it goes from 0 to 90 as an integer.

    I will put your suggestions in my program and get back to the forum.
    Thanks
    H
  • HarpritHarprit Posts: 539
    edited 2015-03-19 13:08
    We need to take it in steps so we can see where I go wrong.

    The manual says there are 2049 16 bit values in the table starting at $E000
    These 2049 values (in 4098 bytes) cover 90 degrees inclusive but go to a wee bit under 90 degrees
    So each degree starting address is 2049/90 words apart. (90 16 bit values =180 8 bit values).
    The best value for 45 degrees would start at byte $E000+1024 or $E000+1025 or be the average of the two values.
    So the formula for each degree is

    sine(Y):=(word[(($E000+(2049)*Y/45))]*10000/65535)

    This works fine but there is an error of between -2 and +7 parts per 10000 on the results as compared with my HP calculator.
    This works OK for a CNC machine but it would be better if it could be eliminated. We need to get things as right as possible.
    There will be plenty of other mechanical problems.

    Using your formula

    sineval[Y] := word[ $E000+2048*Y/90] ** 655360000

    modified to

    sineval[Y] := word[ $E000+2048*Y/45] ** 655360000

    works, the error shifts but the error is not eliminated.

    H
  • Dave HeinDave Hein Posts: 6,347
    edited 2015-03-19 13:20
    Since the table only has about 2000 entries you would expect an error of 1 out of 2000, which which is 5 out of 10000. You could get better results by adding the fractional bits times the slope. The slope of sin(x) is cos(x), so you could look up the slope from the table also. However, that's quite a bit of extra computation, and you might be better off using floating point routines running in a separate cog if you need higher accuracy.
  • Tracy AllenTracy Allen Posts: 6,664
    edited 2015-03-19 15:16
    Harprit, take a look at this thread and links within it, maybe some good insight for you.
    http://forums.parallax.com/showthread.php/117437-Sin-Table-Printout

    I don't understand, how did you manage
    word[ $E000+2048*Y/90]
    modified to
    word[ $E000+2048*Y/45]
    Those are quite different!
    edit: the addresses have to be even numbers word[ $E000 + even number]
    or use this syntax, word[ $E000][2048*Y/90]

    My roundoff, word[ $E000][((4096*Y/90+1)/2)] was attempt to cut the error in half by rounding both up and down. To improve the result, I agree with Dave that you will need to interpolate.
  • AribaAriba Posts: 2,690
    edited 2015-03-19 19:32
    Here is a simple interpolating sine table read out:
        i := 65536*Y/90
        p := i>>4 + $E000
        i := i & 31
        sineval[Y] := ((word[p+2]-word[p])*i/32 + word[p]) ** 655360000
    
    Andy
  • Mark_TMark_T Posts: 1,981
    edited 2015-03-20 03:33
    Harprit wrote: »
    We need to take it in steps so we can see where I go wrong.

    The manual says there are 2049 16 bit values in the table starting at $E000
    These 2049 values (in 4098 bytes) cover 90 degrees inclusive but go to a wee bit under 90 degrees
    So each degree starting address is 2049/90 words apart. (90 16 bit values =180 8 bit values).

    No, the table covers 0 to 90 degrees inclusive, so the correct factor is 2048/90. The $FFFF value
    represents 1.0, not 0.999985

    Try
    sineval[Y] := word[ $E000][ (4096*Y/90 + 1)/2] ** 655370000 ' or
    sineval[Y] := word[ $E000][ (4096*Y/90 + 1)/2] * 10000 / 65535
    
    Yes, 655370000 is correct, its the closest integer to 10000 * 2^32 / 65535
  • Mark_TMark_T Posts: 1,981
    edited 2015-03-20 03:39
    By the way why it's not actually necessary to use sin/cos to do circles - Bressenham's and similar DDA algorithms will do.
    Yes, there is an issue with constant velocity, but there are ways to handle that.

    With the Prop the sin table is extremely useful of course, and good enough for all but most exacting CNC applications. However
    the multiply you need to do after looking up the table is a big hit.
  • HarpritHarprit Posts: 539
    edited 2015-03-20 07:13
    Thanks to all for the enlightening help.
    I continue to be amazed by the Prop forum.
    H
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2015-03-20 12:18
    Late to the party, but here's a thread that might be of interest:

    http://forums.parallax.com/showthread.php/116047-Renormalizing-the-Sine-Table

    -Phil
Sign In or Register to comment.