PID or no PID?

ok, I can now handle 4 motors then what? Actually getting the PWM control working for all motors is just the beginning. Even using 4 motors of the same brand, same model does not mean that all have same performance….

In my case, I am using 4 micro metal-gear motors from POLOLU, the 100:1 HP version. Using their own encoders I am supposed to get same readings, more or less, from all of them since I am controlling them in exact the same way, however, I don’t.

PWM 4 motors - no PID

About 14 pulses per second variation, for a 48 pulses per rotation, or about 5% speed variation and this without any load.

Initially I tried to add a simple “calibration” to reduce the speed to the rest of the wheels to match the slower one. While working well without load and at maximum speed, the results are not really great when we reduce the speed though, while will look fine at high-speed, I have a variation of 10 pulses between the fastest and the slowest, which will be in this case about 8%:

PWM 4 motors - no PID, calibration

Then I decided to try the “old good” PID and the results are actually quite good actually, almost under 1% variation:

PWM 4 motors - PID

To good to be true? Yes, there is a catch, using these encoders you get around 48 pulses per revolution and for these motors this means about 280-290 pulses per second. To get a smooth PID however, you will need to recalculate quite often, and if you are looking at a 10 ms update rate, you only get 2 pulses at maximum speed! This is pretty much useless. The faster I can go is 50 ms, somewhere around 13 pulses at maximum speed…

While working, I just wish I had better encoders… Anyway, the PID code looks something like this:

int encLastErrRF;
int encLastErrRR;
int iErrRF = 0;
int iErrRR = 0;

int KP = 50; 		//PID proportional gain constant
int KI = 50; 		//PID intergral gain constant
int KD = 0; 		//PID derivative gain constant

void pwmSetMototsRightPID(){
	int16_t encErrF; 		//error from left encoder
	int16_t encErrR; 		//error from right encoder
	int16_t dErrF; 			//derivative error left
	int16_t dErrR; 			//derivative error right

	int speedRF;
	int speedRR;

	encErrF = pwmSpeedR - qeRightFrontDelta; //calculate error values
	encErrR = pwmSpeedR - qeRightRearDelta;

	iErrRF += (KI * encErrF);
	iErrRR += (KI * encErrR);

	dErrF = (encErrF - encLastErrRF);
	dErrR = (encErrR - encLastErrRR);

	encLastErrRF = encErrF;
	encLastErrRR = encErrR;

	speedRF = (KP*encErrF + iErrRF + KD*dErrF)/10; //PID equations
	speedRR = (KP*encErrR + iErrRR + KD*dErrR)/10; //PID equations

	if (speedRF > MAXSPEED){
		speedRF = MAXSPEED;

	if (speedRR < -MAXSPEED){
		speedRR = -MAXSPEED;

	pwmSetMototsRight(speedRF, speedRR);

Leave a Reply

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

You are commenting using your 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