Electronic – arduino – Making a robot go straight using encoder motors and micro-controller (Arduino)

arduinoencodermotor

Now I have a simple chassis with two wheels which are powered by encoder motors. I connected Arduino Uno with the chassis and made a simple program to just count the numbers of signals (in simple terms) from each of the encoder motors.

Now theoretically when the chassis moves straight both readings should be exactly the same (I've checked – They are!). And when one motor is faster that certain reading should be more.

So I made a simple program that keeps a check on these encoder readings and when the difference exceeds a certain value it shuts off one motor until the values don't become equal and then turn on that motor.

Now theoretically the chassis should go in a straight line but it doesn't and performs weird stuff. (Code is attached below).

Now sometimes the code gets stuck in one of the while loops. I've also tinkered with my code a lot. For example instead of while(left_counter != right_counter) I've even done while ((left_counter - right_counter) > Certain_Range

The only problem I can think of is that it takes time for the motors to turn off and in that time the interrupts are wreaking havoc. (I'm new to micro controller programming and stuff although I have quite a lot of experience in C++ etc.)

Please can any one explain why isn't this approach working in keeping the motor straight?

Code (Arduino UNO):

int motor_vcc_left = 12; //LEFT TIRE - BLUE
int pull_up_left = 3; //LEFT TIRE - GREEN

int motor_vcc_right = 11; //RIGHT TIRE - ORANGE
int pull_up_right = 2; //RIGHT TIRE - BLUE

int encoder_vcc_pin = 7;

volatile int left_counter = 0;
volatile int right_counter = 0;

void setup() {
  pinMode(motor_vcc_left, OUTPUT);
  pinMode(motor_vcc_right, OUTPUT);

  pinMode(encoder_vcc_pin, OUTPUT);
  digitalWrite(encoder_vcc_pin, HIGH);

  pinMode(3, INPUT_PULLUP); //LEFT TIRE
  attachInterrupt(1, blinkleft, CHANGE); //LEFT TIRE

  pinMode(2, INPUT_PULLUP); //RIGHT TIRE
  attachInterrupt(0, blinkright, CHANGE); //RIGHT TIRE

  digitalWrite(motor_vcc_left, HIGH);
  digitalWrite(motor_vcc_right, HIGH);
}

void loop() {
  if ((left_counter - right_counter) > 10) {
    while (left_counter != right_counter) {
      digitalWrite(motor_vcc_left, LOW);
    }
    digitalWrite(motor_vcc_left, HIGH);
  } else if ((right_counter - left_counter) > 10) {
    while (right_counter != left_counter) {
      digitalWrite(motor_vcc_right, LOW);
    }
    digitalWrite(motor_vcc_right, HIGH);
  }
}

void blinkleft() {
  left_counter++;
}

void blinkright() {
  right_counter++;
}

Best Answer

Simply turning the motors on and off won't get you far when it comes to driving straight. Motors and the robot itself have some inertia, so they won't just stop in place when you switch them off. Much better approach would be to implement a PID controller, or at least proportional part of it.

How proportional controller works?

  • First you measure how many ticks you get in a certain, constant period, i.e. 10 ms, for each of wheels.
  • You compare the result, with desired target value, let's say 40 ticks.
  • When measured value is greater than the target you slow down motor a bit, when it's smaller you speed it up.

On Arduino, where you control a motor speed by PWM it looks like:

void loop() {
  if(micros() - t > PERIOD) {
    error = target - ticks;
    newPWM = error * proportionalGain;
    runMotor(newPWM);
    t = micros();
  }
}

This example is for only one motor, but I hope you get the general idea. You will need to tune PERIOD and proprtionalGain yourself. Remember, that valid PWM range for Arduino is 0-255.

Problems you will probably encounter Even when you have your motor running at the exactly same speed, you may still observe that your robot will turn. Here are few possible reasons: - Unequal wheels diameters - Uneven mass distribution in the robot (more mass on one wheel than on another) - Misalignment of wheels Here's a great paper, on a method called UMBmark developed by Johann Borenstein, that helps to counter these errors: http://www-personal.umich.edu/~johannb/Papers/paper60.pdf