PWM - compensate for variances between 2 motors

I am trying to figure out how to make my robot move in a relative straight line.
I am using the 29:1 Metal Gearmotor 37Dx52L mm and Dual MC33926 Motor Driver Carrier

It seems that even though the motors are “identical”, the robot veers hard to one side.
(I know rotary encoders providing feedback to the MCU are the best method, but hope to compensate thru program code.)

I tried switching the motors on the Dual MC33926 Motor Driver Carrier and connected the inputs for both input channels together to make sure the difference was in the motors, not the H-Bridge driver module.

The robot can be seen at

I am using a simple BS2 program to ramp up/down the motors to just move forward, pause, and backward. I tried increasing the Duty value for the second motor but it doesn’t make much difference.

Any suggestions would be appreciated… (910 Bytes)


That’s a pretty nice chassis you have there! Varying the PWM duty cycle is a good way to compensate for motor variance. How much compensation have you tried? I am not that familiar with Basic Stamp; but it seems weird to me that you have a FOR loop around your PWM commands. What is the reason for that FOR loop? To get a better sense for what the correction offset should be, can you try making a simpler program that just sets a PWM for both motors and keep adjusting that until you have your robot driving straight?

- Ryan

that sure is a nice chassis… if you bought it can you please pm me the store’s name you bought it from?

now about the robot going in a straight line. the code is correcting the offset in the motor speeds by adding an extra 10% voltage to the slower motor. This may produce results during calibration. But may not be repeatable because the battery voltage drop as the battery discharges. Therefore the constant 10% offset may not work. Feel free to correct me if i am wrong, but in my opinion, it may be better to make the slower motor’s PWM be dependent on the higher motor’s PWM. Or you can try using a voltage regulator and give steady voltage to your motor drivers and not worry about the battery discharging issue. You can initially test this by using a wall mounted SMPS as the power source and see if it makes a difference. If it works, then you may be able to get away with using a constant correction factor that can give repeatable results… in this case, going in a straight line.

Although the best was to solve this issue is to use encoders and PID control.

regardless of the approach you use, please share your experience and let me know how it works out.


seems weird to me that you have a FOR loop around your PWM commands. What is the reason for that FOR loop? [/quote]

The FOR loop is repeating the short cycle PWM signal for both motors. If I eliminate the loop and increase the duration e.g. (number of cycles in the BS2 PWM command), the alteranting pulses cause the robot to oscillate as each motor is activated - e.g PWM M1D2, pwmduty, 50 rather than PWM M1D2, pwmduty,5

Unless I am missing something, the way to use the Dual MC33926 Motor Driver is to:
take IN1 LOW (or HIGH for opposite direction)
take IN2 HIGH (or LOW for opposite direction)
repeatedly PWM D2 (to continue motor rotation)
take D2 LOW (to stop motor)


[quote]that sure is a nice chassis… if you bought it can you please pm me the store’s name you bought it from?

Thanks! I made it from a large piece of 1/8" aluminum with hours of cutting with a hacksaw, filing and sanding(320,400,600 &1000 grit wet/dry sandpaper). I used Mother’s Mag & Aluminum polish to finish it off.

I considered that the variance between the motors might not be linear - as you said “it may be better to make the slower motor’s PWM be dependent on the higher motor’s PWM”.

I hope the battery level doesn’t cause too much of an issue. I was trying to get by with the expense and complexity of encoders but that might be only way…

Thanks for your help!

I forgot to mention in my first response that the motors you are using have a higher stall current than the MC33926 can supply continuously, so you’ll want to try to avoid stalling your motors to avoid taxing the motor drivers.

I looked at how the PWM command works and I understand why you have that loop there now. Since you are never running both motors at the same time there might be additional effects even beyond what thegreatskywalker is describing. In general, the approach you are doing in your code is going to have worse results than sending two PWM signals simultaneously to the motor driver. Your description of how to control one motor channel is correct, assuming you use the board default for D1.

I still recommend trying a much simpler program that lets you experiment to get the right compensation.

- Ryan

Thanks for the info! When I ordered the motors and driver board, I was a little concerned about the stall current but it looks like the “load current feedback feature” can be used to monitor the current and take action.

The Basic Stamp can’t send two PWM signals simultaneously - I will probably end up using the Parallax 8-core Propeller MCU instead - especially if I have to use encoders to monitor RPMs.

On the Parallax forum, one person suggested:

[quote]You basically have two choices:

  1. add an encoder of some type


  1. set both motors at 50% duty cycle

  2. let it run for 10 feet, measure the difference of where it ended up compared to a straight line

  3. if significantly off a straight line, use the difference to increase or decrease the duty cycle on one of the motors, goto 3

  4. now you should have settings for a straight line; and you should be able to increase/decrease the “default” by the same % to go faster/slower more or less straight

and another person said:

Thanks again! I will keep experimenting. Probably should have just sprung for the motors with the encoders on the back!!

may be you can try a “car type” drive instead of a differential drive. Use one motor and give its output to two rear wheels by using gears. This way only one PWM is required and the robot will go straight. Your machining skills seem good, so it shouldn’t be a problem for you. For steering, you can use a servo attached to the front wheel.

I placed the Parallax Absolute Binary Rotary Encoder on the breadboard a created a program to start with a base PWM duty value of 170 - it was unstable at lower values.

Setting the encoder from 0 to 15 (0xF) and hitting the stamp reset let me change the speed for a short run.

The best results were setting the PWM Duty value of the slower motor 7 higher than the faster motor.

The are differences between repeated runs at the same speed - for various reasons I’m sure, but
adding sensors to detect objects and change direction seems more practical now that I can get it to move relatively straight…

This video shows two runs at different speeds: