Truncated match.
PICList
Thread
'calculate arcTan on a PIC'
1999\04\13@190655
by
Jason Wolfson
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 0100,
I need to find an angle by taking the
arcTan of (y/x).
thanks
Jason Wolfson
1999\04\13@191520
by
Dave VanHorn
> What would be the best way to calculate
> an arcTangent with a PIC?
Me, I'd use a lookup table.
1999\04\13@200513
by
wagnerl

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 96489090 = 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}>
> 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 0100,
> I need to find an angle by taking the
> arcTan of (y/x).
>
> thanks
> Jason Wolfson
1999\04\13@210607
by
Gerhard Fiedler
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 0100,
>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 2dim 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
1999\04\13@210614
by
Scott Dattalo

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 0100,
> 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 firstorder (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
;8bit 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
;radians (brads?). The output corresponds to the range of zero
;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
;in radians.
;
; The algorithm is a table lookup 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
ADDLW 1
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=a2a1, This is always positive.
SUBWF result,F ;a1 = a1  (a1W) = W
CLRF temp ;Clear the product
CLRC
BTFSC x,0
ADDWF temp,F
RRF temp,F
CLRC
BTFSC x,1
ADDWF temp,F
RRF temp,F
CLRC
BTFSC x,2
ADDWF temp,F
RRF temp,F
CLRC
BTFSC x,3
ADDWF temp,F
RRF temp,W
ADDWF result,F
RETURN
arc_sine_table
ADDWF PCL,F
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
1999\04\14@060956
by
Sebasti‡n Dols
>
>What would be the best way to calculate
>an arcTangent with a PIC?
>
>I have 2 values, x and y, values are 0100,
>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
1999\04\15@134123
by
Kolesnikoff, Paul

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 8bit processor, you can get a ratio up to the
range of 0255 (scqle your division operation to produce this). If you use
this ratio value as an offset address into a lookup 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 045 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 0100. If this means that
all your angles are in the first quadrant, then you can skip the quadrant
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}
1999\04\15@140209
by
Jason Wolfson

Paul,
The 8quadrant, <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}>
>
> 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 8bit processor, you can get a ratio up to the
> range of 0255 (scqle your division operation to produce this). If you use
> this ratio value as an offset address into a lookup 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 045 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 0100. If this
> means that
> all your angles are in the first quadrant, then you can skip the quadrant
> 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}
More... (looser matching)
 Last day of these posts
 In 1999
, 2000 only
 Today
 New search...