Softwareserial and Math Calculation issue, with Arduino UNO

Hi Everyone,
My first ever post here in this forum.
I have very strange issue.
i am using Softwareserial library on my Arduino Uno for weeks now, with no issue.
but now,
I have added a function to do some math calculations, if i include Softerserial library, the return of my calculation goes wrong. as soon as i remove the include, the return of calculation is good.

the function is calculating distance of two coordinates which i grabbed it from this forum before and it works perfectly, as i check it against google earth. it is just the issue with Softwareserial.

I also know, with Tinygps library i can get distance easily, but I don't want to use for some other reasons.
I only need softwareserial.

does anyone have any idea?
I will get Arduino mega soon, and fortunately, i dont need this library anymore, but it is just a curiosity, why i got this issue.

my hardwares:
Arduino Uno
Sparkfun GPS EM-506

my code

//#include <SoftwareSerial.h>
#include<math.h>
double latrd1=-20.5060406057703;
double lonrd1=118.628450061973;
//SoftwareSerial ss2(2,3);
             
void setup()
{
Serial.begin(4800); 
// ss2.begin(4800);            //GPS module puts out serial at 4800 bps
}
void loop()
{
double Answer=dist(latrd1,lonrd1,-21.5050406057703,118.628450061973);  
Serial.print("The Distance is = "); Serial.println(Answer);
delay(5000);
}  

//********************************************************************************************************************************************************
// Calculate Disntance between two coordinates
double dist(double dlat1,double dlon1,double dlat2,double dlon2){
double distLat = abs(dlat1 - dlat2) * 111194.9;
double distLong = 111194.9 * abs(dlon1 - dlon2); // cos(radians((dlat1 + dlat2) / 2));
double result = sqrt(pow(distLat, 2) + pow(distLong, 2));
return result; //return dist in meters
}

SoftwareSerial.h contains this chunk:

// Arduino 0012 workaround
#undef int
#undef char
#undef long
#undef byte
#undef float
#undef abs
#undef round

I don't know what this was trying to workaround but version 0012 is very old. It's effect is that it blows up your use of the abs() function and it returns zero instead of the correct value.

Either avoid SoftwareSerial.h or change it to:

#ifdef NOTDEF
// Arduino 0012 workaround
#undef int
#undef char
#undef long
#undef byte
#undef float
#undef abs
#undef round
#endif

Pete

Thanks Pete,
I actually used Serial print for each internal function tags one by one, and the problem was on
"double distLat = abs(dlat1 - dlat2) * 111194.9;" line, where abs() was used, but i couldnt figured it out.
I think you are right, the abs() is the problem.

el_supremo:
It's effect is that it blows up your use of the abs() function and it returns zero instead of the correct value.

by adding #ifdef NOTDEF, we basically exclude the whole undefin, is that right?
that's not going to affect on SoftwareSerial functionality?
and if not, why it is there in first place?

thanks again
Fred

I can't figure out what those #undef statements were meant to fix. SoftwareSerial doesn't even use abs().

Pete

OP should probably be aware that Arduino float and double are the same thing, 32-bit floating point with 6 digit precision (7 digits for some values depending on how large the first one is) and very slow.

20.5060406057703
118.628450061973

Dream On with ideas that your answer will be good past 6 places. It might show more but past 6 is going to be garbage in an operation or two.

That distance formula is good for flat surfaces. I hope that your coordinates are always close, perhaps 200 km (about 2 degrees total) or less.

GoForSmoke:
That distance formula is good for flat surfaces. I hope that your coordinates are always close, perhaps 200 km (about 2 degrees total) or less.

Thanks mate,

my distance is less than 50km.
I used 'Double' since i thought, in Mega, double is 8 bytes. isn't it like that?

by the way, let say, if this distance formula is for short distances, what else i can use?
I tested Haversine formula on Uno with no luck, since it couldn't calculate Atan2. Do u think, mega can calculate that? or is there any other formula?

thanks again,
Fred

I tested Haversine formula on Uno with no luck, since it couldn't calculate Atan2.

The Haversine formula works on the UNO. If you used Atan2 then it wouldn't work. You need to use atan2.

Pete

Hi Pete,
it was a typo here,

for haversine formula, i have added the same formula in excel and check line by line, and the problem with Arduino Uno, since it is 8 bit controller couldnt return right value.

I think atan2() was the bottle neck of calculation for short distances.

Have you used haversine with long distances in Uno?

thanks
Fred

My math is nothing like it was so this would take me a long time but someone else has likely done it,

what will always be closer to right is to find the polar angle between the two locations and get the length of arc between. Longitude and Latitude are polar coordinates but I forget the steps to rotate them, it's been a long time.

But look, 1 degree of Earth Equator is about 66 miles, more than 100 km. The difference between flat and curved at such a small angle is negligible.

There is a discussion of Earth radius at the bottom showing how error margins of 1% and .5% can happen using Earth as a sphere calculations. For close places I think that 32-bit FP errors will be more.

I like this method, you already have the chord length as your distance.

From chord length

A line through three-dimensional space between points of interest on a spherical Earth is the chord of the great circle between the points. The central angle between the two points can be determined from the chord length. The great circle distance is proportional to the central angle.

Also 9th century Muslims had it solved to get the direction and distance to Mecca from anywhere, or so I read.

This thread has code for Haversine:
http://forum.arduino.cc/index.php?topic=336729.0

Pete

For distances up to a few tens of km, the equirectangular approximation works better than haversine. That is what this formula did, before you erroneously removed the term that involves the cosine of the latitude. See this great reference page.

// Calculate Disntance between two coordinates
double dist(double dlat1,double dlon1,double dlat2,double dlon2){
double distLat = abs(dlat1 - dlat2) * 111194.9;
double distLong = 111194.9 * abs(dlon1 - dlon2)*cos(radians((dlat1 + dlat2) / 2));  //restored the required correction!
double result = sqrt(distLat*distLat + distLong*distLong); //don't use pow()!
return result; //return dist in meters
}

The main problem is that as mentioned above, floats (same as doubles) on the Arduino cannot accurately store latitude and longitude coordinates. Most people use long integers to store coordinates, with degrees*106 as the units, which maintains the required precision of 8 decimal places (1 meter accuracy).