They have GPS libraries for Arduino which are fun to play with but not too easy for some one like me to try and make a UGV with. I think it would be a cool idea for diy drones to have code that would just give like distance to your next GPS point and heading needed. You know, a code without all the sensors and outputs but with just the part in figuring out what is needed to get to the next GPS point. I do not know if i am the only one who would like this but there might be others. Or is there is  simple mod for some of the current code that could do this?

Views: 61

Reply to This

Replies to This Discussion

& then what ? just asking Coz I don't understand what will you do with it then. If distance and direction is all that is need then you can use any garmin GPS like 3600A .....
then a UGV. Do you have interface code for a garmin?
My Garmin, which is about as old as you, has a setup screen to configure the serial port to be OFF or NMEA or GARMIN proprietary protocol. I don't know what sort of thrifting Garmin may have implemented since then. Maybe you don't have NMEA? Check your owners manual. ArduPilot works fine in NMEA mode for slower moving vehicles.
Basically what i am looking for is something that i can use to make some GPS locative projects. I currently am using the NewSoftSerial library for arduino which is giving me my latitude and longitude, time, and date. Right now i am trying to get them into some useful numbers that i can do math with. But the current code is just printing the location and not saving it in some kind of data form.

Serial.print("Lat: ");
if (latdir == 'N')
Serial.print('+');
else if (latdir == 'S')
Serial.print('-');

Serial.print(latitude/10000000, DEC); Serial.print('\°', BYTE); Serial.print(' ');
Serial.print((latitude/10000)%100, DEC); Serial.print('\''); Serial.print(' ');
Serial.print((latitude%10000)*6/1000, DEC); Serial.print('.');
Serial.print(((latitude%10000)*6/10)%100, DEC); Serial.println('"');

Serial.print("Long: ");
if (longdir == 'E')
Serial.print('+');
else if (longdir == 'W')
Serial.print('-');
Serial.print(longitude/10000000, DEC); Serial.print('\°', BYTE); Serial.print(' ');
Serial.print((longitude/10000)%100, DEC); Serial.print('\''); Serial.print(' ');
Serial.print((longitude%10000)*6/1000, DEC); Serial.print('.');
Serial.print(((longitude%10000)*6/10)%100, DEC); Serial.println('"');

}

This is just some code that i got from the adafruit website. I would like some way to actually get some useful saved numbers from this. Clearly latitude and longitude is too big and is being divided so i can not use that as my data. Being that i am 15, my programming experience is not that in depth but i have made multiple projects with arduino and currently working on my biggest project so far. I am interested in getting my feet wet in GPS. I would like to start with calculating distance. Just not sure how.
The numbers above aren't "too big." Rather, they are scaled so that they are not a decimal number. This speeds up the work for the CPU. (Little CPUs take forever to crunch decimal numbers.)

How far do you need to go? How close to the poles do you need to get? How accurate must you be? If you are travelling just a couple of miles, not at the poles, you can assume a flat Earth and use good old Pythagorus. If you are going more than a few hundred miles you will likely need to start using great circle distances and steering. Google "aviation formulary."

To start at the simplest,

1 minute of latitude (1/60 of a degree) is 1 nautical mile.
1 minute of longitude (at the equator) is 1 nautical mile. You can improve that by multiplying by the cosine of the latitude. (At 45 degrees north, 1 minute of longitude = sin(45) = 0.707 Nm)

for short distances (such that they approximate great circle routes), ponder this:

avgLat = (Latitude1 + Latitude 2) / 2
correction = cos(avgLat)
dLat = Latitude1 - Latitude 2
dLon = correction * (Longitude1 - Longitude2)
distance = sqrt( dLat * dLat + dLon * dLon)

You will still need to worry about:
1. converting the scaled lats and longs to decimal degrees.
2. signs changing at the date line and equator and such
fortunately i am in pre-calculus and we are doing these things. I was thinking short distance with in my state of Florida. Thanks for the "ponder this" bit at the end. That helps me a lot. Another question i have is how does the GPS figure heading or does it not do that? I know you would want to get your heading before you drove what ever distance towards your end point. So clearly we would be dealing with seconds too if 1 minute is only 1 nautical mile.
GPS figures the heading based on the current position and the previous position. Change in x, change in y, do an arctan2.

You could do your calculations with degrees : minutes : seconds but you'd have to keep track of the 3 parts. Easier to do it all in degrees then convert it as needed for display. Different markets prefer different output formats.

The code you presented at the beginning displayed whole degrees and then a decimal number for minutes.
There looks like there is a lot of good stuff in this code.
Arctan is when given the tangent but trying to find the degree i believe. (seriously just learned this last week and glad to see it has a use). Arduino does that? i mean i know how to do it on my texas instruments calculator but as for what it is actually doing and how to put that in code, i have no clue. Is there a arctan C function? simply arctan(blank);?

// A simple sketch to read GPS data and parse the $GPRMC string
// see http://www.ladyada.net/make/gpsshield for more info

#include

NewSoftSerial mySerial = NewSoftSerial(0, 1);
#define powerpin 4

#define GPSRATE 4800
//#define GPSRATE 38400


