Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Compass radians to direction calculation

Status
Not open for further replies.
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

  • ABS2.jpg
    ABS2.jpg
    196.7 KB · Views: 310
Abs is not needed now, but do you want to calculate the angles with words or longs ?
 
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.
 
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:
Thats really elegant without having to mess with floats or a dedicated maths unit. I will probably use that with the M3 core.
 
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

  • Check.jpg
    Check.jpg
    153.6 KB · Views: 314
hi C,
A Dim, is allowed only one label per line.
E
 
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.
 
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

  • COMPASS CALC.txt
    1.3 KB · Views: 291
  • Compass comparison.txt
    306 bytes · Views: 314
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:
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:
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.
Enjoy your evening.
C
 
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

  • Compass.txt
    142 bytes · Views: 275
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.
 
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.
 
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
 
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:
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top