calculate relative direction to destination

we first were using the course to technique but it gave us the fluctuated heading towards destination why dont know?

AWOL:
is there a particular reason you didn't use the "course_to" method?

The GPS-determined heading fluctuated too much at low speeds because it depends on motion to determine heading. The compass measures absolute heading against an external reference (Earth's magnetic field).

how about using modifying Calc bearing code i got it from my friend i think there is something wrong with this code

#include <math.h>
#include <nmea.h>
#include <Wire.h>
#include <LiquidCrystal.h>
LiquidCrystal myLCD(42, 40, 38, 36, 34, 32);
float lat; 
float lon;
NMEA myGPS(GPRMC);
float dest_latitude = 25.37104;//the destination Latitude 
float dest_longitude = 68.35567;//the destination Longitude
int HMC6352SlaveAddress = 0x42;
int HMC6352ReadAddress = 0x41;
const int potPin = A8;          //Analog pin A8 for reading Potientiometer that drives the Servo steering
const int leftMotor = 27; //Pin connected to the Relay pin for moving the steering to left
const int rightMotor = 26;//Pin connected to the Relay pin for moving the steering to right
int     motorA1=22;       //Pin connected to the Relay pin for moving the car forward
int     motorA2=23;        //Pin connected to the Relay pin for moving the car backward
//below code describes the Steering ranges for left right and center
char Dir;
bool isLeft()          {
  return (analogRead(potPin)/4) <65;
}
bool isLeftOfCenter()  {
  return (analogRead(potPin)/4) < 108;
}
bool isRightOfCenter() {
  return (analogRead(potPin)/4) > 118;
}
bool isRight()         {
  return (analogRead(potPin)/4) > 128;
}
int beeperpin=44;//the following pin is connected to the buzzer pin 
void setup() {
  Serial1.begin(4800);//Start the serial communication of GPS from the Mega Board
  //PIN DESCRIPTION
  pinMode(leftMotor,OUTPUT);
  pinMode(rightMotor,OUTPUT);
  pinMode(motorA1,OUTPUT);
  pinMode(motorA2,OUTPUT);
  myLCD.begin(16,2);//starting the LCD
  myLCD.print("GPS BASED");//Printing on LCD
  delay(3000);
  myLCD.clear();//Clearing the LCD
  myLCD.home();
  Wire.begin();
  HMC6352SlaveAddress = HMC6352SlaveAddress >> 1;
  pinMode(beeperpin,OUTPUT);
  pinMode(13,OUTPUT);
}
void loop(){
  if (Serial1.available() > 0 ) {
    // read incoming character from GPS
    if (myGPS.decode(Serial1.read())) {
      // check if the character completes a valid GPS sentence
      // check if GPS positioning was unactive
      myLCD.setCursor(15,1);
      myLCD.print('V');
      // check if GPS positioning was active
      if (myGPS.gprmc_status() == 'A') {
        myLCD.setCursor(15,1);
        myLCD.print('A');
        lat=myGPS.gprmc_latitude();//Current latitude
        lon = myGPS.gprmc_longitude();//Current longitude
        int d=(round(myGPS.gprmc_distance_to(dest_latitude, dest_longitude, MTR)));
        //calculate the distance by rounding the GPS data from the current latitude,longitude to the desired Longitude 
        myLCD.setCursor(0,0);
        myLCD.print('D:');
        myLCD.setCursor(3, 0);
        myLCD.print(d);//Print the Distnace on LCD
        myLCD.setCursor(7, 0);
        myLCD.print('m');
        //if the distance is less than 6 than it should stop the car
        if (d < 6){
          myLCD.clear();
          myLCD.home();
          myLCD.setCursor(0,0);
          myLCD.print("Destinat");//Print destination 
          digitalWrite(13, HIGH);//Put the LED high
          digitalWrite(beeperpin, HIGH);//On the Buzzer pin 
          carbreak();//apply car breaks 
        }
        //if the distnace is not greater than 6 then move towards the waypoint
        if (d > 6){        
          myLCD.clear();
          myLCD.home();
          myLCD.setCursor(0,0);
          myLCD.print('D:');
          myLCD.setCursor(3, 0);
          myLCD.print(d);//Print the Distnace on LCD
          myLCD.setCursor(7, 0);
          myLCD.print('m');
          digitalWrite(beeperpin, LOW);
          digitalWrite(13, LOW);
          //average the down the direction from current latitude,longitude to destination latitude,longitude
          float mydir= 0;
          for (int x = 0; x<20; x=x+1){
            mydir=mydir + myGPS.gprmc_course_to(dest_latitude, dest_longitude);
          }
          mydir=mydir/20;
          if (mydir < 0) {//thats what i not understand 
            mydir += 360; //thats what i not understand
          }
          if (mydir > 180) { //thats what i not understand
            mydir -= 360; //thats what i not understand
          }
          float currentdir = compassvalue();//its the compass value
          float finaldir =currentdir - mydir;//subtract the compass value form the GPS beairng
          myLCD.setCursor(2,1);
          if ( abs (finaldir) < 20)//if the final direction is +20 or -20 it should go straight
          {
            myLCD.print ('Go Straight');
            motorForward();//car Forward
            steering('C');//Steering Centered  
            while(finaldir < 0)//if the Final direction is less than zero than goto LEFT
            {
              myLCD.print ("L"); 
              motorForward();
              steering('L');
            }
            while(finaldir > 0)//if the Final direction is greater than zero than goto RIGHT
            {
              myLCD.print ("R");
              motorForward();
              steering('R');
            }
            myLCD.print(abs(finaldir), DEC);//print the Direction 
            myLCD.print(223, BYTE);  // print °-character


          }
        }

      }
    }
  }
}
int compassvalue(){
  //"Get Data. Compensate and Calculate New Heading"
  Wire.beginTransmission(HMC6352SlaveAddress);
  Wire.send(HMC6352ReadAddress);              // The "Get Data" command
  Wire.endTransmission();

  //time delays required by HMC6352 upon receipt of the command
  //Get Data. Compensate and Calculate New Heading : 6ms
  delay(6);

  Wire.requestFrom(HMC6352SlaveAddress, 2); //get the two data bytes, MSB and LSB

  //"The heading output data will be the value in tenths of degrees
  //from zero to 3599 and provided in binary format over the two bytes."
  byte MSB = Wire.receive();
  byte LSB = Wire.receive();

  float headingSum = (MSB << 8) + LSB; //(MSB / LSB sum)
  float headingInt = headingSum / 10; 

  //Serial.print(headingInt);
  //Serial.println(" degrees");

  return headingInt;
}
//Motor commands Description 
void motorStop() {
  digitalWrite(leftMotor, LOW); 
  digitalWrite(rightMotor, LOW);
}
void motorLeft() {
  digitalWrite(leftMotor, HIGH);
}
void motorRight() {
  digitalWrite(rightMotor, HIGH);
}

//back wheels
void motorForward()
{
  digitalWrite(motorA1,HIGH);
  digitalWrite(motorA2,LOW);
}

void motorBackward()
{
  digitalWrite(motorA1,LOW);
  digitalWrite(motorA2,HIGH);
}


void carbreak()
{

  digitalWrite(motorA1,LOW);
  digitalWrite(motorA2,LOW);
}
void steering(char Dir)
{
  //if (Serial.available() == 0)
  //return;
  //Dir=toupper(Serial.read());
  switch (Dir)
  {
  case 'L':
    //Serial.println("New command: L");
    if (isLeft())
    {
    }//Serial.println("Already Left");
    else
    {
      //Serial.println("Heading Left");
      motorLeft();
      while (!isLeft()) /* JUST WAITING */;
      motorStop();
      //Serial.println("Is now Left");
    }
    break;

  case 'C':
    //Serial.println("New command: C");
    if (isRightOfCenter())
    {
      //Serial.println("Heading Left toward Center");
      motorLeft();
      while (isRightOfCenter()) /* JUST WAITING */;
      motorStop();
      //Serial.println("Is now Centered");
    }
    else
      if (isLeftOfCenter())
      {
        //Serial.println("Heading Right toward Center");
        motorRight();
        while (isLeftOfCenter()) /* JUST WAITING */;
        motorStop();
        //Serial.println("Is now Centered");
      }
      else
      {
      }
    //Serial.println("Already Centered");
    break;
  case 'R':
    //Serial.println("New command: R");
    if (isRight())
    {
    }//Serial.println("Already Right");
    else
    {
      //Serial.println("Heading Right");
      motorRight();
      while (!isRight()) /* JUST WAITING */;
      motorStop();
      //Serial.println("Is now Right");
    }
    break;
  }  // end of switch on direction
}

should i try this one

should i try this one

Try it by all means, and when you have done, if you still have problems, post the debug output and your observations.

If you don't have problems, pat yourself on the back, and post in the "Exhibitions" section.

This:

          //average the down the direction from current latitude,longitude to destination latitude,longitude
          float mydir= 0;
          for (int x = 0; x<20; x=x+1){
            mydir=mydir + myGPS.gprmc_course_to(dest_latitude, dest_longitude);
          }
          mydir=mydir/20;

seems a bit of a waste of time, if I'm understanding how the library works with the current NMEA sentence. A running average over several sentences would be more sensible.

            myLCD.print ('Go Straight');

Can you see what you did wrong there?

            while(finaldir < 0) {
      while(finaldir > 0) {

Uh-oh!

the above code did not worked for me so i modified it

#include <math.h>
#include <nmea.h>
#include <Wire.h>
#include <LiquidCrystal.h>
LiquidCrystal myLCD(42, 40, 38, 36, 34, 32);
float lat; 
float lon;
NMEA myGPS(GPRMC);
float dest_latitude = 25.37104;//the destination Latitude 
float dest_longitude = 68.35567;//the destination Longitude
int HMC6352SlaveAddress = 0x42;
int HMC6352ReadAddress = 0x41;
const int potPin = A8;          //Analog pin A8 for reading Potientiometer that drives the Servo steering
const int leftMotor = 27; //Pin connected to the Relay pin for moving the steering to left
const int rightMotor = 26;//Pin connected to the Relay pin for moving the steering to right
int     motorA1=22;       //Pin connected to the Relay pin for moving the car forward
int     motorA2=23;        //Pin connected to the Relay pin for moving the car backward
//below code describes the Steering ranges for left right and center
char Dir;
bool isLeft()          {
  return (analogRead(potPin)/4) <65;
}
bool isLeftOfCenter()  {
  return (analogRead(potPin)/4) < 108;
}
bool isRightOfCenter() {
  return (analogRead(potPin)/4) > 118;
}
bool isRight()         {
  return (analogRead(potPin)/4) > 128;
}
int beeperpin=44;//the following pin is connected to the buzzer pin 
void setup() {
  Serial.begin(9600);
  Serial1.begin(4800);//Start the serial communication of GPS from the Mega Board
  //PIN DESCRIPTION
  pinMode(leftMotor,OUTPUT);
  pinMode(rightMotor,OUTPUT);
  pinMode(motorA1,OUTPUT);
  pinMode(motorA2,OUTPUT);
  myLCD.begin(16,2);//starting the LCD
  Serial.print("GPS BASED");
  myLCD.print("GPS BASED");//Printing on LCD
  delay(1000);
  myLCD.clear();//Clearing the LCD
  myLCD.home();
  Wire.begin();
  HMC6352SlaveAddress = HMC6352SlaveAddress >> 1;
  pinMode(beeperpin,OUTPUT);
  pinMode(13,OUTPUT);
}
void loop(){
  if (Serial1.available() > 0 ) {
    // read incoming character from GPS
    if (myGPS.decode(Serial1.read())) {
      // check if the character completes a valid GPS sentence
      // check if GPS positioning was unactive
      Serial.println("V");
      myLCD.setCursor(15,1);
      myLCD.print("V");
      // check if GPS positioning was active
      if (myGPS.gprmc_status() == 'A') {
        Serial.println("A");
        myLCD.setCursor(15,1);
        myLCD.print("A");
        lat=myGPS.gprmc_latitude();//Current latitude
        lon = myGPS.gprmc_longitude();//Current longitude
        int d=(round(myGPS.gprmc_distance_to(dest_latitude, dest_longitude, MTR)));
        //calculate the distance by rounding the GPS data from the current latitude,longitude to the desired Longitude 
        Serial.println("D:");
        Serial.print(d);
        Serial.print("m");
        Serial.print("\n");
        myLCD.setCursor(0,0);
        myLCD.print("D:");
        myLCD.setCursor(3, 0);
        myLCD.print(d);//Print the Distnace on LCD
        myLCD.setCursor(7, 0);
        myLCD.print("m");
        //if the distance is less than 6 than it should stop the car
        if (d < 6){
          myLCD.clear();
          myLCD.home();
          Serial.println("Destination");
          Serial.println("CarbreaK");
          myLCD.setCursor(0,0);
          myLCD.print("Destinat");//Print destination 
          digitalWrite(13, HIGH);//Put the LED high
          digitalWrite(beeperpin, HIGH);//On the Buzzer pin 
          carbreak();//apply car breaks 
        }
        //if the distnace is not greater than 6 then move towards the waypoint
        if (d > 6){        
          Serial.println("D:");
          Serial.print(d);
          Serial.print("m");
          Serial.print("\n");
          myLCD.clear();
          myLCD.home();
          myLCD.setCursor(0,0);
          myLCD.print("D:");
          myLCD.setCursor(3, 0);
          myLCD.print(d);//Print the Distnace on LCD
          myLCD.setCursor(7, 0);
          myLCD.print("m");
          digitalWrite(beeperpin, LOW);
          digitalWrite(13, LOW);
          //average the down the direction from current latitude,longitude to destination latitude,longitude
          float mydir= 0;
          for (int x = 0; x<20; x=x+1){
            mydir=mydir + myGPS.gprmc_course_to(dest_latitude, dest_longitude);
          }
          mydir=mydir/20;
          if (mydir < 0) {//thats what i not understand 
            mydir += 360; //thats what i not understand
          }
          if (mydir > 180) { //thats what i not understand
            mydir -= 360; //thats what i not understand
          }
          Serial.println("GPS degree:");
          Serial.print(mydir);
          Serial.print("deg");
          Serial.print("\n");
          float currentdir = compassvalue();//its the compass value
          Serial.println("Compass Degree");
          Serial.print(currentdir);
          Serial.print("deg");
          Serial.print("\n");
          float finaldir =currentdir - mydir;//subtract the compass value form the GPS beairng
          Serial.println(finaldir);
          Serial.print("\n");
          Serial.println("Straight");

          myLCD.setCursor(2,1);
          if ( finaldir < 20 && finaldir > 340 )//if the final direction is +20 or -20 it should go straight
          {
            Serial.println("Straight");
            myLCD.print ("Go Straight");
            //motorForward();//car Forward
            //steering('C');//Steering Centered
          }  
          if(finaldir >180 && finaldir < 339)
          {
            Serial.print("Straight");
            Serial.println("Left");

            myLCD.print ("L"); 
            //motorForward();
            //steering('L');
          }
          if(finaldir > 20 && finaldir < 179)
          {
            Serial.print("Straight");
            Serial.println("Right");

            myLCD.print ("R");
            //motorForward();
            //steering('R');
          }
          myLCD.print(abs(finaldir), DEC);//print the Direction 
          myLCD.print(223, BYTE);  // print °-character
        }
      }
    }
  }
}
int compassvalue(){
  //"Get Data. Compensate and Calculate New Heading"
  Wire.beginTransmission(HMC6352SlaveAddress);
  Wire.send(HMC6352ReadAddress);              // The "Get Data" command
  Wire.endTransmission();
  //time delays required by HMC6352 upon receipt of the command
  //Get Data. Compensate and Calculate New Heading : 6ms
  delay(6);
  Wire.requestFrom(HMC6352SlaveAddress, 2); //get the two data bytes, MSB and LSB
  //"The heading output data will be the value in tenths of degrees
  //from zero to 3599 and provided in binary format over the two bytes."
  byte MSB = Wire.receive();
  byte LSB = Wire.receive();
  float headingSum = (MSB << 8) + LSB; //(MSB / LSB sum)
  float headingInt = headingSum / 10; 
  //Serial.print(headingInt);
  //Serial.println(" degrees");
  return headingInt;
}
//Motor commands Description 
void motorStop() {
  digitalWrite(leftMotor, LOW); 
  digitalWrite(rightMotor, LOW);
}
void motorLeft() {
  digitalWrite(leftMotor, HIGH);
}
void motorRight() {
  digitalWrite(rightMotor, HIGH);
}

//back wheels
void motorForward()
{
  digitalWrite(motorA1,HIGH);
  digitalWrite(motorA2,LOW);
}

void motorBackward()
{
  digitalWrite(motorA1,LOW);
  digitalWrite(motorA2,HIGH);
}


void carbreak()
{

  digitalWrite(motorA1,LOW);
  digitalWrite(motorA2,LOW);
}
void steering(char Dir)
{
  //if (Serial.available() == 0)
  //return;
  //Dir=toupper(Serial.read());
  switch (Dir)
  {
  case 'L':
    //Serial.println("New command: L");
    if (isLeft())
    {
    }//Serial.println("Already Left");
    else
    {
      //Serial.println("Heading Left");
      motorLeft();
      while (!isLeft()) /* JUST WAITING */;
      motorStop();
      //Serial.println("Is now Left");
    }
    break;

  case 'C':
    //Serial.println("New command: C");
    if (isRightOfCenter())
    {
      //Serial.println("Heading Left toward Center");
      motorLeft();
      while (isRightOfCenter()) /* JUST WAITING */;
      motorStop();
      //Serial.println("Is now Centered");
    }
    else
      if (isLeftOfCenter())
      {
        //Serial.println("Heading Right toward Center");
        motorRight();
        while (isLeftOfCenter()) /* JUST WAITING */;
        motorStop();
        //Serial.println("Is now Centered");
      }
      else
      {
      }
    //Serial.println("Already Centered");
    break;
  case 'R':
    //Serial.println("New command: R");
    if (isRight())
    {
    }//Serial.println("Already Right");
    else
    {
      //Serial.println("Heading Right");
      motorRight();
      while (!isRight()) /* JUST WAITING */;
      motorStop();
      //Serial.println("Is now Right");
    }
    break;
  }  // end of switch on direction
}

and the output is here

output.txt (8.89 KB)

What is the point of this:

          float mydir= 0;
          for (int x = 0; x<20; x=x+1){
            mydir=mydir + myGPS.gprmc_course_to(dest_latitude, dest_longitude);
          }
          mydir=mydir/20;

?

its used for averaging the 20 readings from the GPS

I thought you might say that.

Think of a number, but don't tell me what it is.
Double it.
Multiply that number by five.
Double that number.
Divide the number you have now by twenty.

You have the number you started with.
Amazing, or what?

I'm available for weddings and bar mitzvahs, my rate-sheet is online.

I think I pointed this out earlier.

ok then but it still does not work good from my side

Think of a number, but don't tell me what it is.
Add it to itself twenty times.
Divide the number you have now by twenty.

You have the number you started with.
Amazing, or what?

I'm available for weddings and bar mitzvahs, my rate-sheet is online.

I think I pointed this out earlier.

Well, your debug trace doesn't give any indication of how long it took (hint), but I'd probably go for continuous (1Hz) updates from the GPS, and do a rolling average of lat/long.

it still does not work good from my side

I'm sorry to hear that.

i am just working on the ranges but not able to define it properly so i need help in defining the ranges if you can do me a favour

You can't define the range; the range is simply the distance from where you are to where you want to be, and will obviously vary.

only worried about the direction

if ( finaldir < 20 && finaldir > 340 )//if the final direction is +20 or -20 it should go straight
{
Serial.println("Straight");
myLCD.print ("Go Straight");
//motorForward();//car Forward
//steering('C');//Steering Centered
}
if(finaldir >180 && finaldir < 339)
{
Serial.print("Straight");
Serial.println("Left");

myLCD.print ("L");
//motorForward();
//steering('L');
}
if(finaldir > 20 && finaldir < 179)
{
Serial.print("Straight");
Serial.println("Right");

myLCD.print ("R");
//motorForward();
//steering('R');
}

if ( finaldir < 20 && finaldir > 340 )/

Doesn't seem very likely, does it?

AWOL:

if ( finaldir < 20 && finaldir > 340 )/

Doesn't seem very likely, does it?

Also you have some gaps where if the value is 179 through 180, 339 through 340, or exactly 20 (as examples) there's no result as you've not tested for >= or <=.

tell me the mistakes if any

uncheck_asad_test_new_2.pde (10.2 KB)

Well, as usual, you're ignoring what you're being told.
How many times do you need to be told that adding the same number twenty times and then dividing by twenty is a waste of time?
How many times have I told you that static analysis of software is about the least productive way of debugging?

Again if ( finaldir < 20 && finaldir > 340 )//
Can you list all the values of "finaldir" which are going to trigger this condition?
(Hint: It's a very short list)