Consider a differential drive robot that has two motorized wheels with an encoder attached to each for feedback. Supposed there is a function for each DC motor that takes a float from -1 to 1 and sets the PWM signals to provide a proportional amount of power to that motor. Unfortunately, not all motors are created equal, so sending each motor the same PWM signal makes the robot veer left or right. I'm trying to think about how to drive the robot straight using the encoders attached to each motor as input to a PID loop.

Here's how I would do it: I would take the difference between the left and right encoders, bound the error between some range, normalize it to be from [-1, 1], and then map it to the motor powers 0 to 1. So if I and D were zero, and we get an error of 1 (so the left motor has turned much more than the right motor), then left motor would be set to 0, and the right motor set to 1 (causing a hard left).

Are there any issues with this? What is a better approach?


Are there any issues with this?

The main issue with this is that while your proposed solution will instantaneously correct for a mismatch between the performance of the motors, it will not correct for accumulated error, let alone more complex errors in position such as Abbe error (see later).

What is a better approach?

There are several things you can do, depending on what your tolerance for errors are and how much effort you want to put into correcting them.

The first step would be to set up a pair of PID loops, one for each wheel, giving them both the same demand position. As I suggested in my answer to a similar question, if you keep both wheels within a very tight error bound of where you ask them to be, then it will take some time to accumulate enough of an error to cause noticeable veer.

It will also be much easier to tune two nominally independent Motor level PID loops than to tune a single complex, interdependent combined system. To stand any change of the higher level control working you really need each motor to behave as similarly as possible to the other motor for as much of the time as possible, and that really requires separate servo loops.

There are a number of further complications however, and it depends what accuracy you need and how much effort you are prepared to go to to correct for them as to which solution you go for. It may be that Dead Reckoning is sufficient, or you may need to add Relative or Absolute position determination to your robot.

One problem is that even if your left and right wheels both move 1000 encoder counts, you may still end up in a different position on two different runs.

For example, say you have a maximum following error of 10 encoder counts, and your motors are running at a speed of say 10 encoder counts per PID loop iteration. Your left motor might move 5,10,10,10...10,5 while your right motor might have a profile of 4,11,10,10...10,5 and even that slight difference in acceleration at the start of the move could cause the robot to set off in slightly the wrong direction. Not only that but the further you move in that direction, the greater the error will become in absolute terms. This is what we are talking about when we talk of Abbe error, and without a complex kinematic model or some sort of external reference, you are never going to be able to correct for it.

For more information, see my answer to a similar but not quite duplicate question: How can I use the Arduino PID library to drive a robot in a straight line? and my answer to the also related Line Follower optimization


I have a bot with 2 independently driven wheels.

I chose to use a gyro to keep it heading in the desired direction, bumps slippage and even picking it up and turning it around are of little consequence to it as it will just correct it's heading.

I use a single PID, which adds/subtracts a correction to the desired current speed for each of the 2 motors in accordance with the error in the current heading (direction) as determined by the gyro.

For example I set the speed to 50% and the heading to 20degrees. this would normally drive both motors at 50% power. but as the heading wanders off, the PID will make adjustments adding some power to one motor and removing some power from the other, so you might end up with a 45%/55% power split between the motors as the pid corrects the heading.

Gyros have their problems though, even with some time spent calibrating I'm still finding my gryo has about 1 degree per minute drift. It might be because the earth rotates 15 degrees per hour, this should also be considered in the long run.

As previously stated encoders on the wheels are a great idea for actually knowing how far you have traveled.

  • $\begingroup$ I would love to see your code for this. I am starting down the same path with a gyro/accelerometer/magnetometer but I'm still at the very early stage of just trying to make sense out of the readings from these sensors. $\endgroup$ – Ron Smith Aug 9 '17 at 2:09
  • $\begingroup$ Here is a link to my code, I'm afraid it may not be easy to understand. github.com/rlsutton1/piBot/blob/master/src/main/java/au/com/… $\endgroup$ – Robert Sutton Aug 10 '17 at 3:18

Your Answer