// GPS parser for 406a
#define BUFFSIZ 90 // plenty big
char buffer[BUFFSIZ];
char *parseptr;
char buffidx;
uint8_t hour, minute, second, year, month, date;
uint32_t latitude, longitude;
uint8_t groundspeed, trackangle;
char latdir, longdir;
char status;

void setup()
{
if (powerpin) {
pinMode(powerpin, OUTPUT);
}
pinMode(13, OUTPUT);
Serial.begin(GPSRATE);
mySerial.begin(GPSRATE);

// prints title with ending line break
Serial.println("GPS parser");

digitalWrite(powerpin, LOW); // pull low to turn on!
}


void loop()
{
uint32_t tmp;

Serial.print("\n\rread: ");
readline();

// check if $GPRMC (global positioning fixed data)
if (strncmp(buffer, "$GPRMC",6) == 0) {

// hhmmss time data
parseptr = buffer+7;
tmp = parsedecimal(parseptr);
hour = tmp / 10000;
minute = (tmp / 100) % 100;
second = tmp % 100;

parseptr = strchr(parseptr, ',') + 1;
status = parseptr[0];
parseptr += 2;

// grab latitude & long data
// latitude
latitude = parsedecimal(parseptr);
if (latitude != 0) {
latitude *= 10000;
parseptr = strchr(parseptr, '.')+1;
latitude += parsedecimal(parseptr);
}
parseptr = strchr(parseptr, ',') + 1;
// read latitude N/S data
if (parseptr[0] != ',') {
latdir = parseptr[0];
}

//Serial.println(latdir);

// longitude
parseptr = strchr(parseptr, ',')+1;
longitude = parsedecimal(parseptr);
if (longitude != 0) {
longitude *= 10000;
parseptr = strchr(parseptr, '.')+1;
longitude += parsedecimal(parseptr);
}
parseptr = strchr(parseptr, ',')+1;
// read longitude E/W data
if (parseptr[0] != ',') {
longdir = parseptr[0];
}


// groundspeed
parseptr = strchr(parseptr, ',')+1;
groundspeed = parsedecimal(parseptr);

// track angle
parseptr = strchr(parseptr, ',')+1;
trackangle = parsedecimal(parseptr);


// date
parseptr = strchr(parseptr, ',')+1;
tmp = parsedecimal(parseptr);
date = tmp / 10000;
month = (tmp / 100) % 100;
year = tmp % 100;

Serial.print("\nTime: ");
Serial.print(hour, DEC); Serial.print(':');
Serial.print(minute, DEC); Serial.print(':');
Serial.println(second, DEC);
Serial.print("Date: ");
Serial.print(month, DEC); Serial.print('/');
Serial.print(date, DEC); Serial.print('/');
Serial.println(year, DEC);

Serial.print("Lat: ");
if (latdir == 'N')
Serial.print('+');
else if (latdir == 'S')
Serial.print('-');

Serial.print(latitude/10000000, DEC); Serial.print('\°', BYTE); Serial.print(' ');
Serial.print((latitude/10000)%100, DEC); Serial.print('\''); Serial.print(' ');
Serial.print((latitude%10000)*6/1000, DEC); Serial.print('.');
Serial.print(((latitude%10000)*6/10)%100, DEC); Serial.println('"');

Serial.print("Long: ");
if (longdir == 'E')
Serial.print('+');
else if (longdir == 'W')
Serial.print('-');
Serial.print(longitude/10000000, DEC); Serial.print('\°', BYTE); Serial.print(' ');
Serial.print((longitude/10000)%100, DEC); Serial.print('\''); Serial.print(' ');
Serial.print((longitude%10000)*6/1000, DEC); Serial.print('.');
Serial.print(((longitude%10000)*6/10)%100, DEC); Serial.println('"');

}
//Serial.println(buffer);
}

uint32_t parsedecimal(char *str) {
uint32_t d = 0;

while (str[0] != 0) {
if ((str[0] > '9') || (str[0] < '0'))
return d;
d *= 10;
d += str[0] - '0';
str++;
}
return d;
}

void readline(void) {
char c;

buffidx = 0; // start at begninning
while (1) {
c=mySerial.read();
if (c == -1)
continue;
Serial.print(c);
if (c == '\n')
continue;
if ((buffidx == BUFFSIZ-1) || (c == '\r')) {
buffer[buffidx] = 0;
return;
}
buffer[buffidx++]= c;
}
}
yes, the C compiler for arduino knows sins, cos's, arctans, and more.

atan takes 1 argument.
atan2 takes 2 arguments, (y,x)
But recall your geometry...we measure the angle counter clockwise from the x axis, meaning to the right so you need to convert the output of atan2 from radians to degrees, then spin it 90 degrees so that "0" is up, and reverse the sign so that we count clockwise. Whew.

Test all 4 quadrants to ensure you have the signs right. :)

http://en.wikipedia.org/wiki/Atan2
oh now this sounds like loads of fun :D.
Like they say, the devil is in the details.

Shouldn't you be in bed so you do well on the FCAT?
oh wow your in Florida too i see. Yes i went to bed.

RSS

Contests

Season Two of the Trust Time Trial (T3) Contest has now begun. The third round was a reliablilty/aerial photography round for both planes and copters, which is now closed. Stay tuned for the next round, beginning soon.

A list of all T3 contests is here

 

© 2012   Created by Chris Anderson.

Badges  |  Report an Issue  |  Terms of Service