Summer Robotics Project #8 – Compass Calibration

The past two sessions have just been based on this, because we couldn’t find a way out of this seemingly never-ending circle of problems with the calibration. Our aim for the next few sessions were to finish calibrating the compass, use the compass to define a Turn function, and then to also finish our collision avoidance function. However, we couldn’t complete the tasks associated with the compass.

We are using a HMC5883L compass module, as mentioned in post #5, and I also mentioned how we had written some functions that would allow the robot to turn using compass bearings, increasing it’s accuracy, but that the robot would not run this function properly until it had been turned manually just a little bit, due to fluctuating readings, and not having any wheels. We expected that with the wheels on, the robot would adjust itself, and rotate a little every time until the value was within the needed range, and then carry out the function properly. We had also updated the code so that it sets the bearing, after every turn, as the new zero, in the hope that this should prevent any problems with the angle of rotation. However, this was not the case. The robot would not start the turn unless it was nudged in the direction we needed it to rotate in, after which it would complete the turn, but was always off by a significant amount.

First, we tried re-calibrating the compass, using the same code as before, but this time we proceeded to also use the Matlab files (Debug_plot) to check our calibration data. We re-calibrated the compass countless times over the past few days, and kept the data we felt was the most accurate of the lot (which we found was not that accurate itself anyway). We ran the code again, and noticed that the robot’s turns, which we had set at being 90 degrees in our Turn function, were not always 90 degrees, but the robot would always end up where it had started once it had completed four sets of on the spot turns. That’s when my boyfriend had a thought. After calibrating the compass, we could pre-define a number of positions, in this case 4, which correspond to different angle turns – Position 1 = 0 degrees, Position 2 = 90 degrees from 0, Position 3 = 180 degrees from 0 and so on.

By doing this, we are still setting the starting bearing to zero, and working around the issue of not being able to complete accurate 90 degree turns. We started by adding this into our setup:

 for (int i=0; i<4; i++){
     delay(10000);
     Serial.println(bearing);
     Serial.print("Setting Angle ");
     Serial.print(i);
     Serial.print(" in...");
     delay(1000);
     Serial.print(3);
     delay(1000);
     Serial.println(2);
     delay(1000);
     Serial.println(1);
     delay(1000);

     getAngle();
     delay(50);
 
     positionArray[i] = getAngle();
 
     delay(500);
     Serial.println(positionArray[i]);
     Serial.println("");
 }

Before the setup, we defined an array which is four items long – positionArray[4]. In the for loop, we take four values from our getAngle function, and assign them to the position array. This is completed manually, by turning the robot and placing it in the position we want to be recorded. When the code is run, and the serial monitor is opened up, the code written will prompt us to rotate by printing “Setting Angle 0 in.. 3 2 1” then waiting for 10 seconds to allow us enough time to rotate the robot to the next position, and then will prompt us when it is setting angle 1 and so on until it sets all four angles. We also got the serial monitor to print the array items at the end of each setup so that we can see the value the getAngle function has picked up.

We then modified the first part of the Turn function so that it no longer takes an angle as an input variable, but an item from the position array.

void Turn(int pos, bool clockwise){
    Serial.println("Turning Right");
    compass_heading();
    initialAngle = bearing;

    if (clockwise){
        float(targetAngle) = positionArray[pos];
... 
}

We ran this code, and to making setting the angles for positionArray, we changed some of the Serial.prints to lcd.prints as shown here:

 for (int i=0; i<4; i++){
     delay(10000);
     Serial.println(bearing);
     lcd.print("Setting Angle ");
     lcd.print(i);
     lcd.print(" in...");
     delay(1000);
     lcd.clear();
     lcd.print(3);
     delay(1000);
     lcd.clear();
     lcd.println(2);
     delay(1000);
     lcd.clear();
     lcd.println(1);
     delay(1000);
     lcd.clear();
 
     getAngle();
     delay(50);
 
     positionArray[i] = getAngle();
 
     delay(500);
     Serial.println(positionArray[i]);
     Serial.println("");
 }

After setting the positionArray items, we let the robot undergo a simple manoeuvre; move forwards and turn. We set the pos variable to position 1, which is a 90 degree turn, and set it to rotate clockwise, but noticed the robot was executing perfect 180 degree turns each time. We figured there might be a small error in the way in which we had written the code, and proceeded to test the next position, pos = 2 (180 degree turn) to see if this had executed a 270 degree turn. But to our dismay, it did not. It completed 180 degree turns again, but this time they were not perfect.

On close inspection we figured that the line “initialAngle = bearing” may be causing the issue in the function. What this line does is it sets every new position, that the robot rotates to, as the new zero, and we thought that this might be causing a loop hole in the code. We removed this function, and ran the code again, but with one problem solved we encountered yet another. The robot was, finally, executing the right turns, however due to badly written code, it would only rotate to the position from certain bearings. The code in the Turn function says

if (clockwise){
    float(targetAngle) = positionArray[pos];
  //------ SERIAL PRINTS ------//
    Serial.print("Target Angle: ");
    Serial.println(targetAngle);
    Serial.print("Current Angle: ");
    Serial.println(getAngle());
    Serial.println(" ");
  //----- MOTOR COMMANDS -----//
    do{
        setMotorSpeed(-120, 120); 
    } while(abs(encoder1()) < 10);
    do{
        setMotorSpeed(-120, 120); 
    } while(getAngle() < targetAngle);
}
 
else{
    float(targetAngle) = positionArray[pos];

 //------ SERIAL PRINTS ------//
    Serial.print("Target Angle: ");
    Serial.println(targetAngle);
    Serial.print("Current Angle: ");
    Serial.println(getAngle());
    Serial.println(" ");
 //----- MOTOR COMMANDS -----//
    do{
        setMotorSpeed(-120, 120);
    } while(abs(encoder1()) < 10);
    do{
        setMotorSpeed(120, -120);
    } while(getAngle() > targetAngle);
}
stopMotor();
encodeReset();

However, if you look at the first “do..while..” loop, it says to run the motors while getAngle (which is the current angle the robot is facing) is less than targetAngle (which is the position we want it to face) when rotating clockwise. This means the robot will turn only when its starting position is less than that of the position it needs to face at the end of the manoeuvre. I.e. if it is facing 120 degrees, relative to the new zero, and needs to rotate to face position 1 (90 degrees relative to zero), clockwise, you would expect it to do a complete 330 degree rotation until it reaches position 1. However it does not move at all, and this manoeuvre would be really inefficient either way. If we had set it as rotating from 120 degrees to position 1 counter clockwise, this would work as the counter clockwise loop states to run the motors while getAngle is greater than targetAngle.

When we ran the turn function from 30 degrees to position 1 clockwise, it stopped at the same position every time, which was close to 90 degrees. We won’t necessarily need to change the code, but will need to ensure that we choose the right direction of rotation when assigning the Turn function in any future code.

Advertisements

One thought on “Summer Robotics Project #8 – Compass Calibration

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s