I purchased one of your GPS breakout boards (https://www.adafruit.com/products/746) and was wondering whether there was a way to tell one's direction in degrees. I am working on a rover that navigates to GPS waypoints and was going to sense direction by driving in one direction to tell whether one is moving further away or closer. Is there an easier way to find one's direction? Is it accurate and is a fix necessary?
If I use GPS.angle, is this accurate? Could it guide me to a waypoint?
GPS Direction
Moderators: adafruit_support_bill, adafruit
Please be positive and constructive with your questions and comments.
- adafruit_support_bill
- Posts: 88154
- Joined: Sat Feb 07, 2009 10:11 am
Re: GPS Direction
I believe what you want is track angle - your direction of movement relative to true north: http://forums.adafruit.com/viewtopic.ph ... 9&p=152481
-
- Posts: 84
- Joined: Tue Nov 02, 2010 7:29 am
Re: GPS Direction
I can't see that topic (sorry), and I have one question that's a bit unrelated.
I am trying to read numbers from the serial port (later lat/lon). All the numbers display a "-38" after every piece of data. When I try to input a two digit number, they come up separately. Is there any way to have a two digit number stored by the arduino?
I am trying to read numbers from the serial port (later lat/lon). All the numbers display a "-38" after every piece of data. When I try to input a two digit number, they come up separately. Is there any way to have a two digit number stored by the arduino?
Code: Select all
void setup(){
Serial.begin(9600);
}
void loop(){
}
void serialEvent(){
int coordData = Serial.read() - '0';
Serial.println(coordData);
}
- adafruit_support_bill
- Posts: 88154
- Joined: Sat Feb 07, 2009 10:11 am
Re: GPS Direction
My mistake. Link fixed.
The -38 is the Line-Feed character (ASCII decimal 10) after you subtract the value of '0' (ASCII decimal 48).
To read multi-digit numbers: Start with a value of 0. Then for each new valid digit (you will need to screen out anything that is not between '0' and '9'), multiply your existing value by 10, then add the new digit. When you get to a non-digit characgter (such as the Line Feed), you are done.
The -38 is the Line-Feed character (ASCII decimal 10) after you subtract the value of '0' (ASCII decimal 48).
To read multi-digit numbers: Start with a value of 0. Then for each new valid digit (you will need to screen out anything that is not between '0' and '9'), multiply your existing value by 10, then add the new digit. When you get to a non-digit characgter (such as the Line Feed), you are done.
-
- Posts: 84
- Joined: Tue Nov 02, 2010 7:29 am
Re: GPS Direction
I can't seem to get it right. I've been trying to get this to work and I get really negative numbers - very strange.
Code: Select all
void serialEvent(){
int counter = 1;
float incomingData[15];
while(Serial.read() > 0){
incomingData[counter] = Serial.read() - '0';
incomingTotal += incomingData[counter] * pow(10, counter);
counter ++;
}
Serial.println(incomingTotal);
}
-
- Posts: 84
- Joined: Tue Nov 02, 2010 7:29 am
Re: GPS Direction
I think I was over complicating it. New code:
Code: Select all
void serialEvent(){
while (Serial.available()) {
delay(10);
if (Serial.available() >0) {
char c = Serial.read();
incomingData += c;
}
}
if (incomingData.length() >0) {
Serial.println(incomingData);
incomingData="";
}
}
- adafruit_support_bill
- Posts: 88154
- Joined: Sat Feb 07, 2009 10:11 am
Re: GPS Direction
That's good. It is simpler to just echo the data if you don't need the values for computation,
- adafruit_support_rick
- Posts: 35092
- Joined: Tue Mar 15, 2011 11:42 am
Re: GPS Direction
Well, you've got several problems there.
First of all, your loop test, while (Serial.read() > 0), is going to read a character and throw it away. That means that the next line, incomingData[counter] = Serial.read() - '0'; will only see every other character.
I don't know what the data stream you're trying to parse looks like, so you may want a different loop test than I'm going to give you. My loop test assumes that you are just receiving a single number.
Next, as adafruit_support said, you have to test the characters you read to see if they are digits. You ONLY want to subtract '0' from characters that are between '0' and '9'. There will be other characters in the data stream, such as new lines, that are NOT part of the number you are trying to parse, and so you do NOT want to add them to incomingTotal.
You are not initializing incomingTotal, so you could be starting out with some random value in it.
You also don't need an array for incoming data, since you just add each digit to incomingTotal as it arrives, and never look at it again.
You don't need to use the pow function, either, since you can simply multiply incomingTotal by 10 every time you add a digit.
First of all, your loop test, while (Serial.read() > 0), is going to read a character and throw it away. That means that the next line, incomingData[counter] = Serial.read() - '0'; will only see every other character.
I don't know what the data stream you're trying to parse looks like, so you may want a different loop test than I'm going to give you. My loop test assumes that you are just receiving a single number.
Next, as adafruit_support said, you have to test the characters you read to see if they are digits. You ONLY want to subtract '0' from characters that are between '0' and '9'. There will be other characters in the data stream, such as new lines, that are NOT part of the number you are trying to parse, and so you do NOT want to add them to incomingTotal.
You are not initializing incomingTotal, so you could be starting out with some random value in it.
You also don't need an array for incoming data, since you just add each digit to incomingTotal as it arrives, and never look at it again.
You don't need to use the pow function, either, since you can simply multiply incomingTotal by 10 every time you add a digit.
Code: Select all
void serialEvent(){
char digit;
int incomingTotal = 0;
while(Serial.available() > 0) //while there is something in the input buffer.
{ //You will probably want something different, depending on your input data format.
digit = Serial.read(); //read a character
if ((digit >= '0') and (digit <= '9')) //if the character is a numeric digit
{
incomingTotal = (incomingTotal * 10) + (digit - '0'); //shift current total, convert digit to integer and add
}
}
Serial.println(incomingTotal);
}
-
- Posts: 84
- Joined: Tue Nov 02, 2010 7:29 am
Re: GPS Direction
Thanks so much for your help. I have worked extensively in processing and there is a string.split(string name, anything to split around) function that makes it easy to convert comma separated data into an array. I can't seem to find the same function in arduino - does it exist?
- adafruit_support_rick
- Posts: 35092
- Joined: Tue Mar 15, 2011 11:42 am
Re: GPS Direction
You've got the standard C libraries available to you on arduino. However, you are working with I/O, not strings. You could read chars into a string and process the the string later. Or, you could change the SerialEvent function to recognize commas:
Code: Select all
void readNumber()
{
char digit;
int incomingTotal = 0;
bool complete = false;
while(Serial.available()) && (!complete)) //while there is something to read, and we don't have a complete number yet
{
digit = Serial.read(); //read a character
if ((digit >= '0') and (digit <= '9')) //if the character is a numeric digit
{
incomingTotal = (incomingTotal * 10) + (digit - '0'); //shift current total, convert digit to integer and add
}
else //the number is complete when we see a comma or a newline
{
complete = ((digit == ',') || (digit == '\n'));
}
}
Serial.println(incomingTotal);
}
-
- Posts: 84
- Joined: Tue Nov 02, 2010 7:29 am
Re: GPS Direction
I'm still having troubles - sorry for the beginner problems. When I enter in numbers (new lines or comma separated), the Serial monitor puts each digit on a separate line - not combining them. How can I get them to be in one number?
Also, how can I input a decimal?
Code: Select all
void serialEvent()
{
char digit;
int incomingTotal = 0;
boolean complete = false;
while(Serial.available() && (!complete)) {
digit = Serial.read();
if ((digit >= '0') and (digit <= '9')) {
incomingTotal = (incomingTotal * 10) + (digit - '0'); //shift current total, convert digit to integer and add
}
else if(digit == ',' || complete == '\n'){ //the number is complete when we see a comma or a newline{
complete = true;
}
}
Serial.println(incomingTotal);
}
-
- Posts: 84
- Joined: Tue Nov 02, 2010 7:29 am
Re: GPS Direction
I've gone through this code so many times and it won't work. I just can't get the arduino to read large numbers separated by commas.
Code: Select all
float inputData;
int num1, num2;
String incomingData;
void setup(){
Serial.begin(9600);
}
void loop(){
}
void serialEvent(){
inputData = 0;
boolean complete = false;
while (Serial.available()) {
char c = Serial.read();
if (!complete) {
incomingData += c;
}
if(c == '\n' || ','){
char dataArray[incomingData.length() + 1];
incomingData.toCharArray(dataArray, sizeof(dataArray));
float n = atoi(dataArray);
incomingData = "";
if(inputData == 0) {
num1 = n;
}
else if(inputData == 1){
num2 = n;
}
inputData ++;
Serial.print(num1);
Serial.print(",");
Serial.println(num2);
}
}
}
- adafruit_support_rick
- Posts: 35092
- Joined: Tue Mar 15, 2011 11:42 am
Re: GPS Direction
try this:
Also, you only want to print out num1 and num2 AFTER you have num2:
Code: Select all
if((c == '\n') || (c == ',')){
Code: Select all
else if(inputData == 1){
num2 = n;
Serial.print(num1);
Serial.print(",");
Serial.println(num2);
}
inputData ++;
-
- Posts: 84
- Joined: Tue Nov 02, 2010 7:29 am
Re: GPS Direction
It took a few hours to get here - and I think I'm close - but there is still a problem. It runs through serialEvent and returns a nonsense, incorrect reading the first time. Why does it not read the entire input in the function while(Serial.available >= 0) ?
Here is the entire code I'm using:
Here is the entire code I'm using:
Code: Select all
float inputData;
float num1, num2;
String incomingData;
String data1, data2;
boolean set = false;
void setup(){
Serial.begin(9600);
}
void loop(){
if(set){
data1.trim();
data2.trim();
char dataArray1[data1.length() + 1];
char dataArray2[data2.length() + 1];
data1.toCharArray(dataArray1, sizeof(dataArray1));
data2.toCharArray(dataArray2, sizeof(dataArray2));
num1 = atoi(dataArray1);
num2 = atoi(dataArray2);
Serial.println(num1);
Serial.println(num2);
delay(1000);
}
}
void serialEvent(){
data1 = "";
data2 = "";
inputData = 0;
while (Serial.available() > 0) {
char c = Serial.read();
incomingData += c;
}
char dataArray[incomingData.length()+1];
incomingData.toCharArray(dataArray, sizeof(dataArray));
for(int ii = 0; ii < incomingData.length()+1; ii++){
if((dataArray[ii] == '\n') || (dataArray[ii] == ',')){
inputData ++;
}
else {
if(inputData == 0) {
data1 += dataArray[ii];
}
else if(inputData == 1) {
data2 += dataArray[ii];
}
}
}
set = true;
}
-
- Posts: 84
- Joined: Tue Nov 02, 2010 7:29 am
Re: GPS Direction
I can now get it to accept 6 digit numbers (very important for my project - I'm using latitude and longitude). There is still a fairly large problem - when I divide the 6 digit number by a factor of ten, the Serial monitor prints only 0's to the right of the decimal place - 123456 becomes 12345.00. How can I get this to work?
Is this a problem with the Serial monitor? Is the arduino thinking it is a decimal number but only printing 0s after the decimal?
Code: Select all
#include <stdlib.h>
int inputData;
unsigned long num1, num2;
String incomingData;
String data1, data2;
boolean set = false;
void setup()
{
Serial.begin(9600);
}
void loop()
{
if(set){
char dataArray1[data1.length() + 1];
char dataArray2[data2.length() + 1];
data1.toCharArray(dataArray1, sizeof(dataArray1));
data2.toCharArray(dataArray2, sizeof(dataArray2));
num1 = atol(dataArray1);
num2 = atol(dataArray2);
Serial.print(num1/10000, 6);
Serial.print(",");
Serial.println(num2/10000, 6);
delay(1000);
}
}
void serialEvent(){
set = false;
data1 = "";
data2 = "";
inputData = 0;
while (Serial.available() > 0) {
char c = Serial.read();
incomingData += c;
}
char dataArray[incomingData.length()+1];
incomingData.toCharArray(dataArray, sizeof(dataArray));
for(int ii = 0; ii < incomingData.length()+1; ii++){
if((dataArray[ii] == '\n') || (dataArray[ii] == ',')){
inputData ++;
}
else {
if(inputData == 0) {
data1 += dataArray[ii];
}
else if(inputData == 1) {
data2 += dataArray[ii];
}
}
}
set = true;
}
Please be positive and constructive with your questions and comments.