Searching \ for 'calculate arcTan on a PIC' in subject line. () Help us get a faster server
FAQ page: www.piclist.com/techref/microchip/devices.htm?key=pic
Search entire site for: 'calculate arcTan on a PIC'.

Truncated match.
'calculate arcTan on a PIC'
1999\04\13@190655 by  OK, now I'm starting to spin my wheels,

What would be the best way to calculate
an arcTangent with a PIC?

I have 2 values, x and y, values are 0-100,
I need to find an angle by taking the
arcTan of (y/x).

thanks
Jason Wolfson  > What would be the best way to calculate
> an arcTangent with a PIC?

Me, I'd use a lookup table.  A 200 bytes table would do it (2 bytes per entry), Intermediate values
could be easily calculated by interpolation with a minimum error between
each table entry. For example:

X/Y could be from 0 to 1, equivalent to 0 to 45¡
(from 45¡ to 90¡ is the same as ATan(Y/X).

Table entry 000 = 00000, representing 0¡
Table entry 100 = 45000, (AFC8h) representing 45¡.
(Table values means angle times 1000).

Considere X/Y = 0.167,
table entry 16 is "9090" (2382h) [9.090¡]
table entry 17 is "9648" (25B0h) [9.648¡]
so 9648-9090 = 558 (table step). [0.558¡]

The third decimal digit from the division x/y is 7, means 70% from 0.16
and 0.17, so the correspondent interpolation is 558 x 70% = 390.6
(multiplication routine rounds to 391) [0.391¡], that you need to add to
the 16th table entry "9090", so the result would be decimal 9481
(2509h),

Convert it (2509h) to decimal (9481) and let three digits after the
decimal point, resulting in 9.481¡. The real ATan(0.167) =
9.480903...¡, so a 0.001% of error in a 16 bits table is pretty good.

Whenever Y > X, invert the formula, use Y/X instead and the result would
be 90¡ less the angle found.

To increase the resolution, increase the table entries from 100 to 200.

Wagner

Jason Wolfson wrote:
{Quote hidden}  At 19:02 04/13/99 -0400, Jason Wolfson wrote:
>OK, now I'm starting to spin my wheels,
>
>What would be the best way to calculate
>an arcTangent with a PIC?
>
>I have 2 values, x and y, values are 0-100,
>I need to find an angle by taking the
>arcTan of (y/x).

like dave said, a table is probably the best. look at scott dattalo's sine
function for a 2-dim example. but you either have 3 dimensions (like
(x,y)->angle) or do a division first, and then you'd possibly have to cope
with a big range of possible values. depends on range/precision/resolution
requirements.

ge   On Tue, 13 Apr 1999, Jason Wolfson wrote:

> OK, now I'm starting to spin my wheels,
>
> What would be the best way to calculate
> an arcTangent with a PIC?
>
> I have 2 values, x and y, values are 0-100,
> I need to find an angle by taking the
> arcTan of (y/x).

I don't have the arctan(y/x) function, but I've got the arcsin which is
pretty close (epecially for small angles). It's attached below. It's a
look up table with first-order (linear) interpolation solution. You see
other examples here:

http://www.interstice.com/~sdattalo/technical/software/pic/picsine.html

and

http://www.interstice.com/~sdattalo/technical/software/pic/piclog.html

for sin(x) and log(x) solutions.

;----------------------------------------------------------
;
;arcsine
;
;  The purpose of this routine is to take the arcsine of an
;8-bit number that ranges from 0 < x < 255/256. In other
;words, the input, x, is an unsigned fraction whose implicit
;divisor is 256.
;  The output is in a conveniently awkward format of binary
;to pi/2 for the normal arcsine function. Specifically, this
;algorithm computes:
;
; arcsine(x) = real_arcsine(x/256) * 256 / (pi/2)
;
;  where, real_arcsine returns the real arcsine of its argument
;
;  The algorithm is a table look-up algorithm plus first order
;linear interpolation. The psuedo code is:
;
;unsigned char arcsine(unigned char x)
;{
;  unsigned char i;
;
;  i = x >> 4;
;  return(arcsin[i] + ((arcsin[i+1] - arcsin[i]) * (x & 0xf))/16);
;}
;
;
;  The accuracy is reasonable for x<150 or so. After that, the
;relatively steep arcsine severly deviates from a straight line
;approximation. The maximum error is around 5.

arcsine

SWAPF   x,W
ANDLW   0xf
MOVWF   temp                    ;Temporarily store the index
CALL    arc_sine_table          ;Get a2=asin( (x>>4) + 1)
MOVWF   result                  ;Store temporarily in result

DECF    temp,W                  ;Get the saved index
CALL    arc_sine_table          ;Get a1=asin( (x>>4) )

SUBWF   result,W                ;W=a2-a1, This is always positive.
SUBWF   result,F                ;a1 = a1 - (a1-W) = W

CLRF    temp                    ;Clear the product
CLRC

BTFSC   x,0
RRF     temp,F
CLRC

BTFSC   x,1
RRF     temp,F
CLRC

BTFSC   x,2
RRF     temp,F
CLRC

BTFSC   x,3
RRF     temp,W

RETURN

arc_sine_table
RETLW   0
RETLW   10     ;asin(1/16) = 3.583deg * 256/90
RETLW   20
RETLW   31
RETLW   41
RETLW   52
RETLW   63
RETLW   74
RETLW   85
RETLW   97
RETLW   110
RETLW   124
RETLW   138
RETLW   154
RETLW   173
RETLW   198
RETLW   240  >
>What would be the best way to calculate
>an arcTangent with a PIC?
>
>I have 2 values, x and y, values are 0-100,
>I need to find an angle by taking the
>arcTan of (y/x).
>

If speed is a must or you do not want to spend a lot of time coding,  I
think that the best way is a lookup table, but memory space maybe will be a
problem, 100*100 values are 10.000 possible results. Perhaps if you discard
some (or a lot) not resolutive values (mostly around x/y ~ +-pi/2) and fill
the EEPROM of a PIC..

If space is a must, I think that the best approach is to implement the
Taylor series of  the arcTan(x/y), but surely this will be hard to code, or
at least not very easy. Sorry, I don't remember now the Taylor serie of an
arcTan, but you could find easily in a lot of calculus books.

Hope this help  Jason,
I've looked into this, but never implemented it. However, the first thing
you need to do is determine the level of accuracy required. The method I'll
outline will give you accuracy to about a sixth of a degree. The tangent
like all trig functions repeats in absolute value through each quadrant. The
quadrant that you are in is determined by the sign of x and y. In addition,
in each quadrant, one end is asymptotic because the denominator approaches
0. However, you will find that the asymptotic half of each quadrant is the
inverse of the half that is less than one. Therefore, if you divide by the
greater of x or y, you can always have a well behaved output (no divide by 0
problems). Since this is an 8-bit processor, you can get a ratio up to the
range of 0-255 (scqle your division operation to produce this). If you use
this ratio value as an offset address into a look-up table, you can return a
angular value in the range 0 to 45 degrees.  Then you do a little
housekeeping.

Assuming the variable "angle" is in the range 0-45 degrees, then

If y>x then  angle = 90 - angle

if x<0 and y<0 then angle = angle +180

if x<0 and y>0 then angle = 180 - angle

if x>0 and y<0 then angle = 0 - angle

I notice that your x and y values are in the range 0-100. If this means that
selection process. If a value of 50 is your zero level, then adjust the
quadrant selection accordingly. Also, if you need less than 1/6 degree
resolution, then just use a smaller lookup table, and adjust your division
process accordingly. If you need more resolution, you have to go to 16 bits.

Since I have to actually implement this as soon as time allows, I'd
appreciate it if you let me know how the project went.
Good Luck,
Paul Kolesnikoff

{Original Message removed}  Paul,
The 8-quadrant, <1 X/Y method is what I have come to the
conclusion is best also. I only need 1 degree accuracy.
I will have to do a fixed point division to do an interpolation,
but it looks like it will work great with only a 25 element table.

I'll send an update as soon as I'm done and it's working.
thanks for all the help, especially Scott and Wagner who pointed me in this
direction!

thanks
Jason Wolfson...

{Quote hidden}

>               {Original Message removed}

More... (looser matching)
- Last day of these posts
- In 1999 , 2000 only
- Today
- New search...