Offline
Newbie
Karma: 0
Posts: 35
|
 |
« on: February 16, 2013, 05:34:03 pm » |
Hi, I am trying to determine the direction and distance to a destination using this gps module : http://store.iteadstudio.com/index.php?main_page=product_info&products_id=500I am getting values for distance and direction in the Serial monitor, but when I turn the gps shield/ antenna, the direction values do not change. I would like the direction/ distance values to change as you walk away/towards the destination. The code is below. Thanks for your help #include <SoftwareSerial.h> #include "TinyGPS.h"
/* This sample code demonstrates the normal use of a TinyGPS object. It requires the use of SoftwareSerial, and assumes that you have a 4800-baud serial GPS device hooked up on pins 3(rx) and 4(tx). */
TinyGPS gps; SoftwareSerial ss(3, 4);
float dest_latitude = 42.24313; float dest_longitude = -83.002853; float distance; float distanceangle;
void setup() { Serial.begin(115200);
Serial.print("Simple TinyGPS library v. "); Serial.println(TinyGPS::library_version()); Serial.println("by Mikal Hart"); Serial.println(); }
void loop() { ss.begin(9600); bool newData = false; unsigned long chars; unsigned short sentences, failed;
// For one second we parse GPS data and report some key values for (unsigned long start = millis(); millis() - start < 1000;) { while (ss.available()) { char c = ss.read(); // Serial.write(c); // uncomment this line if you want to see the GPS data flowing if (gps.encode(c)) // Did a new valid sentence come in? newData = true; } }
if (newData) { float flat, flon; unsigned long age; gps.f_get_position(&flat, &flon, &age); Serial.print("LAT="); Serial.print(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flat, 6); Serial.print(" LON="); Serial.print(flon == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flon, 6); Serial.print(" SAT="); Serial.print(gps.satellites() == TinyGPS::GPS_INVALID_SATELLITES ? 0 : gps.satellites()); Serial.print(" PREC="); Serial.print(gps.hdop() == TinyGPS::GPS_INVALID_HDOP ? 0 : gps.hdop());
gps.stats(&chars, &sentences, &failed); Serial.print(" CHARS="); Serial.print(chars); Serial.print(" SENTENCES="); Serial.print(sentences); Serial.print(" CSUM ERR="); Serial.println(failed);
float course = (TinyGPS::course_to(flat, flon, dest_latitude, dest_longitude ));
float distance = (TinyGPS::distance_between(flat, flon, dest_latitude, dest_longitude ));
Serial.print ("course is "); Serial.print (course); Serial.print ( "distance is "); Serial.print (distance);
} }
As I turn the module/antenna, this is what I get in the Serial monitor course is 74.56distance is 543.55LAT=42.241828 LON=-83.009216 SAT=8 PREC=100 CHARS=295151 SENTENCES=1843 CSUM ERR=59 course is 74.56distance is 543.55LAT=42.241828 LON=-83.009216 SAT=8 PREC=100 CHARS=295631 SENTENCES=1845 CSUM ERR=59 course is 74.56distance is 543.55LAT=42.241828 LON=-83.009216 SAT=8 PREC=100 CHARS=295907 SENTENCES=1847 CSUM ERR=59 course is 74.56distance is 543.55LAT=42.241828 LON=-83.009216 SAT=8 PREC=100 CHARS=296183 SENTENCES=1849 CSUM ERR=59 course is 74.56distance is 543.55LAT=42.241828 LON=-83.009216 SAT=8 PREC=100 CHARS=296459 SENTENCES=1851 CSUM ERR=59 course is 74.56distance is 543.55LAT=42.241828 LON=-83.009216 SAT=8 PREC=100 CHARS=296735 SENTENCES=1853 CSUM ERR=59 course is 74.56distance is 543.55LAT=42.241828 LON=-83.009216 SAT=8 PREC=100 CHARS=297215 SENTENCES=1855 CSUM ERR=59 course is 74.56distance is 543.55LAT=42.241828 LON=-83.009216 SAT=8 PREC=100 CHARS=297491 SENTENCES=1857 CSUM ERR=59 course is 74.56distance is 543.55LAT=42.241828 LON=-83.009216 SAT=8 PREC=100 CHARS=297767 SENTENCES=1859 CSUM ERR=59
As you can see, the values don't change
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
UK
Offline
Brattain Member
Karma: 137
Posts: 19006
I don't think you connected the grounds, Dave.
|
 |
« Reply #1 on: February 16, 2013, 05:40:03 pm » |
GPS measures position but when I turn the gps shield/ antenna, the direction values do not change Direction to what?
|
|
|
|
|
Logged
|
Pete, it's a fool looks for logic in the chambers of the human heart.
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 35
|
 |
« Reply #2 on: February 16, 2013, 05:44:28 pm » |
the direction values in degrees to the destination coordinates do not change
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
UK
Offline
Brattain Member
Karma: 137
Posts: 19006
I don't think you connected the grounds, Dave.
|
 |
« Reply #3 on: February 16, 2013, 05:47:09 pm » |
If I stand in my living room, my bearing to the North Pole does not change, whichever direction I face.
|
|
|
|
|
Logged
|
Pete, it's a fool looks for logic in the chambers of the human heart.
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 35
|
 |
« Reply #4 on: February 16, 2013, 05:51:37 pm » |
my ultimate goal is to be able to move a pan/ tilt system to show the user where to navigate. In order to do this, I would have to periodically update the servo values to direct the user the destination. I wrote this code to move the servos, but the servos do not move if I move the module in a different direction. Do you have any ideas on how I could do this. thanks for your help rdeans #include <SoftwareSerial.h> #include "TinyGPS.h" #include <Servo.h>
/* This sample code demonstrates the normal use of a TinyGPS object. It requires the use of SoftwareSerial, and assumes that you have a 4800-baud serial GPS device hooked up on pins 3(rx) and 4(tx). */
Servo panservo; Servo tiltservo;
TinyGPS gps; SoftwareSerial ss(3, 4);
float dest_latitude = 42.24313; float dest_longitude = -83.002853; float distance; float distanceangle;
void setup() { Serial.begin(115200);
Serial.print("Simple TinyGPS library v. "); Serial.println(TinyGPS::library_version()); Serial.println("by Mikal Hart"); Serial.println(); }
void loop() { ss.begin(9600); bool newData = false; unsigned long chars; unsigned short sentences, failed;
// For one second we parse GPS data and report some key values for (unsigned long start = millis(); millis() - start < 1000;) { while (ss.available()) { char c = ss.read(); // Serial.write(c); // uncomment this line if you want to see the GPS data flowing if (gps.encode(c)) // Did a new valid sentence come in? newData = true; } }
if (newData) { float flat, flon; unsigned long age; gps.f_get_position(&flat, &flon, &age); Serial.print("LAT="); Serial.print(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flat, 6); Serial.print(" LON="); Serial.print(flon == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flon, 6); Serial.print(" SAT="); Serial.print(gps.satellites() == TinyGPS::GPS_INVALID_SATELLITES ? 0 : gps.satellites()); Serial.print(" PREC="); Serial.print(gps.hdop() == TinyGPS::GPS_INVALID_HDOP ? 0 : gps.hdop());
gps.stats(&chars, &sentences, &failed); Serial.print(" CHARS="); Serial.print(chars); Serial.print(" SENTENCES="); Serial.print(sentences); Serial.print(" CSUM ERR="); Serial.println(failed);
float course = (TinyGPS::course_to(flat, flon, dest_latitude, dest_longitude )); float courseangle; float distance = (TinyGPS::distance_between(flat, flon, dest_latitude, dest_longitude )); float distanceangle;
ss.end(); delay(4000); panservo.attach(9); tiltservo.attach(10);
if (distance <= 100){ distanceangle =int(-0.6*distance + 120); Serial.print(" distance is less"); Serial.print( distanceangle); tiltservo.write(distanceangle); }
else { distanceangle = 60; Serial.print(" distance is greater "); Serial.print( distanceangle); tiltservo.write(distanceangle); }
if (270 <= course && course < 360){ courseangle = int(-course + 450); Serial.print (" course is case 1 "); Serial.print ( courseangle); panservo.write(courseangle);
} else if (0 <= course && course <= 90){ courseangle = int(-course + 90); Serial.print (" course is case 2 "); Serial.print ( courseangle); panservo.write(courseangle);
} else if (90 < course && course < 180){ courseangle = 0; Serial.print (" course is case 3 "); Serial.print ( courseangle); panservo.write(courseangle);
}
else if (180 <= course && course < 270){ courseangle = 180; Serial.print (" course is case 4 "); Serial.print ( courseangle); panservo.write(courseangle);
} panservo.detach(); tiltservo.detach(); }
}
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Full Member
Karma: 5
Posts: 112
|
 |
« Reply #5 on: February 16, 2013, 05:54:21 pm » |
You need a compass too
|
|
|
|
|
Logged
|
For whom does the clock pulse? It pulses for you!
|
|
|
|
Croatia
Offline
Full Member
Karma: 9
Posts: 240
|
 |
« Reply #6 on: February 16, 2013, 05:54:30 pm » |
A GPS device is not capable of determining which way it is facing so it can not give you directions relative to its own orientation. It can give you direction either in relation to movement or as an angle between north and the desired location based on current location. If you want your device to be sensitive to orientation, you need a compass.
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
UK
Offline
Brattain Member
Karma: 137
Posts: 19006
I don't think you connected the grounds, Dave.
|
 |
« Reply #7 on: February 16, 2013, 05:54:48 pm » |
Use a compass (magnetometer). A GPS tells you where you are, not which way you're looking (difficult to tell from 18 000km away)
|
|
|
|
|
Logged
|
Pete, it's a fool looks for logic in the chambers of the human heart.
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 311
Posts: 35470
Seattle, WA USA
|
 |
« Reply #8 on: February 16, 2013, 06:30:33 pm » |
A GPS tells you where you are, not which way you're looking (difficult to tell from 18 000km away) It can tell you which way you are going, when you are moving, based on a vector between two locations (the current one and the previous one). The GPS on my trike tells me that. But, it hasn't a clue when I'm parked in the driveway.
|
|
|
|
|
Logged
|
|
|
|
|
USA
Offline
Jr. Member
Karma: 1
Posts: 69
If you can't fix it with a hammer, it must be an electrical problem.
|
 |
« Reply #9 on: February 17, 2013, 10:19:36 am » |
Distance is in NM, so .01 = 60 feet, either GPS is not updating (indoors?) or try a destination that is closer.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 35
|
 |
« Reply #10 on: February 17, 2013, 11:03:23 am » |
Thanks for your help I am new to Arduino and don't have any experience working with compass/ gps. Could I use either of these breakout boards/ compass for my project: https://www.sparkfun.com/products/10703https://www.sparkfun.com/products/7915If so, how would I hook it up to the arduino. I don't really understand any of the following example code either. /* LSM303DLH Example Code by: Jim Lindblom SparkFun Electronics date: 9/6/11 license: Creative commons share-alike v3.0 Summary: Show how to calculate level and tilt-compensated heading using the snazzy LSM303DLH 3-axis magnetometer/3-axis accelerometer. Firmware: You can set the accelerometer's full-scale range by setting the SCALE constant to either 2, 4, or 8. This value is used in the initLSM303() function. For the most part, all other registers in the LSM303 will be at their default value. Use the LSM303_write() and LSM303_read() functions to write to and read from the LSM303's internal registers. Use getLSM303_accel() and getLSM303_mag() to get the acceleration and magneto values from the LSM303. You'll need to pass each of those functions an array, where the data will be stored upon return from the void. getHeading() calculates a heading assuming the sensor is level. A float between 0 and 360 is returned. You need to pass it a array with magneto values. getTiltHeading() calculates a tilt-compensated heading. A float between 0 and 360 degrees is returned. You need to pass this function both a magneto and acceleration array. Headings are calculated as specified in AN3192: http://www.sparkfun.com/datasheets/Sensors/Magneto/Tilt%20Compensated%20Compass.pdf Hardware: I'm using SparkFun's LSM303 breakout. Only power and the two I2C lines are connected: LSM303 Breakout ---------- Arduino Vin 5V GND GND SDA A4 SCL A5 */ #include <Wire.h> #include <math.h>
#define SCALE 2 // accel full-scale, should be 2, 4, or 8
/* LSM303 Address definitions */ #define LSM303_MAG 0x1E // assuming SA0 grounded #define LSM303_ACC 0x18 // assuming SA0 grounded
#define X 0 #define Y 1 #define Z 2
/* LSM303 Register definitions */ #define CTRL_REG1_A 0x20 #define CTRL_REG2_A 0x21 #define CTRL_REG3_A 0x22 #define CTRL_REG4_A 0x23 #define CTRL_REG5_A 0x24 #define HP_FILTER_RESET_A 0x25 #define REFERENCE_A 0x26 #define STATUS_REG_A 0x27 #define OUT_X_L_A 0x28 #define OUT_X_H_A 0x29 #define OUT_Y_L_A 0x2A #define OUT_Y_H_A 0x2B #define OUT_Z_L_A 0x2C #define OUT_Z_H_A 0x2D #define INT1_CFG_A 0x30 #define INT1_SOURCE_A 0x31 #define INT1_THS_A 0x32 #define INT1_DURATION_A 0x33 #define CRA_REG_M 0x00 #define CRB_REG_M 0x01 #define MR_REG_M 0x02 #define OUT_X_H_M 0x03 #define OUT_X_L_M 0x04 #define OUT_Y_H_M 0x05 #define OUT_Y_L_M 0x06 #define OUT_Z_H_M 0x07 #define OUT_Z_L_M 0x08 #define SR_REG_M 0x09 #define IRA_REG_M 0x0A #define IRB_REG_M 0x0B #define IRC_REG_M 0x0C
/* Global variables */ int accel[3]; // we'll store the raw acceleration values here int mag[3]; // raw magnetometer values stored here float realAccel[3]; // calculated acceleration values here
void setup() { Serial.begin(9600); // Serial is used for debugging Wire.begin(); // Start up I2C, required for LSM303 communication initLSM303(SCALE); // Initialize the LSM303, using a SCALE full-scale range }
void loop() { getLSM303_accel(accel); // get the acceleration values and store them in the accel array while(!(LSM303_read(SR_REG_M) & 0x01)) ; // wait for the magnetometer readings to be ready getLSM303_mag(mag); // get the magnetometer values, store them in mag //printValues(mag, accel); // print the raw accel and mag values, good debugging for (int i=0; i<3; i++) realAccel[i] = accel[i] / pow(2, 15) * SCALE; // calculate real acceleration values, in units of g /* print both the level, and tilt-compensated headings below to compare */ Serial.print(getHeading(mag), 3); // this only works if the sensor is level Serial.print("\t\t"); // print some tabs Serial.println(getTiltHeading(mag, realAccel), 3); // see how awesome tilt compensation is?! delay(100); // delay for serial readability }
void initLSM303(int fs) { LSM303_write(0x27, CTRL_REG1_A); // 0x27 = normal power mode, all accel axes on if ((fs==8)||(fs==4)) LSM303_write((0x00 | (fs-fs/2-1)<<4), CTRL_REG4_A); // set full-scale else LSM303_write(0x00, CTRL_REG4_A); LSM303_write(0x14, CRA_REG_M); // 0x14 = mag 30Hz output rate LSM303_write(0x00, MR_REG_M); // 0x00 = continouous conversion mode }
void printValues(int * magArray, int * accelArray) { /* print out mag and accel arrays all pretty-like */ Serial.print(accelArray[X], DEC); Serial.print("\t"); Serial.print(accelArray[Y], DEC); Serial.print("\t"); Serial.print(accelArray[Z], DEC); Serial.print("\t\t"); Serial.print(magArray[X], DEC); Serial.print("\t"); Serial.print(magArray[Y], DEC); Serial.print("\t"); Serial.print(magArray[Z], DEC); Serial.println(); }
float getHeading(int * magValue) { // see section 1.2 in app note AN3192 float heading = 180*atan2(magValue[Y], magValue[X])/PI; // assume pitch, roll are 0 if (heading <0) heading += 360; return heading; }
float getTiltHeading(int * magValue, float * accelValue) { // see appendix A in app note AN3192 float pitch = asin(-accelValue[X]); float roll = asin(accelValue[Y]/cos(pitch)); float xh = magValue[X] * cos(pitch) + magValue[Z] * sin(pitch); float yh = magValue[X] * sin(roll) * sin(pitch) + magValue[Y] * cos(roll) - magValue[Z] * sin(roll) * cos(pitch); float zh = -magValue[X] * cos(roll) * sin(pitch) + magValue[Y] * sin(roll) + magValue[Z] * cos(roll) * cos(pitch);
float heading = 180 * atan2(yh, xh)/PI; if (yh >= 0) return heading; else return (360 + heading); }
void getLSM303_mag(int * rawValues) { Wire.beginTransmission(LSM303_MAG); Wire.send(OUT_X_H_M); Wire.endTransmission(); Wire.requestFrom(LSM303_MAG, 6); for (int i=0; i<3; i++) rawValues[i] = (Wire.receive() << 8) | Wire.receive(); }
void getLSM303_accel(int * rawValues) { rawValues[Z] = ((int)LSM303_read(OUT_X_L_A) << 8) | (LSM303_read(OUT_X_H_A)); rawValues[X] = ((int)LSM303_read(OUT_Y_L_A) << 8) | (LSM303_read(OUT_Y_H_A)); rawValues[Y] = ((int)LSM303_read(OUT_Z_L_A) << 8) | (LSM303_read(OUT_Z_H_A)); // had to swap those to right the data with the proper axis }
byte LSM303_read(byte address) { byte temp; if (address >= 0x20) Wire.beginTransmission(LSM303_ACC); else Wire.beginTransmission(LSM303_MAG); Wire.send(address); if (address >= 0x20) Wire.requestFrom(LSM303_ACC, 1); else Wire.requestFrom(LSM303_MAG, 1); while(!Wire.available()) ; temp = Wire.receive(); Wire.endTransmission(); return temp; }
void LSM303_write(byte data, byte address) { if (address >= 0x20) Wire.beginTransmission(LSM303_ACC); else Wire.beginTransmission(LSM303_MAG); Wire.send(address); Wire.send(data); Wire.endTransmission(); } thanks for your help rdeans
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Full Member
Karma: 5
Posts: 112
|
 |
« Reply #11 on: February 17, 2013, 12:12:30 pm » |
A GPS tells you where you are, not which way you're looking (difficult to tell from 18 000km away) It can tell you which way you are going, when you are moving, based on a vector between two locations (the current one and the previous one). The GPS on my trike tells me that. But, it hasn't a clue when I'm parked in the driveway. to expand. You could be travelling backwards, looking toward your original location, but the GPS would not know this, it would display you moving toward your destination. This is why you need a compass to give you rotational information. Yes, you can use breakout boards. It is also useful to have a compass to indicate that the vehicle has turned sharply if you are tracking position on a map, as it will update much faster than the GPS. (rotation is more likely to be a change of course than a spin). Using GPS alone results in jerky updates. This is part of the reason for your TomTom et all having a digital compass. Once moving, the unit can infer absolute direction and so North can quite easily be displayed without a compass. Also not that GPS displays tend to follow roads rather than position. This can be observed by deviating from the programmed route onto a parallel route. The display will keep you on the route until you're just too far away for it to be correct, at that point the display will jump. BTW you would normally have a compensation program to allow the compass to compensate for local magnetic anomalies, this usually consists of making several 360 rotations. My HTC asks me to make figure of eight movements.
|
|
|
|
|
Logged
|
For whom does the clock pulse? It pulses for you!
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 311
Posts: 35470
Seattle, WA USA
|
 |
« Reply #12 on: February 17, 2013, 01:09:31 pm » |
You could be travelling backwards, looking toward your original location, but the GPS would not know this, it would display you moving toward your destination. No, it wouldn't. It would show a vector moving away from the target. Now, it would not know, or care, which way you are facing, or whether you are moving in the direction you are facing, or not. All it knows is which way you are moving.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Full Member
Karma: 5
Posts: 112
|
 |
« Reply #13 on: February 17, 2013, 03:38:19 pm » |
You could be travelling backwards, looking toward your original location, but the GPS would not know this, it would display you moving toward your destination. No, it wouldn't. It would show a vector moving away from the target. Now, it would not know, or care, which way you are facing, or whether you are moving in the direction you are facing, or not. All it knows is which way you are moving. Indeed, re-read 
|
|
|
|
|
Logged
|
For whom does the clock pulse? It pulses for you!
|
|
|
|
USA
Offline
Jr. Member
Karma: 1
Posts: 69
If you can't fix it with a hammer, it must be an electrical problem.
|
 |
« Reply #14 on: February 17, 2013, 08:39:07 pm » |
You could be travelling backwards, looking toward your original location, but the GPS would not know this, it would display you moving toward your destination. No, it wouldn't. It would show a vector moving away from the target. Now, it would not know, or care, which way you are facing, or whether you are moving in the direction you are facing, or not. All it knows is which way you are moving. +1
|
|
|
|
|
Logged
|
|
|
|
|
|