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:
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);
}
}
}
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);
}
}
}
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.
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.
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?