Motor Speed Control

Hello,

We are doing a project for our senior capstone and are using the Arduino Duemilanove 328 and Ardumoto Motor Driver Shield.

We are using the Tamiya Twin Motor Gearbox to drive both of our wheels.

We have them set at the same speed, but no matter what we do, it tends to list to one direction or the other.

Any suggestions as to how to make them run at the exact same speed??

Thanks.

Below is our code in its entirety.

//ONU MAZE ROBOT 2012

#include <EEPROM.h>

const int STATE_FORWARD = 1;
const int STATE_TURN_RIGHT = 2;
const int STATE_BACKWARD = 3;
const int STATE_TURN_LEFT = 4;

int IRpin1 = 1;  
int IRpin2 = 2;
int IRpin3 = 3;

int pwm_a = 3;  //PWM control for motor outputs 1 and 2 is on digital pin 3
int pwm_b = 11;  //PWM control for motor outputs 3 and 4 is on digital pin 11
int dir_a = 12;  //direction control for motor outputs 1 and 2 is on digital pin 12
int dir_b = 13;  //direction control for motor outputs 3 and 4 is on digital pin 13

int state; //current state
int lastState; //previous state

void setup() 
{
  Serial.begin(9600);       // start the serial port
  pinMode(pwm_a, OUTPUT);  //Set control pins to be outputs
  pinMode(pwm_b, OUTPUT);
  pinMode(dir_a, OUTPUT);
  pinMode(dir_b, OUTPUT);
  
  analogWrite(pwm_a, 80);  //set both motors to run at (100/255 = 39)% duty cycle (slow)
  analogWrite(pwm_b, 80);
  lastState = state = STATE_FORWARD;
}

void loop() 
{
 
  float volts1 = analogRead(IRpin1)*0.0048828125;   // value from sensor * (5/1024) - if running 3.3.volts then change 5 to 3.3
  float distance1 = 65*pow(volts1, -1.10);          // worked out from graph 65 = theretical distance / (1/Volts1)S - luckylarry.co.uk
  Serial.println(distance1);                       // print the distance
  delay(20);                                      // arbitary wait time.
  
  float volts2 = analogRead(IRpin2)*0.0048828125;   // value from sensor * (5/1024) - if running 3.3.volts then change 5 to 3.3
  float distance2 = 65*pow(volts2, -1.10);          // worked out from graph 65 = theretical distance / (1/Volts1)S - luckylarry.co.uk
  Serial.println(distance2);                       // print the distance
  delay(20);                                      // arbitary wait time.
  
  float volts3 = analogRead(IRpin3)*0.0048828125;   // value from sensor * (5/1024) - if running 3.3.volts then change 5 to 3.3
  float distance3 = 65*pow(volts3, -1.10);          // worked out from graph 65 = theretical distance / (1/Volts1)S - luckylarry.co.uk
  Serial.println(distance3);                       // print the distance
  delay(20);                                      // arbitary wait time.

  Serial.print('\n');                              // skips a line
  
  if(state == 0) 
  {
    moveRobot();
    return;
  }
  
  if (distance1 > 125)
  {
    state = STATE_FORWARD;
  }
  else if (distance1 < 125 && distance2 > 95 && distance3 < 75)
  {
    state = STATE_TURN_RIGHT;
  }
  else if (distance1 < 125 && distance2 < 75 && distance3 > 95)
   {
      state = STATE_TURN_LEFT;
   }


  Serial.println(state);
  moveRobot();
}

void moveRobot() 
{
  switch( state ) {
    case 1: {
      digitalWrite(dir_a, LOW);  //Set motor direction, 1 low, 2 high
      digitalWrite(dir_b, LOW);  //Set motor direction, 3 high, 4 low
      break;
    }
    case 3: {
      digitalWrite(dir_a, HIGH);  //Set motor direction, 1 low, 2 high
      digitalWrite(dir_b, HIGH);  //Set motor direction, 3 high, 4 low
      break;
    }
    case 2: {
      digitalWrite(dir_a, LOW);  //Set motor direction, 1 low, 2 high
      digitalWrite(dir_b, HIGH);  //Set motor direction, 3 high, 4 low
      break;
    }
    case 4: {
      digitalWrite(dir_a, HIGH);  //Set motor direction, 1 low, 2 high
      digitalWrite(dir_b, LOW);  //Set motor direction, 3 high, 4 low
      break;
    }
  }
}

//END OF LINE

PWM (analogWrite()) only sets the proportion of time the motor gets power. The characteristics of the motor and load determine how fast the motor goes with that input power. To get any sort of precise speed control you need feedback. You need some way to measure the speed and adjust the power to get the speed you want.

You might be able to get close by adding a fudge factor to one motor's control input and manually adjusting that fudge factor to get closer to equal speed on the two motors.

I'm still relatively new to using Arduino.
Can you give me a generic code example???

Thanks man.

void setup() 
{
  Serial.begin(9600);       // start the serial port
  pinMode(pwm_a, OUTPUT);  //Set control pins to be outputs
  pinMode(pwm_b, OUTPUT);
  pinMode(dir_a, OUTPUT);
  pinMode(dir_b, OUTPUT);
  
  analogWrite(pwm_a, 80);  //set both motors to run slow
  analogWrite(pwm_b, 78);  // Motor B runs a little faster than Motor A so apply a little less power
  lastState = state = STATE_FORWARD;
}