I have built a mobile robot with two dc motors. In terms of functionality everything is fine, however due to an inconsistent speeds of two motors, robot is unable to go perfectly straight, or make a proper 90 degree turn. One motor stops slightly later than the other one causing robot to starts sliding right or left side. Same problem when reversing. I have found out about encoders and PID algorithm. However PID is not ideal for me, so I would like to go with encoders but I couldn't find a proper resource to read about encoders to decide which type is right for me. If anyone had a similar problem, please share ideas or solutions.
PIDs and encoders go together. A PID is no good without some way of measuring how far the wheels have rotated in order that the speed of one or both motors can be adjusted in order to ensure that the robot runs straight.
However, you may have a more basic problem than the 2 motors running at different speeds, although that 9s also a common problem Why does one motor stop slightly before the other ? Are you using a motor shield to drive the motors, if so, which one ? Or have you connected the motors in some other way ? Please post a program that exhibits the problem of one motor stopping before the other as you may have exacerbated a mechanical problem by introducing a programming problem.
Thank you for the reply, Actually it could be a exactly what you're saying. Because I had different motors and wheels couple of weeks ago and robot reacted the same way it does now considering the whole chassis, wheels and motors has been replaced . After reading your reply I have tested the wheels once again, one of them definitely stops after the other one, causing the whole problem. I use L298N motor controller. Can you tell me what you think could possibly cause this issue, I will try to get to the bottom of it.
Friction, its a fact of life with small cheap gearmotors that friction will vary quite a lot between
instances of the same motor. This why position feedback is necessary.
@MarkT, No it's nothing to do with friction, same problem occurred with a completely different DC motors and wheels. In fact, I have just switched the H bridge connections of the motors, now the problem occurs on the right motor, originally it was the left motor that had the problem the whole time. So it is something to do with the h bridge. It also makes a beep sound every time it tries to move the motors, does that ring any bells? I will try a different H bridge to see what's it gonna be like.
@UKHeliBob Thank you, two functions are below, for right and left motor.
void DCMotor::leftMotor(int mode, int speed) {
//change the percentage range of 0 -> 100 into the PWM
//range of 0 -> 255 using the map function
int leftDuty = map(speed, 0, 100, 0, 255);
switch (mode) {
case 0: //disable/coast
digitalWrite(ENA, LOW); //set enable low to disable A
break;
case 1: //turn clockwise
//setting IN1 high connects motor lead 1 to +voltage
digitalWrite(IN1, HIGH);
//setting IN2 low connects motor lead 2 to ground
digitalWrite(IN2, LOW);
//use pwm to control motor speed through enable pin
analogWrite(ENA, leftDuty);
break;
case 2: //turn counter-clockwise
//setting IN1 low connects motor lead 1 to ground
digitalWrite(IN1, LOW);
//setting IN2 high connects motor lead 2 to +voltage
digitalWrite(IN2, HIGH);
//use pwm to control motor speed through enable pin
analogWrite(ENA, leftDuty);
break;
case 3: //brake motor
//setting IN1 low connects motor lead 1 to ground
digitalWrite(IN1, LOW);
//setting IN2 high connects motor lead 2 to ground
digitalWrite(IN2, LOW);
//use pwm to control motor braking power
//through enable pin
analogWrite(ENA, leftDuty);
break;
}
}
void DCMotor::rightMotor(int mode, int speed) {
//change the percentage range of 0 -> 100 into the PWM
//range of 0 -> 255 using the map function
int rightDuty = map(speed, 0, 100, 0, 255);//255
switch (mode) {
case 0: //disable/coast
digitalWrite(ENB, LOW); //set enable low to disable B
break;
case 1: //turn clockwise
//setting IN3 high connects motor lead 1 to +voltage
digitalWrite(IN3, HIGH);
//setting IN4 low connects motor lead 2 to ground
digitalWrite(IN4, LOW);
//use pwm to control motor speed through enable pin
analogWrite(ENB, rightDuty);
break;
case 2: //turn counter-clockwise
//setting IN3 low connects motor lead 1 to ground
digitalWrite(IN3, LOW);
//setting IN4 high connects motor lead 2 to +voltage
digitalWrite(IN4, HIGH);
//use pwm to control motor speed through enable pin
analogWrite(ENB, rightDuty);
break;
case 3: //brake motor
//setting IN3 low connects motor lead 1 to ground
digitalWrite(IN3, LOW);
//setting IN4 high connects motor lead 2 to ground
digitalWrite(IN4, LOW);
//use pwm to control motor braking power
//through enable pin
analogWrite(ENB, rightDuty);
break;
}
}
OK, that's part of your code but we still don't know how you call the functions and when. Please post your whole program. For all we know you stop one motor, delay() for a second then stop the second one. I don't suppose you do but it would be good to know for certain how you stop both motors.
here is how I call the stop function. There is a I2C receiveCall function, which receives a command from the master. Then motors are controlled accordingly.
void receiveCall(int byteCount) {
while (Wire.available()) {
recieved = Wire.read();
receivedValue += recieved;
}
if (receivedValue == forward) {
rightMotor.moveForward(rightMotor);
leftMotor.moveForward(leftMotor);
} else if (receivedValue == stop) {
rightMotor.stopMotor();
leftMotor.stopMotor();
} else if (receivedValue == reverse_) {
rightMotor.reverse(rightMotor);
leftMotor.reverse(leftMotor);
} else if (receivedValue == right) {
leftMotor.moveForward(leftMotor);
rightMotor.reverse(rightMotor);
} else if (receivedValue == left) {
rightMotor.moveForward(rightMotor);
leftMotor.reverse(leftMotor);
}