Is it possible to turn the robot to a certain degree with Compass?

Hello Guys,

I am working on a robot project, I am trying to turn the robot to a certain degree with the help of a compass, the robot uses two DC motors. so, I don't have any stepper or encoder to determine the wheel rotation.

My idea was to read the current bearing and add the new angle to it, then turn the robot until it reaches to that angle from north. for example:

compassReading = getBearing(); 
int newAngle = compassReading + 45 ;
if (newAngle > 359) {
newAngle = newAngle -359;
}
turnTheRobot(newAngle);

the Code for turning the robot can be something like this:

void turnTheRobot(int angle){
int counter = getBearing();
while (! counter == angle) {
turnRight(leftmotorSpeed, rightmotorSpeed);
counter= getBearing();
}
}

this code was a simple idea which I tried many times, however it still doesn't work.

Can anyone help me please. If it is possible can you guys provide a simple algorithm or a piece of example code.

I really appreciate your help.

Regard

You probably will want to incorporate some PID logic to get a smoother transistion between headings. Otherwise, your robot may endup fidgety or spastic...

I think one problem is that when you test for "while (! counter == angle)" if you overshoot even one degree you will have to take a full rotation to try again. You should probably turn in the shortest direction:

void turnTheRobot(int newBearing){
  while (1) {  // Repeat unit break
    int currentBearing = getBearing();
    int error = currentBearing - newBearing;
    if (error == 0) 
        break;  // All done!
    if (error > 180)
        error -= 360;  // Shorter to turn left
    if (error < -180)
        error += 360;  // Shorter to turn right

  if (error < 0)  // Turn left
    {
    turnLeft(leftmotorSpeed, rightmotorSpeed);
    }
  else  // turn right
    {
    turnRight(leftmotorSpeed, rightmotorSpeed);
    }
  }
}

Thank you for the reply,

I will check with your solutions.

Regards.

Hi John,

Thanks for your constructive reply, I am not worried to turn the robot to the shortest direction as the application well decide the direction according to the sensors readings. basically, I am turning the robot 30 or 45 degrees (right or left) if right or left is free (No object).

I used bit of your code, now I am able to turn the robot to some degree and I also scarified 5 more degrees because of uncertainties. for example: if I wanted to turn it 30 degrees to right, the robot turns 30 degree, if the compass reading is between 30 to 35, it stops.

If you can please check the code, it has some problem when the compass reading is close to 360 degree because the desired angle will be 10- 40 from north and the current reading is something like 340-360. so, 10-40 is never smaller than 340-360. Can you please suggest any solution here.

void turnTheRobot(int angle){
  int currentBearing = getBearing();
  int newBearing = currentBearing + angle;
  
    if(newBearing > 359) {
      newBearing -= 359;
    }
  while(1) {
    int x = getBearing();
    if(x >= newBearing && x <= newBearing + 5) {
      moveForward(0);
      break;
  }
  else {
    turnRight(80,80);
  }
  }
}

Farhad:
Can you please suggest any solution here.

I suggest you change your design to use the approach that johnwasser showed you.

Hey Guys,

I have followed Johns approach, the problem is: the compass has inaccuracy and it does not give exactly 45 degree. for example, if the desire angle is 45 degrees, it turns the robot but does not stop because the compass has 1 or 2 degrees inaccuracy.

if(error == 0){ somecode; }

Error never become 0, since 45 becomes 46 or 47. what I am trying to do is define a range, between 45 and 50, if the compass reading is between 45 and 50 it should stop.

hey guys,

It seems that I solved the problem, just wanted to post my code for some people facing same problem,

I don't know whether this approach is right or not, but it works. I hope it does not affect other parts of my application.
you are more than welcome to comment and suggest a better approach.

void turnRightTheRobot(int angle){
  int currentBearing = getBearing();
  int desiredBearing = currentBearing + angle;
  if(desiredBearing > 359) {
    desiredBearing -= 359;
  }
  do{
    int newBearing = getBearing();
    double desiredBearingSINE = sin(desiredBearing * (PI/180));
    double currentBearingSINE = sin(newBearing * (PI/180));
    
    if(desiredBearingSINE > 0 && currentBearingSINE < 0) {
     newBearing = newBearing - 360;
       }
     if(newBearing >= desiredBearing) {
      moveForward(0, 0);
      break;
    }
    else {
      turnRight(80,80);
    }
   }while(1);
}

Is your robot using a magnetic compass? If so have you consider what will happen when it is near anything generating magnetic fields or containing iron?

Radman,

Yes, it has a magnetic compass and I have not considered that, Lolzzz

I had no choice, I try to not send it near iron or magnetic stuff. I will try t o solve this problem in future with encoder or stepper motors.