# Compass radians to direction calculation

#### jjw

##### Member
Hi J,
C.
You have commented out the function abs ( ....
Variable arg belongs to abs function, don't use it outside the function.

#### camerart

##### Active Member
You have commented out the function abs ( ....
Variable arg belongs to abs function, don't use it outside the function.
Hi J,
Can you tell, I'm not a hot programmer yet

If you look at my reply #19, when I said "It can't be negative" I meant after the program I attached, the result is now positive, so is ABS needed now?
C

#### Attachments

• 196.7 KB Views: 3

#### jjw

##### Member
Abs is not needed now, but do you want to calculate the angles with words or longs ?

#### camerart

##### Active Member
Abs is not needed now, but do you want to calculate the angles with words or longs ?
Hi J,

I'm not sure. Eventually, the result will be used in calculations. I hope the result will be between 0 and 359.
C.

#### Pommie

##### Well-Known Member
Ok, lets try again.

Assuming x_raw and y_raw are 16 bit variables read directly from the compass then we need to split them into their component parts.
sx=1 if x_raw was negative else 0 and ux is the positive value of x_raw. Ditto y values.
Code:
dim sx,sy,comp as byte
dim ux,uy,degrees as word
if x_raw>32767 then
ux=65535-x_raw
ux=ux+1
sx=1
else
ux=x_raw
sx=0
endif
if y_raw>32767 then
uy=65535-y_raw
uy=uy+1
sy=1
else
uy=y_raw
sy=0
endif
Now we have these parts we can use them to calculate an angle.
This produces a word variable between 0 and 359.
Code:
if ux>uy then
degrees=uy*45/ux
oct=1
else
degrees=ux*45/uy
oct=0
endif
comp=0
if degrees>22
if degrees<44
comp=comp+1
endif
if degrees<41
comp=comp+1
endif
if degrees<37
comp=comp+1
endif
if degrees<32
comp=comp+1
endif
else
if degrees>2
comp=comp+1
endif
if degrees>6
comp=comp+1
endif
if degrees>10
comp=comp+1
endif
if degrees>15
comp=comp+1
endif
endif
degrees=degrees+comp
if oct>0
degrees=90-degrees
endif
if sy>0
if sx>0
degrees=180+degrees
else
degrees=180-degrees
endif
else
if sx>0
degrees=360-degrees
endif
endif
After the above degrees will contain the answer.

Mike.
Edit, the above code is not self explanatory. It is written this way to avoid any floating point numbers and trigonometry functions.

Last edited:

#### large_ghostman

##### Well-Known Member
Thats really elegant without having to mess with floats or a dedicated maths unit. I will probably use that with the M3 core.

#### camerart

##### Active Member
Ok, lets try again.

Assuming x_raw and y_raw are 16 bit variables read directly from the compass then we need to split them into their component parts.
sx=1 if x_raw was negative else 0 and ux is the positive value of x_raw. Ditto y values.

Now we have these parts we can use them to calculate an angle.
This produces a word variable between 0 and 359.

After the above degrees will contain the answer.

Mike.
Edit, the above code is not self explanatory. It is written this way to avoid any floating point numbers and trigonometry functions.
Hi M,
Thanks very much for the code and the clear explanation.

Yes, x_raw and y_raw are 2's compliment 16 BIT variables.

Can I clarify that the orange sections in my attachment are now not needed?

Are the digits inside the blue squares typos, and should be 32767?

I get an error in Oshonsoft when compiling, see red lines, I'll try to figure it out.

Cheers, C.

#### Attachments

• 153.6 KB Views: 7

#### ericgibbs

##### Well-Known Member
hi C,
A Dim, is allowed only one label per line.
E

#### Pommie

##### Well-Known Member
Hi C,
The orange section isn't needed.
The numbers should be 32767.
The errors are (as Eric pointed out) because the DIMs need to be split onto separate lines.

I'm assuming you have 3 values raw x, y & z. Use the two that give you the plane you want the direction in.

Mike.

#### camerart

##### Active Member
Hi, M and E,
Here's the code that works, and gives interesting results when PCB is compared to a compass, see attachments.
I'm pretty sure that X and Y are used for direction and Z is used possibly for tilt?
Thanks,
C.

#### Attachments

• 1.3 KB Views: 4
• 306 bytes Views: 5

#### Pommie

##### Well-Known Member
Don't have time to check it now but looks like I messed up the quadrant part of the code. Will check tomorrow - Saturday night here, time to party.
I have a GY-271 board and, if it's flat, X and Y give the compass bearing.

Mike.
Edit, just noticed ux & uy are bytes - they should be words.

Last edited:

#### jjw

##### Member
You have calculated two times the 2's complement of y_raw
so y_raw is always positive and the sign sy is always 0.
Could you show all x_raw and y_raw values before 2's complement and angles.
2's complement calculations are missing +1 at the end.

Edit: this was a response to Camerart

Last edited:

#### camerart

##### Active Member
Don't have time to check it now but looks like I messed up the quadrant part of the code. Will check tomorrow - Saturday night here, time to party.
I have a GY-271 board and, if it's flat, X and Y give the compass bearing.

Mike.
Edit, just noticed ux & uy are bytes - they should be words.
Hi M,
No hurry.
I can see a kind of pattern.
C

#### Pommie

##### Well-Known Member
Did you change ux and uy to words?

Mike.

#### camerart

##### Active Member
Hi M,
Yes, I changed UX and SX to WORDs.

I added 'degrees = 360 - degrees', to make it read clockwise instead of anti-clockwise, is this ok?

I'm now getting these readings, but I didn't have much time, so I'll try again.
C

#### Attachments

• 142 bytes Views: 6

#### Beau Schwabe

##### Member
Pommie,

Nice code !! .... I'm working on something very similar in Assembly

in your initial stage ux, and uy can be determined by XORing the MSB with a "1"

in your second stage, instead of using 45 to multiply the lowest number and dividing by the highest number, I am multiplying by 128 which is a simple shift left in Assembly language. Division is done by subtraction until there is an underflow. The result is used against a lookup table which effectively does what you have accomplished in a series of IF statements. The lookup table allows for at least 1/2 a Deg resolution.

#### Pommie

##### Well-Known Member
In the initial code I posted I multiply by 32 and adjust so a full circle is 256 degrees. The ux, sx bit is due to the limitations of oshonsoft - it can't handle negative integers!!

Due to your comment I've just realised that an overflow may be taking place (even more so if times 128). My compass module never returns a value greater than 1000 so overflow isn't a problem, the OPs compass may be different and cause errors due to overflow. Cam, do you have actual values from your compass?

Mike.

#### camerart

##### Active Member
In the initial code I posted I multiply by 32 and adjust so a full circle is 256 degrees. The ux, sx bit is due to the limitations of oshonsoft - it can't handle negative integers!!

Due to your comment I've just realised that an overflow may be taking place (even more so if times 128). My compass module never returns a value greater than 1000 so overflow isn't a problem, the OPs compass may be different and cause errors due to overflow. Cam, do you have actual values from your compass?

Mike.
Pommie,

Nice code !! .... I'm working on something very similar in Assembly

in your initial stage ux, and uy can be determined by XORing the MSB with a "1"

in your second stage, instead of using 45 to multiply the lowest number and dividing by the highest number, I am multiplying by 128 which is a simple shift left in Assembly language. Division is done by subtraction until there is an underflow. The result is used against a lookup table which effectively does what you have accomplished in a series of IF statements. The lookup table allows for at least 1/2 a Deg resolution.
Hi B,
Can you verify, that your code works with Oshonsoft, as sometimes there are oddities?
C

#### camerart

##### Active Member
Hi J and P,
I can set, to READ 2x X_raw and 2x Y_raw, Which angles should I READ? e,g, 360 x 6 readings is a lot, so not too many please. Best not to choose exactly as the code changes if possible.

EDIT: Note Oshonsoft needs a THEN for each IF.

Is this all ok ''OCT''
Dim sx As Byte
Dim sy As Byte
Dim comp As Byte
Dim ux As Word
Dim uy As Word
Dim degrees As Word
Dim strdegrees As String
Dim oct As Byte '?????????????????????????????

C.

Last edited: