Go Down

### Topic: using math.h library (sin/cos/acos...) (Read 18487 times)previous topic - next topic

#### missmoun ##### Oct 11, 2006, 12:19 am
I'm trying to do some trigonometry in Arduino.
I need to calculate the distance between 2 points on a sphere. I have the math formula and i'm trying to translate it into Arduino.
I've added an include for the <math.h> library at top.

My main question is: How can i do cos/sin calculations in Arduino if it doesn't support floating points?

Can i write that part in C and insert it inside of Arduino? Would i make a C library that calls the math.h one and sends out results as longs or ints back to Arduino on request?...

Thanks lots.

#### mellis #1
##### Oct 11, 2006, 12:13 pm
The reason Arduino doesn't support floats is because the chip doesn't have for both the Arduino libraries, your program, and the code that performs floating point operations (which are rather complicated, and not support by the ATmega8 hardware).  That means that any code running on the chip (including straight C code), won't be able to use floating point.  You can try a couple of things.  One is doing the calculations on a computer and sending the results back to the board.  Or you could store a lookup table of sins/cos results in the program (but again, you're going to run out of space quickly).  Or you could try to approximate the formula with a simpler one that doesn't require any trigonometry.  If you explain a bit more about what you're trying to do and why, we might be able to come up with something.

#### missmoun #2
##### Oct 11, 2006, 04:32 pm
oh no. that's a little bit of bad news (thanks for the answer though).
What i am trying to do is this: i'm getting longitude latitudes readings from a GPS and i'm trying to calculate distance between 2 given points (thus the distance between 2 points on a sphere).
I first convert my degrees in radians then apply the maths.
And it's a wearable so a computer is not an option.
Is the ATmega168 chip any better than the ATmega8 (... i don't suppose it would be better enough).

#### mellis #3
##### Oct 11, 2006, 05:27 pm
The ATmega168 would probably work.  Or, depending on the accuracy you need, you could do something nasty like summing the difference in latitudes and the difference in longitudes to give you an approximate distance.

#### missmoun #4
##### Oct 11, 2006, 11:15 pm
Thanks a lot.
I'll try the other chip (and look into your ....horrible.... backup plan too) and post back if i came up with anything good.

#### TimI #5
##### Dec 09, 2006, 04:37 pm
Try a search on CORDIC (COrdinate Rotation DIgital Computer). These are the same algorithms used in handheld calculators. Here's a URL for implementing an integer version of sin and cos calculations on the Basic Stamp from Tracy Allen:
http://www.emesystems.com/BS2mathC.htm

There are also links from that page to other implementations. By scaling the values you can get fixed point (as opposed to floating point) results.

Good luck!

#### CosineKitty #6
##### Dec 10, 2006, 11:56 pm
Hello missmoun,

When I read that you are doing this for a wearable device, and that you are processing GPS data to find the distance between two points on the Earth, does that mean that the two points are likely to be very close together?  For example, if you are trying to figure out the distance around the Earth from Japan to England, you definitely need some complicated formulas.  On the other hand, if you just want the distance between two points that are very close together (like a few miles on a sphere the size of the Earth), you can greatly simplify things.

For points very close together, the straight-line distance will be a very good approximation for the curvilinear distance across the ground.  We simplify by assuming that we can break down the distance into an east-west distance (delta_x) and north-south distance (delta_y).

delta_x = cos((latitude1 + latitude2) / 2) * (longitude1 - longitude2) * earth_radius;
delta_y = (latitude1 - latitude2) * earth_radius;   // note that latitudes MUST be in radians!
approx_distance = sqrt (delta_x*delta_x + delta_y*delta_y);

This formula requires only one trig function: cosine.  If you are using this in a particular geographical area, you could do a really easy hack: just hard-code the value cos(your_latitude) into your program!  The formula for delta_x becomes:

delta_x = your_cosine_latitude * (longitude1 - longitude2) * earth_radius;

Then the only tricky math you have to do is sqrt, which is very easy to implement using divide-and-average.

#### kg4wsv #7
##### Dec 11, 2006, 01:45 am
I haven't used it, but a book I've seen recommended is Math Toolkit for Real-Time Programming by Jack Chrenshaw. I'm told it's as much or more for embedded than real-time.

If your two points are "close" together, you don't need to worry about the spherical components of the calculation.

another trick to keep in mind: you may be able to use integer or fixed point calculations instead of floats, depending on what kind of accuracy you need.  This saves a bunch of space.

-j

#### missmoun #8
##### Feb 26, 2007, 08:12 pm
Just to conclude on this topic. The distance calculation included locations all over the world so i had to keep the spherical aspect of the formula. Ended up just switching to an arduino mini, and using the atmega 168 has done the trick for using floating points and the math.h library.

#### xxzeenoxx #9
##### Mar 19, 2008, 03:08 am
I hate to resurrect an old thread, but how did you implement the code on the arduino.  I just began using the arduino and i was trying to implement the formula for the distance between two points on a sphere, but I was having no luck.  Could you maybe post what you had in your code for the formula?  Thanks.

#### g7nbp #10
##### Sep 09, 2008, 02:43 pm
I just spotted this:

http://www.maartenlamers.com/nmea/gps-nav-001.html

Its a complete lib for NMEA decoding from gps which also handles distance and bearing calcs. Not yet had chance to test, but compared to my attempts todate at string parsing and haversine calcs it looks very promising.

hth Go Up